Move get_linker to linker.rs
This commit is contained in:
parent
56ee9864c1
commit
0b061cbeac
2 changed files with 96 additions and 93 deletions
|
@ -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(
|
pub fn each_linked_rlib(
|
||||||
info: &CrateInfo,
|
info: &CrateInfo,
|
||||||
f: &mut dyn FnMut(CrateNum, &Path),
|
f: &mut dyn FnMut(CrateNum, &Path),
|
||||||
|
@ -1804,7 +1713,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
|
||||||
codegen_results: &CodegenResults,
|
codegen_results: &CodegenResults,
|
||||||
) -> Command {
|
) -> Command {
|
||||||
let crt_objects_fallback = crt_objects_fallback(sess, crate_type);
|
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
|
// FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction
|
||||||
// to the linker args construction.
|
// to the linker args construction.
|
||||||
assert!(base_cmd.get_args().is_empty() || sess.target.vendor == "uwp");
|
assert!(base_cmd.get_args().is_empty() || sess.target.vendor == "uwp");
|
||||||
|
|
|
@ -7,8 +7,8 @@ use std::ffi::{OsStr, OsString};
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io::{self, BufWriter};
|
use std::io::{self, BufWriter};
|
||||||
use std::mem;
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::{env, mem, str};
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
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_middle::ty::TyCtxt;
|
||||||
use rustc_serialize::{json, Encoder};
|
use rustc_serialize::{json, Encoder};
|
||||||
use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
|
use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
|
||||||
|
use rustc_session::search_paths::PathKind;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor};
|
use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor};
|
||||||
|
|
||||||
|
use cc::windows_registry;
|
||||||
|
|
||||||
/// Disables non-English messages from localized linkers.
|
/// Disables non-English messages from localized linkers.
|
||||||
/// Such messages may cause issues with text encoding on Windows (#35785)
|
/// 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.
|
/// 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 abstraction used by `back::link` to build up the command to invoke a
|
||||||
/// linker.
|
/// linker.
|
||||||
///
|
///
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue