@@ -219,19 +219,36 @@ pub struct GccLinker<'a> {
219219}
220220
221221impl < ' a > GccLinker < ' a > {
222- /// Argument that must be passed * directly* to the linker
222+ /// Passes an argument directly to the linker.
223223 ///
224- /// These arguments need to be prepended with `-Wl`, when a GCC-style linker is used.
225- fn linker_arg < S > ( & mut self , arg : S ) -> & mut Self
226- where
227- S : AsRef < OsStr > ,
228- {
229- if !self . is_ld {
230- let mut os = OsString :: from ( "-Wl," ) ;
231- os. push ( arg. as_ref ( ) ) ;
232- self . cmd . arg ( os) ;
224+ /// When the linker is not ld-like such as when using a compiler as a linker, the argument is
225+ /// prepended by `-Wl,`.
226+ fn linker_arg ( & mut self , arg : impl AsRef < OsStr > ) -> & mut Self {
227+ self . linker_args ( & [ arg] ) ;
228+ self
229+ }
230+
231+ /// Passes a series of arguments directly to the linker.
232+ ///
233+ /// When the linker is ld-like, the arguments are simply appended to the command. When the
234+ /// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by
235+ /// commas to form an argument that is then prepended with `-Wl`. In this situation, only a
236+ /// single argument is appended to the command to ensure that the order of the arguments is
237+ /// preserved by the compiler.
238+ fn linker_args ( & mut self , args : & [ impl AsRef < OsStr > ] ) -> & mut Self {
239+ if self . is_ld {
240+ args. into_iter ( ) . for_each ( |a| {
241+ self . cmd . arg ( a) ;
242+ } ) ;
233243 } else {
234- self . cmd . arg ( arg) ;
244+ if !args. is_empty ( ) {
245+ let mut s = OsString :: from ( "-Wl" ) ;
246+ for a in args {
247+ s. push ( "," ) ;
248+ s. push ( a) ;
249+ }
250+ self . cmd . arg ( s) ;
251+ }
235252 }
236253 self
237254 }
@@ -289,25 +306,29 @@ impl<'a> GccLinker<'a> {
289306 if let Some ( path) = & self . sess . opts . debugging_opts . profile_sample_use {
290307 self . linker_arg ( & format ! ( "-plugin-opt=sample-profile={}" , path. display( ) ) ) ;
291308 } ;
292- self . linker_arg ( & format ! ( "-plugin-opt={}" , opt_level) ) ;
293- self . linker_arg ( & format ! ( "-plugin-opt=mcpu={}" , self . target_cpu) ) ;
309+ self . linker_args ( & [
310+ & format ! ( "-plugin-opt={}" , opt_level) ,
311+ & format ! ( "-plugin-opt=mcpu={}" , self . target_cpu) ,
312+ ] ) ;
294313 }
295314
296315 fn build_dylib ( & mut self , out_filename : & Path ) {
297316 // On mac we need to tell the linker to let this library be rpathed
298317 if self . sess . target . is_like_osx {
299- self . cmd . arg ( "-dynamiclib" ) ;
318+ if !self . is_ld {
319+ self . cmd . arg ( "-dynamiclib" ) ;
320+ }
321+
300322 self . linker_arg ( "-dylib" ) ;
301323
302324 // Note that the `osx_rpath_install_name` option here is a hack
303325 // purely to support rustbuild right now, we should get a more
304326 // principled solution at some point to force the compiler to pass
305327 // the right `-Wl,-install_name` with an `@rpath` in it.
306328 if self . sess . opts . cg . rpath || self . sess . opts . debugging_opts . osx_rpath_install_name {
307- self . linker_arg ( "-install_name" ) ;
308- let mut v = OsString :: from ( "@rpath/" ) ;
309- v. push ( out_filename. file_name ( ) . unwrap ( ) ) ;
310- self . linker_arg ( & v) ;
329+ let mut rpath = OsString :: from ( "@rpath/" ) ;
330+ rpath. push ( out_filename. file_name ( ) . unwrap ( ) ) ;
331+ self . linker_args ( & [ OsString :: from ( "-install_name" ) , rpath] ) ;
311332 }
312333 } else {
313334 self . cmd . arg ( "-shared" ) ;
@@ -381,8 +402,7 @@ impl<'a> Linker for GccLinker<'a> {
381402 self . build_dylib ( out_filename) ;
382403 }
383404 LinkOutputKind :: WasiReactorExe => {
384- self . linker_arg ( "--entry" ) ;
385- self . linker_arg ( "_initialize" ) ;
405+ self . linker_args ( & [ "--entry" , "_initialize" ] ) ;
386406 }
387407 }
388408 // VxWorks compiler driver introduced `--static-crt` flag specifically for rustc,
@@ -454,8 +474,7 @@ impl<'a> Linker for GccLinker<'a> {
454474 self . cmd . arg ( path) ;
455475 }
456476 fn full_relro ( & mut self ) {
457- self . linker_arg ( "-zrelro" ) ;
458- self . linker_arg ( "-znow" ) ;
477+ self . linker_args ( & [ "-zrelro" , "-znow" ] ) ;
459478 }
460479 fn partial_relro ( & mut self ) {
461480 self . linker_arg ( "-zrelro" ) ;
@@ -639,7 +658,6 @@ impl<'a> Linker for GccLinker<'a> {
639658 }
640659
641660 let is_windows = self . sess . target . is_like_windows ;
642- let mut arg = OsString :: new ( ) ;
643661 let path = tmpdir. join ( if is_windows { "list.def" } else { "list" } ) ;
644662
645663 debug ! ( "EXPORTED SYMBOLS:" ) ;
@@ -691,27 +709,18 @@ impl<'a> Linker for GccLinker<'a> {
691709 }
692710
693711 if self . sess . target . is_like_osx {
694- if !self . is_ld {
695- arg. push ( "-Wl," )
696- }
697- arg. push ( "-exported_symbols_list," ) ;
712+ self . linker_args ( & [ OsString :: from ( "-exported_symbols_list" ) , path. into ( ) ] ) ;
698713 } else if self . sess . target . is_like_solaris {
699- if !self . is_ld {
700- arg. push ( "-Wl," )
701- }
702- arg. push ( "-M," ) ;
714+ self . linker_args ( & [ OsString :: from ( "-M" ) , path. into ( ) ] ) ;
703715 } else {
704- if ! self . is_ld {
705- arg . push ( "-Wl," )
706- }
707- // Both LD and LLD accept export list in *.def file form, there are no flags required
708- if !is_windows {
709- arg . push ( "--version-script=" )
716+ if is_windows {
717+ self . linker_arg ( path ) ;
718+ } else {
719+ let mut arg = OsString :: from ( "--version-script=" ) ;
720+ arg . push ( path ) ;
721+ self . linker_arg ( arg ) ;
710722 }
711723 }
712-
713- arg. push ( & path) ;
714- self . cmd . arg ( arg) ;
715724 }
716725
717726 fn subsystem ( & mut self , subsystem : & str ) {
@@ -769,8 +778,7 @@ impl<'a> Linker for GccLinker<'a> {
769778 self . linker_arg ( "--as-needed" ) ;
770779 } else if self . sess . target . is_like_solaris {
771780 // -z ignore is the Solaris equivalent to the GNU ld --as-needed option
772- self . linker_arg ( "-z" ) ;
773- self . linker_arg ( "ignore" ) ;
781+ self . linker_args ( & [ "-z" , "ignore" ] ) ;
774782 }
775783 }
776784}
0 commit comments