@@ -196,6 +196,14 @@ pub trait Linker {
196196 fn add_no_exec ( & mut self ) { }
197197 fn add_as_needed ( & mut self ) { }
198198 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+ }
199207}
200208
201209impl dyn Linker + ' _ {
@@ -223,38 +231,12 @@ pub struct GccLinker<'a> {
223231}
224232
225233impl < ' 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 ) ;
233236 }
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 ) ;
258240 }
259241
260242 fn takes_hints ( & self ) -> bool {
@@ -278,7 +260,7 @@ impl<'a> GccLinker<'a> {
278260 return ;
279261 }
280262 if self . hinted_static != Some ( true ) {
281- self . linker_arg ( "-Bstatic" ) ;
263+ self . linker_arg_ ( "-Bstatic" ) ;
282264 self . hinted_static = Some ( true ) ;
283265 }
284266 }
@@ -288,7 +270,7 @@ impl<'a> GccLinker<'a> {
288270 return ;
289271 }
290272 if self . hinted_static != Some ( false ) {
291- self . linker_arg ( "-Bdynamic" ) ;
273+ self . linker_arg_ ( "-Bdynamic" ) ;
292274 self . hinted_static = Some ( false ) ;
293275 }
294276 }
@@ -297,7 +279,7 @@ impl<'a> GccLinker<'a> {
297279 if let Some ( plugin_path) = plugin_path {
298280 let mut arg = OsString :: from ( "-plugin=" ) ;
299281 arg. push ( plugin_path) ;
300- self . linker_arg ( & arg) ;
282+ self . linker_arg_ ( & arg) ;
301283 }
302284
303285 let opt_level = match self . sess . opts . optimize {
@@ -308,9 +290,9 @@ impl<'a> GccLinker<'a> {
308290 } ;
309291
310292 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( ) ) ) ;
312294 } ;
313- self . linker_args ( & [
295+ self . linker_args_ ( & [
314296 & format ! ( "-plugin-opt={opt_level}" ) ,
315297 & format ! ( "-plugin-opt=mcpu={}" , self . target_cpu) ,
316298 ] ) ;
@@ -323,7 +305,7 @@ impl<'a> GccLinker<'a> {
323305 self . cmd . arg ( "-dynamiclib" ) ;
324306 }
325307
326- self . linker_arg ( "-dylib" ) ;
308+ self . linker_arg_ ( "-dylib" ) ;
327309
328310 // Note that the `osx_rpath_install_name` option here is a hack
329311 // purely to support rustbuild right now, we should get a more
@@ -332,7 +314,7 @@ impl<'a> GccLinker<'a> {
332314 if self . sess . opts . cg . rpath || self . sess . opts . unstable_opts . osx_rpath_install_name {
333315 let mut rpath = OsString :: from ( "@rpath/" ) ;
334316 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] ) ;
336318 }
337319 } else {
338320 self . cmd . arg ( "-shared" ) ;
@@ -352,7 +334,7 @@ impl<'a> GccLinker<'a> {
352334 if let Some ( implib_name) = implib_name {
353335 let implib = out_filename. parent ( ) . map ( |dir| dir. join ( & implib_name) ) ;
354336 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( ) ) ) ;
356338 }
357339 }
358340 }
@@ -361,6 +343,38 @@ impl<'a> GccLinker<'a> {
361343}
362344
363345impl < ' 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+
364378 fn cmd ( & mut self ) -> & mut Command {
365379 & mut self . cmd
366380 }
@@ -406,7 +420,7 @@ impl<'a> Linker for GccLinker<'a> {
406420 self . build_dylib ( out_filename) ;
407421 }
408422 LinkOutputKind :: WasiReactorExe => {
409- self . linker_args ( & [ "--entry" , "_initialize" ] ) ;
423+ self . linker_args_ ( & [ "--entry" , "_initialize" ] ) ;
410424 }
411425 }
412426 // VxWorks compiler driver introduced `--static-crt` flag specifically for rustc,
@@ -442,7 +456,7 @@ impl<'a> Linker for GccLinker<'a> {
442456 // but we have no way to detect that here.
443457 self . sess . emit_warning ( errors:: Ld64UnimplementedModifier ) ;
444458 } 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" ) ;
446460 } else {
447461 self . sess . emit_warning ( errors:: LinkerUnsupportedModifier ) ;
448462 }
@@ -453,7 +467,7 @@ impl<'a> Linker for GccLinker<'a> {
453467 if self . sess . target . is_like_osx {
454468 // See above FIXME comment
455469 } else if self . is_gnu && !self . sess . target . is_like_windows {
456- self . linker_arg ( "--as-needed" ) ;
470+ self . linker_arg_ ( "--as-needed" ) ;
457471 }
458472 }
459473 }
@@ -478,13 +492,13 @@ impl<'a> Linker for GccLinker<'a> {
478492 self . cmd . arg ( path) ;
479493 }
480494 fn full_relro ( & mut self ) {
481- self . linker_args ( & [ "-z" , "relro" , "-z" , "now" ] ) ;
495+ self . linker_args_ ( & [ "-z" , "relro" , "-z" , "now" ] ) ;
482496 }
483497 fn partial_relro ( & mut self ) {
484- self . linker_args ( & [ "-z" , "relro" ] ) ;
498+ self . linker_args_ ( & [ "-z" , "relro" ] ) ;
485499 }
486500 fn no_relro ( & mut self ) {
487- self . linker_args ( & [ "-z" , "norelro" ] ) ;
501+ self . linker_args_ ( & [ "-z" , "norelro" ] ) ;
488502 }
489503
490504 fn link_rust_dylib ( & mut self , lib : & str , _path : & Path ) {
@@ -513,26 +527,26 @@ impl<'a> Linker for GccLinker<'a> {
513527 self . hint_static ( ) ;
514528 let target = & self . sess . target ;
515529 if !target. is_like_osx {
516- self . linker_arg ( "--whole-archive" ) ;
530+ self . linker_arg_ ( "--whole-archive" ) ;
517531 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" ) ;
519533 } else {
520534 // -force_load is the macOS equivalent of --whole-archive, but it
521535 // involves passing the full path to the library to link.
522- self . linker_arg ( "-force_load" ) ;
536+ self . linker_arg_ ( "-force_load" ) ;
523537 let lib = find_native_static_library ( lib, verbatim, search_path, self . sess ) ;
524- self . linker_arg ( & lib) ;
538+ self . linker_arg_ ( & lib) ;
525539 }
526540 }
527541
528542 fn link_whole_rlib ( & mut self , lib : & Path ) {
529543 self . hint_static ( ) ;
530544 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) ;
533547 } 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" ) ;
536550 }
537551 }
538552
@@ -552,21 +566,21 @@ impl<'a> Linker for GccLinker<'a> {
552566 // for partial linking when using multiple codegen units (-r). So we
553567 // insert it here.
554568 if self . sess . target . is_like_osx {
555- self . linker_arg ( "-dead_strip" ) ;
569+ self . linker_arg_ ( "-dead_strip" ) ;
556570
557571 // If we're building a dylib, we don't use --gc-sections because LLVM
558572 // has already done the best it can do, and we also don't want to
559573 // eliminate the metadata. If we're building an executable, however,
560574 // --gc-sections drops the size of hello world from 1.8MB to 597K, a 67%
561575 // reduction.
562576 } 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" ) ;
564578 }
565579 }
566580
567581 fn no_gc_sections ( & mut self ) {
568582 if self . is_gnu || self . sess . target . is_like_wasm {
569- self . linker_arg ( "--no-gc-sections" ) ;
583+ self . linker_arg_ ( "--no-gc-sections" ) ;
570584 }
571585 }
572586
@@ -580,7 +594,7 @@ impl<'a> Linker for GccLinker<'a> {
580594 if self . sess . opts . optimize == config:: OptLevel :: Default
581595 || self . sess . opts . optimize == config:: OptLevel :: Aggressive
582596 {
583- self . linker_arg ( "-O1" ) ;
597+ self . linker_arg_ ( "-O1" ) ;
584598 }
585599 }
586600
@@ -622,20 +636,20 @@ impl<'a> Linker for GccLinker<'a> {
622636 // The --strip-debug case is handled by running an external
623637 // `strip` utility as a separate step after linking.
624638 if self . sess . target . os != "illumos" {
625- self . linker_arg ( "--strip-debug" ) ;
639+ self . linker_arg_ ( "--strip-debug" ) ;
626640 }
627641 }
628642 Strip :: Symbols => {
629- self . linker_arg ( "--strip-all" ) ;
643+ self . linker_arg_ ( "--strip-all" ) ;
630644 }
631645 }
632646 match self . sess . opts . unstable_opts . debuginfo_compression {
633647 config:: DebugInfoCompression :: None => { }
634648 config:: DebugInfoCompression :: Zlib => {
635- self . linker_arg ( "--compress-debug-sections=zlib" ) ;
649+ self . linker_arg_ ( "--compress-debug-sections=zlib" ) ;
636650 }
637651 config:: DebugInfoCompression :: Zstd => {
638- self . linker_arg ( "--compress-debug-sections=zstd" ) ;
652+ self . linker_arg_ ( "--compress-debug-sections=zstd" ) ;
639653 }
640654 }
641655 }
@@ -724,24 +738,24 @@ impl<'a> Linker for GccLinker<'a> {
724738 }
725739
726740 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 ( ) ] ) ;
728742 } 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 ( ) ] ) ;
730744 } else {
731745 if is_windows {
732- self . linker_arg ( path) ;
746+ self . linker_arg_ ( path) ;
733747 } else {
734748 let mut arg = OsString :: from ( "--version-script=" ) ;
735749 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" ) ;
738752 }
739753 }
740754 }
741755
742756 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) ;
745759 }
746760
747761 fn reset_per_library_state ( & mut self ) {
@@ -766,23 +780,23 @@ impl<'a> Linker for GccLinker<'a> {
766780 // Some versions of `gcc` add it implicitly, some (e.g. `musl-gcc`) don't,
767781 // so we just always add it.
768782 fn add_eh_frame_header ( & mut self ) {
769- self . linker_arg ( "--eh-frame-hdr" ) ;
783+ self . linker_arg_ ( "--eh-frame-hdr" ) ;
770784 }
771785
772786 fn add_no_exec ( & mut self ) {
773787 if self . sess . target . is_like_windows {
774- self . linker_arg ( "--nxcompat" ) ;
788+ self . linker_arg_ ( "--nxcompat" ) ;
775789 } else if self . is_gnu {
776- self . linker_args ( & [ "-z" , "noexecstack" ] ) ;
790+ self . linker_args_ ( & [ "-z" , "noexecstack" ] ) ;
777791 }
778792 }
779793
780794 fn add_as_needed ( & mut self ) {
781795 if self . is_gnu && !self . sess . target . is_like_windows {
782- self . linker_arg ( "--as-needed" ) ;
796+ self . linker_arg_ ( "--as-needed" ) ;
783797 } else if self . sess . target . is_like_solaris {
784798 // -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" ] ) ;
786800 }
787801 }
788802}
0 commit comments