SE-0273: Package Manager Conditional Target Dependencies

Hello Swift community,

The review of SE-0273 “Package Manager Conditional Target Dependencies" begins now and runs through December 20, 2019.

Reviews are an important part of the Swift evolution process. All reviews should be made in this thread on the Swift forums or, if you would like to keep your feedback private, directly in email to me as the review manager.

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

  • What is your evaluation of the proposal?
  • Is the problem being addressed significant enough to warrant a change to the Swift Package Manager?
  • Does this proposal fit well with the feel and direction of Swift?
  • If you have used other languages, libraries, or package managers with a similar feature, how do you feel that this proposal compares to those?
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available on the Swift Evolution website.

As always, thank you for participating in Swift Evolution.

Boris Buegling
Review Manager

8 Likes

It will be nice to have and the design seems straightforward.

I’m curious what the longer‐term plan is for compatibility with Xcode—both for generated projects and directly loaded packages. I’m asking because I saw this in the PR.

  • Presumably Xcode’s direct loading will also be updated to handle this in the same release? Once that is done and Xcode can do conditionals, will generate-xcodeproj be updated to support it too?
  • Would it be possible to work around for the time being by duplicating the entire dependency tree for each relevant condition set? Then nothing is implemented as conditional, but you can still pick the scheme according to platform and configuration and get the right set of dependencies. Is that too much effort? (Not sure if it is a good idea. I’m just brainstorming.)

Regarding generated projects, there's no way to configure an Xcode project to have targets conditionally depend on others. So the implementation doesn't do anything and prints a warning that the generated project might not build as a consequence (we ought to say that in the proposal). With Xcode supporting SwiftPM packages, I'd de surprised if the generate-xcodeproj command isn't long for this world.

Concerning directly-loaded packages, I have no idea what the plan is, and I guess that Apple's rule of secrecy considering non open-source project means we'll not get an answer. But I'd be surprised if something was not done about it.

I know. I just hope it lasts long enough for the bugs in the direct loading to be fixed. Many of the projects I work with cannot switch because the new way cannot handle them yet. (Though it gets better with each minor release.)

This proposal could end up introducing a way that projects would be only compatible with the new way, and not the old. I dread the day when a dependency of one of the blocked projects starts using these conditionals—suddenly the package is completely incompatible with Xcode, because both strategies don’t work for separate reasons.

None of this is to say I don’t want conditional dependencies—I do. I just hope we can get them with as little grief as possible occurring along the way.

1 Like

+1. Super excited to see this proposed, thanks @NeoNacho and @hartbit !


Some nits / ideas:

One small thing is that .byName seems a little weird. Could we have something like .module or .dependency? For example:

import PackageDescription

let package = Package(
    name: "BestPackage",
    dependencies: [
        .package(url: "https://github.com/pureswift/bluetooth", .branch("master")),
        .package(url: "https://github.com/pureswift/bluetoothlinux", .branch("master")),
    ],
    targets: [
        .target(
            name: "BestExecutable",
            dependencies: [
                .module(name: "Bluetooth", condition: .when(platforms: [.macOS])),
                .module(name: "BluetoothLinux", condition: .when(platforms: [.linux])),
                .module(name: "DebugHelpers", condition: .when(configuration: .debug)),
            ]
        ),
        .target(name: "DebugHelpers")
     ]
)

Just a thought though, I'm sure there's good reasoning behind .byName.

My other question is whether .when is needed. Is there some future direction I'm missing where things other than when would be used or could we simplify this to:

.product(name: "Bluetooth", condition: .platforms([.macOS])),
.product(name: "BluetoothLinux", condition: .platforms([.linux])),
.target(name: "DebugHelpers", condition: .configuration(.debug)),

Or perhaps:

.product(name: "Bluetooth", condition: .platform(.macOS)),
.product(name: "BluetoothLinux", condition: .platforms([.linux, .windows])),
.target(name: "DebugHelpers", condition: .buildConfiguration(.debug)),
3 Likes

I think it was expected that .byName would rarely be used directly, as it represents the case when a dependency is represented by a String through ExpressibleByStringLiteral. But now that we can attach conditions to it, it might make sense to introduce a new factory function like .module.

.when is needed because you can combine conditions, exactly the same way as for build settings:

.product(name: "Bluetooth", condition: .when(platforms: [.macOS], configuration: .debug)),
2 Likes

.module seems wrong, since products definitely do not correspond to a module. I would expect .byName to be the least used option here, since it should always be clear to developers whether they are depending on a target or a product, so they can use the corresponding factory function.

1 Like

The review of SE-0273: Package Manager Conditional Target Dependencies ran from December 13th through December 20th, 2019. The proposal is accepted. Thanks to everyone who participated!

Boris Buegling
Review Manager

3 Likes

Sorry to bump this up, but are there still plans to implement configuration conditionals? I'm working on a project that could really benefit from having a dependency that's only used for debugging, and this would provide the easiest way of accomplishing that outside of Carthage (which we just removed from the project).

Yes, we are definitely still planning to implement configuration conditionals in the future. I can't share any concrete timeline at this point, though.

3 Likes

I hate to bump as well, but this is something I'm waiting on as well. And I love SPM!

Any more info on when we can expect configuration conditionals?

Hi, I would like to know if we could have something like this:

 dependencies: [.product(name: "planA", package: "planA", condition: .when(platforms: [.macOS(.v14), .ios(.v13)]))]

For example, I want to deploy a project to an old target, but I also want it can use newer/better framework on newer target.
So I think it would be good to specified not only platform, but also its version.
I hope to know if we can have this feature in the future.

4 Likes

Here is another +1 for the configuration conditionals. I’d find this very useful for a project I’m working on. The use case is a project that is divided in many self-contained SPM packages. I’d like to have fully-featured SwiftUI previews in the packages, which use some resources (e.g images). The previews would use resources from the package, that would be included only in a debug build for SwiftUI previews. The conditional dependency configuration proposed in SE-0273 looks exactly right for this purpose.

1 Like

This would help me as well. My use case: Including a specialized dev tool/library which should only be active and included in a debug build for a given target, via spm.

+1 for configuration conditionals :blush:

2 Likes

Adding another +1

2 Likes

Using SPM extensively and needs configuration conditionals. Here, hoping to use it soon.

1 Like

I could also really use build configuration conditionals for shipping Reveal's SDK via SwiftPM (although it's not clear if the SE as described would work for binary dependencies?).

Is there any chance of this still being implemented, or has this part of SE-0273 fallen off the priority list?

2 Likes

Adding yet another +1

3 Likes