Specify different dependencies of a package based upon a flag

I've distribuited a package which require an external dependency.
This dependency is quite large (firebase) and I would allow using both the precompiled version (link) or the main project source code (link).

Is possible to specify into the Package.swift two different sources of dependencies by setting a flags set into the main host project?
Or eventually, is there a way to accomplish this task with SPM?

Somethinbg like:

// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    ...
    dependencies: [
        .package(
            name: "Firebase",
            url: "https://github.com/firebase/firebase-ios-sdk.git",
            "9.3.0"..<"11.0.0"
        ),
        .package(
            name: "FirebaseXCFramework",
            url: "https://github.com/akaffenberger/firebase-ios-sdk-xcframeworks",
            "9.3.0"..<"11.0.0"
        )
    ],
    targets: [
        .target(
            name: "RealFlags",
            dependencies: [],
            path: "RealFlags/Sources/RealFlags/Classes",
        ),
#if FLAG_SET
.target(
            name: "RealFlagsFirebase",
            dependencies: [
                "RealFlags",
                .product(name: "FirebaseRemoteConfig", package: "FirebaseXCFramework"),
            ],
            path: "RealFlagsFirebase/Sources"
        ),
#else
        .target(
            name: "RealFlagsFirebase",
            dependencies: [
                "RealFlags",
                .product(name: "FirebaseRemoteConfig", package: "Firebase"),
            ],
            path: "RealFlagsFirebase/Sources"
        ),
#endif
)
1 Like

Some of us still use...

import Foundation
if ProcessInfo.processInfo.environment["FLAG_SET"] == "true" {
  package.targets = package.targets.map { /* Make modifications here */ }
}

...in order to smooth over issues with proper platform conditions. (e.g. WASI fails to load a dependency manifest if it declares a dynamic library, so you need to obliterate all references to such packages in your own manifest.)

However, the pins file and several caches are not parameterized for the environment, so the user experience degrades if you try to go back and forth between different environments on the same device.

If your particular use case were made into a feature, I think it would be tied in with the .automatic/.static/.dynamic system for libraries, where automatic is supposed to let the end user choose, but the actual userā€facing toggle flag has never been implemented.

1 Like