}
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
}
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
// 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");
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,
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");
}
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:");
}
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) {
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"]);
}
}
}