From 34c28dc92cb4f28e32e633297e4b8a737228aae5 Mon Sep 17 00:00:00 2001 From: Daniel Mensinger Date: Thu, 17 Jun 2021 00:26:50 +0200 Subject: [PATCH] holders: remove unholder --- mesonbuild/backend/backends.py | 18 ++-- mesonbuild/backend/ninjabackend.py | 4 +- mesonbuild/build.py | 77 +++++++-------- mesonbuild/interpreter/dependencyfallbacks.py | 53 +++++----- mesonbuild/interpreter/interpreter.py | 96 +++++++++---------- mesonbuild/interpreter/mesonmain.py | 3 - mesonbuild/interpreterbase/__init__.py | 4 + mesonbuild/mesonlib/universal.py | 21 ---- mesonbuild/modules/__init__.py | 18 ++-- mesonbuild/modules/cmake.py | 17 ++-- mesonbuild/modules/gnome.py | 70 +++++++------- mesonbuild/modules/hotdoc.py | 11 +-- mesonbuild/modules/i18n.py | 3 +- mesonbuild/modules/pkgconfig.py | 15 +-- mesonbuild/modules/sourceset.py | 1 - mesonbuild/modules/unstable_cuda.py | 11 +-- mesonbuild/modules/unstable_rust.py | 11 +-- mesonbuild/modules/unstable_simd.py | 4 +- mesonbuild/modules/windows.py | 12 +-- run_unittests.py | 11 --- 20 files changed, 203 insertions(+), 257 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 64e0b18c1..2652ae6b0 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -32,7 +32,7 @@ from .. import mlog from ..compilers import LANGUAGES_USING_LDFLAGS from ..mesonlib import ( File, MachineChoice, MesonException, OptionType, OrderedSet, OptionOverrideProxy, - classify_unity_sources, unholder, OptionKey, join_args + classify_unity_sources, OptionKey, join_args ) if T.TYPE_CHECKING: @@ -237,7 +237,7 @@ class Backend: def generate(self) -> None: raise RuntimeError(f'generate is not implemented in {type(self).__name__}') - def get_target_filename(self, t, *, warn_multi_output: bool = True): + def get_target_filename(self, t: T.Union[build.Target, build.CustomTargetIndex], *, warn_multi_output: bool = True): if isinstance(t, build.CustomTarget): if warn_multi_output and len(t.get_outputs()) != 1: mlog.warning(f'custom_target {t.name!r} has more than one output! ' @@ -250,7 +250,7 @@ class Backend: filename = t.get_filename() return os.path.join(self.get_target_dir(t), filename) - def get_target_filename_abs(self, target): + def get_target_filename_abs(self, target: T.Union[build.Target, build.CustomTargetIndex]) -> str: return os.path.join(self.environment.get_build_dir(), self.get_target_filename(target)) def get_base_options_for_target(self, target: build.BuildTarget) -> OptionOverrideProxy: @@ -309,7 +309,7 @@ class Backend: raise AssertionError(f'BUG: Tried to link to {target!r} which is not linkable') @lru_cache(maxsize=None) - def get_target_dir(self, target): + def get_target_dir(self, target: build.Target) -> str: if self.environment.coredata.get_option(OptionKey('layout')) == 'mirror': dirname = target.get_subdir() else: @@ -329,7 +329,7 @@ class Backend: return os.path.join(self.build_to_src, target_dir) return self.build_to_src - def get_target_private_dir(self, target): + def get_target_private_dir(self, target: build.Target) -> str: return os.path.join(self.get_target_filename(target, warn_multi_output=False) + '.p') def get_target_private_dir_abs(self, target): @@ -963,7 +963,7 @@ class Backend: depends = set(t.depends) if isinstance(exe, build.Target): depends.add(exe) - for a in unholder(t.cmd_args): + for a in t.cmd_args: if isinstance(a, build.Target): depends.add(a) if isinstance(a, build.BuildTarget): @@ -1091,10 +1091,10 @@ class Backend: # also be built by default. XXX: Sometime in the future these should be # built only before running tests. for t in self.build.get_tests(): - exe = unholder(t.exe) + exe = t.exe if isinstance(exe, (build.CustomTarget, build.BuildTarget)): result[exe.get_id()] = exe - for arg in unholder(t.cmd_args): + for arg in t.cmd_args: if not isinstance(arg, (build.CustomTarget, build.BuildTarget)): continue result[arg.get_id()] = arg @@ -1133,7 +1133,7 @@ class Backend: Returns the path to them relative to the build root directory. ''' srcs = [] - for i in unholder(target.get_sources()): + for i in target.get_sources(): if isinstance(i, str): fname = [os.path.join(self.build_to_src, target.subdir, i)] elif isinstance(i, build.BuildTarget): diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 688149bb1..192cef384 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -40,7 +40,7 @@ from ..compilers import ( from ..linkers import ArLinker, RSPFileSyntax from ..mesonlib import ( File, LibType, MachineChoice, MesonException, OrderedSet, PerMachine, - ProgressBar, quote_arg, unholder, + ProgressBar, quote_arg ) from ..mesonlib import get_compiler_for_source, has_path_sep, OptionKey from .backends import CleanTrees @@ -937,7 +937,7 @@ int dummy; self.generate_target(t) def custom_target_generator_inputs(self, target): - for s in unholder(target.sources): + for s in target.sources: if isinstance(s, build.GeneratedList): self.generate_genlist_for_target(s, target) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index e2be9b1d2..47ac95485 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -31,15 +31,16 @@ from .mesonlib import ( HoldableObject, File, MesonException, MachineChoice, PerMachine, OrderedSet, listify, extract_as_list, typeslistify, stringlistify, classify_unity_sources, - get_filenames_templates_dict, substitute_values, has_path_sep, unholder, + get_filenames_templates_dict, substitute_values, has_path_sep, OptionKey, PerMachineDefaultable, + MesonBugException, FileOrString, ) from .compilers import ( Compiler, is_object, clink_langs, sort_clink, lang_suffixes, is_known_suffix ) from .linkers import StaticLinker -from .interpreterbase import FeatureNew +from .interpreterbase import FeatureNew, TYPE_nkwargs, TYPE_nvar if T.TYPE_CHECKING: from ._typing import ImmutableListProtocol, ImmutableSetProtocol @@ -47,7 +48,6 @@ if T.TYPE_CHECKING: from .mesonlib import FileMode, FileOrString from .modules import ModuleState from .backend.backends import Backend - from .interpreter.interpreterobjects import GeneratorHolder pch_kwargs = {'c_pch', 'cpp_pch'} @@ -680,7 +680,7 @@ class BuildTarget(Target): def process_objectlist(self, objects): assert(isinstance(objects, list)) - for s in unholder(objects): + for s in objects: if isinstance(s, (str, File, ExtractedObjects)): self.objects.append(s) elif isinstance(s, (GeneratedList, CustomTarget)): @@ -776,7 +776,7 @@ class BuildTarget(Target): # which is what we need. if not is_object(s): sources.append(s) - for d in unholder(self.external_deps): + for d in self.external_deps: for s in d.sources: if isinstance(s, (str, File)): sources.append(s) @@ -847,7 +847,7 @@ class BuildTarget(Target): link_depends. """ sources = listify(sources) - for s in unholder(sources): + for s in sources: if isinstance(s, File): self.link_depends.append(s) elif isinstance(s, str): @@ -864,35 +864,16 @@ class BuildTarget(Target): def get_original_kwargs(self): return self.kwargs - def unpack_holder(self, d): - d = listify(d) - newd = [] - for i in d: - if isinstance(i, list): - i = self.unpack_holder(i) - elif hasattr(i, 'held_object'): - i = i.held_object - for t in ['dependencies', 'link_with', 'include_directories', 'sources']: - if hasattr(i, t): - setattr(i, t, self.unpack_holder(getattr(i, t))) - newd.append(i) - return newd - def copy_kwargs(self, kwargs): self.kwargs = copy.copy(kwargs) - # This sucks quite badly. Arguments - # are holders but they can't be pickled - # so unpack those known. for k, v in self.kwargs.items(): if isinstance(v, list): - self.kwargs[k] = self.unpack_holder(v) - if hasattr(v, 'held_object'): - self.kwargs[k] = v.held_object + self.kwargs[k] = listify(v, flatten=True) for t in ['dependencies', 'link_with', 'include_directories', 'sources']: if t in self.kwargs: - self.kwargs[t] = self.unpack_holder(self.kwargs[t]) + self.kwargs[t] = listify(self.kwargs[t], flatten=True) - def extract_objects(self, srclist): + def extract_objects(self, srclist: T.List[FileOrString]) -> ExtractedObjects: obj_src = [] sources_set = set(self.sources) for src in srclist: @@ -901,14 +882,14 @@ class BuildTarget(Target): elif isinstance(src, File): FeatureNew.single_use('File argument for extract_objects', '0.50.0', self.subproject) else: - raise MesonException('Object extraction arguments must be strings or Files.') + raise MesonException(f'Object extraction arguments must be strings or Files (got {type(src).__name__}).') # FIXME: It could be a generated source if src not in sources_set: raise MesonException(f'Tried to extract unknown source {src}.') obj_src.append(src) return ExtractedObjects(self, obj_src) - def extract_all_objects(self, recursive=True): + def extract_all_objects(self, recursive: bool = True) -> ExtractedObjects: return ExtractedObjects(self, self.sources, self.generated, self.objects, recursive) @@ -960,7 +941,7 @@ class BuildTarget(Target): kwargs.get('modules', []) self.need_install = kwargs.get('install', self.need_install) llist = extract_as_list(kwargs, 'link_with') - for linktarget in unholder(llist): + for linktarget in llist: if isinstance(linktarget, dependencies.ExternalLibrary): raise MesonException(textwrap.dedent('''\ An external library was used in link_with keyword argument, which @@ -1003,7 +984,7 @@ class BuildTarget(Target): if dfeature_debug: dfeatures['debug'] = dfeature_debug if 'd_import_dirs' in kwargs: - dfeature_import_dirs = unholder(extract_as_list(kwargs, 'd_import_dirs')) + dfeature_import_dirs = extract_as_list(kwargs, 'd_import_dirs') for d in dfeature_import_dirs: if not isinstance(d, IncludeDirs): raise InvalidArguments('Arguments to d_import_dirs must be include_directories.') @@ -1200,7 +1181,7 @@ class BuildTarget(Target): def add_deps(self, deps): deps = listify(deps) - for dep in unholder(deps): + for dep in deps: if dep in self.added_deps: continue if isinstance(dep, dependencies.InternalDependency): @@ -1250,7 +1231,7 @@ You probably should put it in link_with instead.''') return isinstance(self, StaticLibrary) and not self.need_install def link(self, target): - for t in unholder(listify(target)): + for t in listify(target): if isinstance(t, BothLibraries): t = t.get_preferred_library() if isinstance(self, StaticLibrary) and self.need_install: @@ -1280,7 +1261,7 @@ You probably should put it in link_with instead.''') self.link_targets.append(t) def link_whole(self, target): - for t in unholder(listify(target)): + for t in listify(target): # Always use the static library from BothLibraries, since shared libs aren't supported anyway if isinstance(t, BothLibraries): t = t.static @@ -1349,7 +1330,7 @@ You probably should put it in link_with instead.''') def add_include_dirs(self, args, set_is_system: T.Optional[str] = None): ids = [] - for a in unholder(args): + for a in args: if not isinstance(a, IncludeDirs): raise InvalidArguments('Include directory to be added is not an include directory object.') ids.append(a) @@ -2063,7 +2044,7 @@ class SharedLibrary(BuildTarget): # Visual Studio module-definitions file if 'vs_module_defs' in kwargs: - path = unholder(kwargs['vs_module_defs']) + path = kwargs['vs_module_defs'] if isinstance(path, str): if os.path.isabs(path): self.vs_module_defs = File.from_absolute_file(path) @@ -2181,7 +2162,7 @@ class BothLibraries(HoldableObject): class CommandBase: def flatten_command(self, cmd): - cmd = unholder(listify(cmd)) + cmd = listify(cmd) final_cmd = [] for c in cmd: if isinstance(c, str): @@ -2256,7 +2237,7 @@ class CustomTarget(Target, CommandBase): def get_target_dependencies(self): deps = self.dependencies[:] deps += self.extra_depends - for c in unholder(self.sources): + for c in self.sources: if isinstance(c, (BuildTarget, CustomTarget)): deps.append(c) return deps @@ -2281,7 +2262,7 @@ class CustomTarget(Target, CommandBase): def process_kwargs(self, kwargs, backend): self.process_kwargs_base(kwargs) - self.sources = unholder(extract_as_list(kwargs, 'input')) + self.sources = extract_as_list(kwargs, 'input') if 'output' not in kwargs: raise InvalidArguments('Missing keyword argument "output".') self.outputs = listify(kwargs['output']) @@ -2360,7 +2341,7 @@ class CustomTarget(Target, CommandBase): if not isinstance(self.build_always_stale, bool): raise InvalidArguments('Argument build_always_stale must be a boolean.') extra_deps, depend_files = [extract_as_list(kwargs, c, pop=False) for c in ['depends', 'depend_files']] - for ed in unholder(extra_deps): + for ed in extra_deps: if not isinstance(ed, (CustomTarget, BuildTarget)): raise InvalidArguments('Can only depend on toplevel targets: custom_target or build_target ' f'(executable or a library) got: {type(ed)}({ed})') @@ -2396,7 +2377,7 @@ class CustomTarget(Target, CommandBase): def get_generated_lists(self): genlists = [] - for c in unholder(self.sources): + for c in self.sources: if isinstance(c, GeneratedList): genlists.append(c) return genlists @@ -2447,7 +2428,7 @@ class CustomTarget(Target, CommandBase): def type_suffix(self): return "@cus" - def __getitem__(self, index): + def __getitem__(self, index: int) -> 'CustomTargetIndex': return CustomTargetIndex(self, self.outputs[index]) def __setitem__(self, index, value): @@ -2606,7 +2587,13 @@ class CustomTargetIndex(HoldableObject): class ConfigurationData(HoldableObject): def __init__(self) -> None: super().__init__() - self.values = {} # T.Dict[str, T.Union[str, int, bool]] + self.values: T.Dict[ + str, + T.Tuple[ + T.Union[str, int, bool], + T.Optional[str] + ] + ] = {} def __repr__(self): return repr(self.values) @@ -2651,7 +2638,7 @@ def get_sources_string_names(sources, backend): get all the output basenames. ''' names = [] - for s in unholder(sources): + for s in sources: if isinstance(s, str): names.append(s) elif isinstance(s, (BuildTarget, CustomTarget, CustomTargetIndex, GeneratedList)): diff --git a/mesonbuild/interpreter/dependencyfallbacks.py b/mesonbuild/interpreter/dependencyfallbacks.py index 5b78d2073..019073c4a 100644 --- a/mesonbuild/interpreter/dependencyfallbacks.py +++ b/mesonbuild/interpreter/dependencyfallbacks.py @@ -1,12 +1,12 @@ -from .interpreterobjects import DependencyHolder, SubprojectHolder, extract_required_kwarg +from .interpreterobjects import SubprojectHolder, extract_required_kwarg from .. import mlog from .. import dependencies from .. import build from ..wrap import WrapMode from ..mesonlib import OptionKey, extract_as_list, stringlistify, version_compare_many -from ..dependencies import DependencyException, NotFoundDependency -from ..interpreterbase import (InterpreterObject, FeatureNew, +from ..dependencies import Dependency, DependencyException, NotFoundDependency +from ..interpreterbase import (MesonInterpreterObject, FeatureNew, InterpreterException, InvalidArguments, TYPE_nkwargs, TYPE_nvar) @@ -15,7 +15,7 @@ if T.TYPE_CHECKING: from .interpreter import Interpreter -class DependencyFallbacksHolder(InterpreterObject): +class DependencyFallbacksHolder(MesonInterpreterObject): def __init__(self, interpreter: 'Interpreter', names: T.List[str], allow_fallback: T.Optional[bool] = None) -> None: super().__init__() self.interpreter = interpreter @@ -75,14 +75,14 @@ class DependencyFallbacksHolder(InterpreterObject): self.subproject_varname = varname self.subproject_kwargs = kwargs - def _do_dependency_cache(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: TYPE_nkwargs) -> T.Optional[DependencyHolder]: + def _do_dependency_cache(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: TYPE_nkwargs) -> T.Optional[Dependency]: name = func_args[0] cached_dep = self._get_cached_dep(name, kwargs) if cached_dep: self._verify_fallback_consistency(cached_dep) return cached_dep - def _do_dependency(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: TYPE_nkwargs) -> T.Optional[DependencyHolder]: + def _do_dependency(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: TYPE_nkwargs) -> T.Optional[Dependency]: # Note that there is no df.dependency() method, this is called for names # given as positional arguments to dependency_fallbacks(name1, ...). # We use kwargs from the dependency() function, for things like version, @@ -94,17 +94,17 @@ class DependencyFallbacksHolder(InterpreterObject): for_machine = self.interpreter.machine_from_native_kwarg(kwargs) identifier = dependencies.get_dep_identifier(name, kwargs) self.coredata.deps[for_machine].put(identifier, dep) - return DependencyHolder(dep, self.subproject) + return dep return None - def _do_existing_subproject(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: TYPE_nkwargs) -> T.Optional[DependencyHolder]: + def _do_existing_subproject(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: TYPE_nkwargs) -> T.Optional[Dependency]: subp_name = func_args[0] varname = self.subproject_varname if subp_name and self._get_subproject(subp_name): return self._get_subproject_dep(subp_name, varname, kwargs) return None - def _do_subproject(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: TYPE_nkwargs) -> T.Optional[DependencyHolder]: + def _do_subproject(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: TYPE_nkwargs) -> T.Optional[Dependency]: if self.nofallback: mlog.log('Not looking for a fallback subproject for the dependency', mlog.bold(self.display_name), 'because:\nUse of fallback dependencies is disabled.') @@ -128,7 +128,7 @@ class DependencyFallbacksHolder(InterpreterObject): return sub return None - def _get_subproject_dep(self, subp_name: str, varname: str, kwargs: TYPE_nkwargs) -> T.Optional[DependencyHolder]: + def _get_subproject_dep(self, subp_name: str, varname: str, kwargs: TYPE_nkwargs) -> T.Optional[Dependency]: # Verify the subproject is found subproject = self._get_subproject(subp_name) if not subproject: @@ -170,7 +170,7 @@ class DependencyFallbacksHolder(InterpreterObject): return var_dep wanted = stringlistify(kwargs.get('version', [])) - found = var_dep.held_object.get_version() + found = var_dep.get_version() if not self._check_version(wanted, found): mlog.log('Dependency', mlog.bold(self.display_name), 'from subproject', mlog.bold(subproject.subdir), 'found:', mlog.red('NO'), @@ -183,7 +183,7 @@ class DependencyFallbacksHolder(InterpreterObject): mlog.normal_cyan(found) if found else None) return var_dep - def _get_cached_dep(self, name: str, kwargs: TYPE_nkwargs) -> T.Optional[DependencyHolder]: + def _get_cached_dep(self, name: str, kwargs: TYPE_nkwargs) -> T.Optional[Dependency]: # Unlike other methods, this one returns not-found dependency instead # of None in the case the dependency is cached as not-found, or if cached # version does not match. In that case we don't want to continue with @@ -202,7 +202,7 @@ class DependencyFallbacksHolder(InterpreterObject): if not cached_dep.found(): mlog.log('Dependency', mlog.bold(self.display_name), 'found:', mlog.red('NO'), *info) - return DependencyHolder(cached_dep, self.subproject) + return cached_dep else: info = [mlog.blue('(cached)')] cached_dep = self.coredata.deps[for_machine].get(identifier) @@ -220,24 +220,27 @@ class DependencyFallbacksHolder(InterpreterObject): info = [mlog.normal_cyan(found_vers), *info] mlog.log('Dependency', mlog.bold(self.display_name), 'found:', mlog.green('YES'), *info) - return DependencyHolder(cached_dep, self.subproject) + return cached_dep return None - def _get_subproject_variable(self, subproject: SubprojectHolder, varname: str) -> T.Optional[DependencyHolder]: - var_dep = subproject.held_object.variables.get(varname) - if not isinstance(var_dep, DependencyHolder): + def _get_subproject_variable(self, subproject: SubprojectHolder, varname: str) -> T.Optional[Dependency]: + try: + var_dep = subproject.get_variable_method([varname], {}) + except InvalidArguments: + var_dep = None + if not isinstance(var_dep, Dependency): mlog.warning(f'Variable {varname!r} in the subproject {subproject.subdir!r} is', 'not found' if var_dep is None else 'not a dependency object') return None return var_dep - def _verify_fallback_consistency(self, cached_dep: DependencyHolder): + def _verify_fallback_consistency(self, cached_dep: Dependency): subp_name = self.subproject_name varname = self.subproject_varname subproject = self._get_subproject(subp_name) if subproject and varname: var_dep = self._get_subproject_variable(subproject, varname) - if var_dep and cached_dep.found() and var_dep.held_object != cached_dep.held_object: + if var_dep and cached_dep.found() and var_dep != cached_dep: mlog.warning(f'Inconsistency: Subproject has overridden the dependency with another variable than {varname!r}') def _handle_featurenew_dependencies(self, name: str) -> None: @@ -253,8 +256,8 @@ class DependencyFallbacksHolder(InterpreterObject): elif name == 'openmp': FeatureNew.single_use('OpenMP Dependency', '0.46.0', self.subproject) - def _notfound_dependency(self) -> DependencyHolder: - return DependencyHolder(NotFoundDependency(self.environment), self.subproject) + def _notfound_dependency(self) -> NotFoundDependency: + return NotFoundDependency(self.environment) @staticmethod def _check_version(wanted: T.Optional[str], found: str) -> bool: @@ -264,7 +267,7 @@ class DependencyFallbacksHolder(InterpreterObject): return False return True - def _get_candidates(self) -> T.List[T.Tuple[T.Callable[[TYPE_nkwargs, TYPE_nvar, TYPE_nkwargs], T.Optional[DependencyHolder]], TYPE_nvar, TYPE_nkwargs]]: + def _get_candidates(self) -> T.List[T.Tuple[T.Callable[[TYPE_nkwargs, TYPE_nvar, TYPE_nkwargs], T.Optional[Dependency]], TYPE_nvar, TYPE_nkwargs]]: candidates = [] # 1. check if any of the names is cached already. for name in self.names: @@ -281,7 +284,7 @@ class DependencyFallbacksHolder(InterpreterObject): candidates.append((self._do_subproject, [self.subproject_name], self.subproject_kwargs)) return candidates - def lookup(self, kwargs: TYPE_nkwargs, force_fallback: bool = False) -> DependencyHolder: + def lookup(self, kwargs: TYPE_nkwargs, force_fallback: bool = False) -> Dependency: self.display_name = self.names[0] if self.names else '(anonymous)' mods = extract_as_list(kwargs, 'modules') if mods: @@ -329,7 +332,7 @@ class DependencyFallbacksHolder(InterpreterObject): func_kwargs['required'] = required and (i == last) kwargs['required'] = required and (i == last) dep = func(kwargs, func_args, func_kwargs) - if dep and dep.held_object.found(): + if dep and dep.found(): # Override this dependency to have consistent results in subsequent # dependency lookups. for name in self.names: @@ -337,7 +340,7 @@ class DependencyFallbacksHolder(InterpreterObject): identifier = dependencies.get_dep_identifier(name, kwargs) if identifier not in self.build.dependency_overrides[for_machine]: self.build.dependency_overrides[for_machine][identifier] = \ - build.DependencyOverride(dep.held_object, self.interpreter.current_node, explicit=False) + build.DependencyOverride(dep, self.interpreter.current_node, explicit=False) return dep elif required and (dep or i == last): # This was the last candidate or the dependency has been cached diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 494807a89..1f72d4cfa 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -128,7 +128,6 @@ class Summary: raise InterpreterException(f'Summary section {section!r} already have key {k!r}') formatted_values = [] for i in listify(v): - i = unholder(i) if isinstance(i, bool) and bool_yn: formatted_values.append(mlog.green('YES') if i else mlog.red('NO')) elif isinstance(i, (str, int, bool)): @@ -609,20 +608,16 @@ class Interpreter(InterpreterBase, HoldableObject): if not isinstance(version, str): raise InterpreterException('Version must be a string.') incs = self.extract_incdirs(kwargs) - libs = unholder(extract_as_list(kwargs, 'link_with')) - libs_whole = unholder(extract_as_list(kwargs, 'link_whole')) + libs = extract_as_list(kwargs, 'link_with') + libs_whole = extract_as_list(kwargs, 'link_whole') sources = extract_as_list(kwargs, 'sources') - sources = unholder(listify(self.source_strings_to_files(sources))) - deps = unholder(extract_as_list(kwargs, 'dependencies')) + sources = listify(self.source_strings_to_files(sources)) + deps = extract_as_list(kwargs, 'dependencies') compile_args = mesonlib.stringlistify(kwargs.get('compile_args', [])) link_args = mesonlib.stringlistify(kwargs.get('link_args', [])) variables = self.extract_variables(kwargs, list_new=True) final_deps = [] for d in deps: - try: - d = d.held_object - except Exception: - pass if not isinstance(d, (dependencies.Dependency, dependencies.ExternalLibrary, dependencies.InternalDependency)): raise InterpreterException('Dependencies must be external deps') final_deps.append(d) @@ -690,17 +685,16 @@ external dependencies (including libraries) must go to "dependencies".''') m = 'must be a string, or the output of find_program(), files() '\ 'or configure_file(), or a compiler object; not {!r}' expanded_args = [] - if isinstance(cmd, ExternalProgramHolder): - cmd = cmd.held_object - if isinstance(cmd, build.Executable): - progname = node.args.arguments[0].value - msg = 'Program {!r} was overridden with the compiled executable {!r}'\ - ' and therefore cannot be used during configuration' - raise InterpreterException(msg.format(progname, cmd.description())) + if isinstance(cmd, build.Executable): + progname = node.args.arguments[0].value + msg = 'Program {!r} was overridden with the compiled executable {!r}'\ + ' and therefore cannot be used during configuration' + raise InterpreterException(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, CompilerHolder): - exelist = cmd.compiler.get_exelist() + elif isinstance(cmd, compilers.Compiler): + exelist = cmd.get_exelist() cmd = exelist[0] prog = ExternalProgram(cmd, silent=True) if not prog.found(): @@ -725,8 +719,8 @@ external dependencies (including libraries) must go to "dependencies".''') expanded_args.append(a) elif isinstance(a, mesonlib.File): expanded_args.append(a.absolute_path(srcdir, builddir)) - elif isinstance(a, ExternalProgramHolder): - expanded_args.append(a.held_object.get_path()) + elif isinstance(a, ExternalProgram): + expanded_args.append(a.get_path()) else: raise InterpreterException('Arguments ' + m.format(a)) # If any file that was used as an argument to the command @@ -880,7 +874,7 @@ external dependencies (including libraries) must go to "dependencies".''') prefix = self.coredata.options[OptionKey('prefix')].value from ..modules.cmake import CMakeSubprojectOptions - options = unholder(kwargs.get('options', CMakeSubprojectOptions())) + options = kwargs.get('options', CMakeSubprojectOptions()) if not isinstance(options, CMakeSubprojectOptions): raise InterpreterException('"options" kwarg must be CMakeSubprojectOptions' ' object (created by cmake.subproject_options())') @@ -1290,14 +1284,14 @@ external dependencies (including libraries) must go to "dependencies".''') return success def program_from_file_for(self, for_machine, prognames): - for p in unholder(prognames): + for p in prognames: if isinstance(p, mesonlib.File): continue # Always points to a local (i.e. self generated) file. if not isinstance(p, str): raise InterpreterException('Executable name must be a string') prog = ExternalProgram.from_bin_list(self.environment, for_machine, p) if prog.found(): - return ExternalProgramHolder(prog, self.subproject) + return prog return None def program_from_system(self, args, search_dirs, extra_info): @@ -1368,7 +1362,7 @@ external dependencies (including libraries) must go to "dependencies".''') if progobj is None: progobj = self.notfound_program(args) - if not progobj.found(): + if isinstance(progobj, ExternalProgram) and not progobj.found(): mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO')) if required: m = 'Program {!r} not found' @@ -1484,7 +1478,7 @@ external dependencies (including libraries) must go to "dependencies".''') if not_found_message: self.message_impl([not_found_message]) raise - assert isinstance(d, DependencyHolder) + assert isinstance(d, Dependency) if not d.found() and not_found_message: self.message_impl([not_found_message]) self.message_impl([not_found_message]) @@ -1653,12 +1647,12 @@ This will become a hard error in the future.''' % kwargs['input'], location=self if 'command' not in kwargs: raise InterpreterException('Missing "command" keyword argument') all_args = extract_as_list(kwargs, 'command') - deps = unholder(extract_as_list(kwargs, 'depends')) + deps = extract_as_list(kwargs, 'depends') else: raise InterpreterException('Run_target needs at least one positional argument.') cleaned_args = [] - for i in unholder(listify(all_args)): + for i in listify(all_args): if not isinstance(i, (str, build.BuildTarget, build.CustomTarget, ExternalProgram, mesonlib.File)): mlog.debug('Wrong type:', str(i)) raise InterpreterException('Invalid argument to run_target.') @@ -1676,8 +1670,8 @@ This will become a hard error in the future.''' % kwargs['input'], location=self raise InterpreterException('Depends items must be build targets.') cleaned_deps.append(d) env = self.unpack_env_kwarg(kwargs) - tg = RunTargetHolder(build.RunTarget(name, cleaned_args, cleaned_deps, self.subdir, self.subproject, env), self) - self.add_target(name, tg.held_object) + tg = build.RunTarget(name, cleaned_args, cleaned_deps, self.subdir, self.subproject, env) + self.add_target(name, tg) full_name = (self.subproject, name) assert(full_name not in self.build.run_target_names) self.build.run_target_names.add(full_name) @@ -1691,28 +1685,28 @@ This will become a hard error in the future.''' % kwargs['input'], location=self name = args[0] if not isinstance(name, str): raise InterpreterException('First argument must be a string.') - deps = unholder(listify(args[1:])) + deps = listify(args[1:]) for d in deps: if not isinstance(d, (build.BuildTarget, build.CustomTarget)): raise InterpreterException('Depends items must be build targets.') - tg = RunTargetHolder(build.AliasTarget(name, deps, self.subdir, self.subproject), self) - self.add_target(name, tg.held_object) + tg = build.AliasTarget(name, deps, self.subdir, self.subproject) + self.add_target(name, tg) return tg @permittedKwargs({'arguments', 'output', 'depends', 'depfile', 'capture', 'preserve_path_from'}) - @typed_pos_args('generator', (ExecutableHolder, ExternalProgramHolder)) + @typed_pos_args('generator', (build.Executable, ExternalProgram)) @typed_kwargs( 'generator', KwargInfo('arguments', ContainerTypeInfo(list, str, allow_empty=False), required=True, listify=True), KwargInfo('output', ContainerTypeInfo(list, str, allow_empty=False), required=True, listify=True), KwargInfo('depfile', str, validator=lambda x: 'Depfile must be a plain filename with a subdirectory' if has_path_sep(x) else None), KwargInfo('capture', bool, default=False, since='0.43.0'), - KwargInfo('depends', ContainerTypeInfo(list, (BuildTargetHolder, CustomTargetHolder)), default=[], listify=True), + KwargInfo('depends', ContainerTypeInfo(list, (build.BuildTarget, build.CustomTarget)), default=[], listify=True), ) def func_generator(self, node: mparser.FunctionNode, - args: T.Tuple[T.Union[ExecutableHolder, ExternalProgramHolder]], - kwargs: 'kwargs.FuncGenerator') -> GeneratorHolder: + args: T.Tuple[T.Union[build.Executable, ExternalProgram]], + kwargs: 'kwargs.FuncGenerator') -> build.Generator: for rule in kwargs['output']: if '@BASENAME@' not in rule and '@PLAINNAME@' not in rule: raise InvalidArguments('Every element of "output" must contain @BASENAME@ or @PLAINNAME@.') @@ -1723,12 +1717,9 @@ This will become a hard error in the future.''' % kwargs['input'], location=self if '@OUTPUT@' in o: raise InvalidArguments('Tried to use @OUTPUT@ in a rule with more than one output.') - depends = [d.held_object for d in kwargs.pop('depends')] - - gen = build.Generator(args[0].held_object, depends=depends, **kwargs) - holder = GeneratorHolder(gen, self) - self.generators.append(holder) - return holder + gen = build.Generator(args[0], **kwargs) + self.generators.append(gen) + return gen @typed_pos_args('benchmark', str, (ExecutableHolder, JarHolder, ExternalProgramHolder, mesonlib.File)) @typed_kwargs('benchmark', *TEST_KWARGS) @@ -1786,10 +1777,10 @@ This will become a hard error in the future.''' % kwargs['input'], location=self return Test(name, prj, suite, - exe.held_object, - [d.held_object for d in kwargs['depends']], + exe, + kwargs['depends'], kwargs.get('is_parallel', False), - [c.held_object if isinstance(c, ObjectHolder) else c for c in kwargs['args']], + kwargs['args'], env, kwargs['should_fail'], kwargs['timeout'], @@ -1862,9 +1853,9 @@ This will become a hard error in the future.''' % kwargs['input'], location=self if self.subdir == '' and args[0].startswith('meson-'): raise InvalidArguments('The "meson-" prefix is reserved and cannot be used for top-level subdir().') for i in mesonlib.extract_as_list(kwargs, 'if_found'): - if not hasattr(i, 'found_method'): + if not hasattr(i, 'found'): raise InterpreterException('Object used in if_found does not have a found method.') - if not i.found_method([], {}): + if not i.found(): return prev_subdir = self.subdir subdir = os.path.join(prev_subdir, args[0]) @@ -2102,7 +2093,7 @@ This will become a hard error in the future.''' % kwargs['input'], location=self os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True) file_encoding = kwargs.setdefault('encoding', 'utf-8') missing_variables, confdata_useless = \ - mesonlib.do_conf_file(inputs_abs[0], ofile_abs, conf.held_object, + mesonlib.do_conf_file(inputs_abs[0], ofile_abs, conf.conf_data, fmt, file_encoding) if missing_variables: var_list = ", ".join(map(repr, sorted(missing_variables))) @@ -2117,7 +2108,7 @@ This will become a hard error in the future.''' % kwargs['input'], location=self 'copy a file to the build dir, use the \'copy:\' keyword ' 'argument added in 0.47.0'.format(ifbase), location=node) else: - mesonlib.dump_conf_header(ofile_abs, conf.held_object, output_format) + mesonlib.dump_conf_header(ofile_abs, conf.conf_data, output_format) conf.mark_used() elif 'command' in kwargs: if len(inputs) > 1: @@ -2275,7 +2266,7 @@ This will become a hard error in the future.''' % kwargs['input'], location=self if ":" not in setup_name: setup_name = (self.subproject if self.subproject else self.build.project_name) + ":" + setup_name try: - inp = unholder(extract_as_list(kwargs, 'exe_wrapper')) + inp = extract_as_list(kwargs, 'exe_wrapper') exe_wrapper = [] for i in inp: if isinstance(i, str): @@ -2611,10 +2602,9 @@ Try setting b_lundef to false instead.'''.format(self.coredata.options[OptionKey target.project_version = self.project_version self.add_stdlib_info(target) - l = targetholder(target, self) - self.add_target(name, l.held_object) + self.add_target(name, target) self.project_args_frozen = True - return l + return target def kwarg_strings_to_includedirs(self, kwargs): if 'd_import_dirs' in kwargs: diff --git a/mesonbuild/interpreter/mesonmain.py b/mesonbuild/interpreter/mesonmain.py index 1a4fbea9f..dbd0ade0c 100644 --- a/mesonbuild/interpreter/mesonmain.py +++ b/mesonbuild/interpreter/mesonmain.py @@ -75,7 +75,6 @@ class MesonMain(MesonInterpreterObject): script_args = [] # T.List[str] new = False for a in args: - a = unholder(a) if isinstance(a, str): script_args.append(a) elif isinstance(a, mesonlib.File): @@ -287,7 +286,6 @@ class MesonMain(MesonInterpreterObject): name, exe = args if not isinstance(name, str): raise InterpreterException('First argument must be a string') - exe = unholder(exe) if isinstance(exe, mesonlib.File): abspath = exe.absolute_path(self.interpreter.environment.source_dir, self.interpreter.environment.build_dir) @@ -307,7 +305,6 @@ class MesonMain(MesonInterpreterObject): dep = args[1] if not isinstance(name, str) or not name: raise InterpreterException('First argument must be a string and cannot be empty') - dep = unholder(dep) if not isinstance(dep, dependencies.Dependency): raise InterpreterException('Second argument must be a dependency object') identifier = dependencies.get_dep_identifier(name, kwargs) diff --git a/mesonbuild/interpreterbase/__init__.py b/mesonbuild/interpreterbase/__init__.py index a4163c3ce..d776ae1f2 100644 --- a/mesonbuild/interpreterbase/__init__.py +++ b/mesonbuild/interpreterbase/__init__.py @@ -46,6 +46,7 @@ __all__ = [ 'ContainerTypeInfo', 'KwargInfo', 'typed_kwargs', + 'FeatureCheckBase', 'FeatureNew', 'FeatureDeprecated', 'FeatureNewKwargs', @@ -60,6 +61,7 @@ __all__ = [ 'TYPE_elementary', 'TYPE_var', 'TYPE_nvar', + 'TYPE_kwargs', 'TYPE_nkwargs', 'TYPE_key_resolver', ] @@ -78,6 +80,7 @@ from .baseobjects import ( TYPE_elementary, TYPE_var, TYPE_nvar, + TYPE_kwargs, TYPE_nkwargs, TYPE_key_resolver, ) @@ -95,6 +98,7 @@ from .decorators import ( ContainerTypeInfo, KwargInfo, typed_kwargs, + FeatureCheckBase, FeatureNew, FeatureDeprecated, FeatureNewKwargs, diff --git a/mesonbuild/mesonlib/universal.py b/mesonbuild/mesonlib/universal.py index 8dc16dc43..3714ecdea 100644 --- a/mesonbuild/mesonlib/universal.py +++ b/mesonbuild/mesonlib/universal.py @@ -131,7 +131,6 @@ __all__ = [ 'substitute_values', 'substring_is_in_list', 'typeslistify', - 'unholder', 'verbose_git', 'version_compare', 'version_compare_condition_with_min', @@ -1246,26 +1245,6 @@ def replace_if_different(dst: str, dst_tmp: str) -> None: os.unlink(dst_tmp) -@T.overload -def unholder(item: 'ObjectHolder[_T]') -> _T: ... - -@T.overload -def unholder(item: T.List['ObjectHolder[_T]']) -> T.List[_T]: ... - -@T.overload -def unholder(item: T.List[_T]) -> T.List[_T]: ... - -@T.overload -def unholder(item: T.List[T.Union[_T, 'ObjectHolder[_T]']]) -> T.List[_T]: ... - -def unholder(item): # type: ignore # TODO fix overload (somehow) - """Get the held item of an object holder or list of object holders.""" - if isinstance(item, list): - return [i.held_object if hasattr(i, 'held_object') else i for i in item] - if hasattr(item, 'held_object'): - return item.held_object - return item - def listify(item: T.Any, flatten: bool = True) -> T.List[T.Any]: ''' diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index 69bb55239..2b53de5c6 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -18,13 +18,12 @@ import os from .. import build -from ..mesonlib import unholder, relpath +from ..mesonlib import relpath, HoldableObject import typing as T if T.TYPE_CHECKING: from ..interpreter import Interpreter - from ..interpreter.interpreterobjects import IncludeDirsHolder, ExternalProgramHolder - from ..interpreterbase import TYPE_var, TYPE_nvar, TYPE_nkwargs + from ..interpreterbase import TYPE_var, TYPE_kwargs from ..programs import ExternalProgram class ModuleState: @@ -61,7 +60,7 @@ class ModuleState: self.target_machine = interpreter.builtin['target_machine'].held_object self.current_node = interpreter.current_node - def get_include_args(self, include_dirs: T.Iterable[T.Union[str, 'IncludeDirsHolder']], prefix: str = '-I') -> T.List[str]: + def get_include_args(self, include_dirs: T.Iterable[T.Union[str, build.IncludeDirs]], prefix: str = '-I') -> T.List[str]: if not include_dirs: return [] @@ -69,7 +68,7 @@ class ModuleState: builddir = self.environment.get_build_dir() dirs_str: T.List[str] = [] - for dirs in unholder(include_dirs): + for dirs in include_dirs: if isinstance(dirs, str): dirs_str += [f'{prefix}{dirs}'] continue @@ -89,14 +88,17 @@ class ModuleState: def find_program(self, prog: T.Union[str, T.List[str]], required: bool = True, version_func: T.Optional[T.Callable[['ExternalProgram'], str]] = None, - wanted: T.Optional[str] = None) -> 'ExternalProgramHolder': + wanted: T.Optional[str] = None) -> 'ExternalProgram': return self._interpreter.find_program_impl(prog, required=required, version_func=version_func, wanted=wanted) -class ModuleObject: +class ModuleObject(HoldableObject): """Base class for all objects returned by modules """ def __init__(self) -> None: - self.methods = {} # type: T.Dict[str, T.Callable[[ModuleState, T.List[TYPE_nvar], TYPE_nkwargs], T.Union[ModuleReturnValue, TYPE_var]]] + self.methods: T.Dict[ + str, + T.Callable[[ModuleState, T.List[TYPE_var], TYPE_kwargs], T.Union[ModuleReturnValue, TYPE_var]] + ] = {} class MutableModuleObject(ModuleObject): pass diff --git a/mesonbuild/modules/cmake.py b/mesonbuild/modules/cmake.py index fac3b245d..cb37edca5 100644 --- a/mesonbuild/modules/cmake.py +++ b/mesonbuild/modules/cmake.py @@ -18,9 +18,9 @@ import typing as T from . import ExtensionModule, ModuleReturnValue, ModuleObject -from .. import build, mesonlib, mlog +from .. import build, mesonlib, mlog, dependencies from ..cmake import SingleTargetOptions, TargetOptions, cmake_defines_to_args -from ..interpreter import ConfigurationDataHolder, SubprojectHolder, DependencyHolder +from ..interpreter import ConfigurationDataObject, SubprojectHolder from ..interpreterbase import ( FeatureNew, FeatureNewKwargs, @@ -32,6 +32,7 @@ from ..interpreterbase import ( noKwargs, InvalidArguments, + InterpreterException, ) from ..programs import ExternalProgram @@ -109,11 +110,11 @@ class CMakeSubproject(ModuleObject): def dependency(self, state, args, kwargs): info = self._args_to_info(args) orig = self.get_variable(state, [info['dep']], {}) - assert isinstance(orig, DependencyHolder) - actual = orig.include_type_method([], {}) + assert isinstance(orig, dependencies.Dependency) + actual = orig.include_type if 'include_type' in kwargs and kwargs['include_type'] != actual: mlog.debug('Current include type is {}. Converting to requested {}'.format(actual, kwargs['include_type'])) - return orig.as_system_method([kwargs['include_type']], {}) + return orig.generate_system_dependency(kwargs['include_type']) return orig @noKwargs @@ -351,7 +352,7 @@ class CmakeModule(ExtensionModule): if 'configuration' not in kwargs: raise mesonlib.MesonException('"configuration" not specified.') conf = kwargs['configuration'] - if not isinstance(conf, ConfigurationDataHolder): + if not isinstance(conf, ConfigurationDataObject): raise mesonlib.MesonException('Argument "configuration" is not of type configuration_data') prefix = state.environment.coredata.get_option(mesonlib.OptionKey('prefix')) @@ -365,7 +366,7 @@ class CmakeModule(ExtensionModule): extra = PACKAGE_INIT_EXT.replace('@absInstallDir@', abs_install_dir) extra = extra.replace('@installPrefix@', prefix) - self.create_package_file(ifile_abs, ofile_abs, PACKAGE_RELATIVE_PATH, extra, conf.held_object) + self.create_package_file(ifile_abs, ofile_abs, PACKAGE_RELATIVE_PATH, extra, conf.conf_data) conf.mark_used() conffile = os.path.normpath(inputfile.relative_name()) @@ -389,7 +390,7 @@ class CmakeModule(ExtensionModule): raise InterpreterException('"options" cannot be used together with "cmake_options"') dirname = args[0] subp = self.interpreter.do_subproject(dirname, 'cmake', kwargs) - if not subp.held_object: + if not subp.found(): return subp return CMakeSubproject(subp, dirname) diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 0a72ad663..0ae1c70ca 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -30,7 +30,7 @@ from . import ExtensionModule from . import ModuleReturnValue from ..mesonlib import ( MachineChoice, MesonException, OrderedSet, Popen_safe, extract_as_list, - join_args, unholder, + join_args, HoldableObject ) from ..dependencies import Dependency, PkgConfigDependency, InternalDependency from ..interpreterbase import noPosargs, noKwargs, permittedKwargs, FeatureNew, FeatureNewKwargs, FeatureDeprecatedKwargs @@ -39,6 +39,7 @@ from ..build import CustomTarget, CustomTargetIndex, GeneratedList if T.TYPE_CHECKING: from ..compilers import Compiler + from ..interpreter import Interpreter # gresource compilation is broken due to the way # the resource compiler and Ninja clash about it @@ -103,14 +104,13 @@ class GnomeModule(ExtensionModule): def _get_dep(self, state, depname, native=False, required=True): kwargs = {'native': native, 'required': required} - holder = self.interpreter.func_dependency(state.current_node, [depname], kwargs) - return holder.held_object + return self.interpreter.func_dependency(state.current_node, [depname], kwargs) def _get_native_binary(self, state, name, depname, varname, required=True): # Look in overrides in case glib/gtk/etc are built as subproject prog = self.interpreter.program_from_overrides([name], []) if prog is not None: - return unholder(prog) + return prog # Look in machine file prog = state.environment.lookup_binary_entry(MachineChoice.HOST, name) @@ -125,7 +125,7 @@ class GnomeModule(ExtensionModule): return ExternalProgram(name, value) # Normal program lookup - return unholder(state.find_program(name, required=required)) + return state.find_program(name, required=required) @permittedKwargs({'glib_compile_schemas', 'gio_querymodules', 'gtk_update_icon_cache'}) @noPosargs @@ -179,7 +179,7 @@ class GnomeModule(ExtensionModule): # Validate dependencies subdirs = [] depends = [] - for (ii, dep) in enumerate(unholder(dependencies)): + for (ii, dep) in enumerate(dependencies): if isinstance(dep, mesonlib.File): subdirs.append(dep.subdir) elif isinstance(dep, (build.CustomTarget, build.CustomTargetIndex)): @@ -323,7 +323,7 @@ class GnomeModule(ExtensionModule): subdirs = [] for resfile in dep_files[:]: resbasename = os.path.basename(resfile) - for dep in unholder(dependencies): + for dep in dependencies: if isinstance(dep, mesonlib.File): if dep.fname != resbasename: continue @@ -399,7 +399,7 @@ class GnomeModule(ExtensionModule): # require two args in order, such as -framework AVFoundation external_ldflags_nodedup = [] gi_includes = OrderedSet() - deps = mesonlib.unholder(mesonlib.listify(deps)) + deps = mesonlib.listify(deps) for dep in deps: if isinstance(dep, Dependency): @@ -409,7 +409,7 @@ class GnomeModule(ExtensionModule): if isinstance(dep, InternalDependency): cflags.update(dep.get_compile_args()) cflags.update(state.get_include_args(dep.include_directories)) - for lib in unholder(dep.libraries): + for lib in dep.libraries: if isinstance(lib, build.SharedLibrary): internal_ldflags.update(self._get_link_args(state, lib, depends, include_rpath)) libdepflags = self._get_dependencies_flags(lib.get_external_deps(), state, depends, include_rpath, @@ -426,7 +426,7 @@ class GnomeModule(ExtensionModule): external_ldflags.update(extdepflags[2]) external_ldflags_nodedup += extdepflags[3] gi_includes.update(extdepflags[4]) - for source in unholder(dep.sources): + for source in dep.sources: if isinstance(source, GirTarget): gi_includes.update([os.path.join(state.environment.get_build_dir(), source.get_subdir())]) @@ -480,9 +480,6 @@ class GnomeModule(ExtensionModule): return cflags, internal_ldflags, external_ldflags, external_ldflags_nodedup, gi_includes def _unwrap_gir_target(self, girtarget, state): - while hasattr(girtarget, 'held_object'): - girtarget = girtarget.held_object - if not isinstance(girtarget, (build.Executable, build.SharedLibrary, build.StaticLibrary)): raise MesonException('Gir target must be an executable or library') @@ -512,8 +509,6 @@ class GnomeModule(ExtensionModule): @functools.lru_cache(maxsize=None) def _gir_has_option(self, option) -> bool: exe = self.giscanner - if hasattr(exe, 'held_object'): - exe = exe.held_object if isinstance(exe, OverrideProgram): # Handle overridden g-ir-scanner assert option in ['--extra-library', '--sources-top-dirs'] @@ -539,7 +534,7 @@ class GnomeModule(ExtensionModule): link_with = mesonlib.extract_as_list(kwargs, 'link_with', pop = True) for link in link_with: - ret += self._get_link_args(state, link.held_object, depends, + ret += self._get_link_args(state, link, depends, use_gir_args=True) return ret @@ -549,7 +544,7 @@ class GnomeModule(ExtensionModule): if 'includes' in kwargs: includes = mesonlib.extract_as_list(kwargs, 'includes', pop = True) - for inc in unholder(includes): + for inc in includes: if isinstance(inc, str): ret += [f'--include={inc}'] elif isinstance(inc, GirTarget): @@ -605,7 +600,7 @@ class GnomeModule(ExtensionModule): def _scan_inc_dirs(self, kwargs): ret = mesonlib.extract_as_list(kwargs, 'include_directories', pop = True) for incd in ret: - if not isinstance(incd.held_object, (str, build.IncludeDirs)): + if not isinstance(incd, (str, build.IncludeDirs)): raise MesonException( 'Gir include dirs should be include_directories().') return ret @@ -708,7 +703,7 @@ class GnomeModule(ExtensionModule): gir_filelist_filename = os.path.join(gir_filelist_dir, f'{ns}_{nsversion}_gir_filelist') with open(gir_filelist_filename, 'w', encoding='utf-8') as gir_filelist: - for s in unholder(libsources): + for s in libsources: if isinstance(s, (build.CustomTarget, build.CustomTargetIndex)): for custom_output in s.get_outputs(): gir_filelist.write(os.path.join(state.environment.get_build_dir(), @@ -763,11 +758,11 @@ class GnomeModule(ExtensionModule): # dependencies and also find the include directories needed for the # typelib generation custom target below. typelib_includes = [] - for dep in unholder(deps): + for dep in deps: # Add a dependency on each GirTarget listed in dependencies and add # the directory where it will be generated to the typelib includes if isinstance(dep, InternalDependency): - for source in unholder(dep.sources): + for source in dep.sources: if isinstance(source, GirTarget) and source not in depends: depends.append(source) subdir = os.path.join(state.environment.get_build_dir(), @@ -846,7 +841,7 @@ class GnomeModule(ExtensionModule): langs_compilers = self._get_girtargets_langs_compilers(girtargets) cflags, internal_ldflags, external_ldflags = self._get_langs_compilers_flags(state, langs_compilers) deps = self._get_gir_targets_deps(girtargets) - deps += mesonlib.unholder(extract_as_list(kwargs, 'dependencies', pop=True)) + deps += extract_as_list(kwargs, 'dependencies', pop=True) deps += [gir_dep] typelib_includes = self._gather_typelib_includes_and_update_depends(state, deps, depends) # ldflags will be misinterpreted by gir scanner (showing @@ -898,7 +893,7 @@ class GnomeModule(ExtensionModule): if fatal_warnings: scan_command.append('--warn-error') - generated_files = [unholder(f) for f in libsources if isinstance(unholder(f), (GeneratedList, CustomTarget, CustomTargetIndex))] + generated_files = [f for f in libsources if isinstance(f, (GeneratedList, CustomTarget, CustomTargetIndex))] scan_target = self._make_gir_target(state, girfile, scan_command, generated_files, depends, kwargs) @@ -1044,8 +1039,7 @@ class GnomeModule(ExtensionModule): src_dirs = mesonlib.extract_as_list(kwargs, 'src_dir') header_dirs = [] for src_dir in src_dirs: - if hasattr(src_dir, 'held_object'): - src_dir = src_dir.held_object + if isinstance(src_dir, HoldableObject): if not isinstance(src_dir, build.IncludeDirs): raise MesonException('Invalid keyword argument for src_dir.') for inc_dir in src_dir.get_incdirs(): @@ -1068,7 +1062,7 @@ class GnomeModule(ExtensionModule): for tool in ['scan', 'scangobj', 'mkdb', 'mkhtml', 'fixxref']: program_name = 'gtkdoc-' + tool program = state.find_program(program_name) - path = program.held_object.get_path() + path = program.get_path() args.append(f'--{program_name}={path}') if namespace: args.append('--namespace=' + namespace) @@ -1082,7 +1076,7 @@ class GnomeModule(ExtensionModule): depends = [] content_files = [] - for s in unholder(mesonlib.extract_as_list(kwargs, 'content_files')): + for s in mesonlib.extract_as_list(kwargs, 'content_files'): if isinstance(s, (build.CustomTarget, build.CustomTargetIndex)): depends.append(s) for o in s.get_outputs(): @@ -1134,14 +1128,14 @@ class GnomeModule(ExtensionModule): def _get_build_args(self, kwargs, state, depends): args = [] - deps = mesonlib.unholder(extract_as_list(kwargs, 'dependencies')) + deps = extract_as_list(kwargs, 'dependencies') cflags = [] cflags.extend(mesonlib.stringlistify(kwargs.pop('c_args', []))) deps_cflags, internal_ldflags, external_ldflags, gi_includes = \ self._get_dependencies_flags(deps, state, depends, include_rpath=True) inc_dirs = mesonlib.extract_as_list(kwargs, 'include_directories') for incd in inc_dirs: - if not isinstance(incd.held_object, (str, build.IncludeDirs)): + if not isinstance(incd, (str, build.IncludeDirs)): raise MesonException( 'Gir include dirs should be include_directories().') @@ -1678,7 +1672,7 @@ G_END_DECLS''' vapi_includes = [] ret = [] remaining_args = [] - for arg in unholder(arg_list): + for arg in arg_list: if isinstance(arg, InternalDependency): targets = [t for t in arg.sources if isinstance(t, VapiTarget)] for target in targets: @@ -1752,11 +1746,11 @@ G_END_DECLS''' for i in inputs: if isinstance(i, str): cmd.append(os.path.join(source_dir, i)) - elif hasattr(i, 'held_object') and isinstance(i.held_object, GirTarget): - link_with += self._get_vapi_link_with(i.held_object) + elif isinstance(i, GirTarget): + link_with += self._get_vapi_link_with(i) subdir = os.path.join(state.environment.get_build_dir(), - i.held_object.get_subdir()) - gir_file = os.path.join(subdir, i.held_object.get_outputs()[0]) + i.get_subdir()) + gir_file = os.path.join(subdir, i.get_outputs()[0]) cmd.append(gir_file) else: raise MesonException('Input must be a str or GirTarget') @@ -1791,4 +1785,10 @@ G_END_DECLS''' return ModuleReturnValue(rv, created_values) def initialize(*args, **kwargs): - return GnomeModule(*args, **kwargs) + mod = GnomeModule(*args, **kwargs) + mod.interpreter.append_holder_map(GResourceTarget, interpreter.CustomTargetHolder) + mod.interpreter.append_holder_map(GResourceHeaderTarget, interpreter.CustomTargetHolder) + mod.interpreter.append_holder_map(GirTarget, interpreter.CustomTargetHolder) + mod.interpreter.append_holder_map(TypelibTarget, interpreter.CustomTargetHolder) + mod.interpreter.append_holder_map(VapiTarget, interpreter.CustomTargetHolder) + return mod diff --git a/mesonbuild/modules/hotdoc.py b/mesonbuild/modules/hotdoc.py index 90635e6b1..26026fb13 100644 --- a/mesonbuild/modules/hotdoc.py +++ b/mesonbuild/modules/hotdoc.py @@ -105,7 +105,6 @@ class HotdocTargetBuilder: self.cmd.extend([option, value]) def check_extra_arg_type(self, arg, value): - value = getattr(value, 'held_object', value) if isinstance(value, list): for v in value: self.check_extra_arg_type(arg, v) @@ -188,7 +187,6 @@ class HotdocTargetBuilder: def process_dependencies(self, deps): cflags = set() for dep in mesonlib.listify(ensure_list(deps)): - dep = getattr(dep, "held_object", dep) if isinstance(dep, InternalDependency): inc_args = self.state.get_include_args(dep.include_directories) cflags.update([self.replace_dirs_in_string(x) @@ -232,7 +230,6 @@ class HotdocTargetBuilder: def flatten_config_command(self): cmd = [] for arg in mesonlib.listify(self.cmd, flatten=True): - arg = getattr(arg, 'held_object', arg) if isinstance(arg, mesonlib.File): arg = arg.absolute_path(self.state.environment.get_source_dir(), self.state.environment.get_build_dir()) @@ -371,7 +368,7 @@ class HotdocTargetHolder(CustomTargetHolder): def config_path_method(self, *args, **kwargs): conf = self.held_object.hotdoc_conf.absolute_path(self.interpreter.environment.source_dir, self.interpreter.environment.build_dir) - return self.interpreter.holderify(conf) + return conf class HotdocTarget(build.CustomTarget): @@ -422,7 +419,7 @@ class HotDocModule(ExtensionModule): project_name = args[0] builder = HotdocTargetBuilder(project_name, state, self.hotdoc, self.interpreter, kwargs) target, install_script = builder.make_targets() - targets = [HotdocTargetHolder(target, self.interpreter)] + targets = [target] if install_script: targets.append(install_script) @@ -430,4 +427,6 @@ class HotDocModule(ExtensionModule): def initialize(interpreter): - return HotDocModule(interpreter) + mod = HotDocModule(interpreter) + mod.interpreter.append_holder_map(HotdocTarget, HotdocTargetHolder) + return mod diff --git a/mesonbuild/modules/i18n.py b/mesonbuild/modules/i18n.py index 98a8b0da3..f10fdbe49 100644 --- a/mesonbuild/modules/i18n.py +++ b/mesonbuild/modules/i18n.py @@ -108,7 +108,8 @@ class I18nModule(ExtensionModule): kwargs['command'] = command inputfile = kwargs['input'] - if hasattr(inputfile, 'held_object'): + # I have no idea why/how this if isinstance(inputfile, mesonlib.HoldableObject) works / used to work... + if isinstance(inputfile, mesonlib.HoldableObject): ct = build.CustomTarget(kwargs['output'] + '_merge', state.subdir, state.subproject, kwargs) else: if isinstance(inputfile, list): diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py index 13af3a6f8..f42c1e64d 100644 --- a/mesonbuild/modules/pkgconfig.py +++ b/mesonbuild/modules/pkgconfig.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os, types +import os from pathlib import PurePath from .. import build @@ -22,7 +22,9 @@ from .. import mesonlib from .. import mlog from . import ModuleReturnValue from . import ExtensionModule -from ..interpreterbase import permittedKwargs, FeatureNew, FeatureNewKwargs +from ..interpreterbase import permittedKwargs, FeatureNew, FeatureNewKwargs, TYPE_var, TYPE_kwargs + +import typing as T already_warned_objs = set() @@ -75,7 +77,7 @@ class DependenciesHelper: def _process_reqs(self, reqs): '''Returns string names of requirements''' processed_reqs = [] - for obj in mesonlib.unholder(mesonlib.listify(reqs)): + for obj in mesonlib.listify(reqs): if not isinstance(obj, str): FeatureNew.single_use('pkgconfig.generate requirement from non-string object', '0.46.0', self.state.subproject) if hasattr(obj, 'generated_pc'): @@ -108,14 +110,13 @@ class DependenciesHelper: def add_cflags(self, cflags): self.cflags += mesonlib.stringlistify(cflags) - def _process_libs(self, libs, public): - libs = mesonlib.unholder(mesonlib.listify(libs)) + def _process_libs(self, libs, public: bool): + libs = mesonlib.listify(libs) libs = [x.get_preferred_library() if isinstance(x, build.BothLibraries) else x for x in libs] processed_libs = [] processed_reqs = [] processed_cflags = [] for obj in libs: - shared_library_only = getattr(obj, 'shared_library_only', False) if hasattr(obj, 'pcdep'): pcdeps = mesonlib.listify(obj.pcdep) for d in pcdeps: @@ -488,7 +489,7 @@ class PkgConfigModule(ExtensionModule): FeatureNew.single_use('pkgconfig.generate implicit version keyword', '0.46.0', state.subproject) elif len(args) == 1: FeatureNew.single_use('pkgconfig.generate optional positional argument', '0.46.0', state.subproject) - mainlib = getattr(args[0], 'held_object', args[0]) + mainlib = args[0] if not isinstance(mainlib, (build.StaticLibrary, build.SharedLibrary)): raise mesonlib.MesonException('Pkgconfig_gen first positional argument must be a library object') default_name = mainlib.name diff --git a/mesonbuild/modules/sourceset.py b/mesonbuild/modules/sourceset.py index e413e32ec..eea3dbde2 100644 --- a/mesonbuild/modules/sourceset.py +++ b/mesonbuild/modules/sourceset.py @@ -101,7 +101,6 @@ class SourceSet(MutableModuleObject): if_true = args elif args: raise InterpreterException('add_all called with both positional and keyword arguments') - if_true = mesonlib.unholder(if_true) keys, dependencies = self.check_conditions(when) for s in if_true: if not isinstance(s, SourceSet): diff --git a/mesonbuild/modules/unstable_cuda.py b/mesonbuild/modules/unstable_cuda.py index af65af38b..a80f9ca73 100644 --- a/mesonbuild/modules/unstable_cuda.py +++ b/mesonbuild/modules/unstable_cuda.py @@ -16,8 +16,7 @@ import typing as T import re from ..mesonlib import version_compare -from ..interpreter import CompilerHolder -from ..compilers import CudaCompiler +from ..compilers import CudaCompiler, Compiler from . import ModuleObject @@ -83,7 +82,7 @@ class CudaModule(ModuleObject): @permittedKwargs(['detected']) def nvcc_arch_flags(self, state: 'ModuleState', - args: T.Tuple[T.Union[CompilerHolder, CudaCompiler, str]], + args: T.Tuple[T.Union[Compiler, CudaCompiler, str]], kwargs: T.Dict[str, T.Any]) -> T.List[str]: nvcc_arch_args = self._validate_nvcc_arch_args(args, kwargs) ret = self._nvcc_arch_flags(*nvcc_arch_args)[0] @@ -91,7 +90,7 @@ class CudaModule(ModuleObject): @permittedKwargs(['detected']) def nvcc_arch_readable(self, state: 'ModuleState', - args: T.Tuple[T.Union[CompilerHolder, CudaCompiler, str]], + args: T.Tuple[T.Union[Compiler, CudaCompiler, str]], kwargs: T.Dict[str, T.Any]) -> T.List[str]: nvcc_arch_args = self._validate_nvcc_arch_args(args, kwargs) ret = self._nvcc_arch_flags(*nvcc_arch_args)[1] @@ -105,16 +104,12 @@ class CudaModule(ModuleObject): @staticmethod def _detected_cc_from_compiler(c): - if isinstance(c, CompilerHolder): - c = c.compiler if isinstance(c, CudaCompiler): return c.detected_cc return '' @staticmethod def _version_from_compiler(c): - if isinstance(c, CompilerHolder): - c = c.compiler if isinstance(c, CudaCompiler): return c.version if isinstance(c, str): diff --git a/mesonbuild/modules/unstable_rust.py b/mesonbuild/modules/unstable_rust.py index f602e0913..e5af2d749 100644 --- a/mesonbuild/modules/unstable_rust.py +++ b/mesonbuild/modules/unstable_rust.py @@ -109,7 +109,7 @@ class RustModule(ExtensionModule): ``` """ name = args[0] - base_target: BuildTarget = unholder(args[1]) + base_target: BuildTarget = args[1] if not base_target.uses_rust(): raise InterpreterException('Second positional argument to rustmod.test() must be a rust based target') extra_args = kwargs['args'] @@ -129,7 +129,7 @@ class RustModule(ExtensionModule): del extra_args[i] break - dependencies = [d.held_object for d in kwargs['dependencies']] + dependencies = [d for d in kwargs['dependencies']] # We need to cast here, as currently these don't have protocol in them, but test itself does. tkwargs = T.cast('_kwargs.FuncTest', kwargs.copy()) @@ -168,7 +168,7 @@ class RustModule(ExtensionModule): header: 'SourceOutputs' _deps: T.Sequence['SourceOutputs'] try: - header, *_deps = unholder(self.interpreter.source_strings_to_files(listify(kwargs['input']))) + header, *_deps = self.interpreter.source_strings_to_files(listify(kwargs['input'])) except KeyError: raise InvalidArguments('rustmod.bindgen() `input` argument must have at least one element.') @@ -179,7 +179,7 @@ class RustModule(ExtensionModule): if not isinstance(output, str): raise InvalidArguments('rustmod.bindgen() `output` argument must be a string.') - include_dirs: T.List[IncludeDirs] = typeslistify(unholder(listify(kwargs.get('include_directories', []))), IncludeDirs) + include_dirs: T.List[IncludeDirs] = typeslistify(listify(kwargs.get('include_directories', [])), IncludeDirs) c_args: T.List[str] = stringlistify(listify(kwargs.get('c_args', []))) bind_args: T.List[str] = stringlistify(listify(kwargs.get('args', []))) @@ -198,8 +198,7 @@ class RustModule(ExtensionModule): inc_strs.extend([f'-I{x}' for x in i.to_string_list(state.environment.get_source_dir())]) if self._bindgen_bin is None: - # there's some bugs in the interpreter typeing. - self._bindgen_bin = state.find_program('bindgen').held_object + self._bindgen_bin = state.find_program('bindgen') name: str if isinstance(header, File): diff --git a/mesonbuild/modules/unstable_simd.py b/mesonbuild/modules/unstable_simd.py index df5faa1ae..3339cea5a 100644 --- a/mesonbuild/modules/unstable_simd.py +++ b/mesonbuild/modules/unstable_simd.py @@ -54,11 +54,11 @@ class SimdModule(ExtensionModule): for key, value in kwargs.items(): if key not in self.isets and key != 'compiler': basic_kwargs[key] = value - compiler = kwargs['compiler'].compiler + compiler = kwargs['compiler'] if not isinstance(compiler, compilers.compilers.Compiler): raise mesonlib.MesonException('Compiler argument must be a compiler object.') cdata = self.interpreter.func_configuration_data(None, [], {}) - conf = cdata.held_object + conf = cdata.conf_data for iset in self.isets: if iset not in kwargs: continue diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py index 441fb9f18..d3228333e 100644 --- a/mesonbuild/modules/windows.py +++ b/mesonbuild/modules/windows.py @@ -18,10 +18,9 @@ import re from .. import mlog from .. import mesonlib, build -from ..mesonlib import MachineChoice, MesonException, extract_as_list, unholder +from ..mesonlib import MachineChoice, MesonException, extract_as_list from . import ModuleReturnValue from . import ExtensionModule -from ..interpreter import CustomTargetHolder from ..interpreterbase import permittedKwargs, FeatureNewKwargs, flatten from ..programs import ExternalProgram @@ -86,11 +85,13 @@ class WindowsModule(ExtensionModule): wrc_depend_files = extract_as_list(kwargs, 'depend_files', pop = True) wrc_depends = extract_as_list(kwargs, 'depends', pop = True) for d in wrc_depends: - if isinstance(d, CustomTargetHolder): - extra_args += state.get_include_args([d.outdir_include()]) + if isinstance(d, build.CustomTarget): + extra_args += state.get_include_args([ + build.IncludeDirs('', [], False, [os.path.join('@BUILD_ROOT@', self.interpreter.backend.get_target_dir(d))]) + ]) inc_dirs = extract_as_list(kwargs, 'include_directories', pop = True) for incd in inc_dirs: - if not isinstance(incd.held_object, (str, build.IncludeDirs)): + if not isinstance(incd, (str, build.IncludeDirs)): raise MesonException('Resource include dirs should be include_directories().') extra_args += state.get_include_args(inc_dirs) @@ -120,7 +121,6 @@ class WindowsModule(ExtensionModule): for subsrc in src: add_target(subsrc) return - src = unholder(src) if isinstance(src, str): name_formatted = src diff --git a/run_unittests.py b/run_unittests.py index 067404f50..b55ba96f6 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -741,17 +741,6 @@ class InternalTests(unittest.TestCase): self.assertEqual([holder1, 2], listify([holder1, 2])) self.assertEqual([holder1, 2, 3], listify([holder1, 2, [3]])) - def test_unholder(self): - unholder = mesonbuild.mesonlib.unholder - - holder1 = ObjectHolder(1) - holder3 = ObjectHolder(3) - holders = [holder1, holder3] - - self.assertEqual(1, unholder(holder1)) - self.assertEqual([1], unholder([holder1])) - self.assertEqual([1, 3], unholder(holders)) - def test_extract_as_list(self): extract = mesonbuild.mesonlib.extract_as_list # Test sanity