Skip to content
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
27 changes: 17 additions & 10 deletions Sources/PackageModel/UserToolchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ public final class UserToolchain: Toolchain {
binDir: AbsolutePath,
useXcrun: Bool,
environment: EnvironmentVariables,
searchPaths: [AbsolutePath]
searchPaths: [AbsolutePath],
extraSwiftFlags: [String]
) throws
-> AbsolutePath
{
Expand All @@ -145,7 +146,12 @@ public final class UserToolchain: Toolchain {
{
return librarian.basename
}
// TODO(5719) use `lld-link` if the build requests lld.
// TODO(5719) handle `-Xmanifest` vs `-Xswiftc`
// `-use-ld=` is always joined in Swift.
if let ld = extraSwiftFlags.first(where: { $0.starts(with: "-use-ld=") }) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems a bit unfortunate to have to parse the flags like this, can/should we ask users to configure alternative linkers more explicitly?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it is unfortunate. How would you recommend that we set that up? The general mechanism for this is -use-ld=... which with CMake you would pass via CMAKE_Swift_FLAGS and that is honoured everywhere.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we have to parse, could we use argument parser to help make this more reliable?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if that is going to be any better because we will need to consider the case of -Xswiftc or -Xclang-linker where the option itself is made opaque. We would need to process both the driver and frontend flags and possibly non-swift-tool flags.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this does seems very brittle. any other ideas on how to make it less so? argument parser was the only one I could think of.

let linker = String(ld.split(separator: "=").last!)
return linker == "lld" ? "lld-link" : linker
}
return "link"
}
// TODO(compnerd) consider defaulting to `llvm-ar` universally with
Expand Down Expand Up @@ -449,14 +455,6 @@ public final class UserToolchain: Toolchain {
// Use the triple from destination or compute the host triple using swiftc.
var triple = destination.targetTriple ?? Triple.getHostTriple(usingSwiftCompiler: swiftCompilers.compile)

self.librarianPath = try UserToolchain.determineLibrarian(
triple: triple,
binDir: binDir,
useXcrun: useXcrun,
environment: environment,
searchPaths: envSearchPaths
)

// Change the triple to the specified arch if there's exactly one of them.
// The Triple property is only looked at by the native build system currently.
if let archs = self.architectures, archs.count == 1 {
Expand All @@ -473,6 +471,15 @@ public final class UserToolchain: Toolchain {
environment: environment
)

self.librarianPath = try UserToolchain.determineLibrarian(
triple: triple,
binDir: binDir,
useXcrun: useXcrun,
environment: environment,
searchPaths: envSearchPaths,
extraSwiftFlags: self.extraFlags.swiftCompilerFlags
)

if let sdkDir = destination.sdkRootDir {
self.extraFlags.cCompilerFlags = [
triple.isDarwin() ? "-isysroot" : "--sysroot", sdkDir.pathString,
Expand Down
78 changes: 73 additions & 5 deletions Tests/PackageModelTests/PackageModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class PackageModelTests: XCTestCase {
checkCodable(.executable)
checkCodable(.test)
}

func testProductFilterCodable() throws {
// Test ProductFilter.everything
try {
Expand All @@ -66,9 +66,77 @@ class PackageModelTests: XCTestCase {
toolchainBinDir: toolchainPath.appending(components: "usr", "bin")
)

XCTAssertEqual(try UserToolchain.deriveSwiftCFlags(triple: triple, destination: destination, environment: .process()), [
// Needed when cross‐compiling for Android. 2020‐03‐01
"-sdk", sdkDir.pathString,
])
XCTAssertEqual(
try UserToolchain.deriveSwiftCFlags(triple: triple, destination: destination, environment: .process()),
[
// Needed when cross‐compiling for Android. 2020‐03‐01
"-sdk", sdkDir.pathString,
]
)
}

func testWindowsLibrarianSelection() throws {
// tiny PE binary from: https://archive.is/w01DO
let contents: [UInt8] = [
0x4D, 0x5A, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0x4C, 0x01, 0x01, 0x00,
0x6A, 0x2A, 0x58, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x00, 0x03, 0x01, 0x0B, 0x01, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x68, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02,
]

#if os(Windows)
let suffix = ".exe"
#else
let suffix = ""
#endif

let triple = try Triple("x86_64-unknown-windows-msvc")
let fs = TSCBasic.localFileSystem

try withTemporaryFile { [contents] _ in
try withTemporaryDirectory(removeTreeOnDeinit: true) { [contents] tmp in
let bin = tmp.appending(component: "bin")
try fs.createDirectory(bin)

let lld = bin.appending(component: "lld-link\(suffix)")
try fs.writeFileContents(lld, bytes: ByteString(contents))

let not = bin.appending(component: "not-link\(suffix)")
try fs.writeFileContents(not, bytes: ByteString(contents))

#if !os(Windows)
try fs.chmod(.executable, path: lld, options: [])
try fs.chmod(.executable, path: not, options: [])
#endif

try XCTAssertEqual(
UserToolchain.determineLibrarian(
triple: triple, binDir: bin, useXcrun: false, environment: [:], searchPaths: [],
extraSwiftFlags: ["-Xswiftc", "-use-ld=lld"]
),
lld
)

try XCTAssertEqual(
UserToolchain.determineLibrarian(
triple: triple, binDir: bin, useXcrun: false, environment: [:], searchPaths: [],
extraSwiftFlags: ["-Xswiftc", "-use-ld=not-link\(suffix)"]
),
not
)

try XCTAssertThrowsError(
UserToolchain.determineLibrarian(
triple: triple, binDir: bin, useXcrun: false, environment: [:], searchPaths: [],
extraSwiftFlags: []
)
)
}
}
}
}