From 0129b01a41a062f82909cecdfd0cc7f0093c71f8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 10 Feb 2018 12:09:25 -0800 Subject: [PATCH] rustc: Tweak default linker selection This commit refactors how the path to the linker that we're going to invoke is selected. Previously all targets listed *both* a `LinkerFlavor` and a `linker` (path) option, but this meant that whenever you changed one you had to change the other. The purpose of this commit is to avoid coupling these where possible. Target specifications now only unconditionally define the *flavor* of the linker that they're using by default. If not otherwise specified each flavor now implies a particular default linker to run. As a result, this means that if you'd like to test out `ld` for example you should be able to do: rustc -Z linker-flavor=ld foo.rs whereas previously you had to do rustc -Z linker-flavor=ld -C linker=ld foo.rs This will hopefully make it a bit easier to tinker around with variants that should otherwise be well known to work, for example with LLD, `ld` on OSX, etc. --- src/bootstrap/dist.rs | 6 +- src/bootstrap/native.rs | 13 ++- src/librustc_back/lib.rs | 6 ++ .../target/aarch64_unknown_cloudabi.rs | 2 +- .../target/armv7_unknown_cloudabi_eabihf.rs | 2 +- .../target/asmjs_unknown_emscripten.rs | 3 - src/librustc_back/target/emscripten_base.rs | 17 ---- src/librustc_back/target/haiku_base.rs | 1 - .../target/i686_unknown_cloudabi.rs | 2 +- src/librustc_back/target/l4re_base.rs | 1 - src/librustc_back/target/mod.rs | 9 +- src/librustc_back/target/msp430_none_elf.rs | 2 +- src/librustc_back/target/thumb_base.rs | 2 +- .../target/wasm32_experimental_emscripten.rs | 3 - .../target/wasm32_unknown_emscripten.rs | 3 - .../target/wasm32_unknown_unknown.rs | 2 - src/librustc_back/target/windows_base.rs | 2 +- src/librustc_back/target/windows_msvc_base.rs | 1 - .../target/x86_64_rumprun_netbsd.rs | 2 +- .../target/x86_64_unknown_cloudabi.rs | 2 +- src/librustc_trans/Cargo.toml | 4 +- src/librustc_trans/back/command.rs | 14 +-- src/librustc_trans/back/link.rs | 95 +++++++++---------- src/librustc_trans/back/linker.rs | 4 + src/librustc_trans/back/write.rs | 2 +- src/librustc_trans/lib.rs | 1 - 26 files changed, 83 insertions(+), 118 deletions(-) delete mode 100644 src/librustc_back/target/emscripten_base.rs diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 02ef7c0e1ff6..576e50782474 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -606,8 +606,10 @@ impl Step for Std { let mut src = builder.sysroot_libdir(compiler, target).to_path_buf(); src.pop(); // Remove the trailing /lib folder from the sysroot_libdir cp_filtered(&src, &dst, &|path| { - path.file_name().and_then(|s| s.to_str()) != - Some(build.config.rust_codegen_backends_dir.as_str()) + let name = path.file_name().and_then(|s| s.to_str()); + name != Some(build.config.rust_codegen_backends_dir.as_str()) && + name != Some("bin") + }); let mut cmd = rust_installer(builder); diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 987d70fd047f..7888f0b938d9 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -208,7 +208,7 @@ impl Step for Llvm { cfg.define("LLVM_NATIVE_BUILD", build.llvm_out(build.build).join("build")); } - configure_cmake(build, target, &mut cfg); + configure_cmake(build, target, &mut cfg, false); // FIXME: we don't actually need to build all LLVM tools and all LLVM // libraries here, e.g. we just want a few components and a few @@ -241,7 +241,8 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) { fn configure_cmake(build: &Build, target: Interned, - cfg: &mut cmake::Config) { + cfg: &mut cmake::Config, + building_dist_binaries: bool) { if build.config.ninja { cfg.generator("Ninja"); } @@ -294,8 +295,10 @@ fn configure_cmake(build: &Build, cfg.build_arg("-j").build_arg(build.jobs().to_string()); cfg.define("CMAKE_C_FLAGS", build.cflags(target).join(" ")); let mut cxxflags = build.cflags(target).join(" "); - if build.config.llvm_static_stdcpp && !target.contains("windows") { - cxxflags.push_str(" -static-libstdc++"); + if building_dist_binaries { + if build.config.llvm_static_stdcpp && !target.contains("windows") { + cxxflags.push_str(" -static-libstdc++"); + } } cfg.define("CMAKE_CXX_FLAGS", cxxflags); if let Some(ar) = build.ar(target) { @@ -350,7 +353,7 @@ impl Step for Lld { t!(fs::create_dir_all(&out_dir)); let mut cfg = cmake::Config::new(build.src.join("src/tools/lld")); - configure_cmake(build, target, &mut cfg); + configure_cmake(build, target, &mut cfg, true); cfg.out_dir(&out_dir) .profile("Release") diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index 141c8954a330..9de56cca3394 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -57,6 +57,9 @@ pub enum LinkerFlavor { RustcEncodable, RustcDecodable)] pub enum LldFlavor { Wasm, + Ld64, + Ld, + Link, } impl ToJson for LinkerFlavor { @@ -94,6 +97,9 @@ flavor_mappings! { ((LinkerFlavor::Ld), "ld"), ((LinkerFlavor::Msvc), "msvc"), ((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"), + ((LinkerFlavor::Lld(LldFlavor::Ld64)), "ld64.lld"), + ((LinkerFlavor::Lld(LldFlavor::Ld)), "ld.lld"), + ((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"), } #[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)] diff --git a/src/librustc_back/target/aarch64_unknown_cloudabi.rs b/src/librustc_back/target/aarch64_unknown_cloudabi.rs index 59c82e06a679..a5d0e5bf166d 100644 --- a/src/librustc_back/target/aarch64_unknown_cloudabi.rs +++ b/src/librustc_back/target/aarch64_unknown_cloudabi.rs @@ -15,7 +15,7 @@ pub fn target() -> TargetResult { let mut base = super::cloudabi_base::opts(); base.max_atomic_width = Some(128); base.abi_blacklist = super::arm_base::abi_blacklist(); - base.linker = "aarch64-unknown-cloudabi-cc".to_string(); + base.linker = Some("aarch64-unknown-cloudabi-cc".to_string()); Ok(Target { llvm_target: "aarch64-unknown-cloudabi".to_string(), diff --git a/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs b/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs index faa2c4fdceb9..fa66a35abbf3 100644 --- a/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs +++ b/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs @@ -17,7 +17,7 @@ pub fn target() -> TargetResult { base.max_atomic_width = Some(64); base.features = "+v7,+vfp3,+neon".to_string(); base.abi_blacklist = super::arm_base::abi_blacklist(); - base.linker = "armv7-unknown-cloudabi-eabihf-cc".to_string(); + base.linker = Some("armv7-unknown-cloudabi-eabihf-cc".to_string()); Ok(Target { llvm_target: "armv7-unknown-cloudabi-eabihf".to_string(), diff --git a/src/librustc_back/target/asmjs_unknown_emscripten.rs b/src/librustc_back/target/asmjs_unknown_emscripten.rs index 5d9f0f6012bf..f114926740a5 100644 --- a/src/librustc_back/target/asmjs_unknown_emscripten.rs +++ b/src/librustc_back/target/asmjs_unknown_emscripten.rs @@ -10,7 +10,6 @@ use LinkerFlavor; use super::{LinkArgs, Target, TargetOptions}; -use super::emscripten_base::{cmd}; pub fn target() -> Result { let mut args = LinkArgs::new(); @@ -19,8 +18,6 @@ pub fn target() -> Result { "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]); let opts = TargetOptions { - linker: cmd("emcc"), - dynamic_linking: false, executables: true, exe_suffix: ".js".to_string(), diff --git a/src/librustc_back/target/emscripten_base.rs b/src/librustc_back/target/emscripten_base.rs deleted file mode 100644 index bacada3f5ab0..000000000000 --- a/src/librustc_back/target/emscripten_base.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub fn cmd(name: &str) -> String { - if cfg!(windows) { - format!("{}.bat", name) - } else { - name.to_string() - } -} diff --git a/src/librustc_back/target/haiku_base.rs b/src/librustc_back/target/haiku_base.rs index 112f424f7a8b..a1ccb632cab7 100644 --- a/src/librustc_back/target/haiku_base.rs +++ b/src/librustc_back/target/haiku_base.rs @@ -13,7 +13,6 @@ use std::default::Default; pub fn opts() -> TargetOptions { TargetOptions { - linker: "cc".to_string(), dynamic_linking: true, executables: true, has_rpath: false, diff --git a/src/librustc_back/target/i686_unknown_cloudabi.rs b/src/librustc_back/target/i686_unknown_cloudabi.rs index e244f443d3e3..69c3b298caba 100644 --- a/src/librustc_back/target/i686_unknown_cloudabi.rs +++ b/src/librustc_back/target/i686_unknown_cloudabi.rs @@ -15,7 +15,7 @@ pub fn target() -> TargetResult { let mut base = super::cloudabi_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.linker = "i686-unknown-cloudabi-cc".to_string(); + base.linker = Some("i686-unknown-cloudabi-cc".to_string()); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); base.stack_probes = true; diff --git a/src/librustc_back/target/l4re_base.rs b/src/librustc_back/target/l4re_base.rs index 31d428d26683..7cb7f8d613de 100644 --- a/src/librustc_back/target/l4re_base.rs +++ b/src/librustc_back/target/l4re_base.rs @@ -73,7 +73,6 @@ pub fn opts() -> Result { has_elf_tls: false, exe_allocation_crate: None, panic_strategy: PanicStrategy::Abort, - linker: "ld".to_string(), pre_link_args, post_link_args, target_family: Some("unix".to_string()), diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index be69127d8f2a..0a3e1826f3a1 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -58,7 +58,6 @@ mod arm_base; mod bitrig_base; mod cloudabi_base; mod dragonfly_base; -mod emscripten_base; mod freebsd_base; mod haiku_base; mod linux_base; @@ -279,8 +278,8 @@ pub struct TargetOptions { /// Whether the target is built-in or loaded from a custom target specification. pub is_builtin: bool, - /// Linker to invoke. Defaults to "cc". - pub linker: String, + /// Linker to invoke + pub linker: Option, /// Linker arguments that are unconditionally passed *before* any /// user-defined libraries. @@ -482,7 +481,7 @@ impl Default for TargetOptions { fn default() -> TargetOptions { TargetOptions { is_builtin: false, - linker: option_env!("CFG_DEFAULT_LINKER").unwrap_or("cc").to_string(), + linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.to_string()), pre_link_args: LinkArgs::new(), post_link_args: LinkArgs::new(), asm_args: Vec::new(), @@ -732,7 +731,7 @@ impl Target { } key!(is_builtin, bool); - key!(linker); + key!(linker, optional); key!(pre_link_args, link_args); key!(pre_link_objects_exe, list); key!(pre_link_objects_dll, list); diff --git a/src/librustc_back/target/msp430_none_elf.rs b/src/librustc_back/target/msp430_none_elf.rs index 966df897f01f..d0f512ae47cd 100644 --- a/src/librustc_back/target/msp430_none_elf.rs +++ b/src/librustc_back/target/msp430_none_elf.rs @@ -32,7 +32,7 @@ pub fn target() -> TargetResult { // to gcc to get object files. For this reason we have a hard // dependency on this specific gcc. asm_args: vec!["-mcpu=msp430".to_string()], - linker: "msp430-elf-gcc".to_string(), + linker: Some("msp430-elf-gcc".to_string()), no_integrated_as: true, // There are no atomic instructions available in the MSP430 diff --git a/src/librustc_back/target/thumb_base.rs b/src/librustc_back/target/thumb_base.rs index 6bb496649a85..6a8f52f50931 100644 --- a/src/librustc_back/target/thumb_base.rs +++ b/src/librustc_back/target/thumb_base.rs @@ -45,7 +45,7 @@ pub fn opts() -> TargetOptions { executables: true, // In 99%+ of cases, we want to use the `arm-none-eabi-gcc` compiler (there aren't many // options around) - linker: "arm-none-eabi-gcc".to_string(), + linker: Some("arm-none-eabi-gcc".to_string()), // Because these devices have very little resources having an unwinder is too onerous so we // default to "abort" because the "unwind" strategy is very rare. panic_strategy: PanicStrategy::Abort, diff --git a/src/librustc_back/target/wasm32_experimental_emscripten.rs b/src/librustc_back/target/wasm32_experimental_emscripten.rs index a261c982b3f2..13dee3a57686 100644 --- a/src/librustc_back/target/wasm32_experimental_emscripten.rs +++ b/src/librustc_back/target/wasm32_experimental_emscripten.rs @@ -10,7 +10,6 @@ use LinkerFlavor; use super::{LinkArgs, Target, TargetOptions}; -use super::emscripten_base::{cmd}; pub fn target() -> Result { let mut post_link_args = LinkArgs::new(); @@ -24,8 +23,6 @@ pub fn target() -> Result { "-g3".to_string()]); let opts = TargetOptions { - linker: cmd("emcc"), - dynamic_linking: false, executables: true, // Today emcc emits two files - a .js file to bootstrap and diff --git a/src/librustc_back/target/wasm32_unknown_emscripten.rs b/src/librustc_back/target/wasm32_unknown_emscripten.rs index 4823541f2262..2770e67e30a5 100644 --- a/src/librustc_back/target/wasm32_unknown_emscripten.rs +++ b/src/librustc_back/target/wasm32_unknown_emscripten.rs @@ -10,7 +10,6 @@ use LinkerFlavor; use super::{LinkArgs, Target, TargetOptions}; -use super::emscripten_base::{cmd}; pub fn target() -> Result { let mut post_link_args = LinkArgs::new(); @@ -21,8 +20,6 @@ pub fn target() -> Result { "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]); let opts = TargetOptions { - linker: cmd("emcc"), - dynamic_linking: false, executables: true, // Today emcc emits two files - a .js file to bootstrap and diff --git a/src/librustc_back/target/wasm32_unknown_unknown.rs b/src/librustc_back/target/wasm32_unknown_unknown.rs index c771762cfc89..1d84e1375174 100644 --- a/src/librustc_back/target/wasm32_unknown_unknown.rs +++ b/src/librustc_back/target/wasm32_unknown_unknown.rs @@ -22,8 +22,6 @@ use super::{Target, TargetOptions, PanicStrategy}; pub fn target() -> Result { let opts = TargetOptions { - linker: "lld".to_string(), - // we allow dynamic linking, but only cdylibs. Basically we allow a // final library artifact that exports some symbols (a wasm module) but // we don't allow intermediate `dylib` crate types diff --git a/src/librustc_back/target/windows_base.rs b/src/librustc_back/target/windows_base.rs index 30038400f6c8..05b6247c9518 100644 --- a/src/librustc_back/target/windows_base.rs +++ b/src/librustc_back/target/windows_base.rs @@ -75,7 +75,7 @@ pub fn opts() -> TargetOptions { TargetOptions { // FIXME(#13846) this should be enabled for windows function_sections: false, - linker: "gcc".to_string(), + linker: Some("gcc".to_string()), dynamic_linking: true, executables: true, dll_prefix: "".to_string(), diff --git a/src/librustc_back/target/windows_msvc_base.rs b/src/librustc_back/target/windows_msvc_base.rs index e0bf36ee4077..34aa17267f8b 100644 --- a/src/librustc_back/target/windows_msvc_base.rs +++ b/src/librustc_back/target/windows_msvc_base.rs @@ -20,7 +20,6 @@ pub fn opts() -> TargetOptions { TargetOptions { function_sections: true, - linker: "link.exe".to_string(), dynamic_linking: true, executables: true, dll_prefix: "".to_string(), diff --git a/src/librustc_back/target/x86_64_rumprun_netbsd.rs b/src/librustc_back/target/x86_64_rumprun_netbsd.rs index 18f6380b6eed..3158665a2e28 100644 --- a/src/librustc_back/target/x86_64_rumprun_netbsd.rs +++ b/src/librustc_back/target/x86_64_rumprun_netbsd.rs @@ -15,7 +15,7 @@ pub fn target() -> TargetResult { let mut base = super::netbsd_base::opts(); base.cpu = "x86-64".to_string(); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); - base.linker = "x86_64-rumprun-netbsd-gcc".to_string(); + base.linker = Some("x86_64-rumprun-netbsd-gcc".to_string()); base.max_atomic_width = Some(64); base.dynamic_linking = false; diff --git a/src/librustc_back/target/x86_64_unknown_cloudabi.rs b/src/librustc_back/target/x86_64_unknown_cloudabi.rs index 1ce3c6444f1e..d1a9cb1cd7e7 100644 --- a/src/librustc_back/target/x86_64_unknown_cloudabi.rs +++ b/src/librustc_back/target/x86_64_unknown_cloudabi.rs @@ -15,7 +15,7 @@ pub fn target() -> TargetResult { let mut base = super::cloudabi_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.linker = "x86_64-unknown-cloudabi-cc".to_string(); + base.linker = Some("x86_64-unknown-cloudabi-cc".to_string()); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); base.stack_probes = true; diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index 4b9c93088a51..805d2086ee4f 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -11,6 +11,7 @@ test = false [dependencies] bitflags = "1.0" +cc = "1.0.1" flate2 = "1.0" jobserver = "0.1.5" libc = "0.2" @@ -34,9 +35,6 @@ syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } tempdir = "0.3" -[target."cfg(windows)".dependencies] -cc = "1.0.1" - [features] # Used to communicate the feature to `rustc_back` in the same manner that the # `rustc` driver script communicate this. diff --git a/src/librustc_trans/back/command.rs b/src/librustc_trans/back/command.rs index e5e0a4e3ba0e..ecf7bf5036e0 100644 --- a/src/librustc_trans/back/command.rs +++ b/src/librustc_trans/back/command.rs @@ -81,17 +81,6 @@ impl Command { self } - pub fn envs(&mut self, envs: I) -> &mut Command - where I: IntoIterator, - K: AsRef, - V: AsRef - { - for (key, value) in envs { - self._env(key.as_ref(), value.as_ref()); - } - self - } - fn _env(&mut self, key: &OsStr, value: &OsStr) { self.env.push((key.to_owned(), value.to_owned())); } @@ -112,6 +101,9 @@ impl Command { let mut c = process::Command::new(p); c.arg("-flavor").arg(match flavor { LldFlavor::Wasm => "wasm", + LldFlavor::Ld => "gnu", + LldFlavor::Link => "link", + LldFlavor::Ld64 => "darwin", }); c } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index c134203a773f..636b3984117d 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use cc::windows_registry; use super::archive::{ArchiveBuilder, ArchiveConfig}; use super::bytecode::RLIB_BYTECODE_EXTENSION; use super::linker::Linker; @@ -35,7 +36,6 @@ use llvm; use std::ascii; use std::char; use std::env; -use std::ffi::OsString; use std::fmt; use std::fs; use std::io; @@ -58,9 +58,7 @@ pub use rustc_trans_utils::link::{find_crate_name, filename_for_input, default_o // 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, Vec<(OsString, OsString)>) { - let envs = vec![("PATH".into(), command_path(sess))]; - +pub fn get_linker(sess: &Session) -> (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 @@ -75,60 +73,57 @@ pub fn get_linker(sess: &Session) -> (PathBuf, Command, Vec<(OsString, OsString) return Command::bat_script(linker) } } - Command::new(linker) + match sess.linker_flavor() { + LinkerFlavor::Lld(f) => Command::lld(linker, f), + _ => Command::new(linker), + + } }; - if let Some(ref linker) = sess.opts.cg.linker { - (linker.clone(), cmd(linker), envs) - } else if sess.target.target.options.is_like_msvc { - let (cmd, envs) = msvc_link_exe_cmd(sess); - (PathBuf::from("link.exe"), cmd, envs) - } else if let LinkerFlavor::Lld(f) = sess.linker_flavor() { - let linker = PathBuf::from(&sess.target.target.options.linker); - let cmd = Command::lld(&linker, f); - (linker, cmd, envs) - } else { - let linker = PathBuf::from(&sess.target.target.options.linker); - let cmd = cmd(&linker); - (linker, cmd, envs) - } -} + let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple, "link.exe"); -#[cfg(windows)] -pub fn msvc_link_exe_cmd(sess: &Session) -> (Command, Vec<(OsString, OsString)>) { - use cc::windows_registry; + 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 target = &sess.opts.target_triple; - let tool = windows_registry::find_tool(target, "link.exe"); + let mut cmd = cmd(linker_path); - if let Some(tool) = tool { - let mut cmd = Command::new(tool.path()); - cmd.args(tool.args()); - for &(ref k, ref v) in tool.env() { - cmd.env(k, v); - } - let envs = tool.env().to_vec(); - (cmd, envs) - } else { - debug!("Failed to locate linker."); - (Command::new("link.exe"), vec![]) - } -} - -#[cfg(not(windows))] -pub fn msvc_link_exe_cmd(_sess: &Session) -> (Command, Vec<(OsString, OsString)>) { - (Command::new("link.exe"), vec![]) -} - -fn command_path(sess: &Session) -> OsString { // 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) .get_tools_search_paths(); - if let Some(path) = env::var_os("PATH") { - new_path.extend(env::split_paths(&path)); + let mut msvc_changed_path = false; + if sess.target.target.options.is_like_msvc { + if let Some(ref tool) = msvc_tool { + cmd.args(tool.args()); + for &(ref k, ref v) in tool.env() { + if k == "PATH" { + new_path.extend(env::split_paths(v)); + msvc_changed_path = true; + } else { + cmd.env(k, v); + } + } + } } - env::join_paths(new_path).unwrap() + + if !msvc_changed_path { + if let Some(path) = env::var_os("PATH") { + new_path.extend(env::split_paths(&path)); + } + } + cmd.env("PATH", env::join_paths(new_path).unwrap()); + + (linker_path.to_path_buf(), cmd) } pub fn remove(sess: &Session, path: &Path) { @@ -618,9 +613,7 @@ fn link_natively(sess: &Session, let flavor = sess.linker_flavor(); // The invocations of cc share some flags across platforms - let (pname, mut cmd, envs) = get_linker(sess); - // This will set PATH on windows - cmd.envs(envs); + let (pname, mut cmd) = get_linker(sess); let root = sess.target_filesearch(PathKind::Native).get_lib_path(); if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) { diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index a82270c5272b..a3ff39a47a29 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -45,6 +45,7 @@ impl LinkerInfo { cmd: Command, sess: &'a Session) -> Box { match sess.linker_flavor() { + LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => { Box::new(MsvcLinker { cmd, @@ -68,6 +69,9 @@ impl LinkerInfo { is_ld: false, }) as Box } + + LinkerFlavor::Lld(LldFlavor::Ld) | + LinkerFlavor::Lld(LldFlavor::Ld64) | LinkerFlavor::Ld => { Box::new(GccLinker { cmd, diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 1664aa9d0b3a..78b26a37485e 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -1369,7 +1369,7 @@ 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); + let (name, mut cmd) = get_linker(sess); cmd.args(&sess.target.target.options.asm_args); Some(Arc::new(AssemblerCommand { name, diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 51ad17fe2051..0b8da10b78e7 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -62,7 +62,6 @@ extern crate rustc_trans_utils; extern crate syntax_pos; extern crate rustc_errors as errors; extern crate serialize; -#[cfg(windows)] extern crate cc; // Used to locate MSVC extern crate tempdir;