Skip to content

Commit b612862

Browse files
authored
Generate entrypoints for test bundles on macOS (#9018)
Closes #8973 Ensure test bundles get a main symbol on macOS so swiftpm-testing-helper can kick off tests. We may want to rename this entrypoint to solve some issues with testable executables though.
1 parent 2e81f26 commit b612862

File tree

3 files changed

+28
-17
lines changed

3 files changed

+28
-17
lines changed

Sources/SwiftBuildSupport/PackagePIFProjectBuilder+Products.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@ extension PackagePIFProjectBuilder {
430430
on: moduleDependencyGUID,
431431
platformFilters: packageConditions
432432
.toPlatformFilter(toolsVersion: package.manifest.toolsVersion),
433-
linkProduct: true
433+
// Only link the testable version of executables which use Swift, as we do not currently support renaming entrypoints written in other languages.
434+
linkProduct: moduleDependency.usesSwift
434435
)
435436
log(.debug, indent: 1, "Added linked dependency on target '\(moduleDependencyGUID)'")
436437
}

Sources/SwiftBuildSupport/SwiftBuildSystem.swift

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
413413
throw error
414414
}
415415

416-
let request = try self.makeBuildRequest(configuredTargets: configuredTargets, derivedDataPath: derivedDataPath, genSymbolGraph: genSymbolGraph)
416+
let request = try await self.makeBuildRequest(session: session, configuredTargets: configuredTargets, derivedDataPath: derivedDataPath, genSymbolGraph: genSymbolGraph)
417417

418418
struct BuildState {
419419
private var targetsByID: [Int: SwiftBuild.SwiftBuildMessage.TargetStartedInfo] = [:]
@@ -521,7 +521,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
521521
case .taskComplete(let info):
522522
let startedInfo = try buildState.completed(task: info)
523523
if info.result != .success {
524-
self.observabilityScope.emit(severity: .error, message: "\(startedInfo.ruleInfo) failed with a nonzero exit code")
524+
self.observabilityScope.emit(severity: .error, message: "\(startedInfo.ruleInfo) failed with a nonzero exit code. Command line: \(startedInfo.commandLineDisplayString ?? "<no command line>")")
525525
}
526526
let targetInfo = try buildState.target(for: startedInfo)
527527
self.delegate?.buildSystem(self, didFinishCommand: BuildSystemCommand(startedInfo, targetInfo: targetInfo))
@@ -631,7 +631,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
631631
)
632632
}
633633

