@@ -117,8 +117,9 @@ fileprivate final class TestSwiftParserDelegate: TaskOutputParserDelegate, Senda
117117 }
118118
119119 /// Check the standard library linking options.
120- @Test ( . requireHostOS( . macOS) )
121- func standardLibraryLinking( ) async throws {
120+ @Test (
121+ . requireHostOS( . macOS)
122+ ) func standardLibraryLinkingMacOS( ) async throws {
122123 let core = try await getCore ( )
123124
124125 // Computes the expected standard swift linker arguments.
@@ -129,8 +130,7 @@ fileprivate final class TestSwiftParserDelegate: TaskOutputParserDelegate, Senda
129130 let spec = try core. specRegistry. getSpec ( ofType: SwiftCompilerSpec . self)
130131
131132 let defaultToolchain = try #require( core. toolchainRegistry. defaultToolchain)
132- let swiftcPath = defaultToolchain. path. join ( " usr/bin/swiftc " )
133-
133+ let swiftcPath = defaultToolchain. path. join ( " usr " ) . join ( " bin " ) . join ( core. hostOperatingSystem. imageFormat. executableName ( basename: " swiftc " ) )
134134 // Check basics.
135135 do {
136136 let producer = try MockCommandProducer ( core: core, productTypeIdentifier: " com.apple.product-type.framework " , platform: " macosx " , toolchain: core. toolchainRegistry. defaultToolchain)
@@ -142,10 +142,22 @@ fileprivate final class TestSwiftParserDelegate: TaskOutputParserDelegate, Senda
142142 let scope = MacroEvaluationScope ( table: table)
143143 let delegate = TestTaskPlanningDelegate ( clientDelegate: MockTestTaskPlanningClientDelegate ( ) , fs: localFS)
144144 let optionContext = await spec. discoveredCommandLineToolSpecInfo ( producer, scope, delegate)
145- try await #expect( spec. computeAdditionalLinkerArgs ( producer, scope: scope, lookup: { _ in nil } , inputFileTypes: [ ] , optionContext: optionContext, delegate: CapturingTaskGenerationDelegate ( producer: producer, userPreferences: . defaultForTesting) ) . args == additionalSwiftLinkerArgs ( spec, producer, scope, stdlibPath) )
145+ let actual = try await spec. computeAdditionalLinkerArgs (
146+ producer,
147+ scope: scope,
148+ lookup: { _ in nil } ,
149+ inputFileTypes: [ ] ,
150+ optionContext: optionContext,
151+ delegate: CapturingTaskGenerationDelegate (
152+ producer: producer,
153+ userPreferences: . defaultForTesting,
154+ ) ,
155+ ) . args
156+ let expected = additionalSwiftLinkerArgs ( spec, producer, scope, stdlibPath)
157+ #expect( actual == expected)
146158 }
147159
148- // Check force static stdlib.
160+ // Check force static stdlib on Apple platforms (macOS) .
149161 do {
150162 let producer = try MockCommandProducer ( core: core, productTypeIdentifier: " com.apple.product-type.framework " , platform: " macosx " )
151163 let stdlibPath = swiftcPath. dirname. dirname. join ( " lib/swift_static/fakeos " )
@@ -157,7 +169,20 @@ fileprivate final class TestSwiftParserDelegate: TaskOutputParserDelegate, Senda
157169 let scope = MacroEvaluationScope ( table: table)
158170 let delegate = TestTaskPlanningDelegate ( clientDelegate: MockTestTaskPlanningClientDelegate ( ) , fs: localFS)
159171 let optionContext = await spec. discoveredCommandLineToolSpecInfo ( producer, scope, delegate)
160- try await #expect( spec. computeAdditionalLinkerArgs ( producer, scope: scope, lookup: { _ in nil } , inputFileTypes: [ ] , optionContext: optionContext, delegate: CapturingTaskGenerationDelegate ( producer: producer, userPreferences: . defaultForTesting) ) . args == ( additionalSwiftLinkerArgs ( spec, producer, scope, stdlibPath) ) + [ [ " -Xlinker " , " -force_load_swift_libs " ] , [ " -lc++ " , " -framework " , " Foundation " ] ] )
172+ // On Apple platforms, should use Apple-specific static linking flags
173+ let actual = try await spec. computeAdditionalLinkerArgs (
174+ producer,
175+ scope: scope,
176+ lookup: { _ in nil } ,
177+ inputFileTypes: [ ] ,
178+ optionContext: optionContext,
179+ delegate: CapturingTaskGenerationDelegate (
180+ producer: producer,
181+ userPreferences: . defaultForTesting,
182+ ) ,
183+ ) . args
184+ let expected = ( additionalSwiftLinkerArgs ( spec, producer, scope, stdlibPath) ) + [ [ " -Xlinker " , " -force_load_swift_libs " ] , [ " -lc++ " , " -framework " , " Foundation " ] ]
185+ #expect( actual == expected)
161186 }
162187
163188 // Check tool product type.
@@ -171,7 +196,18 @@ fileprivate final class TestSwiftParserDelegate: TaskOutputParserDelegate, Senda
171196 let scope = MacroEvaluationScope ( table: table)
172197 let delegate = TestTaskPlanningDelegate ( clientDelegate: MockTestTaskPlanningClientDelegate ( ) , fs: localFS)
173198 let optionContext = await spec. discoveredCommandLineToolSpecInfo ( producer, scope, delegate)
174- try await #expect( spec. computeAdditionalLinkerArgs ( producer, scope: scope, lookup: { _ in nil } , inputFileTypes: [ ] , optionContext: optionContext, delegate: CapturingTaskGenerationDelegate ( producer: producer, userPreferences: . defaultForTesting) ) . args == additionalSwiftLinkerArgs ( spec, producer, scope, stdlibPath) )
199+ let actual = try await spec. computeAdditionalLinkerArgs (
200+ producer,
201+ scope: scope, lookup: { _ in nil } ,
202+ inputFileTypes: [ ] ,
203+ optionContext: optionContext,
204+ delegate: CapturingTaskGenerationDelegate (
205+ producer: producer,
206+ userPreferences: . defaultForTesting,
207+ ) ,
208+ ) . args
209+ let expected = additionalSwiftLinkerArgs ( spec, producer, scope, stdlibPath)
210+ #expect( actual == expected)
175211 }
176212
177213 // Check tool product type forced to dynamic link.
@@ -186,7 +222,19 @@ fileprivate final class TestSwiftParserDelegate: TaskOutputParserDelegate, Senda
186222 let scope = MacroEvaluationScope ( table: table)
187223 let delegate = TestTaskPlanningDelegate ( clientDelegate: MockTestTaskPlanningClientDelegate ( ) , fs: localFS)
188224 let optionContext = await spec. discoveredCommandLineToolSpecInfo ( producer, scope, delegate)
189- try await #expect( spec. computeAdditionalLinkerArgs ( producer, scope: scope, lookup: { _ in nil } , inputFileTypes: [ ] , optionContext: optionContext, delegate: CapturingTaskGenerationDelegate ( producer: producer, userPreferences: . defaultForTesting) ) . args == additionalSwiftLinkerArgs ( spec, producer, scope, stdlibPath) )
225+ let actual = try await spec. computeAdditionalLinkerArgs (
226+ producer,
227+ scope: scope,
228+ lookup: { _ in nil } ,
229+ inputFileTypes: [ ] ,
230+ optionContext: optionContext,
231+ delegate: CapturingTaskGenerationDelegate (
232+ producer: producer,
233+ userPreferences: . defaultForTesting,
234+ ) ,
235+ ) . args
236+ let expected = additionalSwiftLinkerArgs ( spec, producer, scope, stdlibPath)
237+ #expect( actual == expected)
190238 }
191239
192240 // Check system stdlib option.
@@ -201,9 +249,119 @@ fileprivate final class TestSwiftParserDelegate: TaskOutputParserDelegate, Senda
201249 let scope = MacroEvaluationScope ( table: table)
202250 let delegate = TestTaskPlanningDelegate ( clientDelegate: MockTestTaskPlanningClientDelegate ( ) , fs: localFS)
203251 let optionContext = await spec. discoveredCommandLineToolSpecInfo ( producer, scope, delegate)
204- try await #expect( spec. computeAdditionalLinkerArgs ( producer, scope: scope, lookup: { _ in nil } , inputFileTypes: [ ] , optionContext: optionContext, delegate: CapturingTaskGenerationDelegate ( producer: producer, userPreferences: . defaultForTesting) ) . args == ( [ [ " -L/usr/lib/swift " ] ] + additionalSwiftLinkerArgs( spec, producer, scope, stdlibPath) ) )
252+ let actual = try await spec. computeAdditionalLinkerArgs (
253+ producer,
254+ scope: scope,
255+ lookup: { _ in nil } ,
256+ inputFileTypes: [ ] ,
257+ optionContext: optionContext,
258+ delegate: CapturingTaskGenerationDelegate (
259+ producer: producer,
260+ userPreferences: . defaultForTesting,
261+ ) ,
262+ ) . args
263+ let expected = ( [ [ " -L/usr/lib/swift " ] ] + additionalSwiftLinkerArgs( spec, producer, scope, stdlibPath) )
264+ #expect( actual == expected)
265+ }
266+ }
267+
268+ @Test (
269+ arguments: LinkerDriverChoice . allCases. filter { $0 != . auto } ,
270+ )
271+ func standardLibraryLinkingAllPlatforms(
272+ linkerDriverUT: LinkerDriverChoice
273+ ) async throws {
274+ try await withKnownIssue ( isIntermittent: true ) {
275+ let core = try await getCore ( )
276+
277+ // Computes the expected standard swift linker arguments.
278+ func additionalSwiftLinkerArgs( _ spec: CompilerSpec , _ producer: any CommandProducer , _ scope: MacroEvaluationScope , _ stdlibPath: Path ) -> [ [ String ] ] {
279+ return localFS. exists ( stdlibPath) ? [ [ " -L \( stdlibPath. str) " ] , [ " -L/usr/lib/swift " ] ] : [ [ " -L/usr/lib/swift " ] ]
280+ }
281+
282+ let spec = try core. specRegistry. getSpec ( ofType: SwiftCompilerSpec . self)
283+
284+ let defaultToolchain = try #require( core. toolchainRegistry. defaultToolchain)
285+ let swiftcPath = defaultToolchain. path. join ( " usr " ) . join ( " bin " ) . join ( core. hostOperatingSystem. imageFormat. executableName ( basename: " swiftc " ) )
286+ // Check force static stdlib on non-Apple platforms (Linux).
287+ do {
288+ let producer = try MockCommandProducer ( core: core, productTypeIdentifier: " com.apple.product-type.framework " , platform: " linux " )
289+ let stdlibPath = swiftcPath. dirname. dirname. join ( " lib/swift_static/linux " )
290+ var table = MacroValueAssignmentTable ( namespace: core. specRegistry. internalMacroNamespace)
291+ table. push ( BuiltinMacros . SWIFT_EXEC, literal: swiftcPath. str)
292+ table. push ( BuiltinMacros . SWIFT_STDLIB, literal: " swiftCore " )
293+ table. push ( BuiltinMacros . PLATFORM_NAME, literal: " linux " )
294+ table. push ( BuiltinMacros . SWIFT_FORCE_STATIC_LINK_STDLIB, literal: true )
295+ table. push ( BuiltinMacros . LINKER_DRIVER, literal: linkerDriverUT)
296+ let scope = MacroEvaluationScope ( table: table)
297+ let delegate = TestTaskPlanningDelegate ( clientDelegate: MockTestTaskPlanningClientDelegate ( ) , fs: localFS)
298+ let optionContext = await spec. discoveredCommandLineToolSpecInfo ( producer, scope, delegate)
299+ // On non-Apple platforms, should use standard static linking flags (no Darwin-specific flags)
300+ let actual = try await spec. computeAdditionalLinkerArgs (
301+ producer,
302+ scope: scope,
303+ lookup: { _ in nil } ,
304+ inputFileTypes: [ ] ,
305+ optionContext: optionContext,
306+ delegate: CapturingTaskGenerationDelegate (
307+ producer: producer,
308+ userPreferences: . defaultForTesting,
309+ ) ,
310+ ) . args
311+ let expectedAdditionalArgs : [ [ String ] ] = switch linkerDriverUT {
312+ case . swiftc: [ [ " -static-stdlib " ] ]
313+ case . auto, . clang, . qcc: [ ]
314+ }
315+ let expected = additionalSwiftLinkerArgs ( spec, producer, scope, stdlibPath) + expectedAdditionalArgs
316+ #expect( actual == expected)
317+ }
318+
319+ } when: {
320+ linkerDriverUT == . qcc // qcc support is very rough
321+ }
322+ }
323+
324+ #if false
325+ // We should get this test working, though I was encountering compilation errors.
326+ @Test
327+ func standardLibraryLinkingUsingAutoLinkderDriverFails( ) async throws {
328+ try await #require(
329+ processExitsWith: . failure,
330+ ) {
331+ let linkerDriverUT = LinkerDriverChoice . auto
332+ let core = try await getCore ( )
333+
334+ let spec = try core. specRegistry. getSpec ( ofType: SwiftCompilerSpec . self)
335+
336+ // let defaultToolchain = try #require(core.toolchainRegistry.defaultToolchain)
337+ // let swiftcPath = defaultToolchain.path.join("usr").join("bin").join(core.hostOperatingSystem.imageFormat.executableName(basename: "swiftc"))
338+ // Check force static stdlib on non-Apple platforms (Linux).
339+ let producer = try MockCommandProducer ( core: core, productTypeIdentifier: " com.apple.product-type.framework " , platform: " linux " )
340+ // let stdlibPath = swiftcPath.dirname.dirname.join("lib/swift_static/linux")
341+ var table = MacroValueAssignmentTable ( namespace: core. specRegistry. internalMacroNamespace)
342+ // table.push(BuiltinMacros.SWIFT_EXEC, literal: swiftcPath.str)
343+ // table.push(BuiltinMacros.SWIFT_STDLIB, literal: "swiftCore")
344+ table. push ( BuiltinMacros . PLATFORM_NAME, literal: " linux " )
345+ table. push ( BuiltinMacros . SWIFT_FORCE_STATIC_LINK_STDLIB, literal: true )
346+ table. push ( BuiltinMacros . LINKER_DRIVER, literal: linkerDriverUT)
347+ let scope = MacroEvaluationScope ( table: table)
348+ let delegate = TestTaskPlanningDelegate ( clientDelegate: MockTestTaskPlanningClientDelegate ( ) , fs: localFS)
349+ let optionContext = await spec. discoveredCommandLineToolSpecInfo ( producer, scope, delegate)
350+ // On non-Apple platforms, should use standard static linking flags (no Darwin-specific flags)
351+ let _ = try await spec. computeAdditionalLinkerArgs (
352+ producer,
353+ scope: scope,
354+ lookup: { _ in nil } ,
355+ inputFileTypes: [ ] ,
356+ optionContext: optionContext,
357+ delegate: CapturingTaskGenerationDelegate (
358+ producer: producer,
359+ userPreferences: . defaultForTesting,
360+ ) ,
361+ )
205362 }
206363 }
364+ #endif
207365}
208366
209367@Suite fileprivate struct SwiftCompilerOutputParserTests : CoreBasedTests {
0 commit comments