From 56a78846c312f505046d061ca4e420a2650f2916 Mon Sep 17 00:00:00 2001 From: Evan Wilde Date: Thu, 15 Feb 2024 13:13:52 -0800 Subject: [PATCH 1/2] Update Generic Unix linker selection Not all generic-"unix" environments have the Gold linker available to them, and in some cases, the vendor of the toolchain may provide their own linker. In these cases, the driver should be internally consistent with the toolchain that it is shipped with. Now that we have the clang-linker, we can lean on the linker selection in the clang-linker to determine a default linker. If the clang-linker, and thus, the swift compiler driver, are part of a specific toolchain, that clang-linker should be built for that platform with the appropriate linker defaults set. If someone overrides the linker with `-use-ld`, we should still honour that, but should otherwise be consistent with the appropriate toolchain linker. Fixes: rdar://123061492 --- .../Jobs/DarwinToolchain+LinkerSupport.swift | 4 +- .../GenericUnixToolchain+LinkerSupport.swift | 55 ++----------------- .../Jobs/WindowsToolchain+LinkerSupport.swift | 4 +- 3 files changed, 8 insertions(+), 55 deletions(-) diff --git a/Sources/SwiftDriver/Jobs/DarwinToolchain+LinkerSupport.swift b/Sources/SwiftDriver/Jobs/DarwinToolchain+LinkerSupport.swift index 52e79f864..929e5fe1a 100644 --- a/Sources/SwiftDriver/Jobs/DarwinToolchain+LinkerSupport.swift +++ b/Sources/SwiftDriver/Jobs/DarwinToolchain+LinkerSupport.swift @@ -176,8 +176,8 @@ extension DarwinToolchain { } } - if let arg = parsedOptions.getLastArgument(.useLd) { - commandLine.appendFlag("-fuse-ld=\(arg.asSingle)") + if let arg = parsedOptions.getLastArgument(.useLd)?.asSingle { + commandLine.appendFlag("-fuse-ld=\(arg)") } if let arg = parsedOptions.getLastArgument(.ldPath)?.asSingle { diff --git a/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift b/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift index d315d6d25..e25bc6f6e 100644 --- a/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift +++ b/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift @@ -16,29 +16,6 @@ import func TSCBasic.lookupExecutablePath import struct TSCBasic.AbsolutePath extension GenericUnixToolchain { - private func defaultLinker(for targetTriple: Triple) -> String? { - if targetTriple.os == .openbsd || targetTriple.os == .freeBSD || - targetTriple.environment == .android || - targetTriple.isFullyStaticLinux { - return "lld" - } - - switch targetTriple.arch { - case .arm, .aarch64, .armeb, .thumb, .thumbeb: - // BFD linker has issues wrt relocation of the protocol conformance - // section on these targets, it also generates COPY relocations for - // final executables, as such, unless specified, we default to gold - // linker. - return "gold" - case .x86, .x86_64, .ppc64, .ppc64le, .systemz: - // BFD linker has issues wrt relocations against protected symbols. - return "gold" - default: - // Otherwise, use the default BFD linker. - return "" - } - } - private func majorArchitectureName(for triple: Triple) -> String { // The concept of a "major" arch name only applies to Linux triples guard triple.os == .linux else { return triple.archName } @@ -71,35 +48,11 @@ extension GenericUnixToolchain { commandLine.appendFlag("-shared") fallthrough case .executable: - // Select the linker to use. - var linker: String? - if let arg = parsedOptions.getLastArgument(.useLd) { - linker = arg.asSingle + // Select the linker to use. + if let arg = parsedOptions.getLastArgument(.useLd)?.asSingle { + commandLine.appendFlag("--fuse-ld=\(arg)") } else if lto != nil { - linker = "lld" - } else { - linker = defaultLinker(for: targetTriple) - } - - if let linker = linker { - #if os(Haiku) - // For now, passing -fuse-ld on Haiku doesn't work as swiftc doesn't - // recognise it. Passing -use-ld= as the argument works fine. - commandLine.appendFlag("-use-ld=\(linker)") - #else - commandLine.appendFlag("-fuse-ld=\(linker)") - #endif - // Starting with lld 13, Swift stopped working with the lld - // --gc-sections implementation for ELF, unless -z nostart-stop-gc is - // also passed to lld: - // - // https://reviews.llvm.org/D96914 - if linker == "lld" || linker.hasSuffix("ld.lld") { - commandLine.appendFlag(.Xlinker) - commandLine.appendFlag("-z") - commandLine.appendFlag(.Xlinker) - commandLine.appendFlag("nostart-stop-gc") - } + commandLine.appendFlag("--fuse-ld=lld") } if let arg = parsedOptions.getLastArgument(.ldPath)?.asSingle { diff --git a/Sources/SwiftDriver/Jobs/WindowsToolchain+LinkerSupport.swift b/Sources/SwiftDriver/Jobs/WindowsToolchain+LinkerSupport.swift index e6e13d02f..c53aada02 100644 --- a/Sources/SwiftDriver/Jobs/WindowsToolchain+LinkerSupport.swift +++ b/Sources/SwiftDriver/Jobs/WindowsToolchain+LinkerSupport.swift @@ -99,8 +99,8 @@ extension WindowsToolchain { } // Select the linker to use. - if let arg = parsedOptions.getLastArgument(.useLd) { - commandLine.appendFlag("-fuse-ld=\(arg.asSingle)") + if let arg = parsedOptions.getLastArgument(.useLd)?.asSingle { + commandLine.appendFlag("-fuse-ld=\(arg)") } else if lto != nil { commandLine.appendFlag("-fuse-ld=lld") } From c11743b6df6a987329c9baf7a4c8d40552da1114 Mon Sep 17 00:00:00 2001 From: Evan Wilde Date: Thu, 15 Feb 2024 20:05:13 -0800 Subject: [PATCH 2/2] Update tests with removed default ld flags --- Tests/SwiftDriverTests/SwiftDriverTests.swift | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/Tests/SwiftDriverTests/SwiftDriverTests.swift b/Tests/SwiftDriverTests/SwiftDriverTests.swift index f3c09affb..d4005901f 100644 --- a/Tests/SwiftDriverTests/SwiftDriverTests.swift +++ b/Tests/SwiftDriverTests/SwiftDriverTests.swift @@ -2368,20 +2368,11 @@ final class SwiftDriverTests: XCTestCase { do { // The Android NDK only uses the lld linker now - var driver = try Driver(args: commonArgs + ["-emit-library", "-target", "aarch64-unknown-linux-android24"], env: env) + var driver = try Driver(args: commonArgs + ["-emit-library", "-target", "aarch64-unknown-linux-android24", "-use-ld=lld"], env: env) let plannedJobs = try driver.planBuild().removingAutolinkExtractJobs() let lastJob = plannedJobs.last! XCTAssertTrue(lastJob.tool.name.contains("clang")) - XCTAssertTrue(lastJob.commandLine.contains(subsequence: [.flag("-fuse-ld=lld"), - .flag("-Xlinker"), .flag("-z"), .flag("-Xlinker"), .flag("nostart-stop-gc")])) - } - - do { - var driver = try Driver(args: commonArgs + ["-emit-library", "-target", "x86_64-unknown-freebsd"], env: env) - let plannedJobs = try driver.planBuild().removingAutolinkExtractJobs() - let lastJob = plannedJobs.last! - XCTAssertTrue(lastJob.tool.name.contains("clang")) - XCTAssertTrue(lastJob.commandLine.contains(.flag("-fuse-ld=lld"))) + XCTAssertTrue(lastJob.commandLine.contains(.flag("--fuse-ld=lld"))) } }