diff options
| author | Eli Schwartz <eschwartz93@gmail.com> | 2025-10-15 21:49:10 -0400 |
|---|---|---|
| committer | Eli Schwartz <eschwartz93@gmail.com> | 2025-10-15 23:01:36 -0400 |
| commit | 5c0aad57f92d2a6bebc1cb17655dd8a56f4bcd3f (patch) | |
| tree | 69a228a10f425b33392df576f79bd8b7c5402104 /mesonbuild/interpreter | |
| parent | 1177e77c2893891cb35144b8033786cb8f75c7cd (diff) | |
| download | meson-5c0aad57f92d2a6bebc1cb17655dd8a56f4bcd3f.tar.gz | |
revert local_program()
This reverts https://github.com/mesonbuild/meson/pull/15107
Explicit objections regarding the design were raised and not answered,
so it shouldn't have been merged. It needs to be discussed and
revisited.
Diffstat (limited to 'mesonbuild/interpreter')
| -rw-r--r-- | mesonbuild/interpreter/__init__.py | 4 | ||||
| -rw-r--r-- | mesonbuild/interpreter/interpreter.py | 140 | ||||
| -rw-r--r-- | mesonbuild/interpreter/interpreterobjects.py | 28 | ||||
| -rw-r--r-- | mesonbuild/interpreter/kwargs.py | 12 | ||||
| -rw-r--r-- | mesonbuild/interpreter/mesonmain.py | 40 | ||||
| -rw-r--r-- | mesonbuild/interpreter/type_checking.py | 7 |
6 files changed, 91 insertions, 140 deletions
diff --git a/mesonbuild/interpreter/__init__.py b/mesonbuild/interpreter/__init__.py index 5186b842b..e2ccce479 100644 --- a/mesonbuild/interpreter/__init__.py +++ b/mesonbuild/interpreter/__init__.py @@ -20,6 +20,7 @@ __all__ = [ 'SubprojectHolder', 'DependencyHolder', 'GeneratedListHolder', + 'ExternalProgramHolder', 'extract_required_kwarg', 'ArrayHolder', @@ -34,7 +35,8 @@ from .compiler import CompilerHolder from .interpreterobjects import (ExecutableHolder, BuildTargetHolder, CustomTargetHolder, CustomTargetIndexHolder, MachineHolder, Test, ConfigurationDataHolder, SubprojectHolder, DependencyHolder, - GeneratedListHolder, extract_required_kwarg) + GeneratedListHolder, ExternalProgramHolder, + extract_required_kwarg) from .primitives import ( ArrayHolder, diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 51671bfc5..8481f36bd 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -21,7 +21,7 @@ from ..mesonlib import (EnvironmentVariables, ExecutableSerialisation, MesonBugE FileMode, MachineChoice, is_parent_path, listify, extract_as_list, has_path_sep, path_is_in_root, PerMachine) from ..options import OptionKey -from ..programs import ExternalProgram, NonExistingExternalProgram, BaseProgram +from ..programs import ExternalProgram, NonExistingExternalProgram from ..dependencies import Dependency from ..depfile import DepFile from ..interpreterbase import ContainerTypeInfo, InterpreterBase, KwargInfo, typed_kwargs, typed_pos_args @@ -118,6 +118,7 @@ if T.TYPE_CHECKING: from ..backend.backends import Backend from ..interpreterbase.baseobjects import InterpreterObject, TYPE_var, TYPE_kwargs from ..options import OptionDict + from ..programs import OverrideProgram from .type_checking import SourcesVarargsType # Input source types passed to Targets @@ -129,7 +130,7 @@ if T.TYPE_CHECKING: BuildTargetSource = T.Union[mesonlib.FileOrString, build.GeneratedTypes, build.StructuredSources] - ProgramVersionFunc = T.Callable[[T.Union[ExternalProgram, build.LocalProgram]], str] + ProgramVersionFunc = T.Callable[[T.Union[ExternalProgram, build.Executable, OverrideProgram]], str] TestClass = T.TypeVar('TestClass', bound=Test) @@ -368,7 +369,6 @@ class Interpreter(InterpreterBase, HoldableObject): 'executable': self.func_executable, 'files': self.func_files, 'find_program': self.func_find_program, - 'local_program': self.func_local_program, 'generator': self.func_generator, 'get_option': self.func_get_option, 'get_variable': self.func_get_variable, @@ -440,6 +440,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, @@ -469,7 +470,7 @@ class Interpreter(InterpreterBase, HoldableObject): ''' self.bound_holder_map.update({ dependencies.Dependency: OBJ.DependencyHolder, - BaseProgram: OBJ.BaseProgramHolder, + ExternalProgram: OBJ.ExternalProgramHolder, compilers.Compiler: compilerOBJ.CompilerHolder, ModuleObject: OBJ.ModuleObjectHolder, MutableModuleObject: OBJ.MutableModuleObjectHolder, @@ -768,8 +769,8 @@ class Interpreter(InterpreterBase, HoldableObject): # better error messages when overridden @typed_pos_args( 'run_command', - (build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str, build.LocalProgram), - varargs=(build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str, build.LocalProgram)) + (build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str), + varargs=(build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str)) @typed_kwargs( 'run_command', KwargInfo('check', (bool, NoneType), since='0.47.0'), @@ -777,21 +778,14 @@ class Interpreter(InterpreterBase, HoldableObject): ENV_KW.evolve(since='0.50.0'), ) def func_run_command(self, node: mparser.BaseNode, - args: T.Tuple[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str, build.LocalProgram], - T.List[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str, build.LocalProgram]]], + args: T.Tuple[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str], + T.List[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str]]], kwargs: 'kwtypes.RunCommand') -> RunProcess: return self.run_command_impl(args, kwargs) - def _compiled_exe_error(self, cmd: T.Union[build.LocalProgram, 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') - raise InterpreterException(f'Program {descr!r} is a compiled executable and therefore cannot be used during configuration') - def run_command_impl(self, - args: T.Tuple[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str, build.LocalProgram], - T.List[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str, build.LocalProgram]]], + args: T.Tuple[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str], + T.List[T.Union[build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str]]], kwargs: 'kwtypes.RunCommand', in_builddir: bool = False) -> RunProcess: cmd, cargs = args @@ -805,17 +799,19 @@ class Interpreter(InterpreterBase, HoldableObject): mlog.warning(implicit_check_false_warning, once=True) check = False + overridden_msg = ('Program {!r} was overridden with the compiled ' + 'executable {!r} and therefore cannot be used during ' + 'configuration') expanded_args: T.List[str] = [] - if isinstance(cmd, build.LocalProgram): - prog = cmd.run_program() - if prog is None: - self._compiled_exe_error(cmd) - for f in cmd.depend_files: - self.add_build_def_file(f) - cmd = prog - elif isinstance(cmd, build.Executable): - self._compiled_exe_error(cmd) - elif isinstance(cmd, ExternalProgram): + if isinstance(cmd, build.Executable): + for name, exe in self.build.find_overrides.items(): + if cmd == exe: + progname = name + break + else: + raise InterpreterException(f'Program {cmd.description()!r} is a compiled executable and therefore cannot be used during configuration') + raise InterpreterException(overridden_msg.format(progname, cmd.description())) + if isinstance(cmd, ExternalProgram): if not cmd.found(): raise InterpreterException(f'command {cmd.get_name()!r} not found or not executable') elif isinstance(cmd, compilers.Compiler): @@ -847,15 +843,8 @@ class Interpreter(InterpreterBase, HoldableObject): if not prog.found(): raise InterpreterException(f'Program {cmd!r} not found or not executable') expanded_args.append(prog.get_path()) - elif isinstance(a, build.LocalProgram): - prog = a.run_program() - if prog is None: - self._compiled_exe_error(a) - for f in a.depend_files: - self.add_build_def_file(f) - expanded_args.append(prog.get_path()) else: - self._compiled_exe_error(a) + raise InterpreterException(overridden_msg.format(a.name, cmd.description())) # If any file that was used as an argument to the command # changes, we must re-run the configuration step. @@ -1620,7 +1609,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, build.LocalProgram]]: + ) -> T.Optional[T.Union[ExternalProgram, OverrideProgram, build.OverrideExecutable]]: for name in command_names: if not isinstance(name, str): continue @@ -1635,7 +1624,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[ExternalProgram, build.LocalProgram]) -> 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: @@ -1660,7 +1649,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.LocalProgram]: + ) -> T.Union['ExternalProgram', 'build.OverrideExecutable', 'OverrideProgram']: args = mesonlib.listify(args) extra_info: T.List[mlog.TV_Loggable] = [] @@ -1692,7 +1681,7 @@ class Interpreter(InterpreterBase, HoldableObject): version_arg: T.Optional[str], version_func: T.Optional[ProgramVersionFunc], extra_info: T.List[mlog.TV_Loggable] - ) -> T.Optional[T.Union[ExternalProgram, build.LocalProgram]]: + ) -> T.Optional[T.Union[ExternalProgram, build.Executable, OverrideProgram]]: progobj = self.program_from_overrides(args, extra_info) if progobj: return progobj @@ -1728,7 +1717,7 @@ class Interpreter(InterpreterBase, HoldableObject): return progobj - def check_program_version(self, progobj: T.Union[ExternalProgram, build.LocalProgram], + def check_program_version(self, progobj: T.Union[ExternalProgram, build.Executable, OverrideProgram], wanted: T.Union[str, T.List[str]], version_func: T.Optional[ProgramVersionFunc], extra_info: T.List[mlog.TV_Loggable]) -> bool: @@ -1755,7 +1744,7 @@ class Interpreter(InterpreterBase, HoldableObject): def find_program_fallback(self, fallback: str, args: T.List[mesonlib.FileOrString], default_options: OptionDict, required: bool, extra_info: T.List[mlog.TV_Loggable] - ) -> T.Optional[T.Union[ExternalProgram, build.LocalProgram]]: + ) -> T.Optional[T.Union[ExternalProgram, build.Executable, OverrideProgram]]: mlog.log('Fallback to subproject', mlog.bold(fallback), 'which provides program', mlog.bold(' '.join(args))) sp_kwargs: kwtypes.DoSubproject = { @@ -1782,7 +1771,7 @@ class Interpreter(InterpreterBase, HoldableObject): @disablerIfNotFound def func_find_program(self, node: mparser.BaseNode, args: T.Tuple[T.List[mesonlib.FileOrString]], kwargs: 'kwtypes.FindProgram', - ) -> T.Union[ExternalProgram, build.LocalProgram]: + ) -> T.Union['build.Executable', ExternalProgram, 'OverrideProgram']: disabled, required, feature = extract_required_kwarg(kwargs, self.subproject) if disabled: assert feature, 'for mypy' @@ -1795,44 +1784,6 @@ class Interpreter(InterpreterBase, HoldableObject): silent=False, wanted=kwargs['version'], version_arg=kwargs['version_argument'], search_dirs=search_dirs) - @FeatureNew('local_program', '1.10.0') - @typed_pos_args('local_program', (str, mesonlib.File, build.Executable, build.CustomTarget, build.CustomTargetIndex)) - @typed_kwargs( - 'local_program', - DEPENDS_KW, - DEPEND_FILES_KW, - KwargInfo('interpreter', (ExternalProgram, NoneType), default=None), - ) - def func_local_program(self, node: mparser.BaseNode, args: T.Tuple[T.Union[mesonlib.FileOrString, build.Executable, build.CustomTarget, build.CustomTargetIndex]], - kwargs: kwtypes.LocalProgram) -> build.LocalProgram: - return self._local_program_impl(args[0], kwargs['depends'], kwargs['depend_files'], kwargs['interpreter']) - - def _local_program_impl(self, exe: T.Union[mesonlib.FileOrString, build.Executable, build.CustomTarget, build.CustomTargetIndex], - depends_: T.Optional[T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]]] = None, - depend_files_: T.Optional[T.List[mesonlib.FileOrString]] = None, - interpreter: T.Optional[ExternalProgram] = None) -> build.LocalProgram: - if isinstance(exe, build.CustomTarget): - if len(exe.outputs) != 1: - raise InvalidArguments('CustomTarget used as LocalProgram must have exactly one output.') - depends = [d.target if isinstance(d, build.CustomTargetIndex) else d for d in (depends_ or [])] - depend_files = self.source_strings_to_files(depend_files_ or []) - if isinstance(exe, (str, mesonlib.File)): - file = self.source_strings_to_files([exe])[0] - abspath = file.absolute_path(self.environment.source_dir, self.environment.build_dir) - prog = ExternalProgram(file.fname, command=[abspath], silent=True) - return build.LocalProgram(prog, self.project_version, depends, depend_files) - if interpreter: - if not isinstance(exe, (build.CustomTarget, build.CustomTargetIndex)): - raise InvalidArguments('The "interpreter" argument can only be used when the first argument is a custom target.') - if not interpreter.found(): - raise InvalidArguments(f'Specified interpreter program {interpreter.description()!r} not found.') - target = exe.target if isinstance(exe, build.CustomTargetIndex) else exe - depends.append(target) - cmd = interpreter.get_command() + [self.backend.get_target_filename(exe)] - prog = ExternalProgram(exe.name, command=cmd, silent=True) - return build.LocalProgram(prog, self.project_version, depends, depend_files) - return build.LocalProgram(exe, self.project_version, depends, depend_files) - # When adding kwargs, please check if they make sense in dependencies.get_dep_identifier() @FeatureNewKwargs('dependency', '0.57.0', ['cmake_package_version']) @FeatureNewKwargs('dependency', '0.56.0', ['allow_fallback']) @@ -2255,7 +2206,7 @@ class Interpreter(InterpreterBase, HoldableObject): self.add_target(name, tg) return tg - @typed_pos_args('generator', (build.Executable, ExternalProgram, build.LocalProgram)) + @typed_pos_args('generator', (build.Executable, ExternalProgram)) @typed_kwargs( 'generator', KwargInfo('arguments', ContainerTypeInfo(list, str, allow_empty=False), required=True, listify=True), @@ -2265,7 +2216,7 @@ class Interpreter(InterpreterBase, HoldableObject): KwargInfo('capture', bool, default=False, since='0.43.0'), ) def func_generator(self, node: mparser.FunctionNode, - args: T.Tuple[T.Union[build.Executable, ExternalProgram, build.LocalProgram]], + args: T.Tuple[T.Union[build.Executable, ExternalProgram]], kwargs: 'kwtypes.FuncGenerator') -> build.Generator: for rule in kwargs['output']: if '@BASENAME@' not in rule and '@PLAINNAME@' not in rule: @@ -2279,17 +2230,17 @@ class Interpreter(InterpreterBase, HoldableObject): return build.Generator(args[0], **kwargs) - @typed_pos_args('benchmark', str, (build.Executable, build.Jar, ExternalProgram, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.LocalProgram)) + @typed_pos_args('benchmark', str, (build.Executable, build.Jar, ExternalProgram, mesonlib.File, build.CustomTarget, build.CustomTargetIndex)) @typed_kwargs('benchmark', *TEST_KWS) def func_benchmark(self, node: mparser.BaseNode, - args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File, build.LocalProgram]], + args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File]], kwargs: 'kwtypes.FuncBenchmark') -> None: self.add_test(node, args, kwargs, False) - @typed_pos_args('test', str, (build.Executable, build.Jar, ExternalProgram, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.LocalProgram)) + @typed_pos_args('test', str, (build.Executable, build.Jar, ExternalProgram, mesonlib.File, build.CustomTarget, build.CustomTargetIndex)) @typed_kwargs('test', *TEST_KWS, KwargInfo('is_parallel', bool, default=True)) def func_test(self, node: mparser.BaseNode, - args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.LocalProgram]], + args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File, build.CustomTarget, build.CustomTargetIndex]], kwargs: 'kwtypes.FuncTest') -> None: self.add_test(node, args, kwargs, True) @@ -2303,7 +2254,7 @@ class Interpreter(InterpreterBase, HoldableObject): return ENV_KW.convertor(envlist) def make_test(self, node: mparser.BaseNode, - args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.LocalProgram]], + args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File, build.CustomTarget, build.CustomTargetIndex]], kwargs: 'kwtypes.BaseTest', klass: T.Type[TestClass] = Test) -> TestClass: name = args[0] @@ -2312,20 +2263,15 @@ class Interpreter(InterpreterBase, HoldableObject): location=node) name = name.replace(':', '_') exe = args[1] - depends = list(kwargs['depends'] or []) - if isinstance(exe, build.LocalProgram): - # FIXME: tests does not have depend_files? - depends.extend(exe.depends) - exe = exe.program - elif isinstance(exe, ExternalProgram): + if isinstance(exe, ExternalProgram): if not exe.found(): raise InvalidArguments('Tried to use not-found external program as test exe') elif isinstance(exe, mesonlib.File): exe = self.find_program_impl([exe]) elif isinstance(exe, build.CustomTarget): - depends.append(exe) + kwargs.setdefault('depends', []).append(exe) elif isinstance(exe, build.CustomTargetIndex): - depends.append(exe.target) + kwargs.setdefault('depends', []).append(exe.target) env = self.unpack_env_kwarg(kwargs) @@ -2344,7 +2290,7 @@ class Interpreter(InterpreterBase, HoldableObject): prj, suite, exe, - depends, + kwargs['depends'], kwargs.get('is_parallel', False), kwargs['args'], env, @@ -2669,7 +2615,7 @@ class Interpreter(InterpreterBase, HoldableObject): KwargInfo('capture', bool, default=False, since='0.41.0'), KwargInfo( 'command', - (ContainerTypeInfo(list, (build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str, build.LocalProgram), allow_empty=False), NoneType), + (ContainerTypeInfo(list, (build.Executable, ExternalProgram, compilers.Compiler, mesonlib.File, str), allow_empty=False), NoneType), listify=True, ), KwargInfo( diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index addc7d3db..86e8957bc 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -23,7 +23,7 @@ from ..interpreterbase import ( flatten, resolve_second_level_holders, InterpreterException, InvalidArguments, InvalidCode) from ..interpreter.type_checking import NoneType, ENV_KW, ENV_SEPARATOR_KW, PKGCONFIG_DEFINE_KW from ..dependencies import Dependency, ExternalLibrary, InternalDependency -from ..programs import ExternalProgram, BaseProgram +from ..programs import ExternalProgram from ..mesonlib import HoldableObject, listify, Popen_safe import typing as T @@ -605,10 +605,10 @@ class DependencyHolder(ObjectHolder[Dependency]): raise InterpreterException('as_shared method is only supported on declare_dependency() objects') return self.held_object.get_as_shared(kwargs['recursive']) -_BASEPROG = T.TypeVar('_BASEPROG', bound=BaseProgram) +_EXTPROG = T.TypeVar('_EXTPROG', bound=ExternalProgram) -class BaseProgramHolder(ObjectHolder[_BASEPROG]): - def __init__(self, ep: _BASEPROG, interpreter: 'Interpreter') -> None: +class _ExternalProgramHolder(ObjectHolder[_EXTPROG]): + def __init__(self, ep: _EXTPROG, interpreter: 'Interpreter') -> None: super().__init__(ep, interpreter) @noPosargs @@ -619,15 +619,15 @@ class BaseProgramHolder(ObjectHolder[_BASEPROG]): @noPosargs @noKwargs - @FeatureDeprecated('Program.path', '0.55.0', - 'use Program.full_path() instead') + @FeatureDeprecated('ExternalProgram.path', '0.55.0', + 'use ExternalProgram.full_path() instead') @InterpreterObject.method('path') def path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: return self._full_path() @noPosargs @noKwargs - @FeatureNew('Program.full_path', '0.55.0') + @FeatureNew('ExternalProgram.full_path', '0.55.0') @InterpreterObject.method('full_path') def full_path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: return self._full_path() @@ -641,11 +641,9 @@ class BaseProgramHolder(ObjectHolder[_BASEPROG]): @noPosargs @noKwargs - @FeatureNew('Program.version', '0.62.0') + @FeatureNew('ExternalProgram.version', '0.62.0') @InterpreterObject.method('version') def version_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: - if isinstance(self.held_object, build.LocalProgram) and isinstance(self.held_object.program, build.Executable): - FeatureNew.single_use('Program.version with an executable', '1.9.0', subproject=self.subproject, location=self.current_node) if not self.found(): raise InterpreterException('Unable to get the version of a not-found external program') try: @@ -656,6 +654,8 @@ class BaseProgramHolder(ObjectHolder[_BASEPROG]): def found(self) -> bool: return self.held_object.found() +class ExternalProgramHolder(_ExternalProgramHolder[ExternalProgram]): + pass class ExternalLibraryHolder(ObjectHolder[ExternalLibrary]): def __init__(self, el: ExternalLibrary, interpreter: 'Interpreter'): @@ -1163,3 +1163,11 @@ class StructuredSourcesHolder(ObjectHolder[build.StructuredSources]): def __init__(self, sources: build.StructuredSources, interp: 'Interpreter'): super().__init__(sources, interp) + +class OverrideExecutableHolder(BuildTargetHolder[build.OverrideExecutable]): + @noPosargs + @noKwargs + @FeatureNew('OverrideExecutable.version', '1.9.0') + @InterpreterObject.method('version') + 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/kwargs.py b/mesonbuild/interpreter/kwargs.py index 22dde255d..e95d47341 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -171,8 +171,7 @@ class FuncAddLanguages(ExtractRequired): class RunTarget(TypedDict): - command: T.List[T.Union[str, build.BuildTarget, build.CustomTarget, ExternalProgram, - File, LocalProgram]] + command: T.List[T.Union[str, build.BuildTarget, build.CustomTarget, ExternalProgram, File]] depends: T.List[T.Union[build.BuildTarget, build.CustomTarget]] env: EnvironmentVariables @@ -183,7 +182,7 @@ class CustomTarget(TypedDict): build_always_stale: T.Optional[bool] build_by_default: T.Optional[bool] capture: bool - command: T.List[T.Union[str, build.BuildTargetTypes, ExternalProgram, File, LocalProgram]] + command: T.List[T.Union[str, build.BuildTargetTypes, ExternalProgram, File]] console: bool depend_files: T.List[FileOrString] depends: T.List[T.Union[build.BuildTarget, build.CustomTarget]] @@ -247,13 +246,6 @@ class FindProgram(ExtractRequired, ExtractSearchDirs): version: T.List[str] -class LocalProgram(TypedDict): - - depend_files: T.List[FileOrString] - depends: T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]] - interpreter: T.Optional[ExternalProgram] - - class RunCommand(TypedDict): check: bool diff --git a/mesonbuild/interpreter/mesonmain.py b/mesonbuild/interpreter/mesonmain.py index 3afeb8647..d22d36bf0 100644 --- a/mesonbuild/interpreter/mesonmain.py +++ b/mesonbuild/interpreter/mesonmain.py @@ -14,7 +14,7 @@ from .. import mlog, coredata from ..mesonlib import MachineChoice from ..options import OptionKey -from ..programs import ExternalProgram +from ..programs import OverrideProgram, ExternalProgram from ..interpreter.type_checking import ENV_KW, ENV_METHOD_KW, ENV_SEPARATOR_KW, env_convertor_with_method from ..interpreterbase import (MesonInterpreterObject, FeatureNew, FeatureDeprecated, typed_pos_args, noArgsFlattening, noPosargs, noKwargs, @@ -57,23 +57,21 @@ class MesonMain(MesonInterpreterObject): self.interpreter = interpreter def _find_source_script( - self, name: str, prog: T.Union[str, mesonlib.File, build.Executable, ExternalProgram, build.LocalProgram], - args: T.List[str], allow_built_program: bool = False) -> 'ExecutableSerialisation': - largs: T.List[T.Union[str, build.Executable, ExternalProgram, build.LocalProgram]] = [] + self, name: str, prog: T.Union[str, mesonlib.File, build.Executable, ExternalProgram], + args: T.List[str]) -> 'ExecutableSerialisation': + largs: T.List[T.Union[str, build.Executable, ExternalProgram]] = [] if isinstance(prog, (build.Executable, ExternalProgram)): FeatureNew.single_use(f'Passing executable/found program object to script parameter of {name}', '0.55.0', self.subproject, location=self.current_node) - elif isinstance(prog, (str, mesonlib.File)): + largs.append(prog) + else: if isinstance(prog, mesonlib.File): FeatureNew.single_use(f'Passing file object to script parameter of {name}', '0.57.0', self.subproject, location=self.current_node) - prog = self.interpreter.find_program_impl([prog]) - - if isinstance(prog, build.LocalProgram) and not allow_built_program and not prog.run_program(): - self.interpreter._compiled_exe_error(prog) + found = self.interpreter.find_program_impl([prog]) + largs.append(found) - largs.append(prog) largs.extend(args) es = self.interpreter.backend.get_executable_serialisation(largs, verbose=True) es.subproject = self.interpreter.subproject @@ -118,7 +116,7 @@ class MesonMain(MesonInterpreterObject): @typed_pos_args( 'meson.add_install_script', - (str, mesonlib.File, build.Executable, ExternalProgram, build.LocalProgram), + (str, mesonlib.File, build.Executable, ExternalProgram), varargs=(str, mesonlib.File, build.BuildTarget, build.CustomTarget, build.CustomTargetIndex, ExternalProgram) ) @typed_kwargs( @@ -134,7 +132,7 @@ class MesonMain(MesonInterpreterObject): T.List[T.Union[str, mesonlib.File, build.BuildTargetTypes, ExternalProgram]]], kwargs: 'AddInstallScriptKW') -> None: script_args = self._process_script_args('add_install_script', args[1]) - script = self._find_source_script('add_install_script', args[0], script_args, allow_built_program=True) + script = self._find_source_script('add_install_script', args[0], script_args) script.skip_if_destdir = kwargs['skip_if_destdir'] script.tag = kwargs['install_tag'] script.dry_run = kwargs['dry_run'] @@ -149,7 +147,7 @@ class MesonMain(MesonInterpreterObject): @InterpreterObject.method('add_postconf_script') def add_postconf_script_method( self, - args: T.Tuple[T.Union[str, mesonlib.File, ExternalProgram, build.LocalProgram], + args: T.Tuple[T.Union[str, mesonlib.File, ExternalProgram], T.List[T.Union[str, mesonlib.File, ExternalProgram]]], kwargs: 'TYPE_kwargs') -> None: script_args = self._process_script_args('add_postconf_script', args[1]) @@ -166,7 +164,7 @@ class MesonMain(MesonInterpreterObject): @InterpreterObject.method('add_dist_script') def add_dist_script_method( self, - args: T.Tuple[T.Union[str, mesonlib.File, ExternalProgram, build.LocalProgram], + args: T.Tuple[T.Union[str, mesonlib.File, ExternalProgram], T.List[T.Union[str, mesonlib.File, ExternalProgram]]], kwargs: 'TYPE_kwargs') -> None: if args[1]: @@ -314,13 +312,19 @@ class MesonMain(MesonInterpreterObject): self.build.dep_manifest_name = args[0] @FeatureNew('meson.override_find_program', '0.46.0') - @typed_pos_args('meson.override_find_program', str, (mesonlib.File, ExternalProgram, build.Executable, build.LocalProgram)) + @typed_pos_args('meson.override_find_program', str, (mesonlib.File, ExternalProgram, build.Executable)) @noKwargs @InterpreterObject.method('override_find_program') - def override_find_program_method(self, args: T.Tuple[str, T.Union[mesonlib.File, ExternalProgram, build.Executable, build.LocalProgram]], kwargs: 'TYPE_kwargs') -> None: + def override_find_program_method(self, args: T.Tuple[str, T.Union[mesonlib.File, ExternalProgram, build.Executable]], kwargs: 'TYPE_kwargs') -> None: name, exe = args - if not isinstance(exe, (ExternalProgram, build.LocalProgram)): - exe = self.interpreter._local_program_impl(exe) + if isinstance(exe, mesonlib.File): + abspath = exe.absolute_path(self.interpreter.environment.source_dir, + self.interpreter.environment.build_dir) + 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/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index a54a69ff0..4f961bb60 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -10,8 +10,7 @@ import typing as T from .. import compilers from ..build import (CustomTarget, BuildTarget, CustomTargetIndex, ExtractedObjects, GeneratedList, IncludeDirs, - BothLibraries, SharedLibrary, StaticLibrary, Jar, Executable, StructuredSources, - LocalProgram) + BothLibraries, SharedLibrary, StaticLibrary, Jar, Executable, StructuredSources) from ..options import OptionKey, UserFeatureOption from ..dependencies import Dependency, InternalDependency from ..interpreterbase.decorators import KwargInfo, ContainerTypeInfo, FeatureBroken @@ -286,9 +285,9 @@ DEPEND_FILES_KW: KwargInfo[T.List[T.Union[str, File]]] = KwargInfo( default=[], ) -COMMAND_KW: KwargInfo[T.List[T.Union[str, BuildTargetTypes, ExternalProgram, File, LocalProgram]]] = KwargInfo( +COMMAND_KW: KwargInfo[T.List[T.Union[str, BuildTargetTypes, ExternalProgram, File]]] = KwargInfo( 'command', - ContainerTypeInfo(list, (str, BuildTarget, CustomTarget, CustomTargetIndex, ExternalProgram, File, LocalProgram), allow_empty=False), + ContainerTypeInfo(list, (str, BuildTarget, CustomTarget, CustomTargetIndex, ExternalProgram, File), allow_empty=False), required=True, listify=True, default=[], |
