Skip to content

Commit c342210

Browse files
committed
Attempt to use the current environment to find the tool
1 parent 92ffa53 commit c342210

File tree

1 file changed

+44
-15
lines changed

1 file changed

+44
-15
lines changed

src/windows_registry.rs

+44-15
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ pub fn find_tool(_target: &str, _tool: &str) -> Option<Tool> {
4747
/// Documented above.
4848
#[cfg(windows)]
4949
pub fn find_tool(target: &str, tool: &str) -> Option<Tool> {
50-
use std::env;
51-
5250
// This logic is all tailored for MSVC, if we're not that then bail out
5351
// early.
5452
if !target.contains("msvc") {
@@ -66,26 +64,15 @@ pub fn find_tool(target: &str, tool: &str) -> Option<Tool> {
6664
return impl_::find_devenv(target);
6765
}
6866

69-
// If VCINSTALLDIR is set, then someone's probably already run vcvars and we
70-
// should just find whatever that indicates.
71-
if env::var_os("VCINSTALLDIR").is_some() {
72-
return env::var_os("PATH")
73-
.and_then(|path| {
74-
env::split_paths(&path)
75-
.map(|p| p.join(tool))
76-
.find(|p| p.exists())
77-
})
78-
.map(|path| Tool::with_family(path.into(), MSVC_FAMILY));
79-
}
80-
8167
// Ok, if we're here, now comes the fun part of the probing. Default shells
8268
// or shells like MSYS aren't really configured to execute `cl.exe` and the
8369
// various compiler tools shipped as part of Visual Studio. Here we try to
8470
// first find the relevant tool, then we also have to be sure to fill in
8571
// environment variables like `LIB`, `INCLUDE`, and `PATH` to ensure that
8672
// the tool is actually usable.
8773

88-
return impl_::find_msvc_15plus(tool, target)
74+
return impl_::find_msvc_environment(tool, target)
75+
.or_else(|| impl_::find_msvc_15plus(tool, target))
8976
.or_else(|| impl_::find_msvc_14(tool, target))
9077
.or_else(|| impl_::find_msvc_12(tool, target))
9178
.or_else(|| impl_::find_msvc_11(tool, target));
@@ -218,6 +205,48 @@ mod impl_ {
218205
}
219206
}
220207

208+
/// Checks to see if the `VSCMD_ARG_TGT_ARCH` environment variable matches the
209+
/// given target's arch. Returns `None` if the variable does not exist.
210+
#[cfg(windows)]
211+
fn is_vscmd_target(target: &str) -> Option<bool> {
212+
let vscmd_arch = env::var("VSCMD_ARG_TGT_ARCH").ok()?;
213+
// Convert the Rust target arch to its VS arch equivalent.
214+
let arch = match target.split("-").next() {
215+
Some("x86_64") => "x64",
216+
Some("aarch64") => "arm64",
217+
Some("i686") | Some("i586") => "x86",
218+
Some("thumbv7a") => "arm",
219+
// An unrecognized arch.
220+
_ => return Some(false),
221+
};
222+
Some(vscmd_arch == arch)
223+
}
224+
225+
/// Attempt to find the tool using environment variables set by vcvars.
226+
pub fn find_msvc_environment(target: &str, tool: &str) -> Option<Tool> {
227+
// Early return if the environment doesn't contain a VC install.
228+
if env::var_os("VCINSTALLDIR").is_none() {
229+
return None;
230+
}
231+
let vs_install_dir = env::var_os("VSINSTALLDIR")?.into();
232+
233+
// If the vscmd target differs from the requested target then
234+
// attempt to get the tool using the VS install directory.
235+
if is_vscmd_target(target) == Some(false) {
236+
// We will only get here with versions 15+.
237+
tool_from_vs15plus_instance(tool, target, &vs_install_dir)
238+
} else {
239+
// Fallback to simply using the current environment.
240+
env::var_os("PATH")
241+
.and_then(|path| {
242+
env::split_paths(&path)
243+
.map(|p| p.join(tool))
244+
.find(|p| p.exists())
245+
})
246+
.map(|path| Tool::with_family(path.into(), MSVC_FAMILY))
247+
}
248+
}
249+
221250
#[allow(bare_trait_objects)]
222251
fn vs16_instances(target: &str) -> Box<Iterator<Item = PathBuf>> {
223252
let instances = if let Some(instances) = vs15plus_instances(target) {

0 commit comments

Comments
 (0)