Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ld64 flags #90717

Merged
merged 3 commits into from
Nov 15, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 50 additions & 42 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,19 +219,36 @@ pub struct GccLinker<'a> {
}

impl<'a> GccLinker<'a> {
/// Argument that must be passed *directly* to the linker
/// Passes an argument directly to the linker.
///
/// These arguments need to be prepended with `-Wl`, when a GCC-style linker is used.
fn linker_arg<S>(&mut self, arg: S) -> &mut Self
where
S: AsRef<OsStr>,
{
if !self.is_ld {
let mut os = OsString::from("-Wl,");
os.push(arg.as_ref());
self.cmd.arg(os);
/// 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
}

/// 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 {
self.cmd.arg(arg);
if !args.is_empty() {
let mut s = OsString::from("-Wl");
for a in args {
s.push(",");
s.push(a);
}
self.cmd.arg(s);
}
}
self
}
Expand Down Expand Up @@ -289,25 +306,29 @@ impl<'a> GccLinker<'a> {
if let Some(path) = &self.sess.opts.debugging_opts.profile_sample_use {
self.linker_arg(&format!("-plugin-opt=sample-profile={}", path.display()));
};
self.linker_arg(&format!("-plugin-opt={}", opt_level));
self.linker_arg(&format!("-plugin-opt=mcpu={}", self.target_cpu));
self.linker_args(&[
&format!("-plugin-opt={}", opt_level),
&format!("-plugin-opt=mcpu={}", self.target_cpu),
]);
}

fn build_dylib(&mut self, out_filename: &Path) {
// On mac we need to tell the linker to let this library be rpathed
if self.sess.target.is_like_osx {
self.cmd.arg("-dynamiclib");
if !self.is_ld {
self.cmd.arg("-dynamiclib");
}

self.linker_arg("-dylib");

// Note that the `osx_rpath_install_name` option here is a hack
// purely to support rustbuild right now, we should get a more
// principled solution at some point to force the compiler to pass
// the right `-Wl,-install_name` with an `@rpath` in it.
if self.sess.opts.cg.rpath || self.sess.opts.debugging_opts.osx_rpath_install_name {
self.linker_arg("-install_name");
let mut v = OsString::from("@rpath/");
v.push(out_filename.file_name().unwrap());
self.linker_arg(&v);
let mut rpath = OsString::from("@rpath/");
rpath.push(out_filename.file_name().unwrap());
self.linker_args(&[OsString::from("-install_name"), rpath]);
}
} else {
self.cmd.arg("-shared");
Expand Down Expand Up @@ -381,8 +402,7 @@ impl<'a> Linker for GccLinker<'a> {
self.build_dylib(out_filename);
}
LinkOutputKind::WasiReactorExe => {
self.linker_arg("--entry");
self.linker_arg("_initialize");
self.linker_args(&["--entry", "_initialize"]);
}
}
// VxWorks compiler driver introduced `--static-crt` flag specifically for rustc,
Expand Down Expand Up @@ -454,8 +474,7 @@ impl<'a> Linker for GccLinker<'a> {
self.cmd.arg(path);
}
fn full_relro(&mut self) {
self.linker_arg("-zrelro");
self.linker_arg("-znow");
self.linker_args(&["-zrelro", "-znow"]);
}
fn partial_relro(&mut self) {
self.linker_arg("-zrelro");
Expand Down Expand Up @@ -639,7 +658,6 @@ impl<'a> Linker for GccLinker<'a> {
}

let is_windows = self.sess.target.is_like_windows;
let mut arg = OsString::new();
let path = tmpdir.join(if is_windows { "list.def" } else { "list" });

debug!("EXPORTED SYMBOLS:");
Expand Down Expand Up @@ -691,27 +709,18 @@ impl<'a> Linker for GccLinker<'a> {
}

if self.sess.target.is_like_osx {
if !self.is_ld {
arg.push("-Wl,")
}
arg.push("-exported_symbols_list,");
self.linker_args(&[OsString::from("-exported_symbols_list"), path.into()]);
} else if self.sess.target.is_like_solaris {
if !self.is_ld {
arg.push("-Wl,")
}
arg.push("-M,");
self.linker_args(&[OsString::from("-M"), path.into()]);
} else {
if !self.is_ld {
arg.push("-Wl,")
}
// Both LD and LLD accept export list in *.def file form, there are no flags required
if !is_windows {
arg.push("--version-script=")
if is_windows {
self.linker_arg(path);
} else {
let mut arg = OsString::from("--version-script=");
arg.push(path);
self.linker_arg(arg);
}
}

arg.push(&path);
self.cmd.arg(arg);
}

fn subsystem(&mut self, subsystem: &str) {
Expand Down Expand Up @@ -769,8 +778,7 @@ impl<'a> Linker for GccLinker<'a> {
self.linker_arg("--as-needed");
} else if self.sess.target.is_like_solaris {
// -z ignore is the Solaris equivalent to the GNU ld --as-needed option
self.linker_arg("-z");
self.linker_arg("ignore");
self.linker_args(&["-z", "ignore"]);
}
}
}
Expand Down