Skip to content

Commit 3f4b10f

Browse files
committed
PackageModel: partially address #5719
Handle `-use-ld=` from the configuration in the selection of the librarian. We do not honour the `-Xmanifest` or `-Xswiftc` flags being passed on the command line rather than the plist as we cannot pre-compute the flags.
1 parent ff94963 commit 3f4b10f

File tree

2 files changed

+90
-15
lines changed

2 files changed

+90
-15
lines changed

Sources/PackageModel/UserToolchain.swift

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ public final class UserToolchain: Toolchain {
128128
binDir: AbsolutePath,
129129
useXcrun: Bool,
130130
environment: EnvironmentVariables,
131-
searchPaths: [AbsolutePath]
131+
searchPaths: [AbsolutePath],
132+
extraSwiftFlags: [String]
132133
) throws
133134
-> AbsolutePath
134135
{
@@ -145,7 +146,12 @@ public final class UserToolchain: Toolchain {
145146
{
146147
return librarian.basename
147148
}
148-
// TODO(5719) use `lld-link` if the build requests lld.
149+
// TODO(5719) handle `-Xmanifest` vs `-Xswiftc`
150+
// `-use-ld=` is always joined in Swift.
151+
if let ld = extraSwiftFlags.first(where: { $0.starts(with: "-use-ld=") }) {
152+
let linker = String(ld.split(separator: "=").last!)
153+
return linker == "lld" ? "lld-link" : linker
154+
}
149155
return "link"
150156
}
151157
// TODO(compnerd) consider defaulting to `llvm-ar` universally with
@@ -449,14 +455,6 @@ public final class UserToolchain: Toolchain {
449455
// Use the triple from destination or compute the host triple using swiftc.
450456
var triple = destination.targetTriple ?? Triple.getHostTriple(usingSwiftCompiler: swiftCompilers.compile)
451457

452-
self.librarianPath = try UserToolchain.determineLibrarian(
453-
triple: triple,
454-
binDir: binDir,
455-
useXcrun: useXcrun,
456-
environment: environment,
457-
searchPaths: envSearchPaths
458-
)
459-
460458
// Change the triple to the specified arch if there's exactly one of them.
461459
// The Triple property is only looked at by the native build system currently.
462460
if let archs = self.architectures, archs.count == 1 {
@@ -473,6 +471,15 @@ public final class UserToolchain: Toolchain {
473471
environment: environment
474472
)
475473

474+
self.librarianPath = try UserToolchain.determineLibrarian(
475+
triple: triple,
476+
binDir: binDir,
477+
useXcrun: useXcrun,
478+
environment: environment,
479+
searchPaths: envSearchPaths,
480+
extraSwiftFlags: self.extraFlags.swiftCompilerFlags
481+
)
482+
476483
if let sdkDir = destination.sdkRootDir {
477484
self.extraFlags.cCompilerFlags = [
478485
triple.isDarwin() ? "-isysroot" : "--sysroot", sdkDir.pathString,

Tests/PackageModelTests/PackageModelTests.swift

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class PackageModelTests: XCTestCase {
3939
checkCodable(.executable)
4040
checkCodable(.test)
4141
}
42-
42+
4343
func testProductFilterCodable() throws {
4444
// Test ProductFilter.everything
4545
try {
@@ -66,9 +66,77 @@ class PackageModelTests: XCTestCase {
6666
toolchainBinDir: toolchainPath.appending(components: "usr", "bin")
6767
)
6868

69-
XCTAssertEqual(try UserToolchain.deriveSwiftCFlags(triple: triple, destination: destination, environment: .process()), [
70-
// Needed when cross‐compiling for Android. 2020‐03‐01
71-
"-sdk", sdkDir.pathString,
72-
])
69+
XCTAssertEqual(
70+
try UserToolchain.deriveSwiftCFlags(triple: triple, destination: destination, environment: .process()),
71+
[
72+
// Needed when cross‐compiling for Android. 2020‐03‐01
73+
"-sdk", sdkDir.pathString,
74+
]
75+
)
76+
}
77+
78+
func testWindowsLibrarianSelection() throws {
79+
// tiny PE binary from: https://archive.is/w01DO
80+
let contents: [UInt8] = [
81+
0x4D, 0x5A, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0x4C, 0x01, 0x01, 0x00,
82+
0x6A, 0x2A, 0x58, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83+
0x04, 0x00, 0x03, 0x01, 0x0B, 0x01, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00,
84+
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
85+
0x04, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
86+
0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
87+
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88+
0x68, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89+
0x02,
90+
]
91+
92+
#if os(Windows)
93+
let suffix = ".exe"
94+
#else
95+
let suffix = ""
96+
#endif
97+
98+
let triple = try Triple("x86_64-unknown-windows-msvc")
99+
let fs = TSCBasic.localFileSystem
100+
101+
try withTemporaryFile { [contents] _ in
102+
try withTemporaryDirectory(removeTreeOnDeinit: true) { [contents] tmp in
103+
let bin = tmp.appending(component: "bin")
104+
try fs.createDirectory(bin)
105+
106+
let lld = bin.appending(component: "lld-link\(suffix)")
107+
try fs.writeFileContents(lld, bytes: ByteString(contents))
108+
109+
let not = bin.appending(component: "not-link\(suffix)")
110+
try fs.writeFileContents(not, bytes: ByteString(contents))
111+
112+
#if !os(Windows)
113+
try fs.chmod(.executable, path: lld, options: [])
114+
try fs.chmod(.executable, path: not, options: [])
115+
#endif
116+
117+
try XCTAssertEqual(
118+
UserToolchain.determineLibrarian(
119+
triple: triple, binDir: bin, useXcrun: false, environment: [:], searchPaths: [],
120+
extraSwiftFlags: ["-Xswiftc", "-use-ld=lld"]
121+
),
122+
lld
123+
)
124+
125+
try XCTAssertEqual(
126+
UserToolchain.determineLibrarian(
127+
triple: triple, binDir: bin, useXcrun: false, environment: [:], searchPaths: [],
128+
extraSwiftFlags: ["-Xswiftc", "-use-ld=not-link\(suffix)"]
129+
),
130+
not
131+
)
132+
133+
try XCTAssertThrowsError(
134+
UserToolchain.determineLibrarian(
135+
triple: triple, binDir: bin, useXcrun: false, environment: [:], searchPaths: [],
136+
extraSwiftFlags: []
137+
)
138+
)
139+
}
140+
}
73141
}
74142
}

0 commit comments

Comments
 (0)