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/interpreter.py | |
| 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/interpreter.py')
| -rw-r--r-- | mesonbuild/interpreter/interpreter.py | 140 |
1 files changed, 43 insertions, 97 deletions
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( |
