Introducing `swift package add-setting` command

This new swift package sub-command adds a way to programmatically insert new settings into a package manifest per target similarly to existing add-target and add-{target}-dependency commands.

Currently only a limited number of Swift settings is supported, namely: enable{Upcoming, Experimental}Feature, languageMode and strictMemorySafety by passing --swift option to the command; but the command could be expanded to support more Swift (C, C++, linker) settings in the future.

Interface

OVERVIEW: Add a new setting to the manifest

USAGE: swift package add-setting --target <target> --swift <swift> ...

OPTIONS:
  --target <target>       The target to add the setting to
  --swift <swift>         The Swift language setting(s) to add. Supported settings: experimentalFeature, upcomingFeature, languageMode, strictMemorySafety
  --version               Show the version.
  -h, -help, --help       Show help information.

Use case

swift package add-setting --target MyTarget --swift upcomingFeature=InferSendableFromCaptures  --swift strictMemorySafety

which would add following swiftSettings to MyTarget:

.target(
  name: "MyTarget",
  ...
  swiftSettings: [
    // ... existing settings,
    .enableUpcomingFeature("InferSendableFromCaptures"),
    .strictMemorySafety
  ]
)

Note that the command checks the tools-version of the manifest to avoid adding settings that won't be supported. For example, attempting to add strictMemorySafety setting to 6.0.0 manifest would result in the following error:

error: package manifest version 6.0.0 is too old: please update to manifest version 6.2.0 or newer

Attempting to add a setting to a .plugin target is going to result in an error as well since plugins don't support settings.

Impact on Interface

This introduces a new Package manifest editing command but does not interfere with existing commands. It follows the same pattern as add-target-dependency, allowing users to add settings to .target(...), .macro(...) and .testTarget(...) in a consistent manner.

See SwiftPM PR for more details.

9 Likes

Please feel free to leave any feedback in this thread, the command is under development so all feedback is welcome!

This seems really useful... to clarify would this validate that something like InferSendablesFromCaptures would be validated as an upcoming feature?

Maybe an unrelated command/question would be, is there a way to see a list of upcoming features from the swift package api?

Yes, in fact I'm working on this bit at the moment. It would be possible to ask the compiler about all of the upcoming/experimental features supported by Swift and validate them.

2 Likes

Swift and driver work is done - [Jobs] Add a job for `-print-supported-features` by xedin · Pull Request #1880 · swiftlang/swift-driver · GitHub, [Frontend] Add a way to print features supported by the compiler by xedin · Pull Request #80833 · swiftlang/swift · GitHub. Working on swiftpm integration at the moment.

Thanks for the work on this! It is very useful when testing new features on different swift new features through swift package.

Since it is mainly focus on swiftSettings of Package.swift, would it be possible to add flags/unsafe flags through the command also?

And a sudden thought: will remove-setting be a possible reverse for add-setting?

would it be possible to add flags/unsafe flags through the command also?

Yes, we can look into that, the "unsafeFlags" are somewhat tricky because they are themselves an array

And a sudden thought: will remove-setting be a possible reverse for add-setting?

Yes, but before we can make that work we need to make it possible to match the nodes, it's something that has to be implemented on the swift-syntax side.

2 Likes

I assume this is just a me thing, but I don’t see what the point of these CLI commands is. When would you programmatically be adding settings? And if it’s not for scripting, why is this better than editing the Package.swift file yourself?

4 Likes

That's a very good point I personally missed.
My personal habit used to search for available commands from swift package first, if not then I will edit the package manifest.

Interestingly, for build.gradle, I mostly start with edit with editor first, CLI is like a last-resort thing.

But I agree it does the same thing if you just open Package.swift in any editor that can change swiftSettings.

I like the sanity-checking that happens against the manifest version. Also the ability to ask the compiler about all available upcoming/experimental features helps with discoverability.

An example of such a tool would be to migrate to a new upcoming feature, which can then use this to add the relevant setting. But in addition to @rhx's comment, I also like the discoverability aspect of the command line tool.

At the most basic level, doing it through the command line provides both documentation and, with the right shell plugins, autocomplete, both of which may be missing if you try to edit the file yourself. Given the sheer number of options for each part of the package manifest it's extremely tedious to update it manually, unless you do it so often you remember where things go.

1 Like