From eb74f21f5a66fcb667a6d7fdf9b4c2521c4d4030 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 6 Jul 2018 00:41:42 -0500 Subject: [PATCH 1/9] try to infer linker flavor from linker name and vice versa --- src/librustc/session/mod.rs | 9 +- src/librustc_codegen_llvm/back/link.rs | 108 +++++++++++++++++------ src/librustc_codegen_llvm/back/linker.rs | 5 +- src/librustc_codegen_llvm/back/write.rs | 17 ++-- 4 files changed, 97 insertions(+), 42 deletions(-) diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 9a3ce50fcbdce..58df8f336be96 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -42,7 +42,7 @@ use syntax::feature_gate::AttributeType; use syntax_pos::{MultiSpan, Span}; use util::profiling::SelfProfiler; -use rustc_target::spec::{LinkerFlavor, PanicStrategy}; +use rustc_target::spec::PanicStrategy; use rustc_target::spec::{Target, TargetTriple}; use rustc_data_structures::flock; use jobserver::Client; @@ -607,13 +607,6 @@ impl Session { .panic .unwrap_or(self.target.target.options.panic_strategy) } - pub fn linker_flavor(&self) -> LinkerFlavor { - self.opts - .debugging_opts - .linker_flavor - .unwrap_or(self.target.target.linker_flavor) - } - pub fn fewer_names(&self) -> bool { let more_names = self.opts .output_types diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index 50d41d76986fb..0317dead6c0d6 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -60,7 +60,7 @@ pub use rustc_codegen_utils::link::{find_crate_name, filename_for_input, default // The third parameter is for env vars, used on windows to set up the // path for MSVC to find its DLLs, and gcc to find its bundled // toolchain -pub fn get_linker(sess: &Session) -> (PathBuf, Command) { +pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathBuf, Command) { // If our linker looks like a batch script on Windows then to execute this // we'll need to spawn `cmd` explicitly. This is primarily done to handle // emscripten where the linker is `emcc.bat` and needs to be spawned as @@ -69,36 +69,21 @@ pub fn get_linker(sess: &Session) -> (PathBuf, Command) { // This worked historically but is needed manually since #42436 (regression // was tagged as #42791) and some more info can be found on #44443 for // emscripten itself. - let cmd = |linker: &Path| { + let mut cmd = (|| { if let Some(linker) = linker.to_str() { if cfg!(windows) && linker.ends_with(".bat") { return Command::bat_script(linker) } } - match sess.linker_flavor() { + match flavor { LinkerFlavor::Lld(f) => Command::lld(linker, f), _ => Command::new(linker), } - }; + })(); let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe"); - let linker_path = sess.opts.cg.linker.as_ref().map(|s| &**s) - .or(sess.target.target.options.linker.as_ref().map(|s| s.as_ref())) - .unwrap_or(match sess.linker_flavor() { - LinkerFlavor::Msvc => { - msvc_tool.as_ref().map(|t| t.path()).unwrap_or("link.exe".as_ref()) - } - LinkerFlavor::Em if cfg!(windows) => "emcc.bat".as_ref(), - LinkerFlavor::Em => "emcc".as_ref(), - LinkerFlavor::Gcc => "cc".as_ref(), - LinkerFlavor::Ld => "ld".as_ref(), - LinkerFlavor::Lld(_) => "lld".as_ref(), - }); - - let mut cmd = cmd(linker_path); - // The compiler's sysroot often has some bundled tools, so add it to the // PATH for the child. let mut new_path = sess.host_filesearch(PathKind::All) @@ -125,7 +110,7 @@ pub fn get_linker(sess: &Session) -> (PathBuf, Command) { } cmd.env("PATH", env::join_paths(new_path).unwrap()); - (linker_path.to_path_buf(), cmd) + (linker.to_path_buf(), cmd) } pub fn remove(sess: &Session, path: &Path) { @@ -615,6 +600,71 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary]) { } } +pub fn linker_and_flavor(sess: &Session) -> Result<(PathBuf, LinkerFlavor), ()> { + fn from( + sess: &Session, + linker: Option, + flavor: Option, + otherwise: F, + ) -> Result<(PathBuf, LinkerFlavor), ()> + where + F: FnOnce() -> Result<(PathBuf, LinkerFlavor), ()> + { + match (linker, flavor) { + (Some(linker), Some(flavor)) => Ok((linker, flavor)), + // only the linker flavor is known; use the default linker for the selected flavor + (None, Some(flavor)) => Ok((PathBuf::from(match flavor { + LinkerFlavor::Em => "emcc", + LinkerFlavor::Gcc => "gcc", + LinkerFlavor::Ld => "ld", + LinkerFlavor::Msvc => "link.exe", + LinkerFlavor::Lld(_) => "lld", + }), flavor)), + // infer the linker flavor from the linker name + (Some(linker), None) => { + let stem = linker.file_stem().and_then(|stem| stem.to_str()).ok_or_else(|| { + sess + .struct_err(&format!("couldn't extract file stem from specified linker")) + .emit(); + })?.to_owned(); + + let flavor = if stem == "emcc" { + LinkerFlavor::Em + } else if stem == "gcc" || stem.ends_with("-gcc") { + LinkerFlavor::Gcc + } else if stem == "ld" || stem == "ld.lld" || stem.ends_with("-ld") { + LinkerFlavor::Ld + } else if stem == "link" || stem == "lld-link" { + LinkerFlavor::Msvc + } else { + sess + .struct_err(&format!("couldn't infer linker flavor from specified linker")) + .emit(); + return Err(()); + }; + + Ok((linker, flavor)) + }, + (None, None) => otherwise(), + } + } + + // linker and linker flavor specified via command line have precedence over what the target + // specification specifies + from(sess, sess.opts.cg.linker.clone(), sess.opts.debugging_opts.linker_flavor, || { + from( + sess, + sess.target.target.options.linker.clone().map(PathBuf::from), + Some(sess.target.target.linker_flavor), + || { + sess + .struct_err(&format!("no linker or linker flavor information provided")) + .emit(); + Err(()) + }) + }) +} + // Create a dynamic library or executable // // This will invoke the system linker/cc to create the resulting file. This @@ -625,10 +675,15 @@ fn link_natively(sess: &Session, codegen_results: &CodegenResults, tmpdir: &Path) { info!("preparing {:?} to {:?}", crate_type, out_filename); - let flavor = sess.linker_flavor(); + let (linker, flavor) = if let Ok((linker, flavor)) = linker_and_flavor(sess) { + (linker, flavor) + } else { + sess.abort_if_errors(); + return; + }; // The invocations of cc share some flags across platforms - let (pname, mut cmd) = get_linker(sess); + let (pname, mut cmd) = get_linker(sess, &linker, flavor); let root = sess.target_filesearch(PathKind::Native).get_lib_path(); if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) { @@ -669,8 +724,8 @@ fn link_natively(sess: &Session, } { - let mut linker = codegen_results.linker_info.to_linker(cmd, &sess); - link_args(&mut *linker, sess, crate_type, tmpdir, + let mut linker = codegen_results.linker_info.to_linker(cmd, &sess, flavor); + link_args(&mut *linker, flavor, sess, crate_type, tmpdir, out_filename, codegen_results); cmd = linker.finalize(); } @@ -742,7 +797,7 @@ fn link_natively(sess: &Session, // linking executables as pie. Different versions of gcc seem to use // different quotes in the error message so don't check for them. if sess.target.target.options.linker_is_gnu && - sess.linker_flavor() != LinkerFlavor::Ld && + flavor != LinkerFlavor::Ld && (out.contains("unrecognized command line option") || out.contains("unknown argument")) && out.contains("-no-pie") && @@ -991,6 +1046,7 @@ fn exec_linker(sess: &Session, cmd: &mut Command, out_filename: &Path, tmpdir: & } fn link_args(cmd: &mut dyn Linker, + flavor: LinkerFlavor, sess: &Session, crate_type: config::CrateType, tmpdir: &Path, @@ -1075,7 +1131,7 @@ fn link_args(cmd: &mut dyn Linker, // independent executables by default. We have to pass -no-pie to // explicitly turn that off. Not applicable to ld. if sess.target.target.options.linker_is_gnu - && sess.linker_flavor() != LinkerFlavor::Ld { + && flavor != LinkerFlavor::Ld { cmd.no_position_independent_executable(); } } diff --git a/src/librustc_codegen_llvm/back/linker.rs b/src/librustc_codegen_llvm/back/linker.rs index e0a30ef5dbc9a..efa4b4d52079e 100644 --- a/src/librustc_codegen_llvm/back/linker.rs +++ b/src/librustc_codegen_llvm/back/linker.rs @@ -44,8 +44,9 @@ impl LinkerInfo { pub fn to_linker<'a>(&'a self, cmd: Command, - sess: &'a Session) -> Box { - match sess.linker_flavor() { + sess: &'a Session, + flavor: LinkerFlavor) -> Box { + match flavor { LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => { Box::new(MsvcLinker { diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 640e1c1f3d4f1..e5e837d05de38 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -1503,12 +1503,17 @@ fn start_executing_work(tcx: TyCtxt, let assembler_cmd = if modules_config.no_integrated_as { // HACK: currently we use linker (gcc) as our assembler - let (name, mut cmd) = get_linker(sess); - cmd.args(&sess.target.target.options.asm_args); - Some(Arc::new(AssemblerCommand { - name, - cmd, - })) + if let Ok((linker, flavor)) = link::linker_and_flavor(sess) { + let (name, mut cmd) = get_linker(sess, &linker, flavor); + cmd.args(&sess.target.target.options.asm_args); + Some(Arc::new(AssemblerCommand { + name, + cmd, + })) + } else { + sess.abort_if_errors(); + None + } } else { None }; From a0911cf95d3cf6bc0fe50ad95c2578771b122e64 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Thu, 9 Aug 2018 16:08:12 -0500 Subject: [PATCH 2/9] address review comments --- src/librustc_codegen_llvm/back/link.rs | 84 +++++++++++-------------- src/librustc_codegen_llvm/back/write.rs | 19 +++--- 2 files changed, 43 insertions(+), 60 deletions(-) diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index 0317dead6c0d6..c31928afb220e 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -69,18 +69,13 @@ pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathB // This worked historically but is needed manually since #42436 (regression // was tagged as #42791) and some more info can be found on #44443 for // emscripten itself. - let mut cmd = (|| { - if let Some(linker) = linker.to_str() { - if cfg!(windows) && linker.ends_with(".bat") { - return Command::bat_script(linker) - } - } - match flavor { + let mut cmd = match linker.to_str() { + Some(linker) if cfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker), + _ => match flavor { LinkerFlavor::Lld(f) => Command::lld(linker, f), _ => Command::new(linker), - } - })(); + }; let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe"); @@ -600,33 +595,26 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary]) { } } -pub fn linker_and_flavor(sess: &Session) -> Result<(PathBuf, LinkerFlavor), ()> { - fn from( +pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { + fn infer_from( sess: &Session, linker: Option, flavor: Option, - otherwise: F, - ) -> Result<(PathBuf, LinkerFlavor), ()> - where - F: FnOnce() -> Result<(PathBuf, LinkerFlavor), ()> - { + ) -> Option<(PathBuf, LinkerFlavor)> { match (linker, flavor) { - (Some(linker), Some(flavor)) => Ok((linker, flavor)), + (Some(linker), Some(flavor)) => Some((linker, flavor)), // only the linker flavor is known; use the default linker for the selected flavor - (None, Some(flavor)) => Ok((PathBuf::from(match flavor { - LinkerFlavor::Em => "emcc", + (None, Some(flavor)) => Some((PathBuf::from(match flavor { + LinkerFlavor::Em => if cfg!(windows) { "emcc.bat" } else { "emcc" }, LinkerFlavor::Gcc => "gcc", LinkerFlavor::Ld => "ld", LinkerFlavor::Msvc => "link.exe", LinkerFlavor::Lld(_) => "lld", }), flavor)), - // infer the linker flavor from the linker name (Some(linker), None) => { - let stem = linker.file_stem().and_then(|stem| stem.to_str()).ok_or_else(|| { - sess - .struct_err(&format!("couldn't extract file stem from specified linker")) - .emit(); - })?.to_owned(); + let stem = linker.file_stem().and_then(|stem| stem.to_str()).unwrap_or_else(|| { + sess.fatal("couldn't extract file stem from specified linker"); + }).to_owned(); let flavor = if stem == "emcc" { LinkerFlavor::Em @@ -637,32 +625,35 @@ pub fn linker_and_flavor(sess: &Session) -> Result<(PathBuf, LinkerFlavor), ()> } else if stem == "link" || stem == "lld-link" { LinkerFlavor::Msvc } else { - sess - .struct_err(&format!("couldn't infer linker flavor from specified linker")) - .emit(); - return Err(()); + // fall back to the value in the target spec + sess.target.target.linker_flavor }; - Ok((linker, flavor)) + Some((linker, flavor)) }, - (None, None) => otherwise(), + (None, None) => None, } } // linker and linker flavor specified via command line have precedence over what the target // specification specifies - from(sess, sess.opts.cg.linker.clone(), sess.opts.debugging_opts.linker_flavor, || { - from( - sess, - sess.target.target.options.linker.clone().map(PathBuf::from), - Some(sess.target.target.linker_flavor), - || { - sess - .struct_err(&format!("no linker or linker flavor information provided")) - .emit(); - Err(()) - }) - }) + if let Some(ret) = infer_from( + sess, + sess.opts.cg.linker.clone(), + sess.opts.debugging_opts.linker_flavor, + ) { + return ret; + } + + if let Some(ret) = infer_from( + sess, + sess.target.target.options.linker.clone().map(PathBuf::from), + Some(sess.target.target.linker_flavor), + ) { + return ret; + } + + sess.fatal("Not enough information provided to determine how to invoke the linker"); } // Create a dynamic library or executable @@ -675,12 +666,7 @@ fn link_natively(sess: &Session, codegen_results: &CodegenResults, tmpdir: &Path) { info!("preparing {:?} to {:?}", crate_type, out_filename); - let (linker, flavor) = if let Ok((linker, flavor)) = linker_and_flavor(sess) { - (linker, flavor) - } else { - sess.abort_if_errors(); - return; - }; + let (linker, flavor) = linker_and_flavor(sess); // The invocations of cc share some flags across platforms let (pname, mut cmd) = get_linker(sess, &linker, flavor); diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index e5e837d05de38..14abbe3f183d7 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -1503,17 +1503,14 @@ fn start_executing_work(tcx: TyCtxt, let assembler_cmd = if modules_config.no_integrated_as { // HACK: currently we use linker (gcc) as our assembler - if let Ok((linker, flavor)) = link::linker_and_flavor(sess) { - let (name, mut cmd) = get_linker(sess, &linker, flavor); - cmd.args(&sess.target.target.options.asm_args); - Some(Arc::new(AssemblerCommand { - name, - cmd, - })) - } else { - sess.abort_if_errors(); - None - } + let (linker, flavor) = link::linker_and_flavor(sess); + + let (name, mut cmd) = get_linker(sess, &linker, flavor); + cmd.args(&sess.target.target.options.asm_args); + Some(Arc::new(AssemblerCommand { + name, + cmd, + })) } else { None }; From 750e72b9e0881529dad5010862ffc8dec7c28fe8 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 18 Aug 2018 16:31:36 +0200 Subject: [PATCH 3/9] add lld_flavor info to target spec this field defaults to the LD / GNU flavor --- src/librustc_codegen_llvm/back/link.rs | 2 ++ src/librustc_target/spec/mod.rs | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index c31928afb220e..86cef587d5b90 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -624,6 +624,8 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { LinkerFlavor::Ld } else if stem == "link" || stem == "lld-link" { LinkerFlavor::Msvc + } else if stem == "lld" || stem == "rust-lld" { + LinkerFlavor::Lld(sess.target.target.options.lld_flavor) } else { // fall back to the value in the target spec sess.target.target.linker_flavor diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 6faab77d7709f..98b20f00265e8 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -433,6 +433,9 @@ pub struct TargetOptions { /// Linker to invoke pub linker: Option, + /// LLD flavor + pub lld_flavor: LldFlavor, + /// Linker arguments that are passed *before* any user-defined libraries. pub pre_link_args: LinkArgs, // ... unconditionally pub pre_link_args_crt: LinkArgs, // ... when linking with a bundled crt @@ -650,6 +653,7 @@ impl Default for TargetOptions { TargetOptions { is_builtin: false, linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.to_string()), + lld_flavor: LldFlavor::Ld, pre_link_args: LinkArgs::new(), pre_link_args_crt: LinkArgs::new(), post_link_args: LinkArgs::new(), From 27390fcbcb38cee66a6ebbe2ca74789436882779 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 18 Aug 2018 16:36:24 +0200 Subject: [PATCH 4/9] wasm32-unknown-unknown uses the WASM LLD flavor --- src/librustc_target/spec/wasm32_unknown_unknown.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_target/spec/wasm32_unknown_unknown.rs b/src/librustc_target/spec/wasm32_unknown_unknown.rs index 51d402e197da9..94e7739b1a05a 100644 --- a/src/librustc_target/spec/wasm32_unknown_unknown.rs +++ b/src/librustc_target/spec/wasm32_unknown_unknown.rs @@ -53,6 +53,7 @@ pub fn target() -> Result { // we use the LLD shipped with the Rust toolchain by default linker: Some("rust-lld".to_owned()), + lld_flavor: LldFlavor::Wasm, .. Default::default() }; From cafeb6f05b95a888267fd525597ec8a3fb737b40 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 18 Aug 2018 17:19:42 +0200 Subject: [PATCH 5/9] fatal -> bug --- src/librustc_codegen_llvm/back/link.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index 86cef587d5b90..f29b4d95b28fa 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -655,7 +655,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { return ret; } - sess.fatal("Not enough information provided to determine how to invoke the linker"); + bug!("Not enough information provided to determine how to invoke the linker"); } // Create a dynamic library or executable From 4bbedd7dd21f3bb01ec144035918fb29942b9b7d Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 18 Aug 2018 20:16:04 +0200 Subject: [PATCH 6/9] fully implement lld-flavor --- src/librustc_target/spec/mod.rs | 39 +++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 98b20f00265e8..a6c0fdccd3327 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -94,6 +94,29 @@ pub enum LldFlavor { Link, } +impl LldFlavor { + fn from_str(s: &str) -> Option { + Some(match s { + "darwin" => LldFlavor::Ld64, + "gnu" => LldFlavor::Ld, + "link" => LldFlavor::Link, + "wasm" => LldFlavor::Wasm, + _ => return None, + }) + } +} + +impl ToJson for LldFlavor { + fn to_json(&self) -> Json { + match *self { + LldFlavor::Ld64 => "darwin", + LldFlavor::Ld => "gnu", + LldFlavor::Link => "link", + LldFlavor::Wasm => "wasm", + }.to_json() + } +} + impl ToJson for LinkerFlavor { fn to_json(&self) -> Json { self.desc().to_json() @@ -860,6 +883,20 @@ impl Target { .map(|s| s.to_string() ); } } ); + ($key_name:ident, LldFlavor) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + if let Some(flavor) = LldFlavor::from_str(&s) { + base.options.$key_name = flavor; + } else { + return Some(Err(format!( + "'{}' is not a valid value for lld-flavor. \ + Use 'darwin', 'gnu', 'link' or 'wasm.", + s))) + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); ($key_name:ident, LinkerFlavor) => ( { let name = (stringify!($key_name)).replace("_", "-"); obj.find(&name[..]).and_then(|o| o.as_string().map(|s| { @@ -915,6 +952,7 @@ impl Target { key!(is_builtin, bool); key!(linker, optional); + try!(key!(lld_flavor, LldFlavor)); key!(pre_link_args, link_args); key!(pre_link_args_crt, link_args); key!(pre_link_objects_exe, list); @@ -1124,6 +1162,7 @@ impl ToJson for Target { target_option_val!(is_builtin); target_option_val!(linker); + target_option_val!(lld_flavor); target_option_val!(link_args - pre_link_args); target_option_val!(link_args - pre_link_args_crt); target_option_val!(pre_link_objects_exe); From c8ef8b6602732e5448cfd0d9d05c955aa1815aed Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sun, 19 Aug 2018 09:39:19 +0200 Subject: [PATCH 7/9] LinkerFlavor::Gcc defaults to cc, not gcc --- src/librustc_codegen_llvm/back/link.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index f29b4d95b28fa..227ae22e69359 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -606,7 +606,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { // only the linker flavor is known; use the default linker for the selected flavor (None, Some(flavor)) => Some((PathBuf::from(match flavor { LinkerFlavor::Em => if cfg!(windows) { "emcc.bat" } else { "emcc" }, - LinkerFlavor::Gcc => "gcc", + LinkerFlavor::Gcc => "cc", LinkerFlavor::Ld => "ld", LinkerFlavor::Msvc => "link.exe", LinkerFlavor::Lld(_) => "lld", From 98e4cd50f9908dcf2330196baa756a775343e47d Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sun, 19 Aug 2018 12:35:58 +0200 Subject: [PATCH 8/9] fix: use detected MSVC's link.exe --- src/librustc_codegen_llvm/back/link.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index 227ae22e69359..afbcaf4c659d7 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -61,6 +61,8 @@ pub use rustc_codegen_utils::link::{find_crate_name, filename_for_input, default // path for MSVC to find its DLLs, and gcc to find its bundled // toolchain pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathBuf, Command) { + let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe"); + // If our linker looks like a batch script on Windows then to execute this // we'll need to spawn `cmd` explicitly. This is primarily done to handle // emscripten where the linker is `emcc.bat` and needs to be spawned as @@ -73,12 +75,13 @@ pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathB Some(linker) if cfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker), _ => match flavor { LinkerFlavor::Lld(f) => Command::lld(linker, f), + LinkerFlavor::Msvc => { + Command::new(msvc_tool.as_ref().map(|t| t.path()).unwrap_or(linker)) + }, _ => Command::new(linker), } }; - let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe"); - // The compiler's sysroot often has some bundled tools, so add it to the // PATH for the child. let mut new_path = sess.host_filesearch(PathKind::All) From a6f4ae864eb9a99117f7475325bf9ffb2c8e8b90 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sun, 19 Aug 2018 23:59:20 +0200 Subject: [PATCH 9/9] fix: preserve msvc linker fallback logic --- src/librustc_codegen_llvm/back/link.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index afbcaf4c659d7..91515d1c85b86 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -75,7 +75,9 @@ pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathB Some(linker) if cfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker), _ => match flavor { LinkerFlavor::Lld(f) => Command::lld(linker, f), - LinkerFlavor::Msvc => { + LinkerFlavor::Msvc + if sess.opts.cg.linker.is_none() && sess.target.target.options.linker.is_none() => + { Command::new(msvc_tool.as_ref().map(|t| t.path()).unwrap_or(linker)) }, _ => Command::new(linker),