@@ -353,20 +353,69 @@ mod impl_ {
353
353
}
354
354
}
355
355
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
+
356
362
/// Checks to see if the `VSCMD_ARG_TGT_ARCH` environment variable matches the
357
363
/// 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 > {
359
365
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" ) ,
366
387
// 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
+ }
370
419
}
371
420
372
421
/// Attempt to find the tool using environment variables set by vcvars.
0 commit comments