It's really common to see Package.swift files that apply the Swift language settings to all targets. Here's a common approach.
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "MyPackage",
products: [
.library(name: "MyPackage", targets: ["MyPackage"]),
],
dependencies: [],
targets: [
.target(name: "MyPackage"),
]
)
let swiftSettings: [SwiftSetting] = [
.enableExperimentalFeature("StrictConcurrency"),
.enableUpcomingFeature("DisableOutwardActorInference"),
]
for target in package.targets {
var settings = target.swiftSettings ?? []
settings.append(contentsOf: swiftSettings)
target.swiftSettings = settings
}
I'd like to propose adding a new top-level property to the Package structure that makes it easier to define default settings for all Swift targets. Per-target settings would be merged with higher precedence. I'm also proposing this specifically to Swift and not C/C++, because I think this is by far the most-common case. But, if there are strong feelings here, I'm definitely open to expanding the idea.
Here's the new proposed manifest:
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "MyPackage",
products: [
.library(name: "MyPackage", targets: ["MyPackage"]),
],
// new stuff goes here!
swiftSettings: [
.enableExperimentalFeature("StrictConcurrency"),
.enableUpcomingFeature("DisableOutwardActorInference"),
],
dependencies: [],
targets: [
.target(name: "MyPackage"),
]
)
What do you think?
11 Likes
Sajjon
(Alexander Cyon)
2
Very reasonable, but I think I would like to call it defaultSwiftSettings (like your title suggests)
2 Likes
NeoNacho
(Boris Buegling)
3
I think the pitch makes sense at a high-level.
I think this will need a lot more concrete design, potentially with different merging strategies based on the type of settings. For example, Xcode has a pretty sophisticated model here, with multi- and single-value settings, $(inherited) etc -- a lot of the cases that solves will likely come up in a multi-layer build settings model for SwiftPM as well.
There's also the question of how to address potential ambiguity with swiftLanguageVersion (see SE-0435) since that would also be part of SwiftSetting now, but there's an existing package level property for this already.
2 Likes
I thought about this! I opted for more straight-forward spelling because I think the risk for ambigitity/confusion is small. But I'm definitely open to it!
You are absolutely right! I didn't even know a multi-layer settings model existed. Where can I learn more about it?
Shoot. Am I correct that there is currently no validation on the strings that go into these settings vs the active language model? And if I am, I'm inclined to use that as precedent to say that, just like there, you have to be equally careful.
grynspan
(Jonathan Grynspan)
6
I would want to see a similar treatment for C and C++ compiler settings. 
5 Likes
NeoNacho
(Boris Buegling)
8
I think I was a bit unclear about my concern. Basically if we take your pitch and SE-0435, it will be possible to write something like this:
let package = Package(
name: "pkg",
...
swiftSettings: [
.swiftLanguageVersion(.v6),
],
...
swiftLanguageVersions: [.v5]
)
I think that is pretty ambiguous.
4 Likes
That is confusing! Am I correct that this would be equivalent to:
let package = Package(
name: "pkg",
...
targets: [
.target(
name: "target",
swiftSettings: [.swiftVersion(.v6)]
),
],
...
swiftLanguageVersions: [.v5]
)
Could this handle the situation in the same way?