Skip to content

Commit ede5b78

Browse files
committed
Introduce a new linux-musl platform and avoid linking relocatable objects when we target it
1 parent f2b080c commit ede5b78

4 files changed

Lines changed: 168 additions & 3 deletions

File tree

Sources/SWBGenericUnixPlatform/Plugin.swift

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ struct GenericUnixPlatformSpecsExtension: SpecificationsExtension {
8989
func specificationDomains() -> [String: [String]] {
9090
[
9191
"linux": ["generic-unix"],
92+
"linux-musl": ["linux"],
9293
"freebsd": ["generic-unix"],
9394
"openbsd": ["generic-unix"],
9495
]
@@ -97,7 +98,7 @@ struct GenericUnixPlatformSpecsExtension: SpecificationsExtension {
9798

9899
struct GenericUnixPlatformInfoExtension: PlatformInfoExtension {
99100
func additionalPlatforms(context: any PlatformInfoExtensionAdditionalPlatformsContext) throws -> [(path: Path, data: [String: PropertyListItem])] {
100-
return try OperatingSystem.createFallbackSystemToolchains.compactMap { operatingSystem in
101+
var platforms: [(path: Path, data: [String: PropertyListItem])] = try OperatingSystem.createFallbackSystemToolchains.compactMap { operatingSystem in
101102
// Only create platforms if the host OS allows a fallback toolchain, or we're cross compiling.
102103
guard operatingSystem.createFallbackSystemToolchain || operatingSystem != context.hostOperatingSystem else {
103104
return nil
@@ -112,14 +113,28 @@ struct GenericUnixPlatformInfoExtension: PlatformInfoExtension {
112113
"IsDeploymentPlatform": .plString("YES"),
113114
])
114115
}
116+
platforms.append(
117+
(.root, [
118+
"Type": .plString("Platform"),
119+
"Name": .plString("linux-musl"),
120+
"Identifier": .plString("linux-musl"),
121+
"Description": .plString("linux-musl"),
122+
"FamilyName": .plString("Static Linux"),
123+
"FamilyIdentifier": .plString("linux-musl"),
124+
"IsDeploymentPlatform": .plString("YES"),
125+
])
126+
)
127+
return platforms
115128
}
116129

117130
func platformName(triple: LLVMTriple) -> String? {
118131
switch triple.system {
119-
case "linux" where triple.environment?.hasPrefix("gnu") == true || triple.environment == "musl",
132+
case "linux" where triple.environment?.hasPrefix("gnu") == true,
120133
"freebsd",
121134
"openbsd":
122135
return triple.system
136+
case "linux" where triple.environment == "musl":
137+
return "linux-musl"
123138
default:
124139
return nil
125140
}

Sources/SWBGenericUnixPlatform/Specs/Unix.xcspec

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,5 +92,19 @@
9292
Extensions = (so);
9393
IsLibrary = YES;
9494
IsDynamicLibrary = YES;
95-
}
95+
},
96+
97+
{
98+
Domain = linux-musl;
99+
Type = ProductType;
100+
Identifier = org.swift.product-type.common.object;
101+
BasedOn = org.swift.product-type.library.object;
102+
},
103+
104+
{
105+
Domain = linux-musl;
106+
Type = ProductType;
107+
Identifier = org.swift.product-type.library.static;
108+
BasedOn = org.swift.product-type.library.object;
109+
},
96110
)

Sources/SWBTestSupport/TestWorkspaces.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,7 @@ package final class TestStandardTarget: TestInternalTarget, Sendable {
926926
case staticFramework
927927
case staticLibrary
928928
case objectFile
929+
case commonObject
929930
case objectLibrary
930931
case dynamicLibrary
931932
case bundle
@@ -969,6 +970,8 @@ package final class TestStandardTarget: TestInternalTarget, Sendable {
969970
return "com.apple.product-type.library.static"
970971
case .objectFile:
971972
return "com.apple.product-type.objfile"
973+
case .commonObject:
974+
return "org.swift.product-type.common.object"
972975
case .objectLibrary:
973976
return "org.swift.product-type.library.object"
974977
case .dynamicLibrary:
@@ -1040,6 +1043,8 @@ package final class TestStandardTarget: TestInternalTarget, Sendable {
10401043
return "lib\(name).a"
10411044
case .objectFile:
10421045
return "\(name).o"
1046+
case .commonObject:
1047+
return "$(EXECUTABLE_NAME)"
10431048
case .objectLibrary:
10441049
return "\(name).objlib"
10451050
case .dynamicLibrary:

Tests/StaticLinuxSDKIntegrationTests/StaticLinuxSDKIntegrationTests.swift

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,135 @@ fileprivate struct StaticLinuxSDKIntegrationTests: CoreBasedTests {
104104
}
105105
}
106106
}
107+
108+
// Regression test for https://github.com/swiftlang/swift-package-manager/issues/10237
109+
@Test(.requireSDKs(.host), .requiresStaticLinuxSwiftSDK, .skipXcodeToolchain)
110+
func cxxabiStaticLinking() async throws {
111+
try await withTemporaryDirectory { (tmpDir: Path) in
112+
let testProject = try await TestProject(
113+
"TestProject",
114+
sourceRoot: tmpDir,
115+
groupTree: TestGroup(
116+
"SomeFiles",
117+
children: [
118+
TestFile("main.swift"),
119+
TestFile("bridging.h"),
120+
TestFile("cxx1.cpp"),
121+
TestFile("cxx2.cpp"),
122+
]),
123+
buildConfigurations: [
124+
TestBuildConfiguration("Debug", buildSettings: [
125+
"PRODUCT_NAME": "$(TARGET_NAME)",
126+
"SDKROOT": "auto",
127+
"SUPPORTED_PLATFORMS": "$(AVAILABLE_PLATFORMS)",
128+
"SWIFT_VERSION": swiftVersion,
129+
"LINKER_DRIVER": "auto",
130+
])
131+
],
132+
targets: [
133+
TestStandardTarget(
134+
"tool",
135+
type: .commandLineTool,
136+
buildConfigurations: [
137+
TestBuildConfiguration("Debug", buildSettings: [
138+
"SWIFT_OBJC_BRIDGING_HEADER": "$(SRCROOT)/bridging.h",
139+
])
140+
],
141+
buildPhases: [
142+
TestSourcesBuildPhase(["main.swift"]),
143+
TestFrameworksBuildPhase([
144+
TestBuildFile(.target("cxx1")),
145+
TestBuildFile(.target("cxx2")),
146+
])
147+
],
148+
dependencies: [
149+
"cxx1",
150+
"cxx2",
151+
]
152+
),
153+
TestStandardTarget(
154+
"cxx1",
155+
type: .commonObject,
156+
buildConfigurations: [
157+
TestBuildConfiguration("Debug")
158+
],
159+
buildPhases: [
160+
TestSourcesBuildPhase(["cxx1.cpp"]),
161+
]
162+
),
163+
TestStandardTarget(
164+
"cxx2",
165+
type: .commonObject,
166+
buildConfigurations: [
167+
TestBuildConfiguration("Debug")
168+
],
169+
buildPhases: [
170+
TestSourcesBuildPhase(["cxx2.cpp"]),
171+
]
172+
),
173+
])
174+
175+
let core = try await Self.getSwiftSDKIntegrationTestingCore()
176+
let tester = try await BuildOperationTester(core, testProject, simulated: false)
177+
178+
let projectDir = tester.workspace.projects[0].sourceRoot
179+
180+
try await tester.fs.writeFileContents(projectDir.join("main.swift")) { stream in
181+
stream <<< """
182+
#if canImport(Musl)
183+
print("Hello from Static Linux! \\(cxx1() + cxx2())")
184+
#else
185+
#error("should not be active")
186+
#endif
187+
"""
188+
}
189+
190+
try await tester.fs.writeFileContents(projectDir.join("bridging.h")) { stream in
191+
stream <<< """
192+
int cxx1(void);
193+
int cxx2(void);
194+
"""
195+
}
196+
197+
try await tester.fs.writeFileContents(projectDir.join("cxx1.cpp")) { stream in
198+
stream <<< """
199+
extern "C" int cxx1() {
200+
try {
201+
throw 1;
202+
} catch (...) {
203+
return 1;
204+
}
205+
return 0;
206+
}
207+
"""
208+
}
209+
210+
try await tester.fs.writeFileContents(projectDir.join("cxx2.cpp")) { stream in
211+
stream <<< """
212+
extern "C" int cxx2() {
213+
try {
214+
throw 2;
215+
} catch (...) {
216+
return 2;
217+
}
218+
return 0;
219+
}
220+
"""
221+
}
222+
223+
let hostArch = try {
224+
let arch = try #require(Architecture.hostStringValue)
225+
if arch == "arm64" {
226+
return "aarch64"
227+
}
228+
return arch
229+
}()
230+
let triple = "\(hostArch)-swift-linux-musl"
231+
let swiftSDK = try #require(await core.findStaticLinuxSwiftSDK())
232+
let destination = try RunDestinationInfo(sdkManifestPath: swiftSDK.manifestPath, triple: triple, targetArchitecture: hostArch, supportedArchitectures: [hostArch], disableOnlyActiveArch: false, core: core)
233+
try await tester.checkBuild(runDestination: destination) { results in
234+
results.checkNoErrors()
235+
}
236+
}
237+
}
107238
}

0 commit comments

Comments
 (0)