Skip to content

Commit 256c95c

Browse files
authored
Driver: allow static executables when using Musl (#1383)
This error diagnostic doesn't make sense when linking on Linux with Musl, which allows fully statically linked executables.
1 parent 07277b7 commit 256c95c

File tree

3 files changed

+50
-4
lines changed

3 files changed

+50
-4
lines changed

Sources/SwiftDriver/Driver/Driver.swift

+5-2
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,9 @@ public struct Driver {
660660

661661
self.lto = Self.ltoKind(&parsedOptions, diagnosticsEngine: diagnosticsEngine)
662662
// Figure out the primary outputs from the driver.
663-
(self.compilerOutputType, self.linkerOutputType) = Self.determinePrimaryOutputs(&parsedOptions, driverKind: driverKind, diagnosticsEngine: diagnosticEngine)
663+
(self.compilerOutputType, self.linkerOutputType) =
664+
Self.determinePrimaryOutputs(&parsedOptions, targetTriple: self.frontendTargetInfo.target.triple,
665+
driverKind: driverKind, diagnosticsEngine: diagnosticEngine)
664666

665667
// Multithreading.
666668
self.numThreads = Self.determineNumThreads(&parsedOptions, compilerMode: compilerMode, diagnosticsEngine: diagnosticEngine)
@@ -1994,6 +1996,7 @@ extension Driver {
19941996
/// Determine the primary compiler and linker output kinds.
19951997
private static func determinePrimaryOutputs(
19961998
_ parsedOptions: inout ParsedOptions,
1999+
targetTriple: Triple,
19972000
driverKind: DriverKind,
19982001
diagnosticsEngine: DiagnosticsEngine
19992002
) -> (FileType?, LinkOutputType?) {
@@ -2005,7 +2008,7 @@ extension Driver {
20052008
if let outputOption = parsedOptions.getLast(in: .modes) {
20062009
switch outputOption.option {
20072010
case .emitExecutable:
2008-
if parsedOptions.contains(.static) {
2011+
if parsedOptions.contains(.static) && !targetTriple.supportsStaticExecutables {
20092012
diagnosticsEngine.emit(.error_static_emit_executable_disallowed)
20102013
}
20112014
linkerOutputType = .executable

Sources/SwiftDriver/Utilities/Triple.swift

+11
Original file line numberDiff line numberDiff line change
@@ -1705,3 +1705,14 @@ fileprivate extension Array {
17051705
}
17061706
}
17071707
}
1708+
1709+
// MARK: - Linker support
1710+
1711+
extension Triple {
1712+
/// Returns `true` if a given triple supports producing fully statically linked executables by providing `-static`
1713+
/// flag to the linker. This implies statically linking platform's libc, and of those that Swift supports currently
1714+
/// only Musl allows that reliably.
1715+
var supportsStaticExecutables: Bool {
1716+
self.environment == .musl
1717+
}
1718+
}

Tests/SwiftDriverTests/SwiftDriverTests.swift

+34-2
Original file line numberDiff line numberDiff line change
@@ -2100,10 +2100,42 @@ final class SwiftDriverTests: XCTestCase {
21002100
XCTAssertFalse(cmd.contains(.flag("-dylib")))
21012101
XCTAssertFalse(cmd.contains(.flag("-shared")))
21022102
}
2103+
2104+
do {
2105+
// executable linking linux static stdlib with musl
2106+
var driver = try Driver(args: commonArgs + [
2107+
"-emit-executable", "-Osize", "-static-stdlib", "-static-executable", "-target", "x86_64-unknown-linux-musl"
2108+
], env: env)
2109+
let plannedJobs = try driver.planBuild()
2110+
2111+
XCTAssertEqual(plannedJobs.count, 4)
2112+
2113+
let autolinkExtractJob = plannedJobs[2]
2114+
XCTAssertEqual(autolinkExtractJob.kind, .autolinkExtract)
2115+
2116+
let autolinkCmd = autolinkExtractJob.commandLine
2117+
XCTAssertTrue(commandContainsTemporaryPath(autolinkCmd, "foo.o"))
2118+
XCTAssertTrue(commandContainsTemporaryPath(autolinkCmd, "bar.o"))
2119+
XCTAssertTrue(commandContainsTemporaryPath(autolinkCmd, "Test.autolink"))
2120+
2121+
let linkJob = plannedJobs[3]
2122+
let cmd = linkJob.commandLine
2123+
XCTAssertTrue(cmd.contains(.flag("-o")))
2124+
XCTAssertTrue(commandContainsTemporaryPath(cmd, "foo.o"))
2125+
XCTAssertTrue(commandContainsTemporaryPath(cmd, "bar.o"))
2126+
XCTAssertTrue(cmd.contains(.flag("--start-group")))
2127+
XCTAssertTrue(cmd.contains(.flag("--end-group")))
2128+
XCTAssertTrue(cmd.contains(.flag("-Os")))
2129+
XCTAssertTrue(cmd.contains(.flag("-static")))
2130+
XCTAssertEqual(linkJob.outputs[0].file, try VirtualPath(path: "Test"))
2131+
2132+
XCTAssertFalse(cmd.contains(.flag("-dylib")))
2133+
XCTAssertFalse(cmd.contains(.flag("-shared")))
2134+
}
21032135
#endif
21042136

21052137
do {
2106-
// static WASM linking
2138+
// static Wasm linking
21072139
var driver = try Driver(args: commonArgs + ["-emit-library", "-static", "-target", "wasm32-unknown-wasi"], env: env)
21082140
let plannedJobs = try driver.planBuild()
21092141

@@ -2135,7 +2167,7 @@ final class SwiftDriverTests: XCTestCase {
21352167
try withTemporaryDirectory { path in
21362168
try localFileSystem.writeFileContents(
21372169
path.appending(components: "wasi", "static-executable-args.lnk")) { $0 <<< "garbage" }
2138-
// WASM executable linking
2170+
// Wasm executable linking
21392171
var driver = try Driver(args: commonArgs + ["-emit-executable", "-Ounchecked",
21402172
"-target", "wasm32-unknown-wasi",
21412173
"-resource-dir", path.pathString,

0 commit comments

Comments
 (0)