@@ -16,6 +16,29 @@ import func TSCBasic.lookupExecutablePath
1616import struct TSCBasic. AbsolutePath
1717
1818extension GenericUnixToolchain {
19+ private func defaultLinker( for targetTriple: Triple ) -> String ? {
20+ if targetTriple. os == . openbsd || targetTriple. os == . freeBSD ||
21+ targetTriple. environment == . android ||
22+ targetTriple. isFullyStaticLinux {
23+ return " lld "
24+ }
25+
26+ switch targetTriple. arch {
27+ case . arm, . aarch64, . armeb, . thumb, . thumbeb:
28+ // BFD linker has issues wrt relocation of the protocol conformance
29+ // section on these targets, it also generates COPY relocations for
30+ // final executables, as such, unless specified, we default to gold
31+ // linker.
32+ return " gold "
33+ case . x86, . x86_64, . ppc64, . ppc64le, . systemz:
34+ // BFD linker has issues wrt relocations against protected symbols.
35+ return " gold "
36+ default :
37+ // Otherwise, use the default BFD linker.
38+ return " "
39+ }
40+ }
41+
1942 private func majorArchitectureName( for triple: Triple ) -> String {
2043 // The concept of a "major" arch name only applies to Linux triples
2144 guard triple. os == . linux else { return triple. archName }
@@ -48,11 +71,35 @@ extension GenericUnixToolchain {
4871 commandLine. appendFlag ( " -shared " )
4972 fallthrough
5073 case . executable:
51- // Select the linker to use.
52- if let arg = parsedOptions. getLastArgument ( . useLd) ? . asSingle {
53- commandLine. appendFlag ( " --fuse-ld= \( arg) " )
74+ // Select the linker to use.
75+ var linker : String ?
76+ if let arg = parsedOptions. getLastArgument ( . useLd) {
77+ linker = arg. asSingle
5478 } else if lto != nil {
55- commandLine. appendFlag ( " --fuse-ld=lld " )
79+ linker = " lld "
80+ } else {
81+ linker = defaultLinker ( for: targetTriple)
82+ }
83+
84+ if let linker = linker {
85+ #if os(Haiku)
86+ // For now, passing -fuse-ld on Haiku doesn't work as swiftc doesn't
87+ // recognise it. Passing -use-ld= as the argument works fine.
88+ commandLine. appendFlag ( " -use-ld= \( linker) " )
89+ #else
90+ commandLine. appendFlag ( " -fuse-ld= \( linker) " )
91+ #endif
92+ // Starting with lld 13, Swift stopped working with the lld
93+ // --gc-sections implementation for ELF, unless -z nostart-stop-gc is
94+ // also passed to lld:
95+ //
96+ // https://reviews.llvm.org/D96914
97+ if linker == " lld " || linker. hasSuffix ( " ld.lld " ) {
98+ commandLine. appendFlag ( . Xlinker)
99+ commandLine. appendFlag ( " -z " )
100+ commandLine. appendFlag ( . Xlinker)
101+ commandLine. appendFlag ( " nostart-stop-gc " )
102+ }
56103 }
57104
58105 if let arg = parsedOptions. getLastArgument ( . ldPath) ? . asSingle {
0 commit comments