Skip to content

Commit 901e1e8

Browse files
authored
Merge pull request #555 from drexin/wip-static-linking
Use library search group when linking statically
2 parents 8450cfc + 10675b8 commit 901e1e8

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,14 @@ extension GenericUnixToolchain {
152152
)
153153
commandLine.appendPath(swiftrtPath)
154154

155+
// If we are linking statically, we need to add all
156+
// dependencies to a library search group to resolve
157+
// potential circular dependencies
158+
if staticStdlib || staticExecutable {
159+
commandLine.appendFlag(.Xlinker)
160+
commandLine.appendFlag("--start-group")
161+
}
162+
155163
let inputFiles: [Job.ArgTemplate] = inputs.compactMap { input in
156164
// Autolink inputs are handled specially
157165
if input.type == .autolink {
@@ -166,6 +174,11 @@ extension GenericUnixToolchain {
166174
}
167175
commandLine.append(contentsOf: inputFiles)
168176

177+
if staticStdlib || staticExecutable {
178+
commandLine.appendFlag(.Xlinker)
179+
commandLine.appendFlag("--end-group")
180+
}
181+
169182
let fSystemArgs = parsedOptions.arguments(for: .F, .Fsystem)
170183
for opt in fSystemArgs {
171184
if opt.option == .Fsystem {

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,8 +1289,43 @@ final class SwiftDriverTests: XCTestCase {
12891289
XCTAssertFalse(cmd.contains(.flag("-dylib")))
12901290
XCTAssertFalse(cmd.contains(.flag("-static")))
12911291
XCTAssertFalse(cmd.contains(.flag("-shared")))
1292+
XCTAssertFalse(cmd.contains(.flag("--start-group")))
1293+
XCTAssertFalse(cmd.contains(.flag("--end-group")))
12921294
}
12931295

1296+
// /usr/lib/swift_static/linux/static-stdlib-args.lnk is required for static
1297+
// linking on Linux, but is not present in macOS toolchains
1298+
#if os(Linux)
1299+
do {
1300+
// executable linking linux static stdlib
1301+
var driver = try Driver(args: commonArgs + ["-emit-executable", "-static-stdlib", "-target", "x86_64-unknown-linux"], env: env)
1302+
let plannedJobs = try driver.planBuild()
1303+
1304+
XCTAssertEqual(plannedJobs.count, 4)
1305+
1306+
let autolinkExtractJob = plannedJobs[2]
1307+
XCTAssertEqual(autolinkExtractJob.kind, .autolinkExtract)
1308+
1309+
let autolinkCmd = autolinkExtractJob.commandLine
1310+
XCTAssertTrue(autolinkCmd.contains(.path(.temporary(RelativePath("foo.o")))))
1311+
XCTAssertTrue(autolinkCmd.contains(.path(.temporary(RelativePath("bar.o")))))
1312+
XCTAssertTrue(autolinkCmd.contains(.path(.temporary(RelativePath("Test.autolink")))))
1313+
1314+
let linkJob = plannedJobs[3]
1315+
let cmd = linkJob.commandLine
1316+
XCTAssertTrue(cmd.contains(.flag("-o")))
1317+
XCTAssertTrue(cmd.contains(.path(.temporary(RelativePath("foo.o")))))
1318+
XCTAssertTrue(cmd.contains(.path(.temporary(RelativePath("bar.o")))))
1319+
XCTAssertTrue(cmd.contains(.flag("--start-group")))
1320+
XCTAssertTrue(cmd.contains(.flag("--end-group")))
1321+
XCTAssertEqual(linkJob.outputs[0].file, try VirtualPath(path: "Test"))
1322+
1323+
XCTAssertFalse(cmd.contains(.flag("-static")))
1324+
XCTAssertFalse(cmd.contains(.flag("-dylib")))
1325+
XCTAssertFalse(cmd.contains(.flag("-shared")))
1326+
}
1327+
#endif
1328+
12941329
do {
12951330
// static WASM linking
12961331
var driver = try Driver(args: commonArgs + ["-emit-library", "-static", "-target", "wasm32-unknown-wasi"], env: env)

0 commit comments

Comments
 (0)