@@ -1051,14 +1051,33 @@ def detect_vala_compiler(env: 'Environment', for_machine: MachineChoice) -> Comp
10511051 return comp_class (exelist , version , for_machine , env )
10521052 raise EnvironmentException ('Unknown compiler: ' + join_args (exelist ))
10531053
1054+
1055+ def _get_rust_target (compiler : T .List [str ]) -> T .Optional [str ]:
1056+ """Extract the Rust target from compiler arguments or rustc -vV output."""
1057+ # Check for explicit --target in compiler arguments
1058+ for i , arg in enumerate (compiler ):
1059+ if arg == '--target' and i + 1 < len (compiler ):
1060+ return compiler [i + 1 ]
1061+ if arg .startswith ('--target=' ):
1062+ return arg .split ('=' , 1 )[1 ]
1063+
1064+ # Query rustc for its host target
1065+ try :
1066+ out = Popen_safe (compiler + ['-vV' ])[1 ]
1067+ for line in out .splitlines ():
1068+ if line .startswith ('host:' ):
1069+ return line .split (':' , 1 )[1 ].strip ()
1070+ except OSError :
1071+ pass
1072+
1073+ return None
1074+
1075+
10541076def detect_rust_compiler (env : 'Environment' , for_machine : MachineChoice ) -> RustCompiler :
10551077 from . import rust
10561078 from ..linkers import linkers
10571079 popen_exceptions : T .Dict [str , Exception ] = {}
10581080 compilers , _ = _get_compilers (env , 'rust' , for_machine )
1059-
1060- cc = detect_c_compiler (env , for_machine )
1061- is_link_exe = isinstance (cc .linker , linkers .VisualStudioLikeLinkerMixin )
10621081 override = env .lookup_binary_entry (for_machine , 'rust_ld' )
10631082
10641083 for compiler in compilers :
@@ -1101,12 +1120,33 @@ def detect_rust_compiler(env: 'Environment', for_machine: MachineChoice) -> Rust
11011120 if 'rustc' in out :
11021121 # On Linux and mac rustc will invoke gcc (clang for mac
11031122 # presumably) and it can do this windows, for dynamic linking.
1104- # this means the easiest way to C compiler for dynamic linking.
1105- # figure out what linker to use is to just get the value of the
1106- # C compiler and use that as the basis of the rust linker.
1123+ # this means the easiest way to figure out what linker to use
1124+ # is to just get the value of the C compiler and use that as
1125+ # the basis of the rust linker.
1126+ #
11071127 # However, there are two things we need to change, if CC is not
11081128 # the default use that, and second add the necessary arguments
11091129 # to rust to use -fuse-ld
1130+ #
1131+ # For MSVC targets, require an MSVC-compatible C compiler to get
1132+ # the corresponding linker
1133+ rust_target = _get_rust_target (compiler )
1134+ if rust_target and rust_target .endswith ('-msvc' ):
1135+ try :
1136+ cc = _detect_c_or_cpp_compiler (env , 'c' , for_machine ,
1137+ override_compiler = ['clang-cl' , 'cl' ])
1138+ except EnvironmentException :
1139+ popen_exceptions [join_args (compiler )] = \
1140+ EnvironmentException ('No MSVC-compatible C compiler found for MSVC Rust target' )
1141+ continue
1142+ else :
1143+ try :
1144+ cc = detect_c_compiler (env , for_machine )
1145+ except EnvironmentException as e :
1146+ popen_exceptions [join_args (compiler )] = e
1147+ continue
1148+
1149+ is_link_exe = isinstance (cc .linker , linkers .VisualStudioLikeLinkerMixin )
11101150
11111151 if any (a .startswith ('linker=' ) for a in compiler ):
11121152 mlog .warning (
0 commit comments