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

3 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. 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.

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
Terms of Service

Privacy Policy

Cookie Policy