Skip to content

Commit c66858d

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 e24e5af commit c66858d

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
@@ -2522,7 +2522,7 @@ fn add_native_libs_from_crate(
25222522
NativeLibKind::WasmImportModule => {}
25232523
NativeLibKind::LinkArg => {
25242524
if link_static {
2525-
cmd.arg(name);
2525+
cmd.linker_arg(&OsString::from(name), verbatim);
25262526
}
25272527
}
25282528
}

compiler/rustc_codegen_ssa/src/back/linker.rs

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

200208
impl dyn Linker + '_ {
@@ -222,38 +230,12 @@ pub struct GccLinker<'a> {
222230
}
223231

224232
impl<'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

362344
impl<'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
}
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)