diff options
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/link.rs | 93 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/linker.rs | 96 |
2 files changed, 96 insertions, 93 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index cb8fd263a60..5f133f7afe4 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -147,97 +147,6 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( }); } -// 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 -fn get_linker( - sess: &Session, - linker: &Path, - flavor: LinkerFlavor, - self_contained: bool, -) -> 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 - // `cmd /c emcc.bat ...`. - // - // 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 = 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), - LinkerFlavor::Msvc if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() => { - Command::new(msvc_tool.as_ref().map_or(linker, |t| t.path())) - } - _ => Command::new(linker), - }, - }; - - // UWP apps have API restrictions enforced during Store submissions. - // To comply with the Windows App Certification Kit, - // MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc). - let t = &sess.target; - if (flavor == LinkerFlavor::Msvc || flavor == LinkerFlavor::Lld(LldFlavor::Link)) - && t.vendor == "uwp" - { - if let Some(ref tool) = msvc_tool { - let original_path = tool.path(); - if let Some(ref root_lib_path) = original_path.ancestors().nth(4) { - let arch = match t.arch.as_str() { - "x86_64" => Some("x64"), - "x86" => Some("x86"), - "aarch64" => Some("arm64"), - "arm" => Some("arm"), - _ => None, - }; - if let Some(ref a) = arch { - // FIXME: Move this to `fn linker_with_args`. - let mut arg = OsString::from("/LIBPATH:"); - arg.push(format!("{}\\lib\\{}\\store", root_lib_path.display(), a)); - cmd.arg(&arg); - } else { - warn!("arch is not supported"); - } - } else { - warn!("MSVC root path lib location not found"); - } - } else { - warn!("link.exe not found"); - } - } - - // 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(self_contained); - let mut msvc_changed_path = false; - if sess.target.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); - } - } - } - } - - 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()); - - cmd -} - pub fn each_linked_rlib( info: &CrateInfo, f: &mut dyn FnMut(CrateNum, &Path), @@ -1804,7 +1713,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( codegen_results: &CodegenResults, ) -> Command { let crt_objects_fallback = crt_objects_fallback(sess, crate_type); - let base_cmd = get_linker(sess, path, flavor, crt_objects_fallback); + let base_cmd = super::linker::get_linker(sess, path, flavor, crt_objects_fallback); // FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction // to the linker args construction. assert!(base_cmd.get_args().is_empty() || sess.target.vendor == "uwp"); diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 49b58829483..8d76f9814e0 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -7,8 +7,8 @@ use std::ffi::{OsStr, OsString}; use std::fs::{self, File}; use std::io::prelude::*; use std::io::{self, BufWriter}; -use std::mem; use std::path::{Path, PathBuf}; +use std::{env, mem, str}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; @@ -16,10 +16,13 @@ use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::ty::TyCtxt; use rustc_serialize::{json, Encoder}; use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip}; +use rustc_session::search_paths::PathKind; use rustc_session::Session; use rustc_span::symbol::Symbol; use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor}; +use cc::windows_registry; + /// Disables non-English messages from localized linkers. /// Such messages may cause issues with text encoding on Windows (#35785) /// and prevent inspection of linker output in case of errors, which we occasionally do. @@ -90,6 +93,97 @@ impl LinkerInfo { } } +// 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, + linker: &Path, + flavor: LinkerFlavor, + self_contained: bool, +) -> 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 + // `cmd /c emcc.bat ...`. + // + // 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 = 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), + LinkerFlavor::Msvc if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() => { + Command::new(msvc_tool.as_ref().map_or(linker, |t| t.path())) + } + _ => Command::new(linker), + }, + }; + + // UWP apps have API restrictions enforced during Store submissions. + // To comply with the Windows App Certification Kit, + // MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc). + let t = &sess.target; + if (flavor == LinkerFlavor::Msvc || flavor == LinkerFlavor::Lld(LldFlavor::Link)) + && t.vendor == "uwp" + { + if let Some(ref tool) = msvc_tool { + let original_path = tool.path(); + if let Some(ref root_lib_path) = original_path.ancestors().nth(4) { + let arch = match t.arch.as_str() { + "x86_64" => Some("x64"), + "x86" => Some("x86"), + "aarch64" => Some("arm64"), + "arm" => Some("arm"), + _ => None, + }; + if let Some(ref a) = arch { + // FIXME: Move this to `fn linker_with_args`. + let mut arg = OsString::from("/LIBPATH:"); + arg.push(format!("{}\\lib\\{}\\store", root_lib_path.display(), a)); + cmd.arg(&arg); + } else { + warn!("arch is not supported"); + } + } else { + warn!("MSVC root path lib location not found"); + } + } else { + warn!("link.exe not found"); + } + } + + // 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(self_contained); + let mut msvc_changed_path = false; + if sess.target.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); + } + } + } + } + + 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()); + + cmd +} + /// Linker abstraction used by `back::link` to build up the command to invoke a /// linker. /// |
