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