Skip to content

Commit 30e47ba

Browse files
committed
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).
1 parent acb32b2 commit 30e47ba

File tree

6 files changed

+40
-6
lines changed

6 files changed

+40
-6
lines changed

mesonbuild/build.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ def __init__(self, environment: environment.Environment):
275275
self.stdlibs = PerMachine({}, {})
276276
self.test_setups: T.Dict[str, TestSetup] = {}
277277
self.test_setup_default_name = None
278-
self.find_overrides: T.Dict[str, T.Union['Executable', programs.ExternalProgram, programs.OverrideProgram]] = {}
278+
self.find_overrides: T.Dict[str, T.Union['OverrideExecutable', programs.ExternalProgram, programs.OverrideProgram]] = {}
279279
self.searched_programs: T.Set[str] = set() # The list of all programs that have been searched for.
280280

281281
# If we are doing a cross build we need two caches, if we're doing a
@@ -3129,6 +3129,18 @@ def get(self, name: str) -> T.Tuple[T.Union[str, int, bool], T.Optional[str]]:
31293129
def keys(self) -> T.Iterator[str]:
31303130
return self.values.keys()
31313131

3132+
class OverrideExecutable(Executable):
3133+
def __init__(self, executable: Executable, version: str):
3134+
self._executable = executable
3135+
self._version = version
3136+
3137+
def __getattr__(self, name: str) -> T.Any:
3138+
_executable = object.__getattribute__(self, '_executable')
3139+
return getattr(_executable, name)
3140+
3141+
def get_version(self, interpreter: T.Optional[Interpreter] = None) -> str:
3142+
return self._version
3143+
31323144
# A bit poorly named, but this represents plain data files to copy
31333145
# during install.
31343146
@dataclass(eq=False)

mesonbuild/interpreter/interpreter.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,7 @@ def build_holder_map(self) -> None:
426426
build.Generator: OBJ.GeneratorHolder,
427427
build.GeneratedList: OBJ.GeneratedListHolder,
428428
build.ExtractedObjects: OBJ.GeneratedObjectsHolder,
429+
build.OverrideExecutable: OBJ.OverrideExecutableHolder,
429430
build.RunTarget: OBJ.RunTargetHolder,
430431
build.AliasTarget: OBJ.AliasTargetHolder,
431432
build.Headers: OBJ.HeadersHolder,
@@ -1589,7 +1590,7 @@ def program_from_system(self, args: T.List[mesonlib.FileOrString], search_dirs:
15891590

15901591
def program_from_overrides(self, command_names: T.List[mesonlib.FileOrString],
15911592
extra_info: T.List['mlog.TV_Loggable']
1592-
) -> T.Optional[T.Union[ExternalProgram, OverrideProgram, build.Executable]]:
1593+
) -> T.Optional[T.Union[ExternalProgram, OverrideProgram, build.OverrideExecutable]]:
15931594
for name in command_names:
15941595
if not isinstance(name, str):
15951596
continue
@@ -1604,7 +1605,7 @@ def store_name_lookups(self, command_names: T.List[mesonlib.FileOrString]) -> No
16041605
if isinstance(name, str):
16051606
self.build.searched_programs.add(name)
16061607

1607-
def add_find_program_override(self, name: str, exe: T.Union[build.Executable, ExternalProgram, 'OverrideProgram']) -> None:
1608+
def add_find_program_override(self, name: str, exe: T.Union[build.OverrideExecutable, ExternalProgram, 'OverrideProgram']) -> None:
16081609
if name in self.build.searched_programs:
16091610
raise InterpreterException(f'Tried to override finding of executable "{name}" which has already been found.')
16101611
if name in self.build.find_overrides:
@@ -1629,7 +1630,7 @@ def find_program_impl(self, args: T.List[mesonlib.FileOrString],
16291630
search_dirs: T.Optional[T.List[str]] = None,
16301631
version_arg: T.Optional[str] = '',
16311632
version_func: T.Optional[ProgramVersionFunc] = None
1632-
) -> T.Union['ExternalProgram', 'build.Executable', 'OverrideProgram']:
1633+
) -> T.Union['ExternalProgram', 'build.OverrideExecutable', 'OverrideProgram']:
16331634
args = mesonlib.listify(args)
16341635

