Skip to content

Commit 0a6b21c

Browse files
committed
rust: use clang-cl or cl as linkers for -msvc targets
With clang exists in the system path and cl does not, meson generates build.ninja file using clang as linker even for -msvc targets. Look at the target, and detect the correct C/C++ compiler based on whether it is a MSVC target. Fixes: #6638 Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 64e3f46 commit 0a6b21c

File tree

1 file changed

+46
-6
lines changed

1 file changed

+46
-6
lines changed

mesonbuild/compilers/detect.py

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
10541076
def 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

Comments
 (0)