From a6c6df0f5b3b11b44bbd5cfc3bbd3a48094eae8e Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Thu, 11 Dec 2025 15:35:26 -0500 Subject: [PATCH 1/4] Use prebuilts for all targets that build for destination == host. Add a hidden HostCondition that will check the build parameters to see if we're building a target for host enable the include and link settings to use the prebuilts and disable the dependency on swift-syntax products. Doesn't support SwiftBuild yet. Need to figure out how to use the same condition there. Also cleaned up BuildPlanTests so they are just Native BuildPlan tests as designed and created a separate BuildTests for the two tests that used the build system kind setting. --- .../PackageGraph/ModulesGraph+Loading.swift | 19 +- Sources/PackageLoading/PackageBuilder.swift | 57 ++- Sources/PackageModel/BuildEnvironment.swift | 4 +- .../PackageConditionDescription.swift | 33 +- .../BuildParameters/BuildParameters.swift | 2 +- .../PackagePIFBuilder+Helpers.swift | 71 ++-- Tests/BuildTests/BuildPlanTests.swift | 387 ++++++++++-------- Tests/BuildTests/BuildTests.swift | 163 ++++++++ .../LLBuildManifestBuilderTests.swift | 4 + Tests/BuildTests/PluginInvocationTests.swift | 8 +- .../ProductBuildDescriptionTests.swift | 2 +- 11 files changed, 488 insertions(+), 262 deletions(-) create mode 100644 Tests/BuildTests/BuildTests.swift diff --git a/Sources/PackageGraph/ModulesGraph+Loading.swift b/Sources/PackageGraph/ModulesGraph+Loading.swift index 4576b28a65d..30696b8a384 100644 --- a/Sources/PackageGraph/ModulesGraph+Loading.swift +++ b/Sources/PackageGraph/ModulesGraph+Loading.swift @@ -728,23 +728,10 @@ private func createResolvedPackages( moduleBuilder.dependencies += implicitSystemLibraryDeps.map { .module($0, conditions: []) } // Establish product dependencies. - for case .product(let productRef, let conditions) in moduleBuilder.module.dependencies { + for case .product(let productRef, var conditions) in moduleBuilder.module.dependencies { if let package = productRef.package, prebuilts[.plain(package)]?[productRef.name] != nil { - // See if we're using a prebuilt instead - if moduleBuilder.module.type == .macro { - continue - } else if moduleBuilder.module.type == .test { - // use prebuilt if this is a test that depends a macro target - // these are guaranteed built for host - if moduleBuilder.module.dependencies.contains(where: { dep in - guard let module = dep.module else { - return false - } - return module.type == .macro - }) { - continue - } - } + // Mark the dependency as not host. We'll add host build settings for the prebuilts later. + conditions.append(.isHost(.init(isHost: false))) } // Find the product in this package's dependency products. diff --git a/Sources/PackageLoading/PackageBuilder.swift b/Sources/PackageLoading/PackageBuilder.swift index 77169042aa0..804c86e45cd 100644 --- a/Sources/PackageLoading/PackageBuilder.swift +++ b/Sources/PackageLoading/PackageBuilder.swift @@ -1407,40 +1407,39 @@ public final class PackageBuilder { table.add(assignment, for: .SWIFT_ACTIVE_COMPILATION_CONDITIONS) } - // Add in flags for prebuilts if the target is a macro or a macro test. - // Currently we only support prebuilts for macros. - if target.type == .macro || target.isMacroTest(in: manifest) { - let prebuiltLibraries: [String: PrebuiltLibrary] = target.dependencies.reduce(into: .init()) { - guard case let .product(name: name, package: package, moduleAliases: _, condition: _) = $1, - let package = package, - let prebuilt = prebuilts[.plain(package)]?[name] - else { - return - } - - $0[prebuilt.libraryName] = prebuilt + // Add in flags for prebuilts for host + let prebuiltLibraries: [String: PrebuiltLibrary] = target.dependencies.reduce(into: .init()) { + guard case let .product(name: name, package: package, moduleAliases: _, condition: _) = $1, + let package = package, + let prebuilt = prebuilts[.plain(package)]?[name] + else { + return } - for prebuilt in prebuiltLibraries.values { - let lib = prebuilt.path.appending(components: ["lib", "lib\(prebuilt.libraryName).a"]).pathString - var ldFlagsAssignment = BuildSettings.Assignment() - ldFlagsAssignment.values = [lib] - table.add(ldFlagsAssignment, for: .OTHER_LDFLAGS) + $0[prebuilt.libraryName] = prebuilt + } - var includeDirs: [AbsolutePath] = [prebuilt.path.appending(component: "Modules")] - if let checkoutPath = prebuilt.checkoutPath, let includePath = prebuilt.includePath { - for includeDir in includePath { - includeDirs.append(checkoutPath.appending(includeDir)) - } - } else { - for cModule in prebuilt.cModules { - includeDirs.append(prebuilt.path.appending(components: "include", cModule)) - } + for prebuilt in prebuiltLibraries.values { + let lib = prebuilt.path.appending(components: ["lib", "lib\(prebuilt.libraryName).a"]).pathString + var ldFlagsAssignment = BuildSettings.Assignment() + ldFlagsAssignment.values = [lib] + ldFlagsAssignment.conditions = [.isHost(.init(isHost: true))] + table.add(ldFlagsAssignment, for: .OTHER_LDFLAGS) + + var includeDirs: [AbsolutePath] = [prebuilt.path.appending(component: "Modules")] + if let checkoutPath = prebuilt.checkoutPath, let includePath = prebuilt.includePath { + for includeDir in includePath { + includeDirs.append(checkoutPath.appending(includeDir)) + } + } else { + for cModule in prebuilt.cModules { + includeDirs.append(prebuilt.path.appending(components: "include", cModule)) } - var includeAssignment = BuildSettings.Assignment() - includeAssignment.values = includeDirs.map({ "-I\($0.pathString)" }) - table.add(includeAssignment, for: .OTHER_SWIFT_FLAGS) } + var includeAssignment = BuildSettings.Assignment() + includeAssignment.values = includeDirs.map({ "-I\($0.pathString)" }) + includeAssignment.conditions = [.isHost(.init(isHost: true))] + table.add(includeAssignment, for: .OTHER_SWIFT_FLAGS) } return table diff --git a/Sources/PackageModel/BuildEnvironment.swift b/Sources/PackageModel/BuildEnvironment.swift index d6545c46166..a4aa70cd2bd 100644 --- a/Sources/PackageModel/BuildEnvironment.swift +++ b/Sources/PackageModel/BuildEnvironment.swift @@ -13,10 +13,12 @@ /// A build environment with which to evaluate conditions. public struct BuildEnvironment { public let platform: Platform + public let isHost: Bool public let configuration: BuildConfiguration? - public init(platform: Platform, configuration: BuildConfiguration? = nil) { + public init(platform: Platform, isHost: Bool, configuration: BuildConfiguration? = nil) { self.platform = platform + self.isHost = isHost self.configuration = configuration } } diff --git a/Sources/PackageModel/Manifest/PackageConditionDescription.swift b/Sources/PackageModel/Manifest/PackageConditionDescription.swift index b8257bc5650..fed1981dd15 100644 --- a/Sources/PackageModel/Manifest/PackageConditionDescription.swift +++ b/Sources/PackageModel/Manifest/PackageConditionDescription.swift @@ -28,6 +28,7 @@ public struct PackageConditionDescription: Codable, Hashable, Sendable { /// build configurations. public enum PackageCondition: Hashable, Sendable { case platforms(PlatformsCondition) + case isHost(HostCondition) case configuration(ConfigurationCondition) case traits(TraitCondition) @@ -37,6 +38,8 @@ public enum PackageCondition: Hashable, Sendable { return configuration.satisfies(environment) case .platforms(let platforms): return platforms.satisfies(environment) + case .isHost(let hostCondition): + return hostCondition.satisfies(environment) case .traits(let traits): return traits.satisfies(environment) } @@ -66,6 +69,14 @@ public enum PackageCondition: Hashable, Sendable { return traitCondition } + public var hostCondition: HostCondition? { + guard case let .isHost(hostCondition) = self else { + return nil + } + + return hostCondition + } + public init(platforms: [Platform]) { self = .platforms(.init(platforms: platforms)) } @@ -73,6 +84,10 @@ public enum PackageCondition: Hashable, Sendable { public init(configuration: BuildConfiguration) { self = .configuration(.init(configuration: configuration)) } + + public init(isHost: Bool) { + self = .isHost(.init(isHost: isHost)) + } } /// Platforms condition implies that an assignment is valid on these platforms. @@ -107,9 +122,8 @@ public struct ConfigurationCondition: Hashable, Sendable { } } - -/// A configuration condition implies that an assignment is valid on -/// a particular build configuration. +/// By the time we get to evaluating the condition, the package loader would have filtered out +/// disabled traits. As such, this should always evaluate to true. public struct TraitCondition: Hashable, Sendable { public let traits: Set @@ -122,3 +136,16 @@ public struct TraitCondition: Hashable, Sendable { } } +/// A hidden condition that is true if the target is building for the host platform. +/// Currently only used for prebuilts. +public struct HostCondition: Hashable, Sendable { + public let isHost: Bool + + public init(isHost: Bool) { + self.isHost = isHost + } + + public func satisfies(_ environment: BuildEnvironment) -> Bool { + environment.isHost == isHost + } +} diff --git a/Sources/SPMBuildCore/BuildParameters/BuildParameters.swift b/Sources/SPMBuildCore/BuildParameters/BuildParameters.swift index a9fe2744794..966e2c240e1 100644 --- a/Sources/SPMBuildCore/BuildParameters/BuildParameters.swift +++ b/Sources/SPMBuildCore/BuildParameters/BuildParameters.swift @@ -90,7 +90,7 @@ public struct BuildParameters: Encodable { /// The current build environment. public var buildEnvironment: BuildEnvironment { - BuildEnvironment(platform: currentPlatform, configuration: configuration) + BuildEnvironment(platform: currentPlatform, isHost: destination == .host, configuration: configuration) } /// The current platform we're building for. diff --git a/Sources/SwiftBuildSupport/PackagePIFBuilder+Helpers.swift b/Sources/SwiftBuildSupport/PackagePIFBuilder+Helpers.swift index 47c3c43ec57..21a01ea5c20 100644 --- a/Sources/SwiftBuildSupport/PackagePIFBuilder+Helpers.swift +++ b/Sources/SwiftBuildSupport/PackagePIFBuilder+Helpers.swift @@ -48,6 +48,7 @@ import class PackageModel.SwiftModule import class PackageModel.SystemLibraryModule import struct PackageModel.ToolsVersion import struct PackageModel.TraitCondition +import struct PackageModel.HostCondition import struct PackageGraph.ResolvedModule import struct PackageGraph.ResolvedPackage @@ -246,42 +247,6 @@ extension Sequence { } return Set(pifPlatforms.flatMap { $0.toPlatformFilter() }) } - - var splitIntoConcreteConditions: ( - [PackageModel.Platform?], - [PackageModel.BuildConfiguration], - [PackageModel.TraitCondition] - ) { - var platformConditions: [PackageModel.PlatformsCondition] = [] - var configurationConditions: [PackageModel.ConfigurationCondition] = [] - var traitConditions: [PackageModel.TraitCondition] = [] - - for packageCondition in self { - switch packageCondition { - case .platforms(let condition): platformConditions.append(condition) - case .configuration(let condition): configurationConditions.append(condition) - case .traits(let condition): traitConditions.append(condition) - } - } - - // Determine the *platform* conditions, if any. - // An empty set means that there are no platform restrictions. - let platforms: [PackageModel.Platform?] = if platformConditions.isEmpty { - [nil] - } else { - platformConditions.flatMap(\.platforms) - } - - // Determine the *configuration* conditions, if any. - // If there are none, we apply the setting to both debug and release builds (ie, `allCases`). - let configurations: [BuildConfiguration] = if configurationConditions.isEmpty { - BuildConfiguration.allCases - } else { - configurationConditions.map(\.configuration) - } - - return (platforms, configurations, traitConditions) - } } extension PackageModel.BuildSettings.Declaration { @@ -646,8 +611,38 @@ extension PackageGraph.ResolvedModule { values = settingAssignment.values } - // TODO: We are currently ignoring package traits (see rdar://138149810). - let (platforms, configurations, _) = settingAssignment.conditions.splitIntoConcreteConditions + var platformConditions: [PackageModel.PlatformsCondition] = [] + var configurationConditions: [PackageModel.ConfigurationCondition] = [] + + // Traits always evaluate to true at this point. + // TODO: Platforms aren't currently sufficient to describe building for host + // especially Linux. We could have different Linux for host versus target. + // Native build has host versus target explicitly modeled with + // BuildParameters.Destination. + for packageCondition in settingAssignment.conditions { + switch packageCondition { + case .platforms(let condition): platformConditions.append(condition) + case .configuration(let condition): configurationConditions.append(condition) + case .traits(_): break + case .isHost(_): break + } + } + + // Determine the *platform* conditions, if any. + // An empty set means that there are no platform restrictions. + let platforms: [PackageModel.Platform?] = if platformConditions.isEmpty { + [nil] + } else { + platformConditions.flatMap(\.platforms) + } + + // Determine the *configuration* conditions, if any. + // If there are none, we apply the setting to both debug and release builds (ie, `allCases`). + let configurations: [BuildConfiguration] = if configurationConditions.isEmpty { + BuildConfiguration.allCases + } else { + configurationConditions.map(\.configuration) + } for platform in platforms { let pifPlatform: ProjectModel.BuildSettings.Platform? diff --git a/Tests/BuildTests/BuildPlanTests.swift b/Tests/BuildTests/BuildPlanTests.swift index 4370b856710..05470c7fb5a 100644 --- a/Tests/BuildTests/BuildPlanTests.swift +++ b/Tests/BuildTests/BuildPlanTests.swift @@ -48,11 +48,7 @@ extension Build.BuildPlan { } } -class BuildPlanTestCase: BuildSystemProviderTestCase { - override func setUpWithError() throws { - try XCTSkipIf(type(of: self) == BuildPlanTestCase.self, "Skipping this test since it will be run in subclasses that will provide different build systems to test.") - } - +class BuildPlanTestCase: XCTestCase { let inputsDir = AbsolutePath(#file).parentDirectory.appending(components: "Inputs") /// The j argument. @@ -621,129 +617,6 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { XCTAssertTrue(result.targetMap.values.contains { $0.module.name == "BarLogging" }) } - func testPackageNameFlag() async throws { - try XCTSkipIfPlatformCI() // test is disabled because it isn't stable, see rdar://118239206 - try XCTSkipOnWindows(because: "https://github.com/swiftlang/swift-package-manager/issues/8547: 'swift test' was stalled.") - let isFlagSupportedInDriver = try DriverSupport.checkToolchainDriverFlags( - flags: ["package-name"], - toolchain: UserToolchain.default, - fileSystem: localFileSystem - ) - try await fixtureXCTest(name: "Miscellaneous/PackageNameFlag") { fixturePath in - let (stdout, stderr) = try await executeSwiftBuild( - fixturePath.appending("appPkg"), - extraArgs: ["--vv"], - buildSystem: buildSystemProvider - ) - - let out = if buildSystemProvider == .swiftbuild { - stderr - } else { - stdout - } - - XCTAssertMatch(out, .contains("-module-name Foo")) - XCTAssertMatch(out, .contains("-module-name Zoo")) - XCTAssertMatch(out, .contains("-module-name Bar")) - XCTAssertMatch(out, .contains("-module-name Baz")) - XCTAssertMatch(out, .contains("-module-name App")) - XCTAssertMatch(out, .contains("-module-name exe")) - if isFlagSupportedInDriver { - XCTAssertMatch(out, .contains("-package-name apppkg")) - XCTAssertMatch(out, .contains("-package-name foopkg")) - // the flag is not supported if tools-version < 5.9 - XCTAssertNoMatch(out, .contains("-package-name barpkg")) - } else { - XCTAssertNoMatch(out, .contains("-package-name")) - } - XCTAssertMatch(stdout, .contains("Build complete!")) - } - } - - #if os(macOS) - func testPackageNameFlagXCBuild() async throws { - let isFlagSupportedInDriver = try DriverSupport.checkToolchainDriverFlags( - flags: ["package-name"], - toolchain: UserToolchain.default, - fileSystem: localFileSystem - ) - try await fixtureXCTest(name: "Miscellaneous/PackageNameFlag") { fixturePath in - let (stdout, _) = try await executeSwiftBuild( - fixturePath.appending("appPkg"), - extraArgs: ["--vv"], - buildSystem: .xcode - ) - XCTAssertMatch(stdout, .contains("-module-name Foo")) - XCTAssertMatch(stdout, .contains("-module-name Zoo")) - XCTAssertMatch(stdout, .contains("-module-name Bar")) - XCTAssertMatch(stdout, .contains("-module-name Baz")) - XCTAssertMatch(stdout, .contains("-module-name App")) - XCTAssertMatch(stdout, .contains("-module-name exe")) - if isFlagSupportedInDriver { - XCTAssertMatch(stdout, .contains("-package-name apppkg")) - XCTAssertMatch(stdout, .contains("-package-name foopkg")) - // the flag is not supported if tools-version < 5.9 - XCTAssertNoMatch(stdout, .contains("-package-name barpkg")) - } else { - XCTAssertNoMatch(stdout, .contains("-package-name")) - } - XCTAssertMatch(stdout, .contains("Build succeeded")) - } - } - #endif - - func testTargetsWithPackageAccess() async throws { - let isFlagSupportedInDriver = try DriverSupport.checkToolchainDriverFlags( - flags: ["package-name"], - toolchain: UserToolchain.default, - fileSystem: localFileSystem - ) - try await fixtureXCTest(name: "Miscellaneous/TargetPackageAccess") { fixturePath in - let (stdout, _) = try await executeSwiftBuild( - fixturePath.appending("libPkg"), - extraArgs: ["-v"], - buildSystem: buildSystemProvider - ) - if isFlagSupportedInDriver { - let moduleFlag1 = stdout.range(of: "-module-name DataModel") - XCTAssertNotNil(moduleFlag1) - let stdoutNext1 = stdout[moduleFlag1!.upperBound...] - let packageFlag1 = stdoutNext1.range(of: "-package-name libpkg") - XCTAssertNotNil(packageFlag1) - - let moduleFlag2 = stdoutNext1.range(of: "-module-name DataManager") - XCTAssertNotNil(moduleFlag2) - XCTAssertTrue(packageFlag1!.upperBound < moduleFlag2!.lowerBound) - let stdoutNext2 = stdoutNext1[moduleFlag2!.upperBound...] - let packageFlag2 = stdoutNext2.range(of: "-package-name libpkg") - XCTAssertNotNil(packageFlag2) - - let moduleFlag3 = stdoutNext2.range(of: "-module-name Core") - XCTAssertNotNil(moduleFlag3) - XCTAssertTrue(packageFlag2!.upperBound < moduleFlag3!.lowerBound) - let stdoutNext3 = stdoutNext2[moduleFlag3!.upperBound...] - let packageFlag3 = stdoutNext3.range(of: "-package-name libpkg") - XCTAssertNotNil(packageFlag3) - - let moduleFlag4 = stdoutNext3.range(of: "-module-name MainLib") - XCTAssertNotNil(moduleFlag4) - XCTAssertTrue(packageFlag3!.upperBound < moduleFlag4!.lowerBound) - let stdoutNext4 = stdoutNext3[moduleFlag4!.upperBound...] - let packageFlag4 = stdoutNext4.range(of: "-package-name libpkg") - XCTAssertNotNil(packageFlag4) - - let moduleFlag5 = stdoutNext4.range(of: "-module-name ExampleApp") - XCTAssertNotNil(moduleFlag5) - XCTAssertTrue(packageFlag4!.upperBound < moduleFlag5!.lowerBound) - let stdoutNext5 = stdoutNext4[moduleFlag5!.upperBound...] - let packageFlag5 = stdoutNext5.range(of: "-package-name") - XCTAssertNil(packageFlag5) - } else { - XCTAssertNoMatch(stdout, .contains("-package-name")) - } - XCTAssertMatch(stdout, .contains("Build complete!")) - } - } func testBasicSwiftPackage() async throws { let fs = InMemoryFileSystem( @@ -957,6 +830,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { let plan = try await mockBuildPlan( environment: BuildEnvironment( platform: .linux, + isHost: false, configuration: .release ), graph: graph, @@ -999,6 +873,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { let plan = try await mockBuildPlan( environment: BuildEnvironment( platform: .macOS, + isHost: false, configuration: .debug ), graph: graph, @@ -1507,6 +1382,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { let result = try await BuildPlanResult(plan: mockBuildPlan( environment: BuildEnvironment( platform: .linux, + isHost: false, configuration: .release ), graph: graph, @@ -1526,6 +1402,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { let result = try await BuildPlanResult(plan: mockBuildPlan( environment: BuildEnvironment( platform: .macOS, + isHost: false, configuration: .debug ), graph: graph, @@ -2106,6 +1983,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { let plan = try await mockBuildPlan( environment: BuildEnvironment( platform: .linux, + isHost: false, configuration: .release ), graph: graph, @@ -3527,7 +3405,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { let graphResult = PackageGraphResultXCTest(graph) do { - let linuxDebug = BuildEnvironment(platform: .linux, configuration: .debug) + let linuxDebug = BuildEnvironment(platform: .linux, isHost: false, configuration: .debug) try graphResult.check(reachableBuildProducts: "aexec", "BLibrary1", "BLibrary2", in: linuxDebug) try graphResult.check(reachableBuildTargets: "ATarget", "BTarget1", "BTarget2", in: linuxDebug) @@ -3542,7 +3420,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { } do { - let macosDebug = BuildEnvironment(platform: .macOS, configuration: .debug) + let macosDebug = BuildEnvironment(platform: .macOS, isHost: false, configuration: .debug) try graphResult.check(reachableBuildProducts: "aexec", "BLibrary2", in: macosDebug) try graphResult.check(reachableBuildTargets: "ATarget", "BTarget2", "BTarget3", in: macosDebug) @@ -3557,7 +3435,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { } do { - let androidRelease = BuildEnvironment(platform: .android, configuration: .release) + let androidRelease = BuildEnvironment(platform: .android, isHost: false, configuration: .release) try graphResult.check(reachableBuildProducts: "aexec", "CLibrary", in: androidRelease) try graphResult.check(reachableBuildTargets: "ATarget", "CTarget", in: androidRelease) @@ -4764,7 +4642,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { type: .test ) ] - ) + ), ], prebuilts: [prebuiltLibrary.identity: prebuiltLibrary.products.reduce(into: [:]) { $0[$1] = prebuiltLibrary @@ -4864,7 +4742,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { // Test debug configuration do { let result = try await BuildPlanResult(plan: mockBuildPlan( - environment: BuildEnvironment(platform: .macOS, configuration: .debug), + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .debug), graph: graph, fileSystem: fs, observabilityScope: observability.topScope @@ -4886,7 +4764,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { // Test release configuration do { let result = try await BuildPlanResult(plan: mockBuildPlan( - environment: BuildEnvironment(platform: .macOS, configuration: .release), + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .release), graph: graph, fileSystem: fs, observabilityScope: observability.topScope @@ -4952,7 +4830,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { // Test debug configuration do { let result = try await BuildPlanResult(plan: mockBuildPlan( - environment: BuildEnvironment(platform: .macOS, configuration: .debug), + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .debug), graph: graph, fileSystem: fs, observabilityScope: observability.topScope @@ -4970,7 +4848,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { // Test release configuration do { let result = try await BuildPlanResult(plan: mockBuildPlan( - environment: BuildEnvironment(platform: .macOS, configuration: .release), + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .release), graph: graph, fileSystem: fs, observabilityScope: observability.topScope @@ -5090,7 +4968,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { // Test debug configuration do { let result = try await BuildPlanResult(plan: mockBuildPlan( - environment: BuildEnvironment(platform: .macOS, configuration: .debug), + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .debug), graph: graph, fileSystem: fs, observabilityScope: observability.topScope @@ -5121,7 +4999,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { // Test release configuration do { let result = try await BuildPlanResult(plan: mockBuildPlan( - environment: BuildEnvironment(platform: .macOS, configuration: .release), + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .release), graph: graph, fileSystem: fs, observabilityScope: observability.topScope @@ -7308,6 +7186,7 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { let result = try await BuildPlanResult(plan: mockBuildPlan( environment: BuildEnvironment( platform: .linux, + isHost: false, configuration: .release ), graph: graph, @@ -7869,37 +7748,207 @@ class BuildPlanTestCase: BuildSystemProviderTestCase { } } -class BuildPlanNativeTests: BuildPlanTestCase { - override open var buildSystemProvider: BuildSystemProvider.Kind { - return .native - } - - override func testDuplicateProductNamesWithNonDefaultLibsThrowError() async throws { - try await super.testDuplicateProductNamesWithNonDefaultLibsThrowError() - } - -} - -class BuildPlanSwiftBuildTests: BuildPlanTestCase { - override open var buildSystemProvider: BuildSystemProvider.Kind { - return .swiftbuild - } - - override func testDuplicateProductNamesWithNonDefaultLibsThrowError() async throws { - try await super.testDuplicateProductNamesWithNonDefaultLibsThrowError() - } - - override func testTargetsWithPackageAccess() async throws { - throw XCTSkip("Skip until swift build system can support this case.") - } - - override func testTestModule() async throws { - throw XCTSkip("Skip until swift build system can support this case.") - } +@Test func testAllTheThingsPrebuilts() async throws { + // Test macros, plugin-in tools and target executables depending on swift-syntax + // Including a library that is shared by all. + // Right now only macros and plug-in tools should get the prebuilts + // and executables should build depend on swift-syntax source targets + let observability = ObservabilitySystem.makeForTesting() + + let prebuiltLibrary = PrebuiltLibrary( + identity: .plain("swift-syntax"), + libraryName: "MacroSupport", + path: "/MyPackage/.build/prebuilts/swift-syntax/600.0.1/6.1-MacroSupport-macos_aarch64", + checkoutPath: "/MyPackage/.build/checkouts/swift-syntax", + products: [ + "SwiftBasicFormat", + "SwiftCompilerPlugin", + "SwiftDiagnostics", + "SwiftIDEUtils", + "SwiftOperators", + "SwiftParser", + "SwiftParserDiagnostics", + "SwiftRefactor", + "SwiftSyntax", + "SwiftSyntaxBuilder", + "SwiftSyntaxMacros", + "SwiftSyntaxMacroExpansion", + "SwiftSyntaxMacrosTestSupport", + "SwiftSyntaxMacrosGenericTestSupport", + "_SwiftCompilerPluginMessageHandling", + "_SwiftLibraryPluginProvider" + ], + includePath: [ + "Sources/_SwiftSyntaxCShims/include" + ] + ) + + let swiftSyntaxCShimsInclude = try "-I\(#require(prebuiltLibrary.checkoutPath).appending(components: "Sources", "_SwiftSyntaxCShims", "include"))" + let swiftSyntaxLib = prebuiltLibrary.path.appending(components: "lib", "libMacroSupport.a").pathString + + let fs = InMemoryFileSystem( + emptyFiles: [ + "/MyPackage/Plugins/MyPlugin/MyPlugin.swift", + "/MyPackage/Sources/MyLibrary/MyLibrary.swift", + "/MyPackage/Sources/MyMacroMacros/MyMacroMacros.swift", + "/MyPackage/Sources/MyMacros/MyMacros.swift", + "/MyPackage/Sources/MyMacroTests/MyMacroTests.swift", + "/MyPackage/Sources/MyGenerator/MyGenerator.swift", + "/MyPackage/Sources/MyExecutable/MyExecutable.swift", + "/MyPackage/Tests/MyLibraryTests/MyLibraryTests.swift", + "/MyPackage/Tests/MyMacroTests/MyMacroTests.swift", + "/swift-syntax/Sources/SwiftSyntaxMacrosTestSupport/SwiftSyntaxMacrosTestSupport.swift", + "/swift-syntax/Sources/SwiftSyntaxMacros/SwiftSyntaxMacros.swift", + "/swift-syntax/Sources/SwiftCompilerPlugin/SwiftCompilerPlugin.swift", + "/swift-syntax/Sources/SwiftSyntax/SwiftSyntax.swift", + ] + ) + + let graph = try loadModulesGraph( + fileSystem: fs, + manifests: [ + Manifest.createLocalSourceControlManifest( + displayName: "swift-syntax", + path: "/swift-syntax", + products: [ + .init( + name: "SwiftSyntaxMacrosTestSupport", + type: .library(.automatic), + targets: ["SwiftSyntaxMacrosTestSupport"] + ), + .init( + name: "SwiftSyntaxMacros", + type: .library(.automatic), + targets: ["SwiftSyntaxMacros"] + ), + .init( + name: "SwiftCompilerPlugin", + type: .library(.automatic), + targets: ["SwiftCompilerPlugin"] + ), + .init( + name: "SwiftSyntax", + type: .library(.automatic), + targets: ["SwiftSyntax"] + ), + ], + targets: [ + .init(name: "SwiftSyntaxMacrosTestSupport"), + .init(name: "SwiftSyntaxMacros"), + .init(name: "SwiftCompilerPlugin"), + .init(name: "SwiftSyntax"), + ] + ), + Manifest.createRootManifest( + displayName: "MyPackage", + path: "/MyPackage", + dependencies: [ + .localSourceControl(path: "/swift-syntax", requirement: .exact("600.0.1")), + ], + targets: [ + TargetDescription( + name: "MyLibrary", + dependencies: [ + .product(name: "SwiftSyntax", package: "swift-syntax"), + ] + ), + TargetDescription( + name: "MyLibraryTests", + dependencies: [ + "MyLibrary" + ], + type: .test + ), + TargetDescription( + name: "MyMacroMacros", + dependencies: [ + "MyLibrary", + .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), + .product(name: "SwiftCompilerPlugin", package: "swift-syntax"), + ], + type: .macro, + ), + TargetDescription( + name: "MyMacros", + dependencies: [ + "MyMacroMacros", + ] + ), + TargetDescription( + name: "MyMacroTests", + dependencies: [ + "MyMacroMacros", + .product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"), + ], + type: .test + ), + TargetDescription( + name: "MyGenerator", + dependencies: [ + "MyLibrary", + .product(name: "SwiftSyntax", package: "swift-syntax"), + ], + type: .executable + ), + TargetDescription( + name: "MyPlugin", + dependencies: [ + "MyGenerator" + ], + type: .plugin, + pluginCapability: .buildTool + ), + TargetDescription( + name: "MyExecutable", + dependencies: [ + "MyMacros", + "MyLibrary", + ], + type: .executable, + pluginUsages: [.plugin(name: "MyPlugin", package: nil)] + ) + ] + ) + ], + prebuilts: [prebuiltLibrary.identity: prebuiltLibrary.products.reduce(into: [:]) { + $0[$1] = prebuiltLibrary + }], + observabilityScope: observability.topScope + ) + + let result = try await BuildPlanResult( + plan: mockBuildPlan( + triple: .arm64Linux, + graph: graph, + fileSystem: fs, + observabilityScope: observability.topScope + ) + ) - override func testPackageNameFlag() async throws { - try XCTSkipOnWindows(because: "Skip until there is a resolution to the partial linking with Windows that results in a 'subsystem must be defined' error.") - try await super.testPackageNameFlag() - } + let myLibraryHost = try #require(try result.targetMap.values.first(where: { + $0.module.name == "MyLibrary" && $0.destination == .host + })?.swift()) + #expect(myLibraryHost.dependencies(using: result.plan).isEmpty) + #expect(try myLibraryHost.compileArguments().contains(swiftSyntaxCShimsInclude)) + let myLibraryTarget = try #require(try result.targetMap.values.first(where: { + $0.module.name == "MyLibrary" && $0.destination == .target + })?.swift()) + #expect(myLibraryTarget.dependencies(using: result.plan).contains(where: { + guard case let .product(product, _) = $0 else { + return false + } + return product.name == "SwiftSyntax" && product.packageIdentity.description == "swift-syntax" + })) + #expect(try !myLibraryTarget.compileArguments().contains(swiftSyntaxCShimsInclude)) + + let myGeneratorHost = try #require(try result.productMap.values.first(where: { + $0.product.name == "MyGenerator" && $0.destination == .host + })) + #expect(try myGeneratorHost.linkArguments().contains(swiftSyntaxLib)) + + let myExecutableTarget = try #require(try result.productMap.values.first(where: { + $0.product.name == "MyExecutable" && $0.destination == .target + })) + #expect(try !myExecutableTarget.linkArguments().contains(swiftSyntaxLib)) } diff --git a/Tests/BuildTests/BuildTests.swift b/Tests/BuildTests/BuildTests.swift new file mode 100644 index 00000000000..9e0579e3082 --- /dev/null +++ b/Tests/BuildTests/BuildTests.swift @@ -0,0 +1,163 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift open source project +// +// Copyright (c) 2014-2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import _InternalTestSupport +@testable import DriverSupport +import SPMBuildCore +import PackageModel +import TSCBasic +import XCTest + +class BuildTests: BuildSystemProviderTestCase { + override func setUpWithError() throws { + try XCTSkipIf(type(of: self) == BuildTests.self, "Skipping this test since it will be run in subclasses that will provide different build systems to test.") + } + + func testPackageNameFlag() async throws { + try XCTSkipIfPlatformCI() // test is disabled because it isn't stable, see rdar://118239206 + try XCTSkipOnWindows(because: "https://github.com/swiftlang/swift-package-manager/issues/8547: 'swift test' was stalled.") + let isFlagSupportedInDriver = try DriverSupport.checkToolchainDriverFlags( + flags: ["package-name"], + toolchain: UserToolchain.default, + fileSystem: localFileSystem + ) + try await fixtureXCTest(name: "Miscellaneous/PackageNameFlag") { fixturePath in + let (stdout, stderr) = try await executeSwiftBuild( + fixturePath.appending("appPkg"), + extraArgs: ["--vv"], + buildSystem: buildSystemProvider + ) + + let out = if buildSystemProvider == .swiftbuild { + stderr + } else { + stdout + } + + XCTAssertMatch(out, .contains("-module-name Foo")) + XCTAssertMatch(out, .contains("-module-name Zoo")) + XCTAssertMatch(out, .contains("-module-name Bar")) + XCTAssertMatch(out, .contains("-module-name Baz")) + XCTAssertMatch(out, .contains("-module-name App")) + XCTAssertMatch(out, .contains("-module-name exe")) + if isFlagSupportedInDriver { + XCTAssertMatch(out, .contains("-package-name apppkg")) + XCTAssertMatch(out, .contains("-package-name foopkg")) + // the flag is not supported if tools-version < 5.9 + XCTAssertNoMatch(out, .contains("-package-name barpkg")) + } else { + XCTAssertNoMatch(out, .contains("-package-name")) + } + XCTAssertMatch(stdout, .contains("Build complete!")) + } + } + + func testTargetsWithPackageAccess() async throws { + let isFlagSupportedInDriver = try DriverSupport.checkToolchainDriverFlags( + flags: ["package-name"], + toolchain: UserToolchain.default, + fileSystem: localFileSystem + ) + try await fixtureXCTest(name: "Miscellaneous/TargetPackageAccess") { fixturePath in + let (stdout, _) = try await executeSwiftBuild( + fixturePath.appending("libPkg"), + extraArgs: ["-v"], + buildSystem: buildSystemProvider + ) + if isFlagSupportedInDriver { + let moduleFlag1 = stdout.range(of: "-module-name DataModel") + XCTAssertNotNil(moduleFlag1) + let stdoutNext1 = stdout[moduleFlag1!.upperBound...] + let packageFlag1 = stdoutNext1.range(of: "-package-name libpkg") + XCTAssertNotNil(packageFlag1) + + let moduleFlag2 = stdoutNext1.range(of: "-module-name DataManager") + XCTAssertNotNil(moduleFlag2) + XCTAssertTrue(packageFlag1!.upperBound < moduleFlag2!.lowerBound) + let stdoutNext2 = stdoutNext1[moduleFlag2!.upperBound...] + let packageFlag2 = stdoutNext2.range(of: "-package-name libpkg") + XCTAssertNotNil(packageFlag2) + + let moduleFlag3 = stdoutNext2.range(of: "-module-name Core") + XCTAssertNotNil(moduleFlag3) + XCTAssertTrue(packageFlag2!.upperBound < moduleFlag3!.lowerBound) + let stdoutNext3 = stdoutNext2[moduleFlag3!.upperBound...] + let packageFlag3 = stdoutNext3.range(of: "-package-name libpkg") + XCTAssertNotNil(packageFlag3) + + let moduleFlag4 = stdoutNext3.range(of: "-module-name MainLib") + XCTAssertNotNil(moduleFlag4) + XCTAssertTrue(packageFlag3!.upperBound < moduleFlag4!.lowerBound) + let stdoutNext4 = stdoutNext3[moduleFlag4!.upperBound...] + let packageFlag4 = stdoutNext4.range(of: "-package-name libpkg") + XCTAssertNotNil(packageFlag4) + + let moduleFlag5 = stdoutNext4.range(of: "-module-name ExampleApp") + XCTAssertNotNil(moduleFlag5) + XCTAssertTrue(packageFlag4!.upperBound < moduleFlag5!.lowerBound) + let stdoutNext5 = stdoutNext4[moduleFlag5!.upperBound...] + let packageFlag5 = stdoutNext5.range(of: "-package-name") + XCTAssertNil(packageFlag5) + } else { + XCTAssertNoMatch(stdout, .contains("-package-name")) + } + XCTAssertMatch(stdout, .contains("Build complete!")) + } + } + + #if os(macOS) + // This is actually an Xcode build test + func testPackageNameFlagXCBuild() async throws { + let isFlagSupportedInDriver = try DriverSupport.checkToolchainDriverFlags( + flags: ["package-name"], + toolchain: UserToolchain.default, + fileSystem: localFileSystem + ) + try await fixtureXCTest(name: "Miscellaneous/PackageNameFlag") { fixturePath in + let (stdout, _) = try await executeSwiftBuild( + fixturePath.appending("appPkg"), + extraArgs: ["--vv"], + buildSystem: .xcode + ) + XCTAssertMatch(stdout, .contains("-module-name Foo")) + XCTAssertMatch(stdout, .contains("-module-name Zoo")) + XCTAssertMatch(stdout, .contains("-module-name Bar")) + XCTAssertMatch(stdout, .contains("-module-name Baz")) + XCTAssertMatch(stdout, .contains("-module-name App")) + XCTAssertMatch(stdout, .contains("-module-name exe")) + if isFlagSupportedInDriver { + XCTAssertMatch(stdout, .contains("-package-name apppkg")) + XCTAssertMatch(stdout, .contains("-package-name foopkg")) + // the flag is not supported if tools-version < 5.9 + XCTAssertNoMatch(stdout, .contains("-package-name barpkg")) + } else { + XCTAssertNoMatch(stdout, .contains("-package-name")) + } + XCTAssertMatch(stdout, .contains("Build succeeded")) + } + } + #endif + + +} + +class BuildTestsNative: BuildTests { + override open var buildSystemProvider: BuildSystemProvider.Kind { + return .native + } +} + +class BuildTestsSwiftBuild: BuildTests { + override open var buildSystemProvider: BuildSystemProvider.Kind { + return .swiftbuild + } +} diff --git a/Tests/BuildTests/LLBuildManifestBuilderTests.swift b/Tests/BuildTests/LLBuildManifestBuilderTests.swift index f2bf17e5663..ccbec2cc358 100644 --- a/Tests/BuildTests/LLBuildManifestBuilderTests.swift +++ b/Tests/BuildTests/LLBuildManifestBuilderTests.swift @@ -56,6 +56,7 @@ struct LLBuildManifestBuilderTests { var plan = try await mockBuildPlan( environment: BuildEnvironment( platform: .macOS, + isHost: false, configuration: .release ), graph: graph, @@ -86,6 +87,7 @@ struct LLBuildManifestBuilderTests { plan = try await mockBuildPlan( environment: BuildEnvironment( platform: .macOS, + isHost: false, configuration: .debug ), graph: graph, @@ -129,6 +131,7 @@ struct LLBuildManifestBuilderTests { plan = try await mockBuildPlan( environment: BuildEnvironment( platform: .linux, + isHost: false, configuration: .release ), graph: graph, @@ -155,6 +158,7 @@ struct LLBuildManifestBuilderTests { plan = try await mockBuildPlan( environment: BuildEnvironment( platform: .linux, + isHost: false, configuration: .debug ), graph: graph, diff --git a/Tests/BuildTests/PluginInvocationTests.swift b/Tests/BuildTests/PluginInvocationTests.swift index 7569ed86851..b49bbac7c60 100644 --- a/Tests/BuildTests/PluginInvocationTests.swift +++ b/Tests/BuildTests/PluginInvocationTests.swift @@ -233,7 +233,7 @@ final class PluginInvocationTests: XCTestCase { let pluginRunner = MockPluginScriptRunner() let buildParameters = mockBuildParameters( destination: .host, - environment: BuildEnvironment(platform: .macOS, configuration: .debug) + environment: BuildEnvironment(platform: .macOS, isHost: true, configuration: .debug) ) let results = try await invokeBuildToolPlugins( @@ -960,7 +960,7 @@ final class PluginInvocationTests: XCTestCase { let outputDir = packageDir.appending(".build") let buildParameters = mockBuildParameters( destination: .host, - environment: BuildEnvironment(platform: .macOS, configuration: .debug) + environment: BuildEnvironment(platform: .macOS, isHost: true, configuration: .debug) ) let result = try await invokeBuildToolPlugins( @@ -1102,7 +1102,7 @@ final class PluginInvocationTests: XCTestCase { let outputDir = packageDir.appending(".build") let buildParameters = mockBuildParameters( destination: .host, - environment: BuildEnvironment(platform: .macOS, configuration: .debug) + environment: BuildEnvironment(platform: .macOS, isHost: true, configuration: .debug) ) let result = try await invokeBuildToolPlugins( @@ -1456,7 +1456,7 @@ final class PluginInvocationTests: XCTestCase { let outputDir = packageDir.appending(".build") let buildParameters = mockBuildParameters( destination: .host, - environment: BuildEnvironment(platform: .macOS, configuration: .debug) + environment: BuildEnvironment(platform: .macOS, isHost: true, configuration: .debug) ) return try await invokeBuildToolPlugins( diff --git a/Tests/BuildTests/ProductBuildDescriptionTests.swift b/Tests/BuildTests/ProductBuildDescriptionTests.swift index 5674142e10d..60248cdefff 100644 --- a/Tests/BuildTests/ProductBuildDescriptionTests.swift +++ b/Tests/BuildTests/ProductBuildDescriptionTests.swift @@ -63,7 +63,7 @@ final class ProductBuildDescriptionTests: XCTestCase { package: package, product: product, toolsVersion: .v5_9, - buildParameters: mockBuildParameters(destination: .target, environment: .init(platform: .macOS)), + buildParameters: mockBuildParameters(destination: .target, environment: .init(platform: .macOS, isHost: false)), fileSystem: fs, observabilityScope: observability.topScope ) From 6894b73382f5b5b1c9affd71ceb16306fc791162 Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Thu, 11 Dec 2025 15:47:38 -0500 Subject: [PATCH 2/4] fix test --- Tests/SPMBuildCoreTests/BuildParametersTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/SPMBuildCoreTests/BuildParametersTests.swift b/Tests/SPMBuildCoreTests/BuildParametersTests.swift index cf79703fe9b..89f46523baf 100644 --- a/Tests/SPMBuildCoreTests/BuildParametersTests.swift +++ b/Tests/SPMBuildCoreTests/BuildParametersTests.swift @@ -21,7 +21,7 @@ struct BuildParametersTests { func configurationDependentProperties() throws { var parameters = mockBuildParameters( destination: .host, - environment: BuildEnvironment(platform: .linux, configuration: .debug) + environment: BuildEnvironment(platform: .linux, isHost: false, configuration: .debug) ) #expect(parameters.enableTestability) parameters.configuration = .release From df6534004aee99c6c88ad78fcd5adf96967b8e5a Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Thu, 11 Dec 2025 19:40:39 -0500 Subject: [PATCH 3/4] Fix rest of tests --- Tests/FunctionalTests/PluginTests.swift | 4 +- .../PackageGraphTests/ModulesGraphTests.swift | 20 ++--- .../PackageBuilderTests.swift | 84 +++++++++---------- 3 files changed, 54 insertions(+), 54 deletions(-) diff --git a/Tests/FunctionalTests/PluginTests.swift b/Tests/FunctionalTests/PluginTests.swift index 57de65398ca..e6a0bfc590d 100644 --- a/Tests/FunctionalTests/PluginTests.swift +++ b/Tests/FunctionalTests/PluginTests.swift @@ -812,7 +812,7 @@ struct PluginTests { let success = try await withCheckedThrowingContinuation { continuation in plugin.invoke( action: .performCommand(package: package, arguments: arguments), - buildEnvironment: BuildEnvironment(platform: .macOS, configuration: .debug), + buildEnvironment: BuildEnvironment(platform: .macOS, isHost: true, configuration: .debug), scriptRunner: scriptRunner, workingDirectory: package.path, outputDirectory: pluginDir.appending("output"), @@ -1111,7 +1111,7 @@ struct PluginTests { try await withTaskCancellationHandler { _ = try await plugin.invoke( action: .performCommand(package: package, arguments: []), - buildEnvironment: BuildEnvironment(platform: .macOS, configuration: .debug), + buildEnvironment: BuildEnvironment(platform: .macOS, isHost: true, configuration: .debug), scriptRunner: scriptRunner, workingDirectory: package.path, outputDirectory: pluginDir.appending("output"), diff --git a/Tests/PackageGraphTests/ModulesGraphTests.swift b/Tests/PackageGraphTests/ModulesGraphTests.swift index ec2e153d31d..7313f0d0b75 100644 --- a/Tests/PackageGraphTests/ModulesGraphTests.swift +++ b/Tests/PackageGraphTests/ModulesGraphTests.swift @@ -2369,20 +2369,20 @@ struct ModulesGraphTests { try result.checkTarget("Foo") { result in result.check(dependencies: "Bar", "Baz", "Biz") try result.checkDependency("Bar") { result in - result.checkConditions(satisfy: .init(platform: .linux, configuration: .debug)) - result.checkConditions(satisfy: .init(platform: .linux, configuration: .release)) - result.checkConditions(dontSatisfy: .init(platform: .macOS, configuration: .release)) + result.checkConditions(satisfy: .init(platform: .linux, isHost: false, configuration: .debug)) + result.checkConditions(satisfy: .init(platform: .linux, isHost: false, configuration: .release)) + result.checkConditions(dontSatisfy: .init(platform: .macOS, isHost: false, configuration: .release)) } try result.checkDependency("Baz") { result in - result.checkConditions(satisfy: .init(platform: .watchOS, configuration: .debug)) - result.checkConditions(satisfy: .init(platform: .tvOS, configuration: .debug)) - result.checkConditions(dontSatisfy: .init(platform: .tvOS, configuration: .release)) + result.checkConditions(satisfy: .init(platform: .watchOS, isHost: false, configuration: .debug)) + result.checkConditions(satisfy: .init(platform: .tvOS, isHost: false, configuration: .debug)) + result.checkConditions(dontSatisfy: .init(platform: .tvOS, isHost: false, configuration: .release)) } try result.checkDependency("Biz") { result in - result.checkConditions(satisfy: .init(platform: .watchOS, configuration: .release)) - result.checkConditions(satisfy: .init(platform: .iOS, configuration: .release)) - result.checkConditions(dontSatisfy: .init(platform: .iOS, configuration: .debug)) - result.checkConditions(dontSatisfy: .init(platform: .macOS, configuration: .release)) + result.checkConditions(satisfy: .init(platform: .watchOS, isHost: false, configuration: .release)) + result.checkConditions(satisfy: .init(platform: .iOS, isHost: false, configuration: .release)) + result.checkConditions(dontSatisfy: .init(platform: .iOS, isHost: false, configuration: .debug)) + result.checkConditions(dontSatisfy: .init(platform: .macOS, isHost: false, configuration: .release)) } } } diff --git a/Tests/PackageLoadingTests/PackageBuilderTests.swift b/Tests/PackageLoadingTests/PackageBuilderTests.swift index 3d577aaa805..de38dfb4151 100644 --- a/Tests/PackageLoadingTests/PackageBuilderTests.swift +++ b/Tests/PackageLoadingTests/PackageBuilderTests.swift @@ -2635,7 +2635,7 @@ struct PackageBuilderTests { try package.checkModule("cbar") { package in let scope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .debug) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .debug) ) #expect(scope.evaluate(.GCC_PREPROCESSOR_DEFINITIONS) == ["CCC=2", "CXX"]) #expect(scope.evaluate(.HEADER_SEARCH_PATHS) == ["Sources/headers", "Sources/cppheaders"]) @@ -2644,7 +2644,7 @@ struct PackageBuilderTests { let releaseScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .release) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .release) ) #expect(releaseScope.evaluate(.GCC_PREPROCESSOR_DEFINITIONS) == ["CCC=2", "CXX", "RCXX"]) } @@ -2652,20 +2652,20 @@ struct PackageBuilderTests { try package.checkModule("bar") { package in let scope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .linux, configuration: .debug) + environment: BuildEnvironment(platform: .linux, isHost: false, configuration: .debug) ) #expect(scope.evaluate(.SWIFT_ACTIVE_COMPILATION_CONDITIONS) == ["SOMETHING", "LINUX"]) #expect(scope.evaluate(.OTHER_SWIFT_FLAGS) == ["-Isfoo", "-L", "sbar"]) let rscope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .linux, configuration: .release) + environment: BuildEnvironment(platform: .linux, isHost: false, configuration: .release) ) #expect(rscope.evaluate(.SWIFT_ACTIVE_COMPILATION_CONDITIONS) == ["SOMETHING", "LINUX", "RLINUX"]) let mscope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .debug) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .debug) ) #expect(mscope.evaluate(.SWIFT_ACTIVE_COMPILATION_CONDITIONS) == ["SOMETHING", "DMACOS"]) } @@ -2673,7 +2673,7 @@ struct PackageBuilderTests { try package.checkModule("exe") { package in let scope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .linux, configuration: .debug) + environment: BuildEnvironment(platform: .linux, isHost: false, configuration: .debug) ) #expect(scope.evaluate(.LINK_LIBRARIES) == ["sqlite3"]) #expect(scope.evaluate(.OTHER_LDFLAGS) == ["-Ilfoo", "-L", "lbar"]) @@ -2684,7 +2684,7 @@ struct PackageBuilderTests { let mscope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .iOS, configuration: .debug) + environment: BuildEnvironment(platform: .iOS, isHost: false, configuration: .debug) ) #expect(mscope.evaluate(.LINK_LIBRARIES) == ["sqlite3"]) #expect(mscope.evaluate(.LINK_FRAMEWORKS) == ["CoreData"]) @@ -2732,7 +2732,7 @@ struct PackageBuilderTests { try package.checkModule("foo") { package in let macosDebugScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .debug) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .debug) ) #expect(macosDebugScope.evaluate(.OTHER_CFLAGS) == []) #expect(macosDebugScope.evaluate(.OTHER_CPLUSPLUSFLAGS) == []) @@ -2740,7 +2740,7 @@ struct PackageBuilderTests { let macosReleaseScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .release) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .release) ) #expect(macosReleaseScope.evaluate(.OTHER_CFLAGS) == []) #expect(macosReleaseScope.evaluate(.OTHER_CPLUSPLUSFLAGS) == []) @@ -2750,21 +2750,21 @@ struct PackageBuilderTests { try package.checkModule("bar") { package in let linuxDebugScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .linux, configuration: .debug) + environment: BuildEnvironment(platform: .linux, isHost: false, configuration: .debug) ) #expect(linuxDebugScope.evaluate(.OTHER_SWIFT_FLAGS) == []) #expect(linuxDebugScope.evaluate(.OTHER_LDFLAGS) == []) let linuxReleaseScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .linux, configuration: .release) + environment: BuildEnvironment(platform: .linux, isHost: false, configuration: .release) ) #expect(linuxReleaseScope.evaluate(.OTHER_SWIFT_FLAGS) == []) #expect(linuxReleaseScope.evaluate(.OTHER_LDFLAGS) == []) let macosDebugScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .debug) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .debug) ) #expect(macosDebugScope.evaluate(.OTHER_SWIFT_FLAGS) == []) #expect(macosDebugScope.evaluate(.OTHER_LDFLAGS) == []) @@ -2932,22 +2932,22 @@ struct PackageBuilderTests { target.check(dependencies: ["Bar", "Baz", "Biz"]) target.checkDependency("Bar") { result in - result.checkConditions(satisfy: .init(platform: .macOS, configuration: .debug)) - result.checkConditions(satisfy: .init(platform: .macOS, configuration: .release)) - result.checkConditions(dontSatisfy: .init(platform: .watchOS, configuration: .release)) + result.checkConditions(satisfy: .init(platform: .macOS, isHost: false, configuration: .debug)) + result.checkConditions(satisfy: .init(platform: .macOS, isHost: false, configuration: .release)) + result.checkConditions(dontSatisfy: .init(platform: .watchOS, isHost: false, configuration: .release)) } target.checkDependency("Baz") { result in - result.checkConditions(satisfy: .init(platform: .macOS, configuration: .debug)) - result.checkConditions(satisfy: .init(platform: .linux, configuration: .debug)) - result.checkConditions(dontSatisfy: .init(platform: .linux, configuration: .release)) + result.checkConditions(satisfy: .init(platform: .macOS, isHost: false, configuration: .debug)) + result.checkConditions(satisfy: .init(platform: .linux, isHost: false, configuration: .debug)) + result.checkConditions(dontSatisfy: .init(platform: .linux, isHost: false, configuration: .release)) } target.checkDependency("Biz") { result in - result.checkConditions(satisfy: .init(platform: .watchOS, configuration: .release)) - result.checkConditions(satisfy: .init(platform: .iOS, configuration: .release)) - result.checkConditions(dontSatisfy: .init(platform: .linux, configuration: .release)) - result.checkConditions(dontSatisfy: .init(platform: .iOS, configuration: .debug)) + result.checkConditions(satisfy: .init(platform: .watchOS, isHost: false, configuration: .release)) + result.checkConditions(satisfy: .init(platform: .iOS, isHost: false, configuration: .release)) + result.checkConditions(dontSatisfy: .init(platform: .linux, isHost: false, configuration: .release)) + result.checkConditions(dontSatisfy: .init(platform: .iOS, isHost: false, configuration: .debug)) } } } @@ -3238,13 +3238,13 @@ struct PackageBuilderTests { try package.checkModule("foo") { package in let macosDebugScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .debug) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .debug) ) #expect(macosDebugScope.evaluate(.SWIFT_VERSION) == ["5"]) let macosReleaseScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .release) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .release) ) #expect(macosReleaseScope.evaluate(.SWIFT_VERSION) == ["5"]) } @@ -3252,19 +3252,19 @@ struct PackageBuilderTests { try package.checkModule("bar") { package in let linuxDebugScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .linux, configuration: .debug) + environment: BuildEnvironment(platform: .linux, isHost: false, configuration: .debug) ) #expect(linuxDebugScope.evaluate(.SWIFT_VERSION) == ["3"]) let macosDebugScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .debug) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .debug) ) #expect(macosDebugScope.evaluate(.SWIFT_VERSION) == ["4"]) let macosReleaseScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .release) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .release) ) #expect(macosReleaseScope.evaluate(.SWIFT_VERSION) == ["5"]) } @@ -3297,7 +3297,7 @@ struct PackageBuilderTests { try package.checkModule("foo") { package in let macosDebugScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .debug) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .debug) ) #expect( macosDebugScope.evaluate(.OTHER_SWIFT_FLAGS) == @@ -3306,7 +3306,7 @@ struct PackageBuilderTests { let macosReleaseScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .release) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .release) ) #expect( macosReleaseScope.evaluate(.OTHER_SWIFT_FLAGS) == @@ -3343,7 +3343,7 @@ struct PackageBuilderTests { try package.checkModule("cfoo") { package in let macosDebugScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .debug) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .debug) ) #expect( macosDebugScope.evaluate(.OTHER_CFLAGS) == @@ -3352,7 +3352,7 @@ struct PackageBuilderTests { let macosReleaseScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .release) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .release) ) #expect( macosReleaseScope.evaluate(.OTHER_CFLAGS) == @@ -3389,7 +3389,7 @@ struct PackageBuilderTests { try package.checkModule("cxxfoo") { package in let macosDebugScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .debug) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .debug) ) #expect( macosDebugScope.evaluate(.OTHER_CPLUSPLUSFLAGS) == @@ -3398,7 +3398,7 @@ struct PackageBuilderTests { let macosReleaseScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .release) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .release) ) #expect( macosReleaseScope.evaluate(.OTHER_CPLUSPLUSFLAGS) == @@ -3433,7 +3433,7 @@ struct PackageBuilderTests { try package.checkModule("cfoo") { package in let macosDebugScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .debug) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .debug) ) #expect( macosDebugScope.evaluate(.OTHER_CFLAGS) == @@ -3442,7 +3442,7 @@ struct PackageBuilderTests { let macosReleaseScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .release) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .release) ) #expect( macosReleaseScope.evaluate(.OTHER_CFLAGS) == @@ -3477,7 +3477,7 @@ struct PackageBuilderTests { try package.checkModule("cxxfoo") { package in let macosDebugScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .debug) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .debug) ) #expect( macosDebugScope.evaluate(.OTHER_CPLUSPLUSFLAGS) == @@ -3486,7 +3486,7 @@ struct PackageBuilderTests { let macosReleaseScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .release) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .release) ) #expect( macosReleaseScope.evaluate(.OTHER_CPLUSPLUSFLAGS) == @@ -3527,14 +3527,14 @@ struct PackageBuilderTests { try package.checkModule("A") { package in let macosDebugScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .debug) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .debug) ) #expect(macosDebugScope.evaluate(.OTHER_SWIFT_FLAGS).contains("-default-isolation")) #expect(macosDebugScope.evaluate(.OTHER_SWIFT_FLAGS).contains("MainActor")) let macosReleaseScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .release) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .release) ) #expect(macosReleaseScope.evaluate(.OTHER_SWIFT_FLAGS).contains("-default-isolation")) #expect(macosReleaseScope.evaluate(.OTHER_SWIFT_FLAGS).contains("MainActor")) @@ -3544,21 +3544,21 @@ struct PackageBuilderTests { try package.checkModule("B") { package in let linuxDebugScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .linux, configuration: .debug) + environment: BuildEnvironment(platform: .linux, isHost: false, configuration: .debug) ) #expect(linuxDebugScope.evaluate(.OTHER_SWIFT_FLAGS).contains("-default-isolation")) #expect(linuxDebugScope.evaluate(.OTHER_SWIFT_FLAGS).contains("nonisolated")) let macosDebugScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .debug) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .debug) ) #expect(macosDebugScope.evaluate(.OTHER_SWIFT_FLAGS).contains("-default-isolation")) #expect(macosDebugScope.evaluate(.OTHER_SWIFT_FLAGS).contains("MainActor")) let macosReleaseScope = BuildSettings.Scope( package.target.buildSettings, - environment: BuildEnvironment(platform: .macOS, configuration: .release) + environment: BuildEnvironment(platform: .macOS, isHost: false, configuration: .release) ) #expect(!macosReleaseScope.evaluate(.OTHER_SWIFT_FLAGS).contains("-default-isolation") || !macosReleaseScope.evaluate(.OTHER_SWIFT_FLAGS).contains("MainActor")) From 1dbded7e752f64c077acfad06be4481d6bed80c0 Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Fri, 12 Dec 2025 10:34:20 -0500 Subject: [PATCH 4/4] Disable one of the BuildTests for SwiftBuild --- Tests/BuildTests/BuildPlanTests.swift | 33 +++++++++++++++++++++++ Tests/BuildTests/BuildTests.swift | 39 +++------------------------ 2 files changed, 37 insertions(+), 35 deletions(-) diff --git a/Tests/BuildTests/BuildPlanTests.swift b/Tests/BuildTests/BuildPlanTests.swift index 05470c7fb5a..9d543e5e83c 100644 --- a/Tests/BuildTests/BuildPlanTests.swift +++ b/Tests/BuildTests/BuildPlanTests.swift @@ -7746,6 +7746,39 @@ class BuildPlanTestCase: XCTestCase { false ) } + + #if os(macOS) + // This is actually an Xcode build test + func testPackageNameFlagXCBuild() async throws { + let isFlagSupportedInDriver = try DriverSupport.checkToolchainDriverFlags( + flags: ["package-name"], + toolchain: UserToolchain.default, + fileSystem: localFileSystem + ) + try await fixtureXCTest(name: "Miscellaneous/PackageNameFlag") { fixturePath in + let (stdout, _) = try await executeSwiftBuild( + fixturePath.appending("appPkg"), + extraArgs: ["--vv"], + buildSystem: .xcode + ) + XCTAssertMatch(stdout, .contains("-module-name Foo")) + XCTAssertMatch(stdout, .contains("-module-name Zoo")) + XCTAssertMatch(stdout, .contains("-module-name Bar")) + XCTAssertMatch(stdout, .contains("-module-name Baz")) + XCTAssertMatch(stdout, .contains("-module-name App")) + XCTAssertMatch(stdout, .contains("-module-name exe")) + if isFlagSupportedInDriver { + XCTAssertMatch(stdout, .contains("-package-name apppkg")) + XCTAssertMatch(stdout, .contains("-package-name foopkg")) + // the flag is not supported if tools-version < 5.9 + XCTAssertNoMatch(stdout, .contains("-package-name barpkg")) + } else { + XCTAssertNoMatch(stdout, .contains("-package-name")) + } + XCTAssertMatch(stdout, .contains("Build succeeded")) + } + } + #endif } @Test func testAllTheThingsPrebuilts() async throws { diff --git a/Tests/BuildTests/BuildTests.swift b/Tests/BuildTests/BuildTests.swift index 9e0579e3082..2fb2c20ec92 100644 --- a/Tests/BuildTests/BuildTests.swift +++ b/Tests/BuildTests/BuildTests.swift @@ -113,41 +113,6 @@ class BuildTests: BuildSystemProviderTestCase { XCTAssertMatch(stdout, .contains("Build complete!")) } } - - #if os(macOS) - // This is actually an Xcode build test - func testPackageNameFlagXCBuild() async throws { - let isFlagSupportedInDriver = try DriverSupport.checkToolchainDriverFlags( - flags: ["package-name"], - toolchain: UserToolchain.default, - fileSystem: localFileSystem - ) - try await fixtureXCTest(name: "Miscellaneous/PackageNameFlag") { fixturePath in - let (stdout, _) = try await executeSwiftBuild( - fixturePath.appending("appPkg"), - extraArgs: ["--vv"], - buildSystem: .xcode - ) - XCTAssertMatch(stdout, .contains("-module-name Foo")) - XCTAssertMatch(stdout, .contains("-module-name Zoo")) - XCTAssertMatch(stdout, .contains("-module-name Bar")) - XCTAssertMatch(stdout, .contains("-module-name Baz")) - XCTAssertMatch(stdout, .contains("-module-name App")) - XCTAssertMatch(stdout, .contains("-module-name exe")) - if isFlagSupportedInDriver { - XCTAssertMatch(stdout, .contains("-package-name apppkg")) - XCTAssertMatch(stdout, .contains("-package-name foopkg")) - // the flag is not supported if tools-version < 5.9 - XCTAssertNoMatch(stdout, .contains("-package-name barpkg")) - } else { - XCTAssertNoMatch(stdout, .contains("-package-name")) - } - XCTAssertMatch(stdout, .contains("Build succeeded")) - } - } - #endif - - } class BuildTestsNative: BuildTests { @@ -160,4 +125,8 @@ class BuildTestsSwiftBuild: BuildTests { override open var buildSystemProvider: BuildSystemProvider.Kind { return .swiftbuild } + + override func testTargetsWithPackageAccess() async throws { + throw XCTSkip("Skip until swift build system can support this case.") + } }