Skip to content

Commit 0b061cb

Browse files
committed
Move get_linker to linker.rs
1 parent 56ee986 commit 0b061cb

File tree

2 files changed

+96
-93
lines changed

2 files changed

+96
-93
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 1 addition & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -147,97 +147,6 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
147147
});
148148
}
149149

150-
// The third parameter is for env vars, used on windows to set up the
151-
// path for MSVC to find its DLLs, and gcc to find its bundled
152-
// toolchain
153-
fn get_linker(
154-
sess: &Session,
155-
linker: &Path,
156-
flavor: LinkerFlavor,
157-
self_contained: bool,
158-
) -> Command {
159-
let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe");
160-
161-
// If our linker looks like a batch script on Windows then to execute this
162-
// we'll need to spawn `cmd` explicitly. This is primarily done to handle
163-
// emscripten where the linker is `emcc.bat` and needs to be spawned as
164-
// `cmd /c emcc.bat ...`.
165-
//
166-
// This worked historically but is needed manually since #42436 (regression
167-
// was tagged as #42791) and some more info can be found on #44443 for
168-
// emscripten itself.
169-
let mut cmd = match linker.to_str() {
170-
Some(linker) if cfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker),
171-
_ => match flavor {
172-
LinkerFlavor::Lld(f) => Command::lld(linker, f),
173-
LinkerFlavor::Msvc if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() => {
174-
Command::new(msvc_tool.as_ref().map_or(linker, |t| t.path()))
175-
}
176-
_ => Command::new(linker),
177-
},
178-
};
179-
180-
// UWP apps have API restrictions enforced during Store submissions.
181-
// To comply with the Windows App Certification Kit,
182-
// MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc).
183-
let t = &sess.target;
184-
if (flavor == LinkerFlavor::Msvc || flavor == LinkerFlavor::Lld(LldFlavor::Link))
185-
&& t.vendor == "uwp"
186-
{
187-
if let Some(ref tool) = msvc_tool {
188-
let original_path = tool.path();
189-
if let Some(ref root_lib_path) = original_path.ancestors().nth(4) {
190-
let arch = match t.arch.as_str() {
191-
"x86_64" => Some("x64"),
192-
"x86" => Some("x86"),
193-
"aarch64" => Some("arm64"),
194-
"arm" => Some("arm"),
195-
_ => None,
196-
};
197-
if let Some(ref a) = arch {
198-
// FIXME: Move this to `fn linker_with_args`.
199-
let mut arg = OsString::from("/LIBPATH:");
200-
arg.push(format!("{}\\lib\\{}\\store", root_lib_path.display(), a));
201-
cmd.arg(&arg);
202-
} else {
203-
warn!("arch is not supported");
204-
}
205-
} else {
206-
warn!("MSVC root path lib location not found");
207-
}
208-
} else {
209-
warn!("link.exe not found");
210-
}
211-
}
212-
213-
// The compiler's sysroot often has some bundled tools, so add it to the
214-
// PATH for the child.
215-
let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(self_contained);
216-
let mut msvc_changed_path = false;
217-
if sess.target.is_like_msvc {
218-
if let Some(ref tool) = msvc_tool {
219-
cmd.args(tool.args());
220-
for &(ref k, ref v) in tool.env() {
221-
if k == "PATH" {
222-
new_path.extend(env::split_paths(v));
223-
msvc_changed_path = true;
224-
} else {
225-
cmd.env(k, v);
226-
}
227-
}
228-
}
229-
}
230-
231-
if !msvc_changed_path {
232-
if let Some(path) = env::var_os("PATH") {
233-
new_path.extend(env::split_paths(&path));
234-
}
235-
}
236-
cmd.env("PATH", env::join_paths(new_path).unwrap());
237-
238-
cmd
239-
}
240-
241150
pub fn each_linked_rlib(
242151
info: &CrateInfo,
243152
f: &mut dyn FnMut(CrateNum, &Path),
@@ -1804,7 +1713,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
18041713
codegen_results: &CodegenResults,
18051714
) -> Command {
18061715
let crt_objects_fallback = crt_objects_fallback(sess, crate_type);
1807-
let base_cmd = get_linker(sess, path, flavor, crt_objects_fallback);
1716+
let base_cmd = super::linker::get_linker(sess, path, flavor, crt_objects_fallback);
18081717
// FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction
18091718
// to the linker args construction.
18101719
assert!(base_cmd.get_args().is_empty() || sess.target.vendor == "uwp");

compiler/rustc_codegen_ssa/src/back/linker.rs

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,22 @@ use std::ffi::{OsStr, OsString};
77
use std::fs::{self, File};
88
use std::io::prelude::*;
99
use std::io::{self, BufWriter};
10-
use std::mem;
1110
use std::path::{Path, PathBuf};
11+
use std::{env, mem, str};
1212

1313
use rustc_data_structures::fx::FxHashMap;
1414
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
1515
use rustc_middle::middle::dependency_format::Linkage;
1616
use rustc_middle::ty::TyCtxt;
1717
use rustc_serialize::{json, Encoder};
1818
use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
19+
use rustc_session::search_paths::PathKind;
1920
use rustc_session::Session;
2021
use rustc_span::symbol::Symbol;
2122
use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor};
2223

