Skip to content

Commit 7d0bc3d

Browse files
committed
Allow overriding a program with a CustomTarget
Move implementation to a function read to become public API.
1 parent 98b6d3a commit 7d0bc3d

File tree

4 files changed

+46
-14
lines changed

4 files changed

+46
-14
lines changed

docs/yaml/builtins/meson.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,10 @@ methods:
383383
check is passed to [[find_program]] for a program that has been overridden with
384384
an executable, the current project version is used.
385385
386+
*(since 1.10.0)* It is also possible to override with a [[@custom_tgt]] or
387+
[[@custom_idx]]. In that case, be aware that an interpreter could be required
388+
on Windows in which case [[local_program]] should be used.
389+
386390
posargs:
387391
progname:
388392
type: str

mesonbuild/build.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3337,9 +3337,6 @@ def __init__(self, program: T.Union[programs.ExternalProgram, Executable, Custom
33373337
depends: T.Optional[T.List[T.Union[BuildTarget, CustomTarget]]] = None,
33383338
depend_files: T.Optional[T.List[File]] = None) -> None:
33393339
super().__init__()
3340-
if isinstance(program, CustomTarget):
3341-
if len(program.outputs) != 1:
3342-
raise InvalidArguments('CustomTarget used as LocalProgram must have exactly one output.')
33433340
self.name = program.name
33443341
self.program = program
33453342
self.depends = list(depends or [])

mesonbuild/interpreter/interpreter.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1769,6 +1769,38 @@ def func_find_program(self, node: mparser.BaseNode, args: T.Tuple[T.List[mesonli
17691769
silent=False, wanted=kwargs['version'], version_arg=kwargs['version_argument'],
17701770
search_dirs=search_dirs)
17711771

1772+
def _local_program_impl(self, exe: T.Union[mesonlib.FileOrString, build.Executable, build.CustomTarget, build.CustomTargetIndex],
1773+
depends_: T.Optional[T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]]] = None,
1774+
depend_files_: T.Optional[T.List[mesonlib.FileOrString]] = None,
1775+
interpreter: T.Optional[T.Union[ExternalProgram, T.List[T.Union[ExternalProgram, str]]]] = None) -> build.LocalProgram:
1776+
if isinstance(exe, build.CustomTarget):
1777+
if len(exe.outputs) != 1:
1778+
raise InvalidArguments('CustomTarget used as LocalProgram must have exactly one output.')
1779+
depends = [d.target if isinstance(d, build.CustomTargetIndex) else d for d in (depends_ or [])]
1780+
depend_files = self.source_strings_to_files(depend_files_ or [])
1781+
if isinstance(exe, (str, mesonlib.File)):
1782+
file = self.source_strings_to_files([exe])[0]
1783+
abspath = file.absolute_path(self.environment.source_dir, self.environment.build_dir)
1784+
prog = ExternalProgram(file.fname, command=[abspath], silent=True)
1785+
return build.LocalProgram(prog, self.project_version, depends, depend_files)
1786+
if interpreter:
1787+
if not isinstance(exe, (build.CustomTarget, build.CustomTargetIndex)):
1788+
raise InvalidArguments('The "interpreter" argument can only be used when the first argument is a custom target.')
1789+
if isinstance(interpreter, list):
1790+
interpreter, args = interpreter[0], interpreter[1:]
1791+
if not isinstance(interpreter, ExternalProgram) or any(not isinstance(a, str) for a in args):
1792+
raise InvalidArguments('Interpreter must be an ExternalProgram followed by strings.')
1793+
else:
1794+
args = []
1795+
if not interpreter.found():
1796+
raise InvalidArguments(f'Specified interpreter program {interpreter.description()!r} not found.')
1797+
target = exe.target if isinstance(exe, build.CustomTargetIndex) else exe
1798+
depends.append(target)
1799+
cmd = interpreter.get_command() + args + [self.backend.get_target_filename(exe)]
1800+
prog = ExternalProgram(exe.name, command=cmd, silent=True)
1801+
return build.LocalProgram(prog, self.project_version, depends, depend_files)
1802+
return build.LocalProgram(exe, self.project_version, depends, depend_files)
1803+
17721804
# When adding kwargs, please check if they make sense in dependencies.get_dep_identifier()
17731805
@typed_pos_args('dependency', varargs=str, min_varargs=1)
17741806
@typed_kwargs('dependency', *DEPENDENCY_KWS)

mesonbuild/interpreter/mesonmain.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -315,20 +315,19 @@ def install_dependency_manifest_method(self, args: T.Tuple[str], kwargs: 'TYPE_k
315315
self.build.dep_manifest_name = args[0]
316316

317317
@FeatureNew('meson.override_find_program', '0.46.0')
318-
@typed_pos_args('meson.override_find_program', str, (mesonlib.File, ExternalProgram, build.Executable, build.LocalProgram))
318+
@typed_pos_args('meson.override_find_program', str, (mesonlib.File, ExternalProgram, build.Executable, build.LocalProgram,
319+
build.CustomTarget, build.CustomTargetIndex))
319320
@noKwargs
320321
@InterpreterObject.method('override_find_program')
321-
def override_find_program_method(self, args: T.Tuple[str, T.Union[mesonlib.File, ExternalProgram, build.Executable, build.LocalProgram]], kwargs: 'TYPE_kwargs') -> None:
322+
def override_find_program_method(self, args: T.Tuple[str, T.Union[mesonlib.File, ExternalProgram, build.Executable,
323+
build.LocalProgram, build.CustomTarget, build.CustomTargetIndex]],
324+
kwargs: 'TYPE_kwargs') -> None:
322325
name, exe = args
323-
if isinstance(exe, mesonlib.File):
324-
abspath = exe.absolute_path(self.interpreter.environment.source_dir,
325-
self.interpreter.environment.build_dir)
326-
if not os.path.exists(abspath):
327-
raise InterpreterException(f'Tried to override {name} with a file that does not exist.')
328-
prog = ExternalProgram(name, command=[abspath], silent=True)
329-
exe = build.LocalProgram(prog, self.interpreter.project_version)
330-
elif isinstance(exe, build.Executable):
331-
exe = build.LocalProgram(exe, self.interpreter.project_version)
326+
if isinstance(exe, (build.CustomTarget, build.CustomTargetIndex)):
327+
FeatureNew.single_use('Overriding find_program with a CustomTarget or CustomTargetIndex', '1.10.0',
328+
self.subproject, location=self.current_node)
329+
if not isinstance(exe, (ExternalProgram, build.LocalProgram)):
330+
exe = self.interpreter._local_program_impl(exe)
332331
self.interpreter.add_find_program_override(name, exe)
333332

334333
@typed_kwargs(

0 commit comments

Comments
 (0)