@@ -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+ Some ( false )
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+ . rsplit ( |& b| b == b' ' )
410+ . next ( ) ?;
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