24+
use cc::windows_registry;
25+
2326
/// Disables non-English messages from localized linkers.
2427
/// Such messages may cause issues with text encoding on Windows (#35785)
2528
/// and prevent inspection of linker output in case of errors, which we occasionally do.
@@ -90,6 +93,97 @@ impl LinkerInfo {
9093
}
9194
}
9295

96+
// The third parameter is for env vars, used on windows to set up the
97+
// path for MSVC to find its DLLs, and gcc to find its bundled
98+
// toolchain
99+
pub fn get_linker(
100+
sess: &Session,
101+
linker: &Path,
102+
flavor: LinkerFlavor,
103+
self_contained: bool,
104+
) -> Command {
105+
let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe");
106+
107+
// If our linker looks like a batch script on Windows then to execute this
108+
// we'll need to spawn `cmd` explicitly. This is primarily done to handle
109+
// emscripten where the linker is `emcc.bat` and needs to be spawned as
110+
// `cmd /c emcc.bat ...`.
111+
//
112+
// This worked historically but is needed manually since #42436 (regression
113+
// was tagged as #42791) and some more info can be found on #44443 for
114+
// emscripten itself.
115+
let mut cmd = match linker.to_str() {
116+
Some(linker) if cfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker),
117+
_ => match flavor {
118+
LinkerFlavor::Lld(f) => Command::lld(linker, f),
119+
LinkerFlavor::Msvc if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() => {
120+
Command::new(msvc_tool.as_ref().map_or(linker, |t| t.path()))
121+
}
122+
_ => Command::new(linker),
123+
},
124+
};
125+
126+
// UWP apps have API restrictions enforced during Store submissions.
127+
// To comply with the Windows App Certification Kit,
128+
// MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc).
129+
let t = &sess.target;
130+
if (flavor == LinkerFlavor::Msvc || flavor == LinkerFlavor::Lld(LldFlavor::Link))
131+
&& t.vendor == "uwp"
132+
{
133+
if let Some(ref tool) = msvc_tool {
134+
let original_path = tool.path();
135+
if let Some(ref root_lib_path) = original_path.ancestors().nth(4) {
136+
let arch = match t.arch.as_str() {
137+
"x86_64" => Some("x64"),
138+
"x86" => Some("x86"),
139+
"aarch64" => Some("arm64"),
140+
"arm" => Some("arm"),
141+
_ => None,
142+
};
143+
if let Some(ref a) = arch {
144+
// FIXME: Move this to `fn linker_with_args`.
145+
let mut arg = OsString::from("/LIBPATH:");
146+
arg.push(format!("{}\\lib\\{}\\store", root_lib_path.display(), a));
147+
cmd.arg(&arg);
148+
} else {
149+
warn!("arch is not supported");
150+
}
151+
} else {
152+
warn!("MSVC root path lib location not found");
153+
}
154+
} else {
155+
warn!("link.exe not found");
156+
}
157+
}
158+
159+
// The compiler's sysroot often has some bundled tools, so add it to the
160+
// PATH for the child.
161+
let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(self_contained);
162+
let mut msvc_changed_path = false;
163+
if sess.target.is_like_msvc {
164+
if let Some(ref tool) = msvc_tool {
165+
cmd.args(tool.args());
166+
for &(ref k, ref v) in tool.env() {
167+
if k == "PATH" {
168+
new_path.extend(env::split_paths(v));
169+
msvc_changed_path = true;
170+
} else {
171+
cmd.env(k, v);
172+
}
173+
}
174+
}
175+
}
176+
177+
if !msvc_changed_path {
178+
if let Some(path) = env::var_os("PATH") {
179+
new_path.extend(env::split_paths(&path));
180+
}
181+
}
182+
cmd.env("PATH", env::join_paths(new_path).unwrap());
183+
184+
cmd
185+
}
186+
93187
/// Linker abstraction used by `back::link` to build up the command to invoke a
94188
/// linker.
95189
///

0 commit comments

Comments
 (0)