Skip to content

Commit 5b6b170

Browse files
committed
Improve detection of environment when compiling from msbuild or msvc
1 parent 5daf14e commit 5b6b170

File tree

1 file changed

+59
-10
lines changed

1 file changed

+59
-10
lines changed

src/windows/find_tools.rs

+59-10
Original file line numberDiff line numberDiff line change
@@ -353,20 +353,69 @@ mod impl_ {
353353
}
354354
}
355355

356+
/// Checks to see if the target's arch matches the VS environment. Returns `None` if the
357+
/// environment is unknown.
358+
fn is_vscmd_target(target: TargetArch<'_>, env_getter: &dyn EnvGetter) -> Option<bool> {
359+
is_vscmd_target_env(target, env_getter).or_else(|| is_vscmd_target_cl(target, env_getter))
360+
}
361+
356362
/// Checks to see if the `VSCMD_ARG_TGT_ARCH` environment variable matches the
357363
/// given target's arch. Returns `None` if the variable does not exist.
358-
fn is_vscmd_target(target: TargetArch<'_>, env_getter: &dyn EnvGetter) -> Option<bool> {
364+
fn is_vscmd_target_env(target: TargetArch<'_>, env_getter: &dyn EnvGetter) -> Option<bool> {
359365
let vscmd_arch = env_getter.get_env("VSCMD_ARG_TGT_ARCH")?;
360-
// Convert the Rust target arch to its VS arch equivalent.
361-
let arch = match target.into() {
362-
"x86_64" => "x64",
363-
"aarch64" | "arm64ec" => "arm64",
364-
"i686" | "i586" => "x86",
365-
"thumbv7a" => "arm",
366+
if let Some(arch) = vsarch_from_target(target) {
367+
Some(arch == vscmd_arch.as_ref())
368+
} else {
369+
None
370+
}
371+
}
372+
373+
/// Checks if the cl.exe target matches the given target's arch. Returns `None` if anything
374+
/// fails.
375+
fn is_vscmd_target_cl(target: TargetArch<'_>, env_getter: &dyn EnvGetter) -> Option<bool> {
376+
let cmd_target = vscmd_target_cl(env_getter)?;
377+
Some(vsarch_from_target(target) == Some(cmd_target))
378+
}
379+
380+
/// Convert the Rust target arch to its VS arch equivalent.
381+
fn vsarch_from_target(target: TargetArch<'_>) -> Option<&'static str> {
382+
match target.into() {
383+
"x86_64" => Some("x64"),
384+
"aarch64" | "arm64ec" => Some("arm64"),
385+
"i686" | "i586" => Some("x86"),
386+
"thumbv7a" => Some("arm"),
366387
// An unrecognized arch.
367-
_ => return Some(false),
368-
};
369-
Some(vscmd_arch.as_ref() == arch)
388+
_ => None,
389+
}
390+
}
391+
392+
/// Detect the target architecture of `cl.exe`` in the current path, and return `None` if this
393+
/// fails for any reason.
394+
fn vscmd_target_cl(env_getter: &dyn EnvGetter) -> Option<&'static str> {
395+
let cl_exe = env_getter.get_env("PATH").and_then(|path| {
396+
env::split_paths(&path)
397+
.map(|p| p.join("cl.exe"))
398+
.find(|p| p.exists())
399+
})?;
400+
let mut cl = Command::new(cl_exe);
401+
cl.stderr(std::process::Stdio::piped())
402+
.stdout(std::process::Stdio::null());
403+
404+
let out = cl.output().ok()?;
405+
let cl_arch = out
406+
.stderr
407+
.split(|&b| b == b'\n' || b == b'\r')
408+
.next()?
409+
.split(|&b| b == b' ')
410+
.last()?;
411+
412+
match cl_arch {
413+
b"x64" => Some("x64"),
414+
b"x86" => Some("x86"),
415+
b"ARM64" => Some("arm64"),
416+
b"ARM" => Some("arm"),
417+
_ => None,
418+
}
370419
}
371420

372421
/// Attempt to find the tool using environment variables set by vcvars.

0 commit comments

Comments
 (0)