Skip to content

Commit 547f649

Browse files
grynspanxedin
andauthored
[6.0] Build one test product for both Swift Testing and XCTest (with Swift Testing enabled by default.) (#7794)
**Explanation:** Refactors the previously-experimental Swift Testing support logic so that only a single build product is produced when using both XCTest and Swift Testing, and detection of Swift Testing usage is no longer needed at compile time. **Scope:** Implementation of Swift Testing/SwiftPM integration; touches mostly `swift test` but affects `swift build` and `swift package init` as well. **Issue:** rdar://120864035 **Original PR:** #7777, #7789, #7796 **Risk:** Moderate—refactors how we build and run tests. **Testing:** Existing test coverage in the package as well as test coverage in the Swift Testing package; additional integration testing will be added once Swift Testing is in the toolchain. **Reviewer:** @bnbarham @xedin @briancroom @dennisweissmann --------- Co-authored-by: Pavel Yaskevich <[email protected]>
1 parent b46e02a commit 547f649

21 files changed

+580
-579
lines changed

Sources/Build/BuildManifest/LLBuildManifestBuilder.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,7 @@ public class LLBuildManifestBuilder {
112112
}
113113
}
114114

115-
if self.plan.destinationBuildParameters.testingParameters.library == .xctest {
116-
try self.addTestDiscoveryGenerationCommand()
117-
}
115+
try self.addTestDiscoveryGenerationCommand()
118116
try self.addTestEntryPointGenerationCommand()
119117