16351636
extra_info: T.List[mlog.TV_Loggable] = []

mesonbuild/interpreter/interpreterobjects.py

+11
Original file line numberDiff line numberDiff line change
@@ -1142,3 +1142,14 @@ class StructuredSourcesHolder(ObjectHolder[build.StructuredSources]):
11421142

11431143
def __init__(self, sources: build.StructuredSources, interp: 'Interpreter'):
11441144
super().__init__(sources, interp)
1145+
1146+
class OverrideExecutableHolder(BuildTargetHolder[build.OverrideExecutable]):
1147+
def __init__(self, exe: build.OverrideExecutable, interpreter: 'Interpreter') -> None:
1148+
super().__init__(exe, interpreter)
1149+
self.methods.update({'version': self.version_method})
1150+
1151+
@noPosargs
1152+
@noKwargs
1153+
@FeatureNew('OverrideExecutable.version', '1.9.0')
1154+
def version_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
1155+
return self.held_object.get_version(self.interpreter)

mesonbuild/interpreter/mesonmain.py

+2
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,8 @@ def override_find_program_method(self, args: T.Tuple[str, T.Union[mesonlib.File,
335335
if not os.path.exists(abspath):
336336
raise InterpreterException(f'Tried to override {name} with a file that does not exist.')
337337
exe = OverrideProgram(name, self.interpreter.project_version, command=[abspath])
338+
elif isinstance(exe, build.Executable):
339+
exe = build.OverrideExecutable(exe, self.interpreter.project_version)
338340
self.interpreter.add_find_program_override(name, exe)
339341

340342
@typed_kwargs(

mesonbuild/modules/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,14 @@ def find_program(self, prog: T.Union[mesonlib.FileOrString, T.List[mesonlib.File
7575
required: bool = True,
7676
version_func: T.Optional[ProgramVersionFunc] = None,
7777
wanted: T.Union[str, T.List[str]] = '', silent: bool = False,
78-
for_machine: MachineChoice = MachineChoice.HOST) -> T.Union[ExternalProgram, build.Executable, OverrideProgram]:
78+
for_machine: MachineChoice = MachineChoice.HOST) -> T.Union[ExternalProgram, build.OverrideExecutable, OverrideProgram]:
7979
if not isinstance(prog, list):
8080
prog = [prog]
8181
return self._interpreter.find_program_impl(prog, required=required, version_func=version_func,
8282
wanted=wanted, silent=silent, for_machine=for_machine)
8383

8484
def find_tool(self, name: str, depname: str, varname: str, required: bool = True,
85-
wanted: T.Optional[str] = None) -> T.Union['build.Executable', ExternalProgram, 'OverrideProgram']:
85+
wanted: T.Optional[str] = None) -> T.Union[build.OverrideExecutable, ExternalProgram, 'OverrideProgram']:
8686
# Look in overrides in case it's built as subproject
8787
progobj = self._interpreter.program_from_overrides([name], [])
8888
if progobj is not None:
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
11
project('sub', 'c', version : '1.0')
22
foobar = executable('foobar', 'foobar.c', native : true)
33
meson.override_find_program('foobar', foobar)
4+
5+
found_foobar = find_program('foobar')
6+
if found_foobar.version() != meson.project_version()
7+
error('Overriden Executable had incorrect version: got @0@, expected @1@'.format(found_foobar.version(), meson.project_version()))
8+
endif
9+
10+
test('foobar executable', foobar, args : [ meson.current_build_dir() / 'test-output.c' ])
11+
test('overriden foobar executable', found_foobar, args : [ meson.current_build_dir() / 'test-output.c' ])

0 commit comments

Comments
 (0)