@@ -219,19 +219,36 @@ pub struct GccLinker<'a> {
219
219
}
220
220
221
221
impl < ' a > GccLinker < ' a > {
222
- /// Argument that must be passed * directly* to the linker
222
+ /// Passes an argument directly to the linker.
223
223
///
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
+ } ) ;
233
243
} 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
+ }
235
252
}
236
253
self
237
254
}
@@ -289,25 +306,29 @@ impl<'a> GccLinker<'a> {
289
306
if let Some ( path) = & self . sess . opts . debugging_opts . profile_sample_use {
290
307
self . linker_arg ( & format ! ( "-plugin-opt=sample-profile={}" , path. display( ) ) ) ;
291
308
} ;
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
+ ] ) ;
294
313
}
295
314
296
315
fn build_dylib ( & mut self , out_filename : & Path ) {
297
316
// On mac we need to tell the linker to let this library be rpathed
298
317
if self . sess . target . is_like_osx {
299
- self . cmd . arg ( "-dynamiclib" ) ;
318
+ if !self . is_ld {
319
+ self . cmd . arg ( "-dynamiclib" ) ;
320
+ }
321
+
300
322
self . linker_arg ( "-dylib" ) ;
301
323
302
324
// Note that the `osx_rpath_install_name` option here is a hack
303
325
// purely to support rustbuild right now, we should get a more
304
326
// principled solution at some point to force the compiler to pass
305
327
// the right `-Wl,-install_name` with an `@rpath` in it.
306
328
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] ) ;
311
332
}
312
333
} else {
313
334
self . cmd . arg ( "-shared" ) ;
@@ -381,8 +402,7 @@ impl<'a> Linker for GccLinker<'a> {
381
402
self . build_dylib ( out_filename) ;
382
403
}
383
404
LinkOutputKind :: WasiReactorExe => {
384
- self . linker_arg ( "--entry" ) ;
385
- self . linker_arg ( "_initialize" ) ;
405
+ self . linker_args ( & [ "--entry" , "_initialize" ] ) ;
386
406
}
387
407
}
388
408
// VxWorks compiler driver introduced `--static-crt` flag specifically for rustc,
@@ -454,8 +474,7 @@ impl<'a> Linker for GccLinker<'a> {
454
474
self . cmd . arg ( path) ;
455
475
}
456
476
fn full_relro ( & mut self ) {
457
- self . linker_arg ( "-zrelro" ) ;
458
- self . linker_arg ( "-znow" ) ;
477
+ self . linker_args ( & [ "-zrelro" , "-znow" ] ) ;
459
478
}
460
479
fn partial_relro ( & mut self ) {
461
480
self . linker_arg ( "-zrelro" ) ;
@@ -639,7 +658,6 @@ impl<'a> Linker for GccLinker<'a> {
639
658
}
640
659
641
660
let is_windows = self . sess . target . is_like_windows ;
642
- let mut arg = OsString :: new ( ) ;
643
661
let path = tmpdir. join ( if is_windows { "list.def" } else { "list" } ) ;
644
662
645
663
debug ! ( "EXPORTED SYMBOLS:" ) ;
@@ -691,27 +709,18 @@ impl<'a> Linker for GccLinker<'a> {
691
709
}
692
710
693
711
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 ( ) ] ) ;
698
713
} 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 ( ) ] ) ;
703
715
} 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 ) ;
710
722
}
711
723
}
712
-
713
- arg. push ( & path) ;
714
- self . cmd . arg ( arg) ;
715
724
}
716
725
717
726
fn subsystem ( & mut self , subsystem : & str ) {
@@ -769,8 +778,7 @@ impl<'a> Linker for GccLinker<'a> {
769
778
self . linker_arg ( "--as-needed" ) ;
770
779
} else if self . sess . target . is_like_solaris {
771
780
// -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" ] ) ;
774
782
}
775
783
}
776
784
}
0 commit comments