120118
// Create command for all products in the plan.
@@ -310,9 +308,7 @@ extension LLBuildManifestBuilder {
310308

311309
let outputs = testEntryPointTarget.target.sources.paths
312310

313-
let mainFileName = TestEntryPointTool.mainFileName(
314-
for: self.plan.destinationBuildParameters.testingParameters.library
315-
)
311+
let mainFileName = TestEntryPointTool.mainFileName
316312
guard let mainOutput = (outputs.first { $0.basename == mainFileName }) else {
317313
throw InternalError("main output (\(mainFileName)) not found")
318314
}

Sources/Build/BuildPlan/BuildPlan+Product.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,8 @@ extension BuildPlan {
275275
}
276276

277277
// Add derived test targets, if necessary
278-
if buildParameters.testingParameters.testProductStyle.requiresAdditionalDerivedTestTargets {
279-
if product.type == .test, let derivedTestTargets = derivedTestTargetsMap[product.id] {
280-
staticTargets.append(contentsOf: derivedTestTargets)
281-
}
278+
if product.type == .test, let derivedTestTargets = derivedTestTargetsMap[product.id] {
279+
staticTargets.append(contentsOf: derivedTestTargets)
282280
}
283281

284282
return (linkLibraries, staticTargets, systemModules, libraryBinaryPaths, providedLibraries, availableTools)

Sources/Build/BuildPlan/BuildPlan+Test.swift

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,12 @@ extension BuildPlan {
3434
_ fileSystem: FileSystem,
3535
_ observabilityScope: ObservabilityScope
3636
) throws -> [(product: ResolvedProduct, discoveryTargetBuildDescription: SwiftModuleBuildDescription?, entryPointTargetBuildDescription: SwiftModuleBuildDescription)] {
37-
guard destinationBuildParameters.testingParameters.testProductStyle.requiresAdditionalDerivedTestTargets,
38-
case .entryPointExecutable(let explicitlyEnabledDiscovery, let explicitlySpecifiedPath) =
39-
destinationBuildParameters.testingParameters.testProductStyle
40-
else {
41-
throw InternalError("makeTestManifestTargets should not be used for build plan which does not require additional derived test targets")
37+
var explicitlyEnabledDiscovery = false
38+
var explicitlySpecifiedPath: AbsolutePath?
39+
if case let .entryPointExecutable(caseExplicitlyEnabledDiscovery, caseExplicitlySpecifiedPath) = destinationBuildParameters.testingParameters.testProductStyle {
40+
explicitlyEnabledDiscovery = caseExplicitlyEnabledDiscovery
41+
explicitlySpecifiedPath = caseExplicitlySpecifiedPath
4242
}
43-
4443
let isEntryPointPathSpecifiedExplicitly = explicitlySpecifiedPath != nil
4544

4645
var isDiscoveryEnabledRedundantly = explicitlyEnabledDiscovery && !isEntryPointPathSpecifiedExplicitly
@@ -116,7 +115,7 @@ extension BuildPlan {
116115
resolvedTargetDependencies: [ResolvedModule.Dependency]
117116
) throws -> SwiftModuleBuildDescription {
118117
let entryPointDerivedDir = destinationBuildParameters.buildPath.appending(components: "\(testProduct.name).derived")
119-
let entryPointMainFileName = TestEntryPointTool.mainFileName(for: destinationBuildParameters.testingParameters.library)
118+
let entryPointMainFileName = TestEntryPointTool.mainFileName
120119
let entryPointMainFile = entryPointDerivedDir.appending(component: entryPointMainFileName)
121120
let entryPointSources = Sources(paths: [entryPointMainFile], root: entryPointDerivedDir)
122121

@@ -153,18 +152,17 @@ extension BuildPlan {
153152
let swiftTargetDependencies: [Module.Dependency]
154153
let resolvedTargetDependencies: [ResolvedModule.Dependency]
155154

156-
switch destinationBuildParameters.testingParameters.library {
157-
case .xctest:
155+
if destinationBuildParameters.triple.isDarwin() {
156+
discoveryTargets = nil
157+
swiftTargetDependencies = []
158+
resolvedTargetDependencies = []
159+
} else {
158160
discoveryTargets = try generateDiscoveryTargets()
159161
swiftTargetDependencies = [.module(discoveryTargets!.target, conditions: [])]
160162
resolvedTargetDependencies = [.module(discoveryTargets!.resolved, conditions: [])]
161-
case .swiftTesting:
162-
discoveryTargets = nil
163-
swiftTargetDependencies = testProduct.modules.map { .module($0.underlying, conditions: []) }
164-
resolvedTargetDependencies = testProduct.modules.map { .module($0, conditions: []) }
165163
}
166164

167-
if let entryPointResolvedTarget = testProduct.testEntryPointModule {
165+
if !destinationBuildParameters.triple.isDarwin(), let entryPointResolvedTarget = testProduct.testEntryPointModule {
168166
if isEntryPointPathSpecifiedExplicitly || explicitlyEnabledDiscovery {
169167
if isEntryPointPathSpecifiedExplicitly {
170168
// Allow using the explicitly-specified test entry point target, but still perform test discovery and thus declare a dependency on the discovery modules.

Sources/Build/BuildPlan/BuildPlan.swift

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -443,31 +443,29 @@ public class BuildPlan: SPMBuildCore.BuildPlan {
443443
}
444444

445445
// Plan the derived test targets, if necessary.
446-
if destinationBuildParameters.testingParameters.testProductStyle.requiresAdditionalDerivedTestTargets {
447-
let derivedTestTargets = try Self.makeDerivedTestTargets(
448-
testProducts: productMap.values.filter {
449-
$0.product.type == .test
450-
},
451-
destinationBuildParameters: destinationBuildParameters,
452-
toolsBuildParameters: toolsBuildParameters,
453-
shouldDisableSandbox: self.shouldDisableSandbox,
454-
self.fileSystem,
455-
self.observabilityScope
456-
)
457-
for item in derivedTestTargets {
458-
var derivedTestTargets = [item.entryPointTargetBuildDescription.target]
459-
460-
targetMap[item.entryPointTargetBuildDescription.target.id] = .swift(
461-
item.entryPointTargetBuildDescription
462-
)
446+
let derivedTestTargets = try Self.makeDerivedTestTargets(
447+
testProducts: productMap.values.filter {
448+
$0.product.type == .test
449+
},
450+
destinationBuildParameters: destinationBuildParameters,
451+
toolsBuildParameters: toolsBuildParameters,
452+
shouldDisableSandbox: self.shouldDisableSandbox,
453+
self.fileSystem,
454+
self.observabilityScope
455+
)
456+
for item in derivedTestTargets {
457+
var derivedTestTargets = [item.entryPointTargetBuildDescription.target]
463458

464-
if let discoveryTargetBuildDescription = item.discoveryTargetBuildDescription {
465-
targetMap[discoveryTargetBuildDescription.target.id] = .swift(discoveryTargetBuildDescription)
466-
derivedTestTargets.append(discoveryTargetBuildDescription.target)
467-
}
459+
targetMap[item.entryPointTargetBuildDescription.target.id] = .swift(
460+
item.entryPointTargetBuildDescription
461+
)
468462

469-
self.derivedTestTargetsMap[item.product.id] = derivedTestTargets
463+
if let discoveryTargetBuildDescription = item.discoveryTargetBuildDescription {
464+
targetMap[discoveryTargetBuildDescription.target.id] = .swift(discoveryTargetBuildDescription)
465+
derivedTestTargets.append(discoveryTargetBuildDescription.target)
470466
}
467+
468+
self.derivedTestTargetsMap[item.product.id] = derivedTestTargets
471469
}
472470

473471
self.productMap = productMap.mapValues(\.buildDescription)

0 commit comments

Comments
 (0)