@@ -195,6 +195,14 @@ pub trait Linker {
195195 fn add_no_exec ( & mut self ) { }
196196 fn add_as_needed ( & mut self ) { }
197197 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+ }
198206}
199207
200208impl dyn Linker + ' _ {
@@ -222,38 +230,12 @@ pub struct GccLinker<'a> {
222230}
223231
224232impl < ' 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 ) ;
232235 }
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 ) ;
257239 }
258240
259241 fn takes_hints ( & self ) -> bool {
@@ -277,7 +259,7 @@ impl<'a> GccLinker<'a> {
277259 return ;
278260 }
279261 if self . hinted_static != Some ( true ) {
280- self . linker_arg ( "-Bstatic" ) ;
262+ self . linker_arg_ ( "-Bstatic" ) ;
281263 self . hinted_static = Some ( true ) ;
282264 }
283265 }
@@ -287,7 +269,7 @@ impl<'a> GccLinker<'a> {
287269 return ;
288270 }
289271 if self . hinted_static != Some ( false ) {
290- self . linker_arg ( "-Bdynamic" ) ;
272+ self . linker_arg_ ( "-Bdynamic" ) ;
291273 self . hinted_static = Some ( false ) ;
292274 }
293275 }
@@ -296,7 +278,7 @@ impl<'a> GccLinker<'a> {
296278 if let Some ( plugin_path) = plugin_path {
297279 let mut arg = OsString :: from ( "-plugin=" ) ;
298280 arg. push ( plugin_path) ;
299- self . linker_arg ( & arg) ;
281+ self . linker_arg_ ( & arg) ;
300282 }
301283
302284 let opt_level = match self . sess . opts . optimize {
@@ -307,9 +289,9 @@ impl<'a> GccLinker<'a> {
307289 } ;
308290
309291 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( ) ) ) ;
311293 } ;
312- self . linker_args ( & [
294+ self . linker_args_ ( & [
313295 & format ! ( "-plugin-opt={opt_level}" ) ,
314296 & format ! ( "-plugin-opt=mcpu={}" , self . target_cpu) ,
315297 ] ) ;
@@ -322,7 +304,7 @@ impl<'a> GccLinker<'a> {
322304 self . cmd . arg ( "-dynamiclib" ) ;
323305 }
324306
325- self . linker_arg ( "-dylib" ) ;
307+ self . linker_arg_ ( "-dylib" ) ;
326308
327309 // Note that the `osx_rpath_install_name` option here is a hack
328310 // purely to support rustbuild right now, we should get a more
@@ -331,7 +313,7 @@ impl<'a> GccLinker<'a> {
331313 if self . sess . opts . cg . rpath || self . sess . opts . unstable_opts . osx_rpath_install_name {
332314 let mut rpath = OsString :: from ( "@rpath/" ) ;
333315 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] ) ;
335317 }
336318 } else {
337319 self . cmd . arg ( "-shared" ) ;
@@ -351,7 +333,7 @@ impl<'a> GccLinker<'a> {
351333 if let Some ( implib_name) = implib_name {
352334 let implib = out_filename. parent ( ) . map ( |dir| dir. join ( & implib_name) ) ;
353335 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( ) ) ) ;
355337 }
356338 }
357339 }
@@ -360,6 +342,38 @@ impl<'a> GccLinker<'a> {
360342}
361343
362344impl < ' 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+
363377 fn cmd ( & mut self ) -> & mut Command {
364378 & mut self . cmd
365379 }
@@ -405,7 +419,7 @@ impl<'a> Linker for GccLinker<'a> {
405419 self . build_dylib ( out_filename) ;
406420 }
407421 LinkOutputKind :: WasiReactorExe => {
408- self . linker_args ( & [ "--entry" , "_initialize" ] ) ;
422+ self . linker_args_ ( & [ "--entry" , "_initialize" ] ) ;
409423 }
410424 }
411425 // VxWorks compiler driver introduced `--static-crt` flag specifically for rustc,
@@ -441,7 +455,7 @@ impl<'a> Linker for GccLinker<'a> {
441455 // but we have no way to detect that here.
442456 self . sess . emit_warning ( errors:: Ld64UnimplementedModifier ) ;
443457 } 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" ) ;
445459 } else {
446460 self . sess . emit_warning ( errors:: LinkerUnsupportedModifier ) ;
447461 }
@@ -452,7 +466,7 @@ impl<'a> Linker for GccLinker<'a> {
452466 if self . sess . target . is_like_osx {
453467 // See above FIXME comment
454468 } else if self . is_gnu && !self . sess . target . is_like_windows {
455- self . linker_arg ( "--as-needed" ) ;
469+ self . linker_arg_ ( "--as-needed" ) ;
456470 }
457471 }
458472 }
@@ -477,13 +491,13 @@ impl<'a> Linker for GccLinker<'a> {
477491 self . cmd . arg ( path) ;
478492 }
479493 fn full_relro ( & mut self ) {
480- self . linker_args ( & [ "-z" , "relro" , "-z" , "now" ] ) ;
494+ self . linker_args_ ( & [ "-z" , "relro" , "-z" , "now" ] ) ;
481495 }
482496 fn partial_relro ( & mut self ) {
483- self . linker_args ( & [ "-z" , "relro" ] ) ;
497+ self . linker_args_ ( & [ "-z" , "relro" ] ) ;
484498 }
485499 fn no_relro ( & mut self ) {
486- self . linker_args ( & [ "-z" , "norelro" ] ) ;
500+ self . linker_args_ ( & [ "-z" , "norelro" ] ) ;
487501 }
488502
489503 fn link_rust_dylib ( & mut self , lib : & str , _path : & Path ) {
@@ -512,26 +526,26 @@ impl<'a> Linker for GccLinker<'a> {
512526 self . hint_static ( ) ;
513527 let target = & self . sess . target ;
514528 if !target. is_like_osx {
515- self . linker_arg ( "--whole-archive" ) ;
529+ self . linker_arg_ ( "--whole-archive" ) ;
516530 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" ) ;
518532 } else {
519533 // -force_load is the macOS equivalent of --whole-archive, but it
520534 // involves passing the full path to the library to link.
521- self . linker_arg ( "-force_load" ) ;
535+ self . linker_arg_ ( "-force_load" ) ;
522536 let lib = find_native_static_library ( lib, verbatim, search_path, & self . sess ) ;
523- self . linker_arg ( & lib) ;
537+ self . linker_arg_ ( & lib) ;
524538 }
525539 }
526540
527541 fn link_whole_rlib ( & mut self , lib : & Path ) {
528542 self . hint_static ( ) ;
529543 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) ;
532546 } 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" ) ;
535549 }
536550 }
537551
@@ -551,21 +565,21 @@ impl<'a> Linker for GccLinker<'a> {
551565 // for partial linking when using multiple codegen units (-r). So we
552566 // insert it here.
553567 if self . sess . target . is_like_osx {
554- self . linker_arg ( "-dead_strip" ) ;
568+ self . linker_arg_ ( "-dead_strip" ) ;
555569
556570 // If we're building a dylib, we don't use --gc-sections because LLVM
557571 // has already done the best it can do, and we also don't want to
558572 // eliminate the metadata. If we're building an executable, however,
559573 // --gc-sections drops the size of hello world from 1.8MB to 597K, a 67%
560574 // reduction.
561575 } 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" ) ;
563577 }
564578 }
565579
566580 fn no_gc_sections ( & mut self ) {
567581 if self . is_gnu || self . sess . target . is_like_wasm {
568- self . linker_arg ( "--no-gc-sections" ) ;
582+ self . linker_arg_ ( "--no-gc-sections" ) ;
569583 }
570584 }
571585
@@ -579,7 +593,7 @@ impl<'a> Linker for GccLinker<'a> {
579593 if self . sess . opts . optimize == config:: OptLevel :: Default
580594 || self . sess . opts . optimize == config:: OptLevel :: Aggressive
581595 {
582- self . linker_arg ( "-O1" ) ;
596+ self . linker_arg_ ( "-O1" ) ;
583597 }
584598 }
585599
@@ -619,20 +633,20 @@ impl<'a> Linker for GccLinker<'a> {
619633 // The --strip-debug case is handled by running an external
620634 // `strip` utility as a separate step after linking.
621635 if self . sess . target . os != "illumos" {
622- self . linker_arg ( "--strip-debug" ) ;
636+ self . linker_arg_ ( "--strip-debug" ) ;
623637 }
624638 }
625639 Strip :: Symbols => {
626- self . linker_arg ( "--strip-all" ) ;
640+ self . linker_arg_ ( "--strip-all" ) ;
627641 }
628642 }
629643 match self . sess . opts . unstable_opts . debuginfo_compression {
630644 config:: DebugInfoCompression :: None => { }
631645 config:: DebugInfoCompression :: Zlib => {
632- self . linker_arg ( "--compress-debug-sections=zlib" ) ;
646+ self . linker_arg_ ( "--compress-debug-sections=zlib" ) ;
633647 }
634648 config:: DebugInfoCompression :: Zstd => {
635- self . linker_arg ( "--compress-debug-sections=zstd" ) ;
649+ self . linker_arg_ ( "--compress-debug-sections=zstd" ) ;
636650 }
637651 }
638652 }
@@ -721,24 +735,24 @@ impl<'a> Linker for GccLinker<'a> {
721735 }
722736
723737 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 ( ) ] ) ;
725739 } 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 ( ) ] ) ;
727741 } else {
728742 if is_windows {
729- self . linker_arg ( path) ;
743+ self . linker_arg_ ( path) ;
730744 } else {
731745 let mut arg = OsString :: from ( "--version-script=" ) ;
732746 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" ) ;
735749 }
736750 }
737751 }
738752
739753 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) ;
742756 }
743757
744758 fn reset_per_library_state ( & mut self ) {
@@ -763,23 +777,23 @@ impl<'a> Linker for GccLinker<'a> {
763777 // Some versions of `gcc` add it implicitly, some (e.g. `musl-gcc`) don't,
764778 // so we just always add it.
765779 fn add_eh_frame_header ( & mut self ) {
766- self . linker_arg ( "--eh-frame-hdr" ) ;
780+ self . linker_arg_ ( "--eh-frame-hdr" ) ;
767781 }
768782
769783 fn add_no_exec ( & mut self ) {
770784 if self . sess . target . is_like_windows {
771- self . linker_arg ( "--nxcompat" ) ;
785+ self . linker_arg_ ( "--nxcompat" ) ;
772786 } else if self . is_gnu {
773- self . linker_args ( & [ "-z" , "noexecstack" ] ) ;
787+ self . linker_args_ ( & [ "-z" , "noexecstack" ] ) ;
774788 }
775789 }
776790
777791 fn add_as_needed ( & mut self ) {
778792 if self . is_gnu && !self . sess . target . is_like_windows {
779- self . linker_arg ( "--as-needed" ) ;
793+ self . linker_arg_ ( "--as-needed" ) ;
780794 } else if self . sess . target . is_like_solaris {
781795 // -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" ] ) ;
783797 }
784798 }
785799}
0 commit comments