Skip to content

Cherry-pick Assure trait-guarded dependencies are not included in resolution; precompute enabled traits before resolution (#8852) #8948

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions Sources/Commands/PackageCommands/APIDiff.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,6 @@ struct APIDiff: AsyncSwiftCommand {
help: "One or more targets to include in the API comparison. If present, only the specified targets (and any products specified using `--products`) will be compared.")
var targets: [String] = []

@OptionGroup(visibility: .hidden)
package var traits: TraitOptions

@Option(name: .customLong("baseline-dir"),
help: "The path to a directory used to store API baseline files. If unspecified, a temporary directory will be used.")
var overrideBaselineDir: AbsolutePath?
Expand All @@ -91,7 +88,6 @@ struct APIDiff: AsyncSwiftCommand {
// We turn build manifest caching off because we need the build plan.
let buildSystem = try await swiftCommandState.createBuildSystem(
explicitBuildSystem: .native,
traitConfiguration: .init(traitOptions: self.traits),
cacheBuildManifest: false
)

Expand Down
2 changes: 1 addition & 1 deletion Sources/Commands/PackageCommands/DumpCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ struct DumpSymbolGraph: AsyncSwiftCommand {
let buildSystem = try await swiftCommandState.createBuildSystem(
explicitBuildSystem: .native,
// We are enabling all traits for dumping the symbol graph.
traitConfiguration: .init(enableAllTraits: true),
enableAllTraits: true,
cacheBuildManifest: false
)
try await buildSystem.build()
Expand Down
2 changes: 1 addition & 1 deletion Sources/Commands/PackageCommands/Install.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ extension SwiftPackageCommand {
commandState.preferredBuildConfiguration = .release
}

try await commandState.createBuildSystem(explicitProduct: productToInstall.name, traitConfiguration: .init())
try await commandState.createBuildSystem(explicitProduct: productToInstall.name)
.build(subset: .product(productToInstall.name))

let binPath = try commandState.productsBuildParameters.buildPath.appending(component: productToInstall.name)
Expand Down
1 change: 0 additions & 1 deletion Sources/Commands/PackageCommands/Migrate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,6 @@ extension SwiftPackageCommand {
}

return try await swiftCommandState.createBuildSystem(
traitConfiguration: .init(),
// Don't attempt to cache manifests with temporary
// feature flags added just for migration purposes.
cacheBuildManifest: false,
Expand Down
1 change: 0 additions & 1 deletion Sources/Commands/PackageCommands/PluginCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,6 @@ struct PluginCommand: AsyncSwiftCommand {
// Build or bring up-to-date any executable host-side tools on which this plugin depends. Add them and any binary dependencies to the tool-names-to-path map.
let buildSystem = try await swiftCommandState.createBuildSystem(
explicitBuildSystem: buildSystemKind,
traitConfiguration: .init(),
cacheBuildManifest: false,
productsBuildParameters: swiftCommandState.productsBuildParameters,
toolsBuildParameters: buildParameters,
Expand Down
10 changes: 3 additions & 7 deletions Sources/Commands/PackageCommands/Resolve.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ extension SwiftPackageCommand {

@Argument(help: "The name of the package to resolve.")
var packageName: String?

/// Specifies the traits to build.
@OptionGroup(visibility: .hidden)
package var traits: TraitOptions
}

struct Resolve: AsyncSwiftCommand {
Expand All @@ -50,10 +46,10 @@ extension SwiftPackageCommand {
func run(_ swiftCommandState: SwiftCommandState) async throws {
// If a package is provided, use that to resolve the dependencies.
if let packageName = resolveOptions.packageName {
let workspace = try swiftCommandState.getActiveWorkspace(traitConfiguration: .init(traitOptions: resolveOptions.traits))
let workspace = try swiftCommandState.getActiveWorkspace()
try await workspace.resolve(
packageName: packageName,
root: swiftCommandState.getWorkspaceRoot(traitConfiguration: .init(traitOptions: resolveOptions.traits)),
root: swiftCommandState.getWorkspaceRoot(),
version: resolveOptions.version,
branch: resolveOptions.branch,
revision: resolveOptions.revision,
Expand All @@ -64,7 +60,7 @@ extension SwiftPackageCommand {
}
} else {
// Otherwise, run a normal resolve.
try await swiftCommandState.resolve(.init(traitOptions: resolveOptions.traits))
try await swiftCommandState.resolve()
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/Commands/Snippets/Cards/SnippetCard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ struct SnippetCard: Card {

func runExample() async throws {
print("Building '\(snippet.path)'\n")
let buildSystem = try await swiftCommandState.createBuildSystem(explicitProduct: snippet.name, traitConfiguration: .init())
let buildSystem = try await swiftCommandState.createBuildSystem(explicitProduct: snippet.name)
try await buildSystem.build(subset: .product(snippet.name))
let executablePath = try swiftCommandState.productsBuildParameters.buildPath.appending(component: snippet.name)
if let exampleTarget = try await buildSystem.getPackageGraph().module(for: snippet.name) {
Expand Down
6 changes: 0 additions & 6 deletions Sources/Commands/SwiftBuildCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,6 @@ struct BuildCommandOptions: ParsableArguments {
@OptionGroup(visibility: .private)
var testLibraryOptions: TestLibraryOptions

/// Specifies the traits to build.
@OptionGroup(visibility: .hidden)
package var traits: TraitOptions

/// If should link the Swift stdlib statically.
@Flag(name: .customLong("static-swift-stdlib"), inversion: .prefixedNo, help: "Link Swift stdlib statically.")
public var shouldLinkStaticSwiftStdlib: Bool = false
Expand Down Expand Up @@ -144,7 +140,6 @@ public struct SwiftBuildCommand: AsyncSwiftCommand {
// FIXME: Doesn't seem ideal that we need an explicit build operation, but this concretely uses the `LLBuildManifest`.
guard let buildOperation = try await swiftCommandState.createBuildSystem(
explicitBuildSystem: .native,
traitConfiguration: .init(traitOptions: self.options.traits)
) as? BuildOperation else {
throw StringError("asked for native build system but did not get it")
}
Expand Down Expand Up @@ -194,7 +189,6 @@ public struct SwiftBuildCommand: AsyncSwiftCommand {
) async throws {
let buildSystem = try await swiftCommandState.createBuildSystem(
explicitProduct: options.product,
traitConfiguration: .init(traitOptions: self.options.traits),
shouldLinkStaticSwiftStdlib: options.shouldLinkStaticSwiftStdlib,
productsBuildParameters: productsBuildParameters,
toolsBuildParameters: toolsBuildParameters,
Expand Down
10 changes: 2 additions & 8 deletions Sources/Commands/SwiftRunCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,6 @@ struct RunCommandOptions: ParsableArguments {
@Argument(help: "The executable to run.", completion: .shellCommand("swift package completion-tool list-executables"))
var executable: String?

/// Specifies the traits to build the product with.
@OptionGroup(visibility: .hidden)
package var traits: TraitOptions

/// The arguments to pass to the executable.
@Argument(parsing: .captureForPassthrough,
help: "The arguments to pass to the executable.")
Expand Down Expand Up @@ -139,7 +135,6 @@ public struct SwiftRunCommand: AsyncSwiftCommand {
// FIXME: We need to implement the build tool invocation closure here so that build tool plugins work with the REPL. rdar://86112934
let buildSystem = try await swiftCommandState.createBuildSystem(
explicitBuildSystem: .native,
traitConfiguration: .init(traitOptions: self.options.traits),
cacheBuildManifest: false,
packageGraphLoader: asyncUnsafeGraphLoader
)
Expand All @@ -161,7 +156,6 @@ public struct SwiftRunCommand: AsyncSwiftCommand {
do {
let buildSystem = try await swiftCommandState.createBuildSystem(
explicitProduct: options.executable,
traitConfiguration: .init(traitOptions: self.options.traits)
)
let productName = try await findProductName(in: buildSystem.getPackageGraph())
if options.shouldBuildTests {
Expand Down Expand Up @@ -217,9 +211,9 @@ public struct SwiftRunCommand: AsyncSwiftCommand {
do {
let buildSystem = try await swiftCommandState.createBuildSystem(
explicitProduct: options.executable,
traitConfiguration: .init(traitOptions: self.options.traits)
)
let productName = try await findProductName(in: buildSystem.getPackageGraph())
let modulesGraph = try await buildSystem.getPackageGraph()
let productName = try findProductName(in: modulesGraph)
if options.shouldBuildTests {
try await buildSystem.build(subset: .allIncludingTests)
} else if options.shouldBuild {
Expand Down
11 changes: 2 additions & 9 deletions Sources/Commands/SwiftTestCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,6 @@ struct TestCommandOptions: ParsableArguments {
var enableExperimentalTestOutput: Bool {
return testOutput == .experimentalSummary
}

@OptionGroup(visibility: .hidden)
package var traits: TraitOptions
}

/// Tests filtering specifier, which is used to filter tests to run.
Expand Down Expand Up @@ -659,7 +656,7 @@ public struct SwiftTestCommand: AsyncSwiftCommand {
productsBuildParameters: productsBuildParameters,
toolsBuildParameters: toolsBuildParameters,
testProduct: self.options.sharedOptions.testProduct,
traitConfiguration: .init(traitOptions: self.options.traits)
traitConfiguration: .init(traitOptions: self.globalOptions.traits)
)
}

Expand Down Expand Up @@ -741,9 +738,6 @@ extension SwiftTestCommand {
@OptionGroup()
var testEventStreamOptions: TestEventStreamOptions

@OptionGroup(visibility: .hidden)
package var traits: TraitOptions

// for deprecated passthrough from SwiftTestTool (parse will fail otherwise)
@Flag(name: [.customLong("list-tests"), .customShort("l")], help: .hidden)
var _deprecated_passthrough: Bool = false
Expand Down Expand Up @@ -850,7 +844,7 @@ extension SwiftTestCommand {
productsBuildParameters: productsBuildParameters,
toolsBuildParameters: toolsBuildParameters,
testProduct: self.sharedOptions.testProduct,
traitConfiguration: .init(traitOptions: self.traits)
traitConfiguration: .init(traitOptions: self.globalOptions.traits)
)
}
}
Expand Down Expand Up @@ -1561,7 +1555,6 @@ private func buildTestsIfNeeded(
traitConfiguration: TraitConfiguration
) async throws -> [BuiltTestProduct] {
let buildSystem = try await swiftCommandState.createBuildSystem(
traitConfiguration: traitConfiguration,
productsBuildParameters: productsBuildParameters,
toolsBuildParameters: toolsBuildParameters
)
Expand Down
1 change: 0 additions & 1 deletion Sources/Commands/Utilities/APIDigester.swift
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@ struct APIDigesterBaselineDumper {
// FIXME: We need to implement the build tool invocation closure here so that build tool plugins work with the APIDigester. rdar://86112934
let buildSystem = try await swiftCommandState.createBuildSystem(
explicitBuildSystem: .native,
traitConfiguration: .init(),
cacheBuildManifest: false,
productsBuildParameters: productsBuildParameters,
toolsBuildParameters: toolsBuildParameters,
Expand Down
4 changes: 1 addition & 3 deletions Sources/Commands/Utilities/PluginDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ final class PluginDelegate: PluginInvocationDelegate {
let buildSystem = try await swiftCommandState.createBuildSystem(
explicitBuildSystem: buildSystem,
explicitProduct: explicitProduct,
traitConfiguration: .init(),
cacheBuildManifest: false,
productsBuildParameters: buildParameters,
outputStream: outputStream,
Expand Down Expand Up @@ -237,7 +236,6 @@ final class PluginDelegate: PluginInvocationDelegate {
toolsBuildParameters.testingParameters.explicitlyEnabledTestability = true
toolsBuildParameters.testingParameters.enableCodeCoverage = parameters.enableCodeCoverage
let buildSystem = try await swiftCommandState.createBuildSystem(
traitConfiguration: .init(),
toolsBuildParameters: toolsBuildParameters
)
try await buildSystem.build(subset: .allIncludingTests)
Expand Down Expand Up @@ -401,7 +399,7 @@ final class PluginDelegate: PluginInvocationDelegate {
// Create a build system for building the target., skipping the the cache because we need the build plan.
let buildSystem = try await swiftCommandState.createBuildSystem(
explicitBuildSystem: buildSystem,
traitConfiguration: TraitConfiguration(enableAllTraits: true),
enableAllTraits: true,
cacheBuildManifest: false
)

Expand Down
17 changes: 9 additions & 8 deletions Sources/CoreCommands/BuildSystemSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ private struct NativeBuildSystemFactory: BuildSystemFactory {

func makeBuildSystem(
explicitProduct: String?,
traitConfiguration: TraitConfiguration,
enableAllTraits: Bool,
cacheBuildManifest: Bool,
productsBuildParameters: BuildParameters?,
toolsBuildParameters: BuildParameters?,
Expand All @@ -38,7 +38,7 @@ private struct NativeBuildSystemFactory: BuildSystemFactory {
logLevel: Diagnostic.Severity?,
observabilityScope: ObservabilityScope?
) async throws -> any BuildSystem {
_ = try await swiftCommandState.getRootPackageInformation(traitConfiguration: traitConfiguration)
_ = try await swiftCommandState.getRootPackageInformation(enableAllTraits)
let testEntryPointPath = productsBuildParameters?.testProductStyle.explicitlySpecifiedEntryPointPath
let cacheBuildManifest = if cacheBuildManifest {
try await self.swiftCommandState.canUseCachedBuildManifest()
Expand All @@ -52,7 +52,7 @@ private struct NativeBuildSystemFactory: BuildSystemFactory {
packageGraphLoader: packageGraphLoader ?? {
try await self.swiftCommandState.loadPackageGraph(
explicitProduct: explicitProduct,
traitConfiguration: traitConfiguration,
enableAllTraits: enableAllTraits,
testEntryPointPath: testEntryPointPath
)
},
Expand All @@ -62,7 +62,7 @@ private struct NativeBuildSystemFactory: BuildSystemFactory {
disableSandbox: self.swiftCommandState.shouldDisableSandbox
),
scratchDirectory: self.swiftCommandState.scratchDirectory,
traitConfiguration: traitConfiguration,
traitConfiguration: enableAllTraits ? .enableAllTraits : self.swiftCommandState.traitConfiguration,
additionalFileRules: FileRuleDescription.swiftpmFileTypes,
pkgConfigDirectories: self.swiftCommandState.options.locations.pkgConfigDirectories,
outputStream: outputStream ?? self.swiftCommandState.outputStream,
Expand All @@ -77,7 +77,7 @@ private struct XcodeBuildSystemFactory: BuildSystemFactory {

func makeBuildSystem(
explicitProduct: String?,
traitConfiguration: TraitConfiguration,
enableAllTraits: Bool,
cacheBuildManifest: Bool,
productsBuildParameters: BuildParameters?,
toolsBuildParameters: BuildParameters?,
Expand All @@ -91,7 +91,7 @@ private struct XcodeBuildSystemFactory: BuildSystemFactory {
packageGraphLoader: packageGraphLoader ?? {
try await self.swiftCommandState.loadPackageGraph(
explicitProduct: explicitProduct,
traitConfiguration: traitConfiguration
enableAllTraits: enableAllTraits
)
},
outputStream: outputStream ?? self.swiftCommandState.outputStream,
Expand All @@ -107,7 +107,7 @@ private struct SwiftBuildSystemFactory: BuildSystemFactory {

func makeBuildSystem(
explicitProduct: String?,
traitConfiguration: TraitConfiguration,
enableAllTraits: Bool,
cacheBuildManifest: Bool,
productsBuildParameters: BuildParameters?,
toolsBuildParameters: BuildParameters?,
Expand All @@ -120,7 +120,8 @@ private struct SwiftBuildSystemFactory: BuildSystemFactory {
buildParameters: productsBuildParameters ?? self.swiftCommandState.productsBuildParameters,
packageGraphLoader: packageGraphLoader ?? {
try await self.swiftCommandState.loadPackageGraph(
explicitProduct: explicitProduct
explicitProduct: explicitProduct,
enableAllTraits: enableAllTraits,
)
},
packageManagerResourcesDirectory: swiftCommandState.packageManagerResourcesDirectory,
Expand Down
13 changes: 8 additions & 5 deletions Sources/CoreCommands/Options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ public struct GlobalOptions: ParsableArguments {

@OptionGroup(title: "Build Options")
public var linker: LinkerOptions

@OptionGroup(title: "Trait Options")
public var traits: TraitOptions
}

public struct LocationOptions: ParsableArguments {
Expand Down Expand Up @@ -683,8 +686,8 @@ public struct TestLibraryOptions: ParsableArguments {
}
}

package struct TraitOptions: ParsableArguments {
package init() {}
public struct TraitOptions: ParsableArguments {
public init() {}

/// The traits to enable for the package.
@Option(
Expand All @@ -694,7 +697,7 @@ package struct TraitOptions: ParsableArguments {
package var _enabledTraits: String?

/// The set of enabled traits for the package.
package var enabledTraits: Set<String>? {
public var enabledTraits: Set<String>? {
self._enabledTraits.flatMap { Set($0.components(separatedBy: ",")) }
}

Expand All @@ -703,7 +706,7 @@ package struct TraitOptions: ParsableArguments {
name: .customLong("enable-all-traits"),
help: "Enables all traits of the package."
)
package var enableAllTraits: Bool = false
public var enableAllTraits: Bool = false

/// Disables all default traits of the package.
@Flag(
Expand All @@ -714,7 +717,7 @@ package struct TraitOptions: ParsableArguments {
}

extension TraitConfiguration {
package init(traitOptions: TraitOptions) {
public init(traitOptions: TraitOptions) {
var enabledTraits = traitOptions.enabledTraits
if traitOptions.disableDefaultTraits {
// If there are no enabled traits specified we can disable the
Expand Down
Loading