Skip to content

[6.0] Build one test product for both Swift Testing and XCTest (with Swift Testing enabled by default.) #7794

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
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
8 changes: 2 additions & 6 deletions Sources/Build/BuildManifest/LLBuildManifestBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,7 @@ public class LLBuildManifestBuilder {
}
}

if self.plan.destinationBuildParameters.testingParameters.library == .xctest {
try self.addTestDiscoveryGenerationCommand()
}
try self.addTestDiscoveryGenerationCommand()
try self.addTestEntryPointGenerationCommand()

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

let outputs = testEntryPointTarget.target.sources.paths

let mainFileName = TestEntryPointTool.mainFileName(
for: self.plan.destinationBuildParameters.testingParameters.library
)
let mainFileName = TestEntryPointTool.mainFileName
guard let mainOutput = (outputs.first { $0.basename == mainFileName }) else {
throw InternalError("main output (\(mainFileName)) not found")
}
Expand Down
6 changes: 2 additions & 4 deletions Sources/Build/BuildPlan/BuildPlan+Product.swift
Original file line number Diff line number Diff line change
Expand Up @@ -275,10 +275,8 @@ extension BuildPlan {
}

// Add derived test targets, if necessary
if buildParameters.testingParameters.testProductStyle.requiresAdditionalDerivedTestTargets {
if product.type == .test, let derivedTestTargets = derivedTestTargetsMap[product.id] {
staticTargets.append(contentsOf: derivedTestTargets)
}
if product.type == .test, let derivedTestTargets = derivedTestTargetsMap[product.id] {
staticTargets.append(contentsOf: derivedTestTargets)
}

return (linkLibraries, staticTargets, systemModules, libraryBinaryPaths, providedLibraries, availableTools)
Expand Down
26 changes: 12 additions & 14 deletions Sources/Build/BuildPlan/BuildPlan+Test.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,12 @@ extension BuildPlan {
_ fileSystem: FileSystem,
_ observabilityScope: ObservabilityScope
) throws -> [(product: ResolvedProduct, discoveryTargetBuildDescription: SwiftModuleBuildDescription?, entryPointTargetBuildDescription: SwiftModuleBuildDescription)] {
guard destinationBuildParameters.testingParameters.testProductStyle.requiresAdditionalDerivedTestTargets,
case .entryPointExecutable(let explicitlyEnabledDiscovery, let explicitlySpecifiedPath) =
destinationBuildParameters.testingParameters.testProductStyle
else {
throw InternalError("makeTestManifestTargets should not be used for build plan which does not require additional derived test targets")
var explicitlyEnabledDiscovery = false
var explicitlySpecifiedPath: AbsolutePath?
if case let .entryPointExecutable(caseExplicitlyEnabledDiscovery, caseExplicitlySpecifiedPath) = destinationBuildParameters.testingParameters.testProductStyle {
explicitlyEnabledDiscovery = caseExplicitlyEnabledDiscovery
explicitlySpecifiedPath = caseExplicitlySpecifiedPath
}

let isEntryPointPathSpecifiedExplicitly = explicitlySpecifiedPath != nil

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

Expand Down Expand Up @@ -153,18 +152,17 @@ extension BuildPlan {
let swiftTargetDependencies: [Module.Dependency]
let resolvedTargetDependencies: [ResolvedModule.Dependency]

switch destinationBuildParameters.testingParameters.library {
case .xctest:
if destinationBuildParameters.triple.isDarwin() {
discoveryTargets = nil
swiftTargetDependencies = []
resolvedTargetDependencies = []
} else {
discoveryTargets = try generateDiscoveryTargets()
swiftTargetDependencies = [.module(discoveryTargets!.target, conditions: [])]
resolvedTargetDependencies = [.module(discoveryTargets!.resolved, conditions: [])]
case .swiftTesting:
discoveryTargets = nil
swiftTargetDependencies = testProduct.modules.map { .module($0.underlying, conditions: []) }
resolvedTargetDependencies = testProduct.modules.map { .module($0, conditions: []) }
}

if let entryPointResolvedTarget = testProduct.testEntryPointModule {
if !destinationBuildParameters.triple.isDarwin(), let entryPointResolvedTarget = testProduct.testEntryPointModule {
if isEntryPointPathSpecifiedExplicitly || explicitlyEnabledDiscovery {
if isEntryPointPathSpecifiedExplicitly {
// Allow using the explicitly-specified test entry point target, but still perform test discovery and thus declare a dependency on the discovery modules.
Expand Down
42 changes: 20 additions & 22 deletions Sources/Build/BuildPlan/BuildPlan.swift
Original file line number Diff line number Diff line change
Expand Up @@ -443,31 +443,29 @@ public class BuildPlan: SPMBuildCore.BuildPlan {
}

// Plan the derived test targets, if necessary.
if destinationBuildParameters.testingParameters.testProductStyle.requiresAdditionalDerivedTestTargets {
let derivedTestTargets = try Self.makeDerivedTestTargets(
testProducts: productMap.values.filter {
$0.product.type == .test
},
destinationBuildParameters: destinationBuildParameters,
toolsBuildParameters: toolsBuildParameters,
shouldDisableSandbox: self.shouldDisableSandbox,
self.fileSystem,
self.observabilityScope
)
for item in derivedTestTargets {
var derivedTestTargets = [item.entryPointTargetBuildDescription.target]

targetMap[item.entryPointTargetBuildDescription.target.id] = .swift(
item.entryPointTargetBuildDescription
)
let derivedTestTargets = try Self.makeDerivedTestTargets(
testProducts: productMap.values.filter {
$0.product.type == .test
},
destinationBuildParameters: destinationBuildParameters,
toolsBuildParameters: toolsBuildParameters,
shouldDisableSandbox: self.shouldDisableSandbox,
self.fileSystem,
self.observabilityScope
)
for item in derivedTestTargets {
var derivedTestTargets = [item.entryPointTargetBuildDescription.target]

if let discoveryTargetBuildDescription = item.discoveryTargetBuildDescription {
targetMap[discoveryTargetBuildDescription.target.id] = .swift(discoveryTargetBuildDescription)
derivedTestTargets.append(discoveryTargetBuildDescription.target)
}
targetMap[item.entryPointTargetBuildDescription.target.id] = .swift(
item.entryPointTargetBuildDescription
)

self.derivedTestTargetsMap[item.product.id] = derivedTestTargets
if let discoveryTargetBuildDescription = item.discoveryTargetBuildDescription {
targetMap[discoveryTargetBuildDescription.target.id] = .swift(discoveryTargetBuildDescription)
derivedTestTargets.append(discoveryTargetBuildDescription.target)
}

self.derivedTestTargetsMap[item.product.id] = derivedTestTargets
}

self.productMap = productMap.mapValues(\.buildDescription)
Expand Down
Loading