interpreter: add native argument to override_find_program()

Co-authored-by: Dylan Baker <dylan@pnwbakers.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo BonziniandDylan Baker authored and Dylan Baker committed 2026-06-17 13:05:22 -07:00
1 parent b74736b160
commit 3cba9ee127
5 files changed
+40 -23

No files matched your search

+9
View File
@@ -392,6 +392,15 @@ methods:
type: exe | file | program
description: The program to set as the override for `progname`.
native:
type: bool
since: 1.12.0
default: false
description : |
If set to `true`, the override is for the build machine, and will be returned
by `find_program(..., native : true)`, otherwise for the host machine. This
is an important distinction when cross compiling.
- name: override_dependency
returns: void
since: 0.54.0
+5 -2
View File
@@ -344,8 +344,11 @@ class Build:
self.dep_manifest: T.Dict[str, DepManifest] = {}
self.test_setups: T.Dict[str, TestSetup] = {}
self.test_setup_default_name: str | None = None
self.find_overrides: T.Dict[str, programs.Program] = {}
self.searched_programs: T.Set[str] = set() # The list of all programs that have been searched for.
self.find_overrides: PerMachine[T.Dict[str, programs.Program]] = PerMachineDefaultable.default(
environment.is_cross_build(), {}, {})
# The list of all programs that have been searched for.
self.searched_programs: PerMachine[T.Set[str]] = PerMachineDefaultable.default(
environment.is_cross_build(), set(), set())
# If we are doing a cross build we need two caches, if we're doing a
# build == host compilation the both caches should point to the same place.
+20 -17
View File
@@ -797,9 +797,10 @@ class Interpreter(InterpreterBase, HoldableObject):
def _compiled_exe_error(self, cmd: T.Union[Program, build.Executable]) -> T.NoReturn:
descr = cmd.name if isinstance(cmd, build.Executable) else cmd.description()
for name, exe in self.build.find_overrides.items():
if cmd == exe:
raise InterpreterException(f'Program {name!r} was overridden with the compiled executable {descr!r} and therefore cannot be used during configuration')
for for_machine in MachineChoice:
for name, exe in self.build.find_overrides[for_machine].items():
if cmd == exe:
raise InterpreterException(f'Program {name!r} was overridden with the compiled executable {descr!r} and therefore cannot be used during configuration')
raise InterpreterException(f'Program {descr!r} is a compiled executable and therefore cannot be used during configuration')
def run_command_impl(self,
@@ -1696,31 +1697,32 @@ class Interpreter(InterpreterBase, HoldableObject):
return None
def program_from_overrides(self, command_names: T.List[mesonlib.FileOrString],
for_machine: MachineChoice,
extra_info: T.List['mlog.TV_Loggable']
) -> T.Optional[Program]:
for name in command_names:
if not isinstance(name, str):
continue
if name in self.build.find_overrides:
exe = self.build.find_overrides[name]
if name in self.build.find_overrides[for_machine]:
exe = self.build.find_overrides[for_machine][name]
extra_info.append(mlog.blue('(overridden)'))
return exe
return None
def store_name_lookups(self, command_names: T.List[mesonlib.FileOrString]) -> None:
def store_name_lookups(self, command_names: T.List[mesonlib.FileOrString], for_machine: MachineChoice) -> None:
for name in command_names:
if isinstance(name, str):
self.build.searched_programs.add(name)
self.build.searched_programs[for_machine].add(name)
def add_find_program_override(self, name: str, exe: Program) -> None:
if name in self.build.searched_programs:
def add_find_program_override(self, name: str, exe: Program, for_machine: MachineChoice) -> None:
if name in self.build.searched_programs[for_machine]:
raise InterpreterException(f'Tried to override finding of executable "{name}" which has already been found.')
if name in self.build.find_overrides:
if name in self.build.find_overrides[for_machine]:
raise InterpreterException(f'Tried to override executable "{name}" which has already been overridden.')
self.build.find_overrides[name] = exe
self.build.find_overrides[for_machine][name] = exe
if name == 'pkg-config' and isinstance(exe, ExternalProgram):
from ..dependencies.pkgconfig import PkgConfigInterface
PkgConfigInterface.set_program_override(exe, MachineChoice.HOST)
PkgConfigInterface.set_program_override(exe, for_machine)
def notfound_program(self, args: T.List[mesonlib.FileOrString]) -> ExternalProgram:
return NonExistingExternalProgram(' '.join(
@@ -1754,7 +1756,7 @@ class Interpreter(InterpreterBase, HoldableObject):
return progobj
# Only store successful lookups
self.store_name_lookups(args)
self.store_name_lookups(args, for_machine)
if not silent:
mlog.log('Program', mlog.bold(progobj.name), 'found:', mlog.green('YES'), *extra_info)
return progobj
@@ -1768,7 +1770,7 @@ class Interpreter(InterpreterBase, HoldableObject):
version_func: T.Optional[ProgramVersionFunc],
extra_info: T.List[mlog.TV_Loggable]
) -> T.Optional[Program]:
progobj = self.program_from_overrides(args, extra_info)
progobj = self.program_from_overrides(args, for_machine, extra_info)
if progobj:
return progobj
@@ -1783,7 +1785,7 @@ class Interpreter(InterpreterBase, HoldableObject):
if wrap_mode != WrapMode.nofallback and self.environment.wrap_resolver:
fallback = self.environment.wrap_resolver.find_program_provider(args)
if fallback and wrap_mode == WrapMode.forcefallback:
return self.find_program_fallback(fallback, args, default_options, required, extra_info)
return self.find_program_fallback(fallback, args, for_machine, default_options, required, extra_info)
progobj = self.program_from_file_for(for_machine, args)
if progobj is None:
@@ -1801,7 +1803,7 @@ class Interpreter(InterpreterBase, HoldableObject):
progobj = self.notfound_program(args)
mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO'), *extra_info)
extra_info.clear()
progobj = self.find_program_fallback(fallback, args, default_options, required, extra_info)
progobj = self.find_program_fallback(fallback, args, for_machine, default_options, required, extra_info)
return progobj
@@ -1830,6 +1832,7 @@ class Interpreter(InterpreterBase, HoldableObject):
return True
def find_program_fallback(self, fallback: SubProject, args: T.List[mesonlib.FileOrString],
for_machine: MachineChoice,
default_options: OptionDict,
required: bool, extra_info: T.List[mlog.TV_Loggable]
) -> T.Optional[Program]:
@@ -1843,7 +1846,7 @@ class Interpreter(InterpreterBase, HoldableObject):
'options': None,
}
self.do_subproject(fallback, sp_kwargs)
return self.program_from_overrides(args, extra_info)
return self.program_from_overrides(args, for_machine, extra_info)
@typed_pos_args('find_program', varargs=(str, mesonlib.File), min_varargs=1)
@typed_kwargs(
+5 -3
View File
@@ -326,9 +326,11 @@ class MesonMain(MesonInterpreterObject):
@FeatureNew('meson.override_find_program', '0.46.0')
@typed_pos_args('meson.override_find_program', str, (mesonlib.File, Program, build.Executable))
@noKwargs
@typed_kwargs('meson.override_find_program', NATIVE_KW.evolve(since='1.12.0'))
@InterpreterObject.method('override_find_program')
def override_find_program_method(self, args: T.Tuple[str, T.Union[mesonlib.File, Program, build.Executable]], kwargs: 'TYPE_kwargs') -> None:
@apply_machine_map
def override_find_program_method(self, args: T.Tuple[str, T.Union[mesonlib.File, Program, build.Executable]],
kwargs: NativeKW) -> None:
name, exe = args
if isinstance(exe, mesonlib.File):
abspath = exe.absolute_path(self.interpreter.environment.source_dir,
@@ -339,7 +341,7 @@ class MesonMain(MesonInterpreterObject):
exe = build.LocalProgram(prog, self.interpreter.project_version, file=exe)
elif isinstance(exe, build.Executable):
exe = build.LocalProgram(exe, self.interpreter.project_version)
self.interpreter.add_find_program_override(name, exe)
self.interpreter.add_find_program_override(name, exe, kwargs['native'])
@typed_kwargs(
'meson.override_dependency',
+1 -1
View File
@@ -92,7 +92,7 @@ class ModuleState:
def find_tool(self, name: str, depname: str, varname: str, required: bool = True,
wanted: T.Optional[str] = None, native: bool = True) -> Program:
# Look in overrides in case it's built as subproject
progobj = self._interpreter.program_from_overrides([name], [])
progobj = self._interpreter.program_from_overrides([name], MachineChoice.HOST, [])
if progobj is not None:
return progobj