634-
private func makeBuildParameters(genSymbolGraph: Bool) throws -> SwiftBuild.SWBBuildParameters {
634+
private func makeBuildParameters(session: SWBBuildServiceSession, genSymbolGraph: Bool) async throws -> SwiftBuild.SWBBuildParameters {
635635
// Generate the run destination parameters.
636636
let runDestination = makeRunDestination()
637637

@@ -642,11 +642,20 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
642642

643643
// Generate a table of any overriding build settings.
644644
var settings: [String: String] = [:]
645-
// An error with determining the override should not be fatal here.
646-
settings["CC"] = try? buildParameters.toolchain.getClangCompiler().pathString
647-
// Always specify the path of the effective Swift compiler, which was determined in the same way as for the
648-
// native build system.
649-
settings["SWIFT_EXEC"] = buildParameters.toolchain.swiftCompilerPath.pathString
645+
646+
// If the SwiftPM toolchain corresponds to a toolchain registered with the lower level build system, add it to the toolchain stack.
647+
// Otherwise, apply overrides for each component of the SwiftPM toolchain.
648+
if let toolchainID = try await session.lookupToolchain(at: buildParameters.toolchain.toolchainDir.pathString) {
649+
settings["TOOLCHAINS"] = "\(toolchainID.rawValue) $(inherited)"
650+
} else {
651+
// FIXME: This list of overrides is incomplete.
652+
// An error with determining the override should not be fatal here.
653+
settings["CC"] = try? buildParameters.toolchain.getClangCompiler().pathString
654+
// Always specify the path of the effective Swift compiler, which was determined in the same way as for the
655+
// native build system.
656+
settings["SWIFT_EXEC"] = buildParameters.toolchain.swiftCompilerPath.pathString
657+
}
658+
650659
// FIXME: workaround for old Xcode installations such as what is in CI
651660
settings["LM_SKIP_METADATA_EXTRACTION"] = "YES"
652661
if genSymbolGraph {
@@ -705,6 +714,11 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
705714
settings["ARCHS"] = architectures.joined(separator: " ")
706715
}
707716

717+
// When building with the CLI for macOS, test bundles should generate entrypoints for compatibility with swiftpm-testing-helper.
718+
if buildParameters.triple.isMacOSX {
719+
settings["GENERATE_TEST_ENTRYPOINTS_FOR_BUNDLES"] = "YES"
720+
}
721+
708722
func reportConflict(_ a: String, _ b: String) throws -> String {
709723
throw StringError("Build parameters constructed conflicting settings overrides '\(a)' and '\(b)'")
710724
}
@@ -727,9 +741,9 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
727741
return params
728742
}
729743

730-
public func makeBuildRequest(configuredTargets: [SWBTargetGUID], derivedDataPath: Basics.AbsolutePath, genSymbolGraph: Bool) throws -> SWBBuildRequest {
744+
public func makeBuildRequest(session: SWBBuildServiceSession, configuredTargets: [SWBTargetGUID], derivedDataPath: Basics.AbsolutePath, genSymbolGraph: Bool) async throws -> SWBBuildRequest {
731745
var request = SWBBuildRequest()
732-
request.parameters = try makeBuildParameters(genSymbolGraph: genSymbolGraph)
746+
request.parameters = try await makeBuildParameters(session: session, genSymbolGraph: genSymbolGraph)
733747
request.configuredTargets = configuredTargets.map { SWBConfiguredTarget(guid: $0.rawValue, parameters: request.parameters) }
734748
request.useParallelTargets = true
735749
request.useImplicitDependencies = false

Tests/CommandsTests/TestCommandTests.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,6 @@ struct TestCommandTests {
221221
}
222222

223223
@Test(
224-
.issue("https://github.com/swiftlang/swift-package-manager/issues/8955", relationship: .defect),
225224
arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases,
226225
)
227226
func enableDisableTestabilityDefaultShouldRunWithTestability(
@@ -274,7 +273,7 @@ struct TestCommandTests {
274273
}
275274

276275
#expect(
277-
stderr.contains("was not compiled for testing"),
276+
stderr.contains("was not compiled for testing") || stderr.contains("ignore swiftmodule built without '-enable-testing'"),
278277
"got stdout: \(stdout), stderr: \(stderr)",
279278
)
280279
}
@@ -668,7 +667,6 @@ struct TestCommandTests {
668667
} when: {
669668
(buildSystem == .swiftbuild && .linux == ProcessInfo.hostOperatingSystem)
670669
|| ProcessInfo.hostOperatingSystem == .windows
671-
|| (buildSystem == .swiftbuild && .macOS == ProcessInfo.hostOperatingSystem && tcdata.testRunner == .SwiftTesting)
672670
}
673671
}
674672

@@ -995,8 +993,6 @@ struct TestCommandTests {
995993
}
996994

997995
@Test(
998-
.SWBINTTODO("Fails to find test executable"),
999-
.issue("https://github.com/swiftlang/swift-package-manager/pull/8722", relationship: .fixedBy),
1000996
arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases,
1001997
)
1002998
func basicSwiftTestingIntegration(
@@ -1017,7 +1013,7 @@ struct TestCommandTests {
10171013
)
10181014
}
10191015
} when: {
1020-
buildSystem == .swiftbuild
1016+
buildSystem == .swiftbuild && ProcessInfo.hostOperatingSystem != .macOS
10211017
}
10221018
}
10231019

0 commit comments

Comments
 (0)