Skip to content

Commit

Permalink
Rollup merge of #118202 - azhogin:azhogin/link_args_wrapping, r=petro…
Browse files Browse the repository at this point in the history
…chenkov

Added linker_arg(s) Linker trait methods for link-arg to be prefixed "-Wl," for cc-like linker args and not verbatim

#99427 (comment)

> here's one possible improvement to -l link-arg making it more portable between linkers and useful - befriending it with the verbatim modifier (#99425).
>
> -l link-arg:-verbatim=-foo would add -Wl,-foo (or equivalent) when C compiler is used as a linker, and just -foo when bare linker is used.
> -l link-arg:+verbatim=-bar on the other hand would always pass just -bar.
  • Loading branch information
compiler-errors committed Nov 28, 2023
2 parents 7aa513b + 7a88458 commit 4936b3a
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 34 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ use tempfile::Builder as TempFileBuilder;
use itertools::Itertools;
use std::cell::OnceCell;
use std::collections::BTreeSet;
use std::ffi::OsString;
use std::ffi::{OsStr, OsString};
use std::fs::{read, File, OpenOptions};
use std::io::{BufWriter, Write};
use std::ops::Deref;
Expand Down Expand Up @@ -2527,7 +2527,7 @@ fn add_native_libs_from_crate(
NativeLibKind::WasmImportModule => {}
NativeLibKind::LinkArg => {
if link_static {
cmd.arg(name);
cmd.linker_arg(OsStr::new(name), verbatim);
}
}
}
Expand Down
70 changes: 38 additions & 32 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,14 @@ pub trait Linker {
fn add_no_exec(&mut self) {}
fn add_as_needed(&mut self) {}
fn reset_per_library_state(&mut self) {}
fn linker_arg(&mut self, arg: &OsStr, verbatim: bool) {
self.linker_args(&[arg], verbatim);
}
fn linker_args(&mut self, args: &[&OsStr], _verbatim: bool) {
args.into_iter().for_each(|a| {
self.cmd().arg(a);
});
}
}

impl dyn Linker + '_ {
Expand Down Expand Up @@ -223,38 +231,12 @@ pub struct GccLinker<'a> {
}

impl<'a> GccLinker<'a> {
/// Passes an argument directly to the linker.
///
/// When the linker is not ld-like such as when using a compiler as a linker, the argument is
/// prepended by `-Wl,`.
fn linker_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
self.linker_args(&[arg]);
self
fn linker_arg(&mut self, arg: impl AsRef<OsStr>) {
Linker::linker_arg(self, arg.as_ref(), false);
}

/// Passes a series of arguments directly to the linker.
///
/// When the linker is ld-like, the arguments are simply appended to the command. When the
/// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by
/// commas to form an argument that is then prepended with `-Wl`. In this situation, only a
/// single argument is appended to the command to ensure that the order of the arguments is
/// preserved by the compiler.
fn linker_args(&mut self, args: &[impl AsRef<OsStr>]) -> &mut Self {
if self.is_ld {
args.into_iter().for_each(|a| {
self.cmd.arg(a);
});
} else {
if !args.is_empty() {
let mut s = OsString::from("-Wl");
for a in args {
s.push(",");
s.push(a);
}
self.cmd.arg(s);
}
}
self
fn linker_args(&mut self, args: &[impl AsRef<OsStr>]) {
let args_vec: Vec<&OsStr> = args.iter().map(|x| x.as_ref()).collect();
Linker::linker_args(self, &args_vec, false);
}

fn takes_hints(&self) -> bool {
Expand Down Expand Up @@ -361,6 +343,30 @@ impl<'a> GccLinker<'a> {
}

impl<'a> Linker for GccLinker<'a> {
/// Passes a series of arguments directly to the linker.
///
/// When the linker is ld-like, the arguments are simply appended to the command. When the
/// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by
/// commas to form an argument that is then prepended with `-Wl`. In this situation, only a
/// single argument is appended to the command to ensure that the order of the arguments is
/// preserved by the compiler.
fn linker_args(&mut self, args: &[&OsStr], verbatim: bool) {
if self.is_ld || verbatim {
args.into_iter().for_each(|a| {
self.cmd.arg(a);
});
} else {
if !args.is_empty() {
let mut s = OsString::from("-Wl");
for a in args {
s.push(",");
s.push(a);
}
self.cmd.arg(s);
}
}
}

fn cmd(&mut self) -> &mut Command {
&mut self.cmd
}
Expand Down Expand Up @@ -531,7 +537,7 @@ impl<'a> Linker for GccLinker<'a> {
self.linker_arg("-force_load");
self.linker_arg(&lib);
} else {
self.linker_arg("--whole-archive").cmd.arg(lib);
self.linker_args(&[OsString::from("--whole-archive"), lib.into()]);
self.linker_arg("--no-whole-archive");
}
}
Expand Down
8 changes: 8 additions & 0 deletions tests/run-make/pass-linker-flags-flavor/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# only-linux

include ../tools.mk

all:
$(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'
$(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'
$(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"'
1 change: 1 addition & 0 deletions tests/run-make/pass-linker-flags-flavor/rs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fn main() {}

0 comments on commit 4936b3a

Please sign in to comment.