@@ -195,6 +195,14 @@ pub trait Linker {
195
195
fn add_no_exec ( & mut self ) { }
196
196
fn add_as_needed ( & mut self ) { }
197
197
fn reset_per_library_state ( & mut self ) { }
198
+ fn linker_arg ( & mut self , arg : & OsStr , verbatim : bool ) {
199
+ self . linker_args ( & [ arg] , verbatim) ;
200
+ }
201
+ fn linker_args ( & mut self , args : & [ & OsStr ] , _verbatim : bool ) {
202
+ args. into_iter ( ) . for_each ( |a| {
203
+ self . cmd ( ) . arg ( a) ;
204
+ } ) ;
205
+ }
198
206
}
199
207
200
208
impl dyn Linker + ' _ {
@@ -222,38 +230,12 @@ pub struct GccLinker<'a> {
222
230
}
223
231
224
232
impl < ' a > GccLinker < ' a > {
225
- /// Passes an argument directly to the linker.
226
- ///
227
- /// When the linker is not ld-like such as when using a compiler as a linker, the argument is
228
- /// prepended by `-Wl,`.
229
- fn linker_arg ( & mut self , arg : impl AsRef < OsStr > ) -> & mut Self {
230
- self . linker_args ( & [ arg] ) ;
231
- self
233
+ fn linker_arg_ ( & mut self , arg : impl AsRef < OsStr > ) {
234
+ self . linker_arg ( arg. as_ref ( ) , false ) ;
232
235
}
233
-
234
- /// Passes a series of arguments directly to the linker.
235
- ///
236
- /// When the linker is ld-like, the arguments are simply appended to the command. When the
237
- /// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by
238
- /// commas to form an argument that is then prepended with `-Wl`. In this situation, only a
239
- /// single argument is appended to the command to ensure that the order of the arguments is
240
- /// preserved by the compiler.
241
- fn linker_args ( & mut self , args : & [ impl AsRef < OsStr > ] ) -> & mut Self {
242
- if self . is_ld {
243
- args. into_iter ( ) . for_each ( |a| {
244
- self . cmd . arg ( a) ;
245
- } ) ;
246
- } else {
247
- if !args. is_empty ( ) {
248
- let mut s = OsString :: from ( "-Wl" ) ;
249
- for a in args {
250
- s. push ( "," ) ;
251
- s. push ( a) ;
252
- }
253
- self . cmd . arg ( s) ;
254
- }
255
- }
256
- self
236
+ fn linker_args_ ( & mut self , args : & [ impl AsRef < OsStr > ] ) {
237
+ let args_vec: Vec < & OsStr > = args. iter ( ) . map ( |x| x. as_ref ( ) ) . collect ( ) ;
238
+ self . linker_args ( & args_vec, false ) ;
257
239
}
258
240
259
241
fn takes_hints ( & self ) -> bool {
@@ -277,7 +259,7 @@ impl<'a> GccLinker<'a> {
277
259
return ;
278
260
}
279
261
if self . hinted_static != Some ( true ) {
280
- self . linker_arg ( "-Bstatic" ) ;
262
+ self . linker_arg_ ( "-Bstatic" ) ;
281
263
self . hinted_static = Some ( true ) ;
282
264
}
283
265
}
@@ -287,7 +269,7 @@ impl<'a> GccLinker<'a> {
287
269
return ;
288
270
}
289
271
if self . hinted_static != Some ( false ) {
290
- self . linker_arg ( "-Bdynamic" ) ;
272
+ self . linker_arg_ ( "-Bdynamic" ) ;
291
273
self . hinted_static = Some ( false ) ;
292
274
}
293
275
}
@@ -296,7 +278,7 @@ impl<'a> GccLinker<'a> {
296
278
if let Some ( plugin_path) = plugin_path {
297
279
let mut arg = OsString :: from ( "-plugin=" ) ;
298
280
arg. push ( plugin_path) ;
299
- self . linker_arg ( & arg) ;
281
+ self . linker_arg_ ( & arg) ;
300
282
}
301
283
302
284
let opt_level = match self . sess . opts . optimize {
@@ -307,9 +289,9 @@ impl<'a> GccLinker<'a> {
307
289
} ;
308
290
309
291
if let Some ( path) = & self . sess . opts . unstable_opts . profile_sample_use {
310
- self . linker_arg ( & format ! ( "-plugin-opt=sample-profile={}" , path. display( ) ) ) ;
292
+ self . linker_arg_ ( & format ! ( "-plugin-opt=sample-profile={}" , path. display( ) ) ) ;
311
293
} ;
312
- self . linker_args ( & [
294
+ self . linker_args_ ( & [
313
295
& format ! ( "-plugin-opt={opt_level}" ) ,
314
296
& format ! ( "-plugin-opt=mcpu={}" , self . target_cpu) ,
315
297
] ) ;
@@ -322,7 +304,7 @@ impl<'a> GccLinker<'a> {
322
304
self . cmd . arg ( "-dynamiclib" ) ;
323
305
}
324
306
325
- self . linker_arg ( "-dylib" ) ;
307
+ self . linker_arg_ ( "-dylib" ) ;
326
308
327
309
// Note that the `osx_rpath_install_name` option here is a hack
328
310
// purely to support rustbuild right now, we should get a more
@@ -331,7 +313,7 @@ impl<'a> GccLinker<'a> {
331
313
if self . sess . opts . cg . rpath || self . sess . opts . unstable_opts . osx_rpath_install_name {
332
314
let mut rpath = OsString :: from ( "@rpath/" ) ;
333
315
rpath. push ( out_filename. file_name ( ) . unwrap ( ) ) ;
334
- self . linker_args ( & [ OsString :: from ( "-install_name" ) , rpath] ) ;
316
+ self . linker_args_ ( & [ & OsString :: from ( "-install_name" ) , & rpath] ) ;
335
317
}
336
318
} else {
337
319
self . cmd . arg ( "-shared" ) ;
@@ -351,7 +333,7 @@ impl<'a> GccLinker<'a> {
351
333
if let Some ( implib_name) = implib_name {
352
334
let implib = out_filename. parent ( ) . map ( |dir| dir. join ( & implib_name) ) ;
353
335
if let Some ( implib) = implib {
354
- self . linker_arg ( & format ! ( "--out-implib={}" , ( * implib) . to_str( ) . unwrap( ) ) ) ;
336
+ self . linker_arg_ ( & format ! ( "--out-implib={}" , ( * implib) . to_str( ) . unwrap( ) ) ) ;
355
337
}
356
338
}
357
339
}
@@ -360,6 +342,38 @@ impl<'a> GccLinker<'a> {
360
342
}
361
343
362
344
impl < ' a > Linker for GccLinker < ' a > {
345
+ /// Passes an argument directly to the linker.
346
+ ///
347
+ /// When the linker is not ld-like such as when using a compiler as a linker, the argument is
348
+ /// prepended by `-Wl,`.
349
+ fn linker_arg ( & mut self , arg : & OsStr , verbatim : bool ) {
350
+ self . linker_args ( & [ arg] , verbatim) ;
351
+ }
352
+
353
+ /// Passes a series of arguments directly to the linker.
354
+ ///
355
+ /// When the linker is ld-like, the arguments are simply appended to the command. When the
356
+ /// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by
357
+ /// commas to form an argument that is then prepended with `-Wl`. In this situation, only a
358
+ /// single argument is appended to the command to ensure that the order of the arguments is
359
+ /// preserved by the compiler.
360
+ fn linker_args ( & mut self , args : & [ & OsStr ] , verbatim : bool ) {
361
+ if self . is_ld || verbatim {
362
+ args. into_iter ( ) . for_each ( |a| {
363
+ self . cmd . arg ( a) ;
364
+ } ) ;
365
+ } else {
366
+ if !args. is_empty ( ) {
367
+ let mut s = OsString :: from ( "-Wl" ) ;
368
+ for a in args {
369
+ s. push ( "," ) ;
370
+ s. push ( a) ;
371
+ }
372
+ self . cmd . arg ( s) ;
373
+ }
374
+ }
375
+ }
376
+
363
377
fn cmd ( & mut self ) -> & mut Command {
364
378
& mut self . cmd
365
379
}
@@ -405,7 +419,7 @@ impl<'a> Linker for GccLinker<'a> {
405
419
self . build_dylib ( out_filename) ;
406
420
}
407
421
LinkOutputKind :: WasiReactorExe => {
408
- self . linker_args ( & [ "--entry" , "_initialize" ] ) ;
422
+ self . linker_args_ ( & [ "--entry" , "_initialize" ] ) ;
409
423
}
410
424
}
411
425
// VxWorks compiler driver introduced `--static-crt` flag specifically for rustc,
@@ -441,7 +455,7 @@ impl<'a> Linker for GccLinker<'a> {
441
455
// but we have no way to detect that here.
442
456
self . sess . emit_warning ( errors:: Ld64UnimplementedModifier ) ;
443
457
} else if self . is_gnu && !self . sess . target . is_like_windows {
444
- self . linker_arg ( "--no-as-needed" ) ;
458
+ self . linker_arg_ ( "--no-as-needed" ) ;
445
459
} else {
446
460
self . sess . emit_warning ( errors:: LinkerUnsupportedModifier ) ;
447
461
}
@@ -452,7 +466,7 @@ impl<'a> Linker for GccLinker<'a> {
452
466
if self . sess . target . is_like_osx {
453
467
// See above FIXME comment
454
468
} else if self . is_gnu && !self . sess . target . is_like_windows {
455
- self . linker_arg ( "--as-needed" ) ;
469
+ self . linker_arg_ ( "--as-needed" ) ;
456
470
}
457
471
}
458
472
}
@@ -477,13 +491,13 @@ impl<'a> Linker for GccLinker<'a> {
477
491
self . cmd . arg ( path) ;
478
492
}
479
493
fn full_relro ( & mut self ) {
480
- self . linker_args ( & [ "-z" , "relro" , "-z" , "now" ] ) ;
494
+ self . linker_args_ ( & [ "-z" , "relro" , "-z" , "now" ] ) ;
481
495
}
482
496
fn partial_relro ( & mut self ) {
483
- self . linker_args ( & [ "-z" , "relro" ] ) ;
497
+ self . linker_args_ ( & [ "-z" , "relro" ] ) ;
484
498
}
485
499
fn no_relro ( & mut self ) {
486
- self . linker_args ( & [ "-z" , "norelro" ] ) ;
500
+ self . linker_args_ ( & [ "-z" , "norelro" ] ) ;
487
501
}
488
502
489
503
fn link_rust_dylib ( & mut self , lib : & str , _path : & Path ) {
@@ -512,26 +526,26 @@ impl<'a> Linker for GccLinker<'a> {
512
526
self . hint_static ( ) ;
513
527
let target = & self . sess . target ;
514
528
if !target. is_like_osx {
515
- self . linker_arg ( "--whole-archive" ) ;
529
+ self . linker_arg_ ( "--whole-archive" ) ;
516
530
self . cmd . arg ( format ! ( "-l{}{lib}" , if verbatim && self . is_gnu { ":" } else { "" } , ) ) ;
517
- self . linker_arg ( "--no-whole-archive" ) ;
531
+ self . linker_arg_ ( "--no-whole-archive" ) ;
518
532
} else {
519
533
// -force_load is the macOS equivalent of --whole-archive, but it
520
534
// involves passing the full path to the library to link.
521
- self . linker_arg ( "-force_load" ) ;
535
+ self . linker_arg_ ( "-force_load" ) ;
522
536
let lib = find_native_static_library ( lib, verbatim, search_path, & self . sess ) ;
523
- self . linker_arg ( & lib) ;
537
+ self . linker_arg_ ( & lib) ;
524
538
}
525
539
}
526
540
527
541
fn link_whole_rlib ( & mut self , lib : & Path ) {
528
542
self . hint_static ( ) ;
529
543
if self . sess . target . is_like_osx {
530
- self . linker_arg ( "-force_load" ) ;
531
- self . linker_arg ( & lib) ;
544
+ self . linker_arg_ ( "-force_load" ) ;
545
+ self . linker_arg_ ( & lib) ;
532
546
} else {
533
- self . linker_arg ( "--whole-archive" ) . cmd . arg ( lib ) ;
534
- self . linker_arg ( "--no-whole-archive" ) ;
547
+ self . linker_args_ ( & [ OsString :: from ( "--whole-archive" ) , lib . into ( ) ] ) ;
548
+ self . linker_arg_ ( "--no-whole-archive" ) ;
535
549
}
536
550
}
537
551
@@ -551,21 +565,21 @@ impl<'a> Linker for GccLinker<'a> {
551
565
// for partial linking when using multiple codegen units (-r). So we
552
566
// insert it here.
553
567
if self . sess . target . is_like_osx {
554
- self . linker_arg ( "-dead_strip" ) ;
568
+ self . linker_arg_ ( "-dead_strip" ) ;
555
569
556
570
// If we're building a dylib, we don't use --gc-sections because LLVM
557
571
// has already done the best it can do, and we also don't want to
558
572
// eliminate the metadata. If we're building an executable, however,
559
573
// --gc-sections drops the size of hello world from 1.8MB to 597K, a 67%
560
574
// reduction.
561
575
} else if ( self . is_gnu || self . sess . target . is_like_wasm ) && !keep_metadata {
562
- self . linker_arg ( "--gc-sections" ) ;
576
+ self . linker_arg_ ( "--gc-sections" ) ;
563
577
}
564
578
}
565
579
566
580
fn no_gc_sections ( & mut self ) {
567
581
if self . is_gnu || self . sess . target . is_like_wasm {
568
- self . linker_arg ( "--no-gc-sections" ) ;
582
+ self . linker_arg_ ( "--no-gc-sections" ) ;
569
583
}
570
584
}
571
585
@@ -579,7 +593,7 @@ impl<'a> Linker for GccLinker<'a> {
579
593
if self . sess . opts . optimize == config:: OptLevel :: Default
580
594
|| self . sess . opts . optimize == config:: OptLevel :: Aggressive
581
595
{
582
- self . linker_arg ( "-O1" ) ;
596
+ self . linker_arg_ ( "-O1" ) ;
583
597
}
584
598
}
585
599
@@ -619,20 +633,20 @@ impl<'a> Linker for GccLinker<'a> {
619
633
// The --strip-debug case is handled by running an external
620
634
// `strip` utility as a separate step after linking.
621
635
if self . sess . target . os != "illumos" {
622
- self . linker_arg ( "--strip-debug" ) ;
636
+ self . linker_arg_ ( "--strip-debug" ) ;
623
637
}
624
638
}
625
639
Strip :: Symbols => {
626
- self . linker_arg ( "--strip-all" ) ;
640
+ self . linker_arg_ ( "--strip-all" ) ;
627
641
}
628
642
}
629
643
match self . sess . opts . unstable_opts . debuginfo_compression {
630
644
config:: DebugInfoCompression :: None => { }
631
645
config:: DebugInfoCompression :: Zlib => {
632
- self . linker_arg ( "--compress-debug-sections=zlib" ) ;
646
+ self . linker_arg_ ( "--compress-debug-sections=zlib" ) ;
633
647
}
634
648
config:: DebugInfoCompression :: Zstd => {
635
- self . linker_arg ( "--compress-debug-sections=zstd" ) ;
649
+ self . linker_arg_ ( "--compress-debug-sections=zstd" ) ;
636
650
}
637
651
}
638
652
}
@@ -721,24 +735,24 @@ impl<'a> Linker for GccLinker<'a> {
721
735
}
722
736
723
737
if self . sess . target . is_like_osx {
724
- self . linker_args ( & [ OsString :: from ( "-exported_symbols_list" ) , path. into ( ) ] ) ;
738
+ self . linker_args_ ( & [ OsString :: from ( "-exported_symbols_list" ) , path. into ( ) ] ) ;
725
739
} else if self . sess . target . is_like_solaris {
726
- self . linker_args ( & [ OsString :: from ( "-M" ) , path. into ( ) ] ) ;
740
+ self . linker_args_ ( & [ OsString :: from ( "-M" ) , path. into ( ) ] ) ;
727
741
} else {
728
742
if is_windows {
729
- self . linker_arg ( path) ;
743
+ self . linker_arg_ ( path) ;
730
744
} else {
731
745
let mut arg = OsString :: from ( "--version-script=" ) ;
732
746
arg. push ( path) ;
733
- self . linker_arg ( arg) ;
734
- self . linker_arg ( "--no-undefined-version" ) ;
747
+ self . linker_arg_ ( arg) ;
748
+ self . linker_arg_ ( "--no-undefined-version" ) ;
735
749
}
736
750
}
737
751
}
738
752
739
753
fn subsystem ( & mut self , subsystem : & str ) {
740
- self . linker_arg ( "--subsystem" ) ;
741
- self . linker_arg ( & subsystem) ;
754
+ self . linker_arg_ ( "--subsystem" ) ;
755
+ self . linker_arg_ ( & subsystem) ;
742
756
}
743
757
744
758
fn reset_per_library_state ( & mut self ) {
@@ -763,23 +777,23 @@ impl<'a> Linker for GccLinker<'a> {
763
777
// Some versions of `gcc` add it implicitly, some (e.g. `musl-gcc`) don't,
764
778
// so we just always add it.
765
779
fn add_eh_frame_header ( & mut self ) {
766
- self . linker_arg ( "--eh-frame-hdr" ) ;
780
+ self . linker_arg_ ( "--eh-frame-hdr" ) ;
767
781
}
768
782
769
783
fn add_no_exec ( & mut self ) {
770
784
if self . sess . target . is_like_windows {
771
- self . linker_arg ( "--nxcompat" ) ;
785
+ self . linker_arg_ ( "--nxcompat" ) ;
772
786
} else if self . is_gnu {
773
- self . linker_args ( & [ "-z" , "noexecstack" ] ) ;
787
+ self . linker_args_ ( & [ "-z" , "noexecstack" ] ) ;
774
788
}
775
789
}
776
790
777
791
fn add_as_needed ( & mut self ) {
778
792
if self . is_gnu && !self . sess . target . is_like_windows {
779
- self . linker_arg ( "--as-needed" ) ;
793
+ self . linker_arg_ ( "--as-needed" ) ;
780
794
} else if self . sess . target . is_like_solaris {
781
795
// -z ignore is the Solaris equivalent to the GNU ld --as-needed option
782
- self . linker_args ( & [ "-z" , "ignore" ] ) ;
796
+ self . linker_args_ ( & [ "-z" , "ignore" ] ) ;
783
797
}
784
798
}
785
799
}
0 commit comments