summaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
authorFlorian "sp1rit"​ <sp1rit@disroot.org>2025-05-01 19:07:27 +0200
committerJussi Pakkanen <jussi.pakkanen@mailbox.org>2025-05-22 12:23:55 +0300
commit7f1437a928d4282e45991ff6145dee8a9043be2f (patch)
tree2d2a7252feddc0b7b9a60368ad77f6f8c9d609bb /mesonbuild
parente8c715786d85dcdbc367f3e379acae25a899c235 (diff)
downloadmeson-7f1437a928d4282e45991ff6145dee8a9043be2f.tar.gz
support .version() for overridden executables
Also ensure that .get_version() can be called on the output of _find_tool by the modules (kind of required for #14422).
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/build.py14
-rw-r--r--mesonbuild/interpreter/interpreter.py7
-rw-r--r--mesonbuild/interpreter/interpreterobjects.py11
-rw-r--r--mesonbuild/interpreter/mesonmain.py2
-rw-r--r--mesonbuild/modules/__init__.py4
5 files changed, 32 insertions, 6 deletions
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index d38abcbb5..73f99cb66 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -275,7 +275,7 @@ class Build:
self.stdlibs = PerMachine({}, {})
self.test_setups: T.Dict[str, TestSetup] = {}
self.test_setup_default_name = None
- self.find_overrides: T.Dict[str, T.Union['Executable', programs.ExternalProgram, programs.OverrideProgram]] = {}
+ self.find_overrides: T.Dict[str, T.Union['OverrideExecutable', programs.ExternalProgram, programs.OverrideProgram]] = {}
self.searched_programs: T.Set[str] = set() # The list of all programs that have been searched for.
# If we are doing a cross build we need two caches, if we're doing a
@@ -3116,6 +3116,18 @@ class ConfigurationData(HoldableObject):
def keys(self) -> T.Iterator[str]:
return self.values.keys()
+class OverrideExecutable(Executable):
+ def __init__(self, executable: Executable, version: str):
+ self._executable = executable
+ self._version = version
+
+ def __getattr__(self, name: str) -> T.Any:
+ _executable = object.__getattribute__(self, '_executable')
+ return getattr(_executable, name)
+
+ def get_version(self, interpreter: T.Optional[Interpreter] = None) -> str:
+ return self._version
+
# A bit poorly named, but this represents plain data files to copy
# during install.
@dataclass(eq=False)
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index 4d1d86b72..750e54742 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -426,6 +426,7 @@ class Interpreter(InterpreterBase, HoldableObject):
build.Generator: OBJ.GeneratorHolder,
build.GeneratedList: OBJ.GeneratedListHolder,
build.ExtractedObjects: OBJ.GeneratedObjectsHolder,
+ build.OverrideExecutable: OBJ.OverrideExecutableHolder,
build.RunTarget: OBJ.RunTargetHolder,
build.AliasTarget: OBJ.AliasTargetHolder,
build.Headers: OBJ.HeadersHolder,
@@ -1592,7 +1593,7 @@ class Interpreter(InterpreterBase, HoldableObject):
def program_from_overrides(self, command_names: T.List[mesonlib.FileOrString],
extra_info: T.List['mlog.TV_Loggable']
- ) -> T.Optional[T.Union[ExternalProgram, OverrideProgram, build.Executable]]:
+ ) -> T.Optional[T.Union[ExternalProgram, OverrideProgram, build.OverrideExecutable]]:
for name in command_names:
if not isinstance(name, str):
continue
@@ -1607,7 +1608,7 @@ class Interpreter(InterpreterBase, HoldableObject):
if isinstance(name, str):
self.build.searched_programs.add(name)
- def add_find_program_override(self, name: str, exe: T.Union[build.Executable, ExternalProgram, 'OverrideProgram']) -> None:
+ def add_find_program_override(self, name: str, exe: T.Union[build.OverrideExecutable, ExternalProgram, 'OverrideProgram']) -> None:
if name in self.build.searched_programs:
raise InterpreterException(f'Tried to override finding of executable "{name}" which has already been found.')
if name in self.build.find_overrides:
@@ -1632,7 +1633,7 @@ class Interpreter(InterpreterBase, HoldableObject):
search_dirs: T.Optional[T.List[str]] = None,
version_arg: T.Optional[str] = '',
version_func: T.Optional[ProgramVersionFunc] = None
- ) -> T.Union['ExternalProgram', 'build.Executable', 'OverrideProgram']:
+ ) -> T.Union['ExternalProgram', 'build.OverrideExecutable', 'OverrideProgram']:
args = mesonlib.listify(args)
extra_info: T.List[mlog.TV_Loggable] = []
diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py
index a2fadbefc..af1322d0e 100644
--- a/mesonbuild/interpreter/interpreterobjects.py
+++ b/mesonbuild/interpreter/interpreterobjects.py
@@ -1142,3 +1142,14 @@ class StructuredSourcesHolder(ObjectHolder[build.StructuredSources]):
def __init__(self, sources: build.StructuredSources, interp: 'Interpreter'):
super().__init__(sources, interp)
+
+class OverrideExecutableHolder(BuildTargetHolder[build.OverrideExecutable]):
+ def __init__(self, exe: build.OverrideExecutable, interpreter: 'Interpreter') -> None:
+ super().__init__(exe, interpreter)
+ self.methods.update({'version': self.version_method})
+
+ @noPosargs
+ @noKwargs
+ @FeatureNew('OverrideExecutable.version', '1.9.0')
+ def version_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+ return self.held_object.get_version(self.interpreter)
diff --git a/mesonbuild/interpreter/mesonmain.py b/mesonbuild/interpreter/mesonmain.py
index 8ede6916a..cc71104cf 100644
--- a/mesonbuild/interpreter/mesonmain.py
+++ b/mesonbuild/interpreter/mesonmain.py
@@ -335,6 +335,8 @@ class MesonMain(MesonInterpreterObject):
if not os.path.exists(abspath):
raise InterpreterException(f'Tried to override {name} with a file that does not exist.')
exe = OverrideProgram(name, self.interpreter.project_version, command=[abspath])
+ elif isinstance(exe, build.Executable):
+ exe = build.OverrideExecutable(exe, self.interpreter.project_version)
self.interpreter.add_find_program_override(name, exe)
@typed_kwargs(
diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py
index 67d16661a..87892e6d7 100644
--- a/mesonbuild/modules/__init__.py
+++ b/mesonbuild/modules/__init__.py
@@ -75,14 +75,14 @@ class ModuleState:
required: bool = True,
version_func: T.Optional[ProgramVersionFunc] = None,
wanted: T.Union[str, T.List[str]] = '', silent: bool = False,
- for_machine: MachineChoice = MachineChoice.HOST) -> T.Union[ExternalProgram, build.Executable, OverrideProgram]:
+ for_machine: MachineChoice = MachineChoice.HOST) -> T.Union[ExternalProgram, build.OverrideExecutable, OverrideProgram]:
if not isinstance(prog, list):
prog = [prog]
return self._interpreter.find_program_impl(prog, required=required, version_func=version_func,
wanted=wanted, silent=silent, for_machine=for_machine)
def find_tool(self, name: str, depname: str, varname: str, required: bool = True,
- wanted: T.Optional[str] = None) -> T.Union['build.Executable', ExternalProgram, 'OverrideProgram']:
+ wanted: T.Optional[str] = None) -> T.Union[build.OverrideExecutable, ExternalProgram, 'OverrideProgram']:
# Look in overrides in case it's built as subproject
progobj = self._interpreter.program_from_overrides([name], [])
if progobj is not None: