Skip to content

Commit 6bb2def

Browse files
committed
Added linker_arg(s) Linker trait methods for link-arg to be prefixed "-Wl," for cc-like linker args and not verbatim
1 parent 41fe75e commit 6bb2def

File tree

4 files changed

+97
-74
lines changed

4 files changed

+97
-74
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2527,7 +2527,7 @@ fn add_native_libs_from_crate(
25272527
NativeLibKind::WasmImportModule => {}
25282528
NativeLibKind::LinkArg => {
25292529
if link_static {
2530-
cmd.arg(name);
2530+
cmd.linker_arg(&OsString::from(name), verbatim);
25312531
}
25322532
}
25332533
}

compiler/rustc_codegen_ssa/src/back/linker.rs

+87-73
Original file line numberDiff line numberDiff line change
@@ -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

201209
impl dyn Linker + '_ {
@@ -223,38 +231,12 @@ pub struct GccLinker<'a> {
223231
}
224232

225233
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);
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

363345
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+
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
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# only-linux
2+
3+
include ../tools.mk
4+
5+
all:
6+
$(RUSTC) rs.rs -Z unstable-options -C linker-flavor=gnu-cc -l static=l1 -l link-arg=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*-Wl,a1.*l2.*-Wl,a2.*d1.*-Wl,a3'
7+
$(RUSTC) rs.rs -Z unstable-options -C linker-flavor=gnu-cc -l static=l1 -l link-arg:+verbatim=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*"a1".*l2.*-Wl,a2.*d1.*-Wl,a3'
8+
$(RUSTC) rs.rs -Z unstable-options -C linker-flavor=ld -l static=l1 -l link-arg=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*"a1".*l2.*"a2".*d1.*"a3"'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn main() {}

0 commit comments

Comments
 (0)