# SwiftPM and swappable libraries?

**URL:** <https://forums.swift.org/t/swiftpm-and-swappable-libraries/43593>\
**Category:** Using Swift\
**Tags:** packagemanager, swiftpm, kitura\
**Created:** [January 6, 2021, 4:33am UTC](https://forums.swift.org/t/swiftpm-and-swappable-libraries/43593 "2021-01-06T04:33:03Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![dannys42](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dannys42/32/3994_2.png) [@dannys42](https://forums.swift.org/u/dannys42)\
**Post date:** [January 6, 2021, 4:33am UTC](https://forums.swift.org/t/swiftpm-and-swappable-libraries/43593/1 "2021-01-06T04:33:03Z")

</div>

I've got a peculiar use-case that I was wondering if anyone has any good solutions for. The [Kitura](https://github.com/Kitura/Kitura) project has a dependency on a network layer... this network layer was originally provided by [Kitura-net](https://github.com/Kitura/Kitura-net), but then NIO came along, and the previous maintainers/authors created an API compatible library called [Kitura-NIO](https://github.com/Kitura/Kitura-NIO). However, they both provide the `KituraNet` product name. So basically right now there are two implementations of the same API, and I'd like an easy way for people adding Kitura to their project to be able to decide which implementation to use.

The previous authors came up with a clever solution using environment variables. Here's a snippet of the Package.swift of the current implementation:

```swift
var kituraNetPackage: Package.Dependency

if ProcessInfo.processInfo.environment["KITURA_NIO"] != nil {
    kituraNetPackage = .package(url: "https://github.com/Kitura/Kitura-NIO.git", from: "2.4.200")
} else {
    kituraNetPackage = .package(url: "https://github.com/Kitura/Kitura-net.git", from: "2.4.200")
}

let package = Package(
    ...
    dependencies: [
        kituraNetPackage,
        ... various dependencies ...
    ]
    ...
)

```

This works really well on the server. However the problem I'm facing is that if wanted to use Kitura in an iOS project with SwiftPM, there is no way to provide the `KITURA_NIO` environment variable to SwiftPM through Xcode. I've tried placing it in the run scripts and setting the environment variable in the scheme editor to no avail.

I thought I might be able to use SwiftPM's multi-product description, something like this:

```swift
    ...
    products: [
        .library(
            name: "Kitura",
            targets: ["Kitura"]
        ),
        .library(
            name: "KituraNIO",
            targets: ["Kitura"]
        )
    ],
    dependencies: [
        .package(url: "https://github.com/Kitura/Kitura-NIO.git", from: "2.4.200"),
        .package(url: "https://github.com/Kitura/Kitura-net.git", from: "2.4.200"),
        ... various dependencies ...
    ]
    ...

```

However, the problem here is that SwiftPM recognizes `Kitura-NIO` and `Kitura-net` both provide the same target and I get this error:

```swift
error: multiple products named 'KituraNet' in: Kitura-NIO, Kitura-net
error: multiple targets named 'KituraNet' in: Kitura-NIO, Kitura-net

```

I could create separate branches, but then I lose the version selection capability that SwiftPM offers.

Does anyone else have any good suggestions? Has anyone seen a similar problem before?

Thanks

---

<div class="post-metadata">

**Author:** ![owenv](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/owenv/32/6137_2.png) [@owenv](https://forums.swift.org/u/owenv)\
**Post date:** [January 6, 2021, 4:51am UTC](https://forums.swift.org/t/swiftpm-and-swappable-libraries/43593/2 "2021-01-06T04:51:07Z")

</div>

It's a hack, but if you go the environment variable route, the integrated manifest loader will inherit Xcode's environment, so something like `KITURA_NIO=1 open Package.swift -a Xcode` should select the appropriate dependency. It's not a very good solution, but I think it's the best one available today and is used by a few of the Swift repos.

In the long term, a better solution will likely involve some sort of mechanism for feature toggles that can be exposed to package clients.

---

<div class="post-metadata">

**Author:** ![NeoNacho](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/neonacho/32/1368_2.png) [@NeoNacho](https://forums.swift.org/u/NeoNacho)\
**Post date:** [January 6, 2021, 7:13pm UTC](https://forums.swift.org/t/swiftpm-and-swappable-libraries/43593/3 "2021-01-06T19:13:23Z")

</div>

> [@owenv](#):
>
> It's a hack, but if you go the environment variable route, the integrated manifest loader will inherit Xcode's environment, so something like `KITURA_NIO=1 open Package.swift -a Xcode` should select the appropriate dependency. It's not a very good solution, but I think it's the best one available today and is used by a few of the Swift repos.

One caveat to keep in mind for the hack, it only works if Xcode isn't running already.

---

<div class="post-metadata">

**Author:** ![ZZZ](https://avatars.discourse-cdn.com/v4/letter/z/cc9497/32.png) [@ZZZ](https://forums.swift.org/u/ZZZ)\
**Post date:** [February 28, 2024, 3:04pm UTC](https://forums.swift.org/t/swiftpm-and-swappable-libraries/43593/5 "2024-02-28T15:04:14Z")

</div>

I am facing a similar problem, i have a swift package and i want to load different dependencies based on a certain condition any updates on how this can be achieved with Xcode and also using a build command to build the package

---

<div class="post-metadata">

**Author:** ![Joseph\_Heck](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joseph_heck/32/22369_2.png) [@Joseph\_Heck](https://forums.swift.org/u/Joseph_Heck)\
**Post date:** [February 28, 2024, 8:47pm UTC](https://forums.swift.org/t/swiftpm-and-swappable-libraries/43593/6 "2024-02-28T20:47:59Z")

</div>

I've used this same "set an environment variable" hack. The key to getting it to work with Xcode is launching Xcode from the space that had the environment variable set: so in effect, set an environment, then use `open Package.swift` or the `open Package.swift -a Xcode` commands to propagate that environment TO Xcode.

If you click on the app icon, that only picks up your default shell/environment background, which makes it a complete PITA to set and unset variables. That said, this "hack" mechanism has been pretty and effective stable for me - and I leverage the same setup when invoking `Xcodebuild` or `swift build` / `swift test` commands in CI to run and validate code.

---

<div class="post-metadata">

**Author:** ![rauhul](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rauhul/32/35207_2.png) [@rauhul](https://forums.swift.org/u/rauhul)\
**Post date:** [February 28, 2024, 10:26pm UTC](https://forums.swift.org/t/swiftpm-and-swappable-libraries/43593/7 "2024-02-28T22:26:22Z")

</div>

I use the following snippet in Package.swift to set feature flags, and be able to easily override them in my editor:

```swift
let interposable = "FEATURE_INTERPOSABLE"
if hasFeature(interposable, override: nil) {
  // do stuff
}

// Package API Extensions
func hasFeature(_ featureName: String, override: Bool?) -> Bool {
  let key = "SWIFT_MMIO_\(featureName)"
  let environment = ProcessInfo.processInfo.environment[key] != nil
  return override ?? environment
}

```
