Skip to content

Commit 84ba94a

Browse files
authored
[PackageModel] Toolchain: Split SwiftTesting flags between swift comp… (#7903)
…iler and linker ### Motivation: Keeping them together broke Symbol Graph Extract tool because it cannot handle `-Xlinker` flags. ### Modifications: - Adjust `deriveMacOSSpecificSwiftTestingFlags` to produce two arrays - one for swift compiler and one for linker flags. ### Result: `extraFlags.swiftCompilerFlags` no longer includes `-Xlinker` flags.
1 parent aa82ab3 commit 84ba94a

File tree

2 files changed

+134
-14
lines changed

2 files changed

+134
-14
lines changed

Sources/PackageModel/UserToolchain.swift

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -410,23 +410,23 @@ public final class UserToolchain: Toolchain {
410410
static func deriveMacOSSpecificSwiftTestingFlags(
411411
derivedSwiftCompiler: AbsolutePath,
412412
fileSystem: any FileSystem
413-
) -> [String] {
413+
) -> (swiftCFlags: [String], linkerFlags: [String]) {
414414
// If this is CommandLineTools all we need to add is a frameworks path.
415415
if let frameworksPath = try? AbsolutePath(
416416
validating: "../../Library/Developer/Frameworks",
417417
relativeTo: resolveSymlinks(derivedSwiftCompiler).parentDirectory
418418
), fileSystem.exists(frameworksPath.appending("Testing.framework")) {
419-
return [
420-
"-F", frameworksPath.pathString,
421-
"-Xlinker", "-rpath",
422-
"-Xlinker", frameworksPath.pathString
423-
]
419+
return (swiftCFlags: [
420+
"-F", frameworksPath.pathString
421+
], linkerFlags: [
422+
"-rpath", frameworksPath.pathString
423+
])
424424
}
425425

426426
guard let toolchainLibDir = try? toolchainLibDir(
427427
swiftCompilerPath: derivedSwiftCompiler
428428
) else {
429-
return []
429+
return (swiftCFlags: [], linkerFlags: [])
430430
}
431431

432432
let testingLibDir = toolchainLibDir.appending(
@@ -438,15 +438,16 @@ public final class UserToolchain: Toolchain {
438438
)
439439

440440
guard fileSystem.exists(testingLibDir), fileSystem.exists(testingPluginsDir) else {
441-
return []
441+
return (swiftCFlags: [], linkerFlags: [])
442442
}
443443

444-
return [
444+
return (swiftCFlags: [
445445
"-I", testingLibDir.pathString,
446446
"-L", testingLibDir.pathString,
447-
"-plugin-path", testingPluginsDir.pathString,
448-
"-Xlinker", "-rpath", "-Xlinker", testingLibDir.pathString,
449-
]
447+
"-plugin-path", testingPluginsDir.pathString
448+
], linkerFlags: [
449+
"-rpath", testingLibDir.pathString
450+
])
450451
}
451452

452453
internal static func deriveSwiftCFlags(
@@ -669,11 +670,15 @@ public final class UserToolchain: Toolchain {
669670
self.targetTriple = triple
670671

671672
var swiftCompilerFlags: [String] = []
673+
var extraLinkerFlags: [String] = []
674+
672675
#if os(macOS)
673-
swiftCompilerFlags += Self.deriveMacOSSpecificSwiftTestingFlags(
676+
let (swiftCFlags, linkerFlags) = Self.deriveMacOSSpecificSwiftTestingFlags(
674677
derivedSwiftCompiler: swiftCompilers.compile,
675678
fileSystem: fileSystem
676679
)
680+
swiftCompilerFlags += swiftCFlags
681+
extraLinkerFlags += linkerFlags
677682
#endif
678683

679684
swiftCompilerFlags += try Self.deriveSwiftCFlags(
@@ -683,11 +688,13 @@ public final class UserToolchain: Toolchain {
683688
fileSystem: fileSystem
684689
)
685690

691+
extraLinkerFlags += swiftSDK.toolset.knownTools[.linker]?.extraCLIOptions ?? []
692+
686693
self.extraFlags = BuildFlags(
687694
cCompilerFlags: swiftSDK.toolset.knownTools[.cCompiler]?.extraCLIOptions ?? [],
688695
cxxCompilerFlags: swiftSDK.toolset.knownTools[.cxxCompiler]?.extraCLIOptions ?? [],
689696
swiftCompilerFlags: swiftCompilerFlags,
690-
linkerFlags: swiftSDK.toolset.knownTools[.linker]?.extraCLIOptions ?? [],
697+
linkerFlags: extraLinkerFlags,
691698
xcbuildFlags: swiftSDK.toolset.knownTools[.xcbuild]?.extraCLIOptions ?? [])
692699

693700
self.includeSearchPaths = swiftSDK.pathsConfiguration.includeSearchPaths ?? []

Tests/BuildTests/BuildPlanTests.swift

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4649,6 +4649,119 @@ final class BuildPlanTests: XCTestCase {
46494649
])
46504650
}
46514651

4652+
func testSwiftTestingFlagsOnMacOSWithCustomToolchain() async throws {
4653+
#if !os(macOS)
4654+
// This is testing swift-testing in a toolchain which is macOS only feature.
4655+
try XCTSkipIf(true, "test is only supported on macOS")
4656+
#endif
4657+
4658+
let fs = InMemoryFileSystem(
4659+
emptyFiles:
4660+
"/fake/path/lib/swift/macosx/testing/Testing.swiftmodule",
4661+
"/fake/path/lib/swift/host/plugins/testing/libTesting.dylib",
4662+
"/Pkg/Sources/Lib/main.swift",
4663+
"/Pkg/Tests/LibTest/test.swift"
4664+
)
4665+
try fs.createMockToolchain()
4666+
4667+
let userSwiftSDK = SwiftSDK(
4668+
hostTriple: .x86_64MacOS,
4669+
targetTriple: .x86_64MacOS,
4670+
toolset: .init(
4671+
knownTools: [
4672+
.cCompiler: .init(extraCLIOptions: []),
4673+
.swiftCompiler: .init(extraCLIOptions: []),
4674+
],
4675+
rootPaths: ["/fake/path/to"]
4676+
),
4677+
pathsConfiguration: .init(
4678+
sdkRootPath: "/fake/sdk",
4679+
swiftResourcesPath: "/fake/lib/swift",
4680+
swiftStaticResourcesPath: "/fake/lib/swift_static"
4681+
)
4682+
)
4683+
let mockToolchain = try UserToolchain(
4684+
swiftSDK: userSwiftSDK,
4685+
environment: .mockEnvironment,
4686+
fileSystem: fs
4687+
)
4688+
4689+
XCTAssertEqual(
4690+
mockToolchain.extraFlags.swiftCompilerFlags,
4691+
[
4692+
"-I", "/fake/path/lib/swift/macosx/testing",
4693+
"-L", "/fake/path/lib/swift/macosx/testing",
4694+
"-plugin-path", "/fake/path/lib/swift/host/plugins/testing",
4695+
"-sdk", "/fake/sdk",
4696+
]
4697+
)
4698+
XCTAssertEqual(
4699+
mockToolchain.extraFlags.linkerFlags,
4700+
["-rpath", "/fake/path/lib/swift/macosx/testing"]
4701+
)
4702+
4703+
let observability = ObservabilitySystem.makeForTesting()
4704+
let graph = try loadModulesGraph(
4705+
fileSystem: fs,
4706+
manifests: [
4707+
Manifest.createRootManifest(
4708+
displayName: "Pkg",
4709+
path: "/Pkg",
4710+
targets: [
4711+
TargetDescription(name: "Lib", dependencies: []),
4712+
TargetDescription(
4713+
name: "LibTest",
4714+
dependencies: ["Lib"],
4715+
type: .test
4716+
),
4717+
]
4718+
),
4719+
],
4720+
observabilityScope: observability.topScope
4721+
)
4722+
XCTAssertNoDiagnostics(observability.diagnostics)
4723+
4724+
let result = try await BuildPlanResult(plan: mockBuildPlan(
4725+
toolchain: mockToolchain,
4726+
graph: graph,
4727+
commonFlags: .init(),
4728+
fileSystem: fs,
4729+
observabilityScope: observability.topScope
4730+
))
4731+
result.checkProductsCount(2)
4732+
result.checkTargetsCount(3)
4733+
4734+
let testProductLinkArgs = try result.buildProduct(for: "Lib").linkArguments()
4735+
XCTAssertMatch(testProductLinkArgs, [
4736+
.anySequence,
4737+
"-I", "/fake/path/lib/swift/macosx/testing",
4738+
"-L", "/fake/path/lib/swift/macosx/testing",
4739+
.anySequence,
4740+
"-Xlinker", "-rpath",
4741+
"-Xlinker", "/fake/path/lib/swift/macosx/testing",
4742+
])
4743+
4744+
let libModuleArgs = try result.moduleBuildDescription(for: "Lib").swift().compileArguments()
4745+
XCTAssertMatch(libModuleArgs, [
4746+
.anySequence,
4747+
"-I", "/fake/path/lib/swift/macosx/testing",
4748+
"-L", "/fake/path/lib/swift/macosx/testing",
4749+
"-plugin-path", "/fake/path/lib/swift/host/plugins/testing",
4750+
.anySequence,
4751+
])
4752+
XCTAssertNoMatch(libModuleArgs, ["-Xlinker"])
4753+
4754+
let testModuleArgs = try result.moduleBuildDescription(for: "LibTest").swift().compileArguments()
4755+
XCTAssertMatch(testModuleArgs, [
4756+
.anySequence,
4757+
"-I", "/fake/path/lib/swift/macosx/testing",
4758+
"-L", "/fake/path/lib/swift/macosx/testing",
4759+
"-plugin-path", "/fake/path/lib/swift/host/plugins/testing",
4760+
.anySequence,
4761+
])
4762+
XCTAssertNoMatch(testModuleArgs, ["-Xlinker"])
4763+
}
4764+
46524765
func testUserToolchainWithToolsetCompileFlags() async throws {
46534766
let fileSystem = InMemoryFileSystem(
46544767
emptyFiles:

0 commit comments

Comments
 (0)