@@ -202,127 +202,52 @@ extension DarwinToolchain {
202202 switch linkerOutputType {
203203 case . dynamicLibrary:
204204 // Same as an executable, but with the -dylib flag
205+ linkerTool = . dynamicLinker
205206 commandLine. appendFlag ( " -dylib " )
206- fallthrough
207+ addLinkInputs ( shouldUseInputFileList: shouldUseInputFileList,
208+ commandLine: & commandLine,
209+ inputs: inputs,
210+ linkerOutputType: linkerOutputType)
211+ try addDynamicLinkerFlags ( targetInfo: targetInfo,
212+ parsedOptions: & parsedOptions,
213+ commandLine: & commandLine,
214+ sanitizers: sanitizers,
215+ linkerOutputType: linkerOutputType,
216+ lto: lto)
217+
207218 case . executable:
208219 linkerTool = . dynamicLinker
209-
210- // FIXME: If we used Clang as a linker instead of going straight to ld,
211- // we wouldn't have to replicate a bunch of Clang's logic here.
212-
213- // Always link the regular compiler_rt if it's present. Note that the
214- // regular libclang_rt.a uses a fat binary for device and simulator; this is
215- // not true for all compiler_rt build products.
216- //
217- // Note: Normally we'd just add this unconditionally, but it's valid to build
218- // Swift and use it as a linker without building compiler_rt.
219- let targetTriple = targetInfo. target. triple
220- let darwinPlatformSuffix =
221- targetTriple. darwinPlatform!. with ( . device) !. libraryNameSuffix
222- let compilerRTPath =
223- try clangLibraryPath (
224- for: targetInfo,
225- parsedOptions: & parsedOptions)
226- . appending ( component: " libclang_rt. \( darwinPlatformSuffix) .a " )
227- if try fileSystem. exists ( compilerRTPath) {
228- commandLine. append ( . path( compilerRTPath) )
229- }
230-
231- let fSystemArgs = parsedOptions. arguments ( for: . F, . Fsystem)
232- for opt in fSystemArgs {
233- commandLine. appendFlag ( . F)
234- commandLine. appendPath ( try VirtualPath ( path: opt. argument. asSingle) )
235- }
236-
237- // Linking sanitizers will add rpaths, which might negatively interact when
238- // other rpaths are involved, so we should make sure we add the rpaths after
239- // all user-specified rpaths.
240- for sanitizer in sanitizers {
241- if sanitizer == . fuzzer {
242- guard linkerOutputType == . executable else { continue }
243- }
244- try addLinkSanitizerLibArgsForDarwin (
245- to: & commandLine,
246- parsedOptions: & parsedOptions,
247- targetInfo: targetInfo,
248- sanitizer: sanitizer,
249- isShared: sanitizer != . fuzzer
250- )
251- }
252-
253- commandLine. appendFlag ( " -arch " )
254- commandLine. appendFlag ( targetTriple. archName)
255-
256- try addArgsToLinkStdlib (
257- to: & commandLine,
258- parsedOptions: & parsedOptions,
259- targetInfo: targetInfo,
260- linkerOutputType: linkerOutputType,
261- fileSystem: fileSystem
262- )
263-
264- try addArgsToLinkARCLite (
265- to: & commandLine,
266- parsedOptions: & parsedOptions,
267- targetTriple: targetTriple
268- )
269-
270- if lto != nil {
271- try addLTOLibArgs ( to: & commandLine)
272- }
273-
274- let targetVariantTriple = targetInfo. targetVariant? . triple
275- addDeploymentTargetArgs (
276- to: & commandLine,
277- targetTriple: targetTriple,
278- targetVariantTriple: targetVariantTriple,
279- sdkPath: targetInfo. sdkPath? . path
280- )
281-
282- try addProfileGenerationArgs (
283- to: & commandLine,
284- parsedOptions: & parsedOptions,
285- targetInfo: targetInfo
286- )
287-
288- commandLine. appendFlags (
289- " -lobjc " ,
290- " -lSystem " ,
291- " -no_objc_category_merging "
292- )
293-
294- // Add the SDK path
295- if let sdkPath = targetInfo. sdkPath? . path {
296- commandLine. appendFlag ( " -syslibroot " )
297- commandLine. appendPath ( sdkPath)
298- }
299-
300- if parsedOptions. contains ( . embedBitcode) ||
301- parsedOptions. contains ( . embedBitcodeMarker) {
302- commandLine. appendFlag ( " -bitcode_bundle " )
303- }
304-
305- if parsedOptions. contains ( . enableAppExtension) {
306- commandLine. appendFlag ( " -application_extension " )
307- }
308-
309- // On Darwin, we only support libc++.
310- if parsedOptions. contains ( . enableExperimentalCxxInterop) {
311- commandLine. appendFlag ( " -lc++ " )
312- }
313-
314- // These custom arguments should be right before the object file at the
315- // end.
316- try commandLine. append (
317- contentsOf: parsedOptions. arguments ( in: . linkerOption)
318- )
319- try commandLine. appendAllArguments ( . Xlinker, from: & parsedOptions)
220+ addLinkInputs ( shouldUseInputFileList: shouldUseInputFileList,
221+ commandLine: & commandLine,
222+ inputs: inputs,
223+ linkerOutputType: linkerOutputType)
224+ try addDynamicLinkerFlags ( targetInfo: targetInfo,
225+ parsedOptions: & parsedOptions,
226+ commandLine: & commandLine,
227+ sanitizers: sanitizers,
228+ linkerOutputType: linkerOutputType,
229+ lto: lto)
320230
321231 case . staticLibrary:
322232 linkerTool = . staticLinker( lto)
323233 commandLine. appendFlag ( . static)
234+ addLinkInputs ( shouldUseInputFileList: shouldUseInputFileList,
235+ commandLine: & commandLine,
236+ inputs: inputs,
237+ linkerOutputType: linkerOutputType)
324238 }
325239
240+ // Add the output
241+ commandLine. appendFlag ( " -o " )
242+ commandLine. appendPath ( outputFile)
243+
244+ return try getToolPath ( linkerTool)
245+ }
246+
247+ private func addLinkInputs( shouldUseInputFileList: Bool ,
248+ commandLine: inout [ Job . ArgTemplate ] ,
249+ inputs: [ TypedVirtualPath ] ,
250+ linkerOutputType: LinkOutputType ) {
326251 // inputs LinkFileList
327252 if shouldUseInputFileList {
328253 commandLine. appendFlag ( . filelist)
@@ -363,12 +288,125 @@ extension DarwinToolchain {
363288 }
364289 } )
365290 }
291+ }
366292
367- // Add the output
368- commandLine. appendFlag ( " -o " )
369- commandLine. appendPath ( outputFile)
293+ private func addDynamicLinkerFlags( targetInfo: FrontendTargetInfo ,
294+ parsedOptions: inout ParsedOptions ,
295+ commandLine: inout [ Job . ArgTemplate ] ,
296+ sanitizers: Set < Sanitizer > ,
297+ linkerOutputType: LinkOutputType ,
298+ lto: LTOKind ? ) throws {
299+ // FIXME: If we used Clang as a linker instead of going straight to ld,
300+ // we wouldn't have to replicate a bunch of Clang's logic here.
301+
302+ // Always link the regular compiler_rt if it's present. Note that the
303+ // regular libclang_rt.a uses a fat binary for device and simulator; this is
304+ // not true for all compiler_rt build products.
305+ //
306+ // Note: Normally we'd just add this unconditionally, but it's valid to build
307+ // Swift and use it as a linker without building compiler_rt.
308+ let targetTriple = targetInfo. target. triple
309+ let darwinPlatformSuffix =
310+ targetTriple. darwinPlatform!. with ( . device) !. libraryNameSuffix
311+ let compilerRTPath =
312+ try clangLibraryPath (
313+ for: targetInfo,
314+ parsedOptions: & parsedOptions)
315+ . appending ( component: " libclang_rt. \( darwinPlatformSuffix) .a " )
316+ if try fileSystem. exists ( compilerRTPath) {
317+ commandLine. append ( . path( compilerRTPath) )
318+ }
370319
371- return try getToolPath ( linkerTool)
320+ try addArgsToLinkARCLite (
321+ to: & commandLine,
322+ parsedOptions: & parsedOptions,
323+ targetTriple: targetTriple
324+ )
325+
326+ if lto != nil {
327+ try addLTOLibArgs ( to: & commandLine)
328+ }
329+
330+ let fSystemArgs = parsedOptions. arguments ( for: . F, . Fsystem)
331+ for opt in fSystemArgs {
332+ commandLine. appendFlag ( . F)
333+ commandLine. appendPath ( try VirtualPath ( path: opt. argument. asSingle) )
334+ }
335+
336+ if parsedOptions. contains ( . enableAppExtension) {
337+ commandLine. appendFlag ( " -application_extension " )
338+ }
339+
340+ // Linking sanitizers will add rpaths, which might negatively interact when
341+ // other rpaths are involved, so we should make sure we add the rpaths after
342+ // all user-specified rpaths.
343+ for sanitizer in sanitizers {
344+ if sanitizer == . fuzzer {
345+ guard linkerOutputType == . executable else { continue }
346+ }
347+ try addLinkSanitizerLibArgsForDarwin (
348+ to: & commandLine,
349+ parsedOptions: & parsedOptions,
350+ targetInfo: targetInfo,
351+ sanitizer: sanitizer,
352+ isShared: sanitizer != . fuzzer
353+ )
354+ }
355+
356+ if parsedOptions. contains ( . embedBitcode) ||
357+ parsedOptions. contains ( . embedBitcodeMarker) {
358+ commandLine. appendFlag ( " -bitcode_bundle " )
359+ }
360+
361+ // Add the SDK path
362+ if let sdkPath = targetInfo. sdkPath? . path {
363+ commandLine. appendFlag ( " -syslibroot " )
364+ commandLine. appendPath ( sdkPath)
365+ }
366+
367+ commandLine. appendFlags (
368+ " -lobjc " ,
369+ " -lSystem "
370+ )
371+
372+ commandLine. appendFlag ( " -arch " )
373+ commandLine. appendFlag ( targetTriple. archName)
374+
375+ // On Darwin, we only support libc++.
376+ if parsedOptions. contains ( . enableExperimentalCxxInterop) {
377+ commandLine. appendFlag ( " -lc++ " )
378+ }
379+
380+ try addArgsToLinkStdlib (
381+ to: & commandLine,
382+ parsedOptions: & parsedOptions,
383+ targetInfo: targetInfo,
384+ linkerOutputType: linkerOutputType,
385+ fileSystem: fileSystem
386+ )
387+
388+ try addProfileGenerationArgs (
389+ to: & commandLine,
390+ parsedOptions: & parsedOptions,
391+ targetInfo: targetInfo
392+ )
393+
394+ let targetVariantTriple = targetInfo. targetVariant? . triple
395+ addDeploymentTargetArgs (
396+ to: & commandLine,
397+ targetTriple: targetTriple,
398+ targetVariantTriple: targetVariantTriple,
399+ sdkPath: targetInfo. sdkPath? . path
400+ )
401+
402+ commandLine. appendFlag ( " -no_objc_category_merging " )
403+
404+ // These custom arguments should be right before the object file at the
405+ // end.
406+ try commandLine. append (
407+ contentsOf: parsedOptions. arguments ( in: . linkerOption)
408+ )
409+ try commandLine. appendAllArguments ( . Xlinker, from: & parsedOptions)
372410 }
373411}
374412
0 commit comments