diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 049ae253fe34..92b88f121bf9 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1877,7 +1877,7 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: self.generate_generator_list_rules(target) # dependencies need to cause a relink, they're not just for ordering - deps: T.List[str] = [] + deps: T.List[str] = [rustc.get_exe_file()] # Dependencies for rust-project.json project_deps: T.List[RustDep] = [] diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index a7bb6c417932..afc223b1f4ae 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -631,6 +631,9 @@ def get_exelist(self, ccache: bool = True) -> T.List[str]: def get_linker_exelist(self) -> T.List[str]: return self.linker.get_exelist() if self.linker else self.get_exelist() + def get_exe_file(self) -> str: + return os.path.realpath(self.exelist_no_ccache[0]) + @abc.abstractmethod def get_output_args(self, outputname: str) -> T.List[str]: pass diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index 1fb94aa4447a..faa340814fb1 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -18,6 +18,8 @@ import re import typing as T +from functools import lru_cache + from .. import coredata from ..mesonlib import EnvironmentException, MesonException, Popen_safe_logged, OptionKey from .compilers import Compiler, rust_buildtype_args, clike_debug_args @@ -79,6 +81,19 @@ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoic if 'link' in self.linker.id: self.base_options.add(OptionKey('b_vscrt')) self.native_static_libs: T.List[str] = [] + # Resolve the real rustc executable. When using rustup, "rustc" in PATH + # is a wrapper that won't change when updating the toolchain, which + # means ninja would not rebuild rust targets after "rustup update". That + # can cause build issues because different rustc versions are generally + # uncompatible. This also means that once a Meson project has been + # configured, changing the default toolchain with e.g. + # "rustup default nightly" won't have any effect. + sysroot = self.get_sysroot() + real_rustc = os.path.join(sysroot, 'bin', 'rustc') + if os.path.exists(real_rustc): + exelist = [real_rustc] + exelist[1:] + self.exelist = exelist + self.exelist_no_ccache = exelist def needs_static_linker(self) -> bool: return False @@ -126,6 +141,7 @@ def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: def get_buildtype_args(self, buildtype: str) -> T.List[str]: return rust_buildtype_args[buildtype] + @lru_cache(maxsize=None) def get_sysroot(self) -> str: cmd = self.get_exelist(ccache=False) + ['--print', 'sysroot'] p, stdo, stde = Popen_safe_logged(cmd) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index e885010b23a1..b339c5157711 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1519,6 +1519,7 @@ def add_languages_for(self, args: T.List[str], required: bool, for_machine: Mach comp = compilers.detect_compiler_for(self.environment, lang, for_machine, skip_sanity_check) if comp is None: raise InvalidArguments(f'Tried to use unknown language "{lang}".') + self.add_build_def_file(comp.get_exe_file()) except mesonlib.MesonException: if not required: mlog.log('Compiler for language',