holders: remove unholder

pull/8903/head
Daniel Mensinger 4 years ago
parent 84a3e459a8
commit 34c28dc92c
  1. 18
      mesonbuild/backend/backends.py
  2. 4
      mesonbuild/backend/ninjabackend.py
  3. 77
      mesonbuild/build.py
  4. 53
      mesonbuild/interpreter/dependencyfallbacks.py
  5. 96
      mesonbuild/interpreter/interpreter.py
  6. 3
      mesonbuild/interpreter/mesonmain.py
  7. 4
      mesonbuild/interpreterbase/__init__.py
  8. 21
      mesonbuild/mesonlib/universal.py
  9. 18
      mesonbuild/modules/__init__.py
  10. 17
      mesonbuild/modules/cmake.py
  11. 70
      mesonbuild/modules/gnome.py
  12. 11
      mesonbuild/modules/hotdoc.py
  13. 3
      mesonbuild/modules/i18n.py
  14. 15
      mesonbuild/modules/pkgconfig.py
  15. 1
      mesonbuild/modules/sourceset.py
  16. 11
      mesonbuild/modules/unstable_cuda.py
  17. 11
      mesonbuild/modules/unstable_rust.py
  18. 4
      mesonbuild/modules/unstable_simd.py
  19. 12
      mesonbuild/modules/windows.py
  20. 11
      run_unittests.py

@ -32,7 +32,7 @@ from .. import mlog
from ..compilers import LANGUAGES_USING_LDFLAGS from ..compilers import LANGUAGES_USING_LDFLAGS
from ..mesonlib import ( from ..mesonlib import (
File, MachineChoice, MesonException, OptionType, OrderedSet, OptionOverrideProxy, File, MachineChoice, MesonException, OptionType, OrderedSet, OptionOverrideProxy,
classify_unity_sources, unholder, OptionKey, join_args classify_unity_sources, OptionKey, join_args
) )
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
@ -237,7 +237,7 @@ class Backend:
def generate(self) -> None: def generate(self) -> None:
raise RuntimeError(f'generate is not implemented in {type(self).__name__}') 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 isinstance(t, build.CustomTarget):
if warn_multi_output and len(t.get_outputs()) != 1: if warn_multi_output and len(t.get_outputs()) != 1:
mlog.warning(f'custom_target {t.name!r} has more than one output! ' mlog.warning(f'custom_target {t.name!r} has more than one output! '
@ -250,7 +250,7 @@ class Backend:
filename = t.get_filename() filename = t.get_filename()
return os.path.join(self.get_target_dir(t), 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)) 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: 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') raise AssertionError(f'BUG: Tried to link to {target!r} which is not linkable')
@lru_cache(maxsize=None) @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': if self.environment.coredata.get_option(OptionKey('layout')) == 'mirror':
dirname = target.get_subdir() dirname = target.get_subdir()
else: else:
@ -329,7 +329,7 @@ class Backend:
return os.path.join(self.build_to_src, target_dir) return os.path.join(self.build_to_src, target_dir)
return self.build_to_src 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') return os.path.join(self.get_target_filename(target, warn_multi_output=False) + '.p')
def get_target_private_dir_abs(self, target): def get_target_private_dir_abs(self, target):
@ -963,7 +963,7 @@ class Backend:
depends = set(t.depends) depends = set(t.depends)
if isinstance(exe, build.Target): if isinstance(exe, build.Target):
depends.add(exe) depends.add(exe)
for a in unholder(t.cmd_args): for a in t.cmd_args:
if isinstance(a, build.Target): if isinstance(a, build.Target):
depends.add(a) depends.add(a)
if isinstance(a, build.BuildTarget): if isinstance(a, build.BuildTarget):
@ -1091,10 +1091,10 @@ class Backend:
# also be built by default. XXX: Sometime in the future these should be # also be built by default. XXX: Sometime in the future these should be
# built only before running tests. # built only before running tests.
for t in self.build.get_tests(): for t in self.build.get_tests():
exe = unholder(t.exe) exe = t.exe
if isinstance(exe, (build.CustomTarget, build.BuildTarget)): if isinstance(exe, (build.CustomTarget, build.BuildTarget)):
result[exe.get_id()] = exe 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)): if not isinstance(arg, (build.CustomTarget, build.BuildTarget)):
continue continue
result[arg.get_id()] = arg result[arg.get_id()] = arg
@ -1133,7 +1133,7 @@ class Backend:
Returns the path to them relative to the build root directory. Returns the path to them relative to the build root directory.
''' '''
srcs = [] srcs = []
for i in unholder(target.get_sources()): for i in target.get_sources():
if isinstance(i, str): if isinstance(i, str):
fname = [os.path.join(self.build_to_src, target.subdir, i)] fname = [os.path.join(self.build_to_src, target.subdir, i)]
elif isinstance(i, build.BuildTarget): elif isinstance(i, build.BuildTarget):

@ -40,7 +40,7 @@ from ..compilers import (
from ..linkers import ArLinker, RSPFileSyntax from ..linkers import ArLinker, RSPFileSyntax
from ..mesonlib import ( from ..mesonlib import (
File, LibType, MachineChoice, MesonException, OrderedSet, PerMachine, 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 ..mesonlib import get_compiler_for_source, has_path_sep, OptionKey
from .backends import CleanTrees from .backends import CleanTrees
@ -937,7 +937,7 @@ int dummy;
self.generate_target(t) self.generate_target(t)
def custom_target_generator_inputs(self, target): def custom_target_generator_inputs(self, target):
for s in unholder(target.sources): for s in target.sources:
if isinstance(s, build.GeneratedList): if isinstance(s, build.GeneratedList):
self.generate_genlist_for_target(s, target) self.generate_genlist_for_target(s, target)

@ -31,15 +31,16 @@ from .mesonlib import (
HoldableObject, HoldableObject,
File, MesonException, MachineChoice, PerMachine, OrderedSet, listify, File, MesonException, MachineChoice, PerMachine, OrderedSet, listify,
extract_as_list, typeslistify, stringlistify, classify_unity_sources, 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, OptionKey, PerMachineDefaultable,
MesonBugException, FileOrString,
) )
from .compilers import ( from .compilers import (
Compiler, is_object, clink_langs, sort_clink, lang_suffixes, Compiler, is_object, clink_langs, sort_clink, lang_suffixes,
is_known_suffix is_known_suffix
) )
from .linkers import StaticLinker from .linkers import StaticLinker
from .interpreterbase import FeatureNew from .interpreterbase import FeatureNew, TYPE_nkwargs, TYPE_nvar
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
from ._typing import ImmutableListProtocol, ImmutableSetProtocol from ._typing import ImmutableListProtocol, ImmutableSetProtocol
@ -47,7 +48,6 @@ if T.TYPE_CHECKING:
from .mesonlib import FileMode, FileOrString from .mesonlib import FileMode, FileOrString
from .modules import ModuleState from .modules import ModuleState
from .backend.backends import Backend from .backend.backends import Backend
from .interpreter.interpreterobjects import GeneratorHolder
pch_kwargs = {'c_pch', 'cpp_pch'} pch_kwargs = {'c_pch', 'cpp_pch'}
@ -680,7 +680,7 @@ class BuildTarget(Target):
def process_objectlist(self, objects): def process_objectlist(self, objects):
assert(isinstance(objects, list)) assert(isinstance(objects, list))
for s in unholder(objects): for s in objects:
if isinstance(s, (str, File, ExtractedObjects)): if isinstance(s, (str, File, ExtractedObjects)):
self.objects.append(s) self.objects.append(s)
elif isinstance(s, (GeneratedList, CustomTarget)): elif isinstance(s, (GeneratedList, CustomTarget)):
@ -776,7 +776,7 @@ class BuildTarget(Target):
# which is what we need. # which is what we need.
if not is_object(s): if not is_object(s):
sources.append(s) sources.append(s)
for d in unholder(self.external_deps): for d in self.external_deps:
for s in d.sources: for s in d.sources:
if isinstance(s, (str, File)): if isinstance(s, (str, File)):
sources.append(s) sources.append(s)
@ -847,7 +847,7 @@ class BuildTarget(Target):
link_depends. link_depends.
""" """
sources = listify(sources) sources = listify(sources)
for s in unholder(sources): for s in sources:
if isinstance(s, File): if isinstance(s, File):
self.link_depends.append(s) self.link_depends.append(s)
elif isinstance(s, str): elif isinstance(s, str):
@ -864,35 +864,16 @@ class BuildTarget(Target):
def get_original_kwargs(self): def get_original_kwargs(self):
return self.kwargs 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): def copy_kwargs(self, kwargs):
self.kwargs = copy.copy(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(): for k, v in self.kwargs.items():
if isinstance(v, list): if isinstance(v, list):
self.kwargs[k] = self.unpack_holder(v) self.kwargs[k] = listify(v, flatten=True)
if hasattr(v, 'held_object'):
self.kwargs[k] = v.held_object
for t in ['dependencies', 'link_with', 'include_directories', 'sources']: for t in ['dependencies', 'link_with', 'include_directories', 'sources']:
if t in self.kwargs: 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 = [] obj_src = []
sources_set = set(self.sources) sources_set = set(self.sources)
for src in srclist: for src in srclist:
@ -901,14 +882,14 @@ class BuildTarget(Target):
elif isinstance(src, File): elif isinstance(src, File):
FeatureNew.single_use('File argument for extract_objects', '0.50.0', self.subproject) FeatureNew.single_use('File argument for extract_objects', '0.50.0', self.subproject)
else: 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 # FIXME: It could be a generated source
if src not in sources_set: if src not in sources_set:
raise MesonException(f'Tried to extract unknown source {src}.') raise MesonException(f'Tried to extract unknown source {src}.')
obj_src.append(src) obj_src.append(src)
return ExtractedObjects(self, obj_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, return ExtractedObjects(self, self.sources, self.generated, self.objects,
recursive) recursive)
@ -960,7 +941,7 @@ class BuildTarget(Target):
kwargs.get('modules', []) kwargs.get('modules', [])
self.need_install = kwargs.get('install', self.need_install) self.need_install = kwargs.get('install', self.need_install)
llist = extract_as_list(kwargs, 'link_with') llist = extract_as_list(kwargs, 'link_with')
for linktarget in unholder(llist): for linktarget in llist:
if isinstance(linktarget, dependencies.ExternalLibrary): if isinstance(linktarget, dependencies.ExternalLibrary):
raise MesonException(textwrap.dedent('''\ raise MesonException(textwrap.dedent('''\
An external library was used in link_with keyword argument, which An external library was used in link_with keyword argument, which
@ -1003,7 +984,7 @@ class BuildTarget(Target):
if dfeature_debug: if dfeature_debug:
dfeatures['debug'] = dfeature_debug dfeatures['debug'] = dfeature_debug
if 'd_import_dirs' in kwargs: 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: for d in dfeature_import_dirs:
if not isinstance(d, IncludeDirs): if not isinstance(d, IncludeDirs):
raise InvalidArguments('Arguments to d_import_dirs must be include_directories.') raise InvalidArguments('Arguments to d_import_dirs must be include_directories.')
@ -1200,7 +1181,7 @@ class BuildTarget(Target):
def add_deps(self, deps): def add_deps(self, deps):
deps = listify(deps) deps = listify(deps)
for dep in unholder(deps): for dep in deps:
if dep in self.added_deps: if dep in self.added_deps:
continue continue
if isinstance(dep, dependencies.InternalDependency): 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 return isinstance(self, StaticLibrary) and not self.need_install
def link(self, target): def link(self, target):
for t in unholder(listify(target)): for t in listify(target):
if isinstance(t, BothLibraries): if isinstance(t, BothLibraries):
t = t.get_preferred_library() t = t.get_preferred_library()
if isinstance(self, StaticLibrary) and self.need_install: 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) self.link_targets.append(t)
def link_whole(self, target): 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 # Always use the static library from BothLibraries, since shared libs aren't supported anyway
if isinstance(t, BothLibraries): if isinstance(t, BothLibraries):
t = t.static 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): def add_include_dirs(self, args, set_is_system: T.Optional[str] = None):
ids = [] ids = []
for a in unholder(args): for a in args:
if not isinstance(a, IncludeDirs): if not isinstance(a, IncludeDirs):
raise InvalidArguments('Include directory to be added is not an include directory object.') raise InvalidArguments('Include directory to be added is not an include directory object.')
ids.append(a) ids.append(a)
@ -2063,7 +2044,7 @@ class SharedLibrary(BuildTarget):
# Visual Studio module-definitions file # Visual Studio module-definitions file
if 'vs_module_defs' in kwargs: if 'vs_module_defs' in kwargs:
path = unholder(kwargs['vs_module_defs']) path = kwargs['vs_module_defs']
if isinstance(path, str): if isinstance(path, str):
if os.path.isabs(path): if os.path.isabs(path):
self.vs_module_defs = File.from_absolute_file(path) self.vs_module_defs = File.from_absolute_file(path)
@ -2181,7 +2162,7 @@ class BothLibraries(HoldableObject):
class CommandBase: class CommandBase:
def flatten_command(self, cmd): def flatten_command(self, cmd):
cmd = unholder(listify(cmd)) cmd = listify(cmd)
final_cmd = [] final_cmd = []
for c in cmd: for c in cmd:
if isinstance(c, str): if isinstance(c, str):
@ -2256,7 +2237,7 @@ class CustomTarget(Target, CommandBase):
def get_target_dependencies(self): def get_target_dependencies(self):
deps = self.dependencies[:] deps = self.dependencies[:]
deps += self.extra_depends deps += self.extra_depends
for c in unholder(self.sources): for c in self.sources:
if isinstance(c, (BuildTarget, CustomTarget)): if isinstance(c, (BuildTarget, CustomTarget)):
deps.append(c) deps.append(c)
return deps return deps
@ -2281,7 +2262,7 @@ class CustomTarget(Target, CommandBase):
def process_kwargs(self, kwargs, backend): def process_kwargs(self, kwargs, backend):
self.process_kwargs_base(kwargs) 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: if 'output' not in kwargs:
raise InvalidArguments('Missing keyword argument "output".') raise InvalidArguments('Missing keyword argument "output".')
self.outputs = listify(kwargs['output']) self.outputs = listify(kwargs['output'])
@ -2360,7 +2341,7 @@ class CustomTarget(Target, CommandBase):
if not isinstance(self.build_always_stale, bool): if not isinstance(self.build_always_stale, bool):
raise InvalidArguments('Argument build_always_stale must be a boolean.') 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']] 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)): if not isinstance(ed, (CustomTarget, BuildTarget)):
raise InvalidArguments('Can only depend on toplevel targets: custom_target or build_target ' raise InvalidArguments('Can only depend on toplevel targets: custom_target or build_target '
f'(executable or a library) got: {type(ed)}({ed})') f'(executable or a library) got: {type(ed)}({ed})')
@ -2396,7 +2377,7 @@ class CustomTarget(Target, CommandBase):
def get_generated_lists(self): def get_generated_lists(self):
genlists = [] genlists = []
for c in unholder(self.sources): for c in self.sources:
if isinstance(c, GeneratedList): if isinstance(c, GeneratedList):
genlists.append(c) genlists.append(c)
return genlists return genlists
@ -2447,7 +2428,7 @@ class CustomTarget(Target, CommandBase):
def type_suffix(self): def type_suffix(self):
return "@cus" return "@cus"
def __getitem__(self, index): def __getitem__(self, index: int) -> 'CustomTargetIndex':
return CustomTargetIndex(self, self.outputs[index]) return CustomTargetIndex(self, self.outputs[index])
def __setitem__(self, index, value): def __setitem__(self, index, value):
@ -2606,7 +2587,13 @@ class CustomTargetIndex(HoldableObject):
class ConfigurationData(HoldableObject): class ConfigurationData(HoldableObject):
def __init__(self) -> None: def __init__(self) -> None:
super().__init__() 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): def __repr__(self):
return repr(self.values) return repr(self.values)
@ -2651,7 +2638,7 @@ def get_sources_string_names(sources, backend):
get all the output basenames. get all the output basenames.
''' '''
names = [] names = []
for s in unholder(sources): for s in sources:
if isinstance(s, str): if isinstance(s, str):
names.append(s) names.append(s)
elif isinstance(s, (BuildTarget, CustomTarget, CustomTargetIndex, GeneratedList)): elif isinstance(s, (BuildTarget, CustomTarget, CustomTargetIndex, GeneratedList)):

@ -1,12 +1,12 @@
from .interpreterobjects import DependencyHolder, SubprojectHolder, extract_required_kwarg from .interpreterobjects import SubprojectHolder, extract_required_kwarg
from .. import mlog from .. import mlog
from .. import dependencies from .. import dependencies
from .. import build from .. import build
from ..wrap import WrapMode from ..wrap import WrapMode
from ..mesonlib import OptionKey, extract_as_list, stringlistify, version_compare_many from ..mesonlib import OptionKey, extract_as_list, stringlistify, version_compare_many
from ..dependencies import DependencyException, NotFoundDependency from ..dependencies import Dependency, DependencyException, NotFoundDependency
from ..interpreterbase import (InterpreterObject, FeatureNew, from ..interpreterbase import (MesonInterpreterObject, FeatureNew,
InterpreterException, InvalidArguments, InterpreterException, InvalidArguments,
TYPE_nkwargs, TYPE_nvar) TYPE_nkwargs, TYPE_nvar)
@ -15,7 +15,7 @@ if T.TYPE_CHECKING:
from .interpreter import Interpreter 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: def __init__(self, interpreter: 'Interpreter', names: T.List[str], allow_fallback: T.Optional[bool] = None) -> None:
super().__init__() super().__init__()
self.interpreter = interpreter self.interpreter = interpreter
@ -75,14 +75,14 @@ class DependencyFallbacksHolder(InterpreterObject):
self.subproject_varname = varname self.subproject_varname = varname
self.subproject_kwargs = kwargs 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] name = func_args[0]
cached_dep = self._get_cached_dep(name, kwargs) cached_dep = self._get_cached_dep(name, kwargs)
if cached_dep: if cached_dep:
self._verify_fallback_consistency(cached_dep) self._verify_fallback_consistency(cached_dep)
return 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 # Note that there is no df.dependency() method, this is called for names
# given as positional arguments to dependency_fallbacks(name1, ...). # given as positional arguments to dependency_fallbacks(name1, ...).
# We use kwargs from the dependency() function, for things like version, # 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) for_machine = self.interpreter.machine_from_native_kwarg(kwargs)
identifier = dependencies.get_dep_identifier(name, kwargs) identifier = dependencies.get_dep_identifier(name, kwargs)
self.coredata.deps[for_machine].put(identifier, dep) self.coredata.deps[for_machine].put(identifier, dep)
return DependencyHolder(dep, self.subproject) return dep
return None 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] subp_name = func_args[0]
varname = self.subproject_varname varname = self.subproject_varname
if subp_name and self._get_subproject(subp_name): if subp_name and self._get_subproject(subp_name):
return self._get_subproject_dep(subp_name, varname, kwargs) return self._get_subproject_dep(subp_name, varname, kwargs)
return None 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: if self.nofallback:
mlog.log('Not looking for a fallback subproject for the dependency', mlog.log('Not looking for a fallback subproject for the dependency',
mlog.bold(self.display_name), 'because:\nUse of fallback dependencies is disabled.') mlog.bold(self.display_name), 'because:\nUse of fallback dependencies is disabled.')
@ -128,7 +128,7 @@ class DependencyFallbacksHolder(InterpreterObject):
return sub return sub
return None 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 # Verify the subproject is found
subproject = self._get_subproject(subp_name) subproject = self._get_subproject(subp_name)
if not subproject: if not subproject:
@ -170,7 +170,7 @@ class DependencyFallbacksHolder(InterpreterObject):
return var_dep return var_dep
wanted = stringlistify(kwargs.get('version', [])) wanted = stringlistify(kwargs.get('version', []))
found = var_dep.held_object.get_version() found = var_dep.get_version()
if not self._check_version(wanted, found): if not self._check_version(wanted, found):
mlog.log('Dependency', mlog.bold(self.display_name), 'from subproject', mlog.log('Dependency', mlog.bold(self.display_name), 'from subproject',
mlog.bold(subproject.subdir), 'found:', mlog.red('NO'), mlog.bold(subproject.subdir), 'found:', mlog.red('NO'),
@ -183,7 +183,7 @@ class DependencyFallbacksHolder(InterpreterObject):
mlog.normal_cyan(found) if found else None) mlog.normal_cyan(found) if found else None)
return var_dep 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 # 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 # 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 # 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(): if not cached_dep.found():
mlog.log('Dependency', mlog.bold(self.display_name), mlog.log('Dependency', mlog.bold(self.display_name),
'found:', mlog.red('NO'), *info) 'found:', mlog.red('NO'), *info)
return DependencyHolder(cached_dep, self.subproject) return cached_dep
else: else:
info = [mlog.blue('(cached)')] info = [mlog.blue('(cached)')]
cached_dep = self.coredata.deps[for_machine].get(identifier) cached_dep = self.coredata.deps[for_machine].get(identifier)
@ -220,24 +220,27 @@ class DependencyFallbacksHolder(InterpreterObject):
info = [mlog.normal_cyan(found_vers), *info] info = [mlog.normal_cyan(found_vers), *info]
mlog.log('Dependency', mlog.bold(self.display_name), mlog.log('Dependency', mlog.bold(self.display_name),
'found:', mlog.green('YES'), *info) 'found:', mlog.green('YES'), *info)
return DependencyHolder(cached_dep, self.subproject) return cached_dep
return None return None
def _get_subproject_variable(self, subproject: SubprojectHolder, varname: str) -> T.Optional[DependencyHolder]: def _get_subproject_variable(self, subproject: SubprojectHolder, varname: str) -> T.Optional[Dependency]:
var_dep = subproject.held_object.variables.get(varname) try:
if not isinstance(var_dep, DependencyHolder): 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', 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') 'not found' if var_dep is None else 'not a dependency object')
return None return None
return var_dep return var_dep
def _verify_fallback_consistency(self, cached_dep: DependencyHolder): def _verify_fallback_consistency(self, cached_dep: Dependency):
subp_name = self.subproject_name subp_name = self.subproject_name
varname = self.subproject_varname varname = self.subproject_varname
subproject = self._get_subproject(subp_name) subproject = self._get_subproject(subp_name)
if subproject and varname: if subproject and varname:
var_dep = self._get_subproject_variable(subproject, 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}') mlog.warning(f'Inconsistency: Subproject has overridden the dependency with another variable than {varname!r}')
def _handle_featurenew_dependencies(self, name: str) -> None: def _handle_featurenew_dependencies(self, name: str) -> None:
@ -253,8 +256,8 @@ class DependencyFallbacksHolder(InterpreterObject):
elif name == 'openmp': elif name == 'openmp':
FeatureNew.single_use('OpenMP Dependency', '0.46.0', self.subproject) FeatureNew.single_use('OpenMP Dependency', '0.46.0', self.subproject)
def _notfound_dependency(self) -> DependencyHolder: def _notfound_dependency(self) -> NotFoundDependency:
return DependencyHolder(NotFoundDependency(self.environment), self.subproject) return NotFoundDependency(self.environment)
@staticmethod @staticmethod
def _check_version(wanted: T.Optional[str], found: str) -> bool: def _check_version(wanted: T.Optional[str], found: str) -> bool:
@ -264,7 +267,7 @@ class DependencyFallbacksHolder(InterpreterObject):
return False return False
return True 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 = [] candidates = []
# 1. check if any of the names is cached already. # 1. check if any of the names is cached already.
for name in self.names: for name in self.names:
@ -281,7 +284,7 @@ class DependencyFallbacksHolder(InterpreterObject):
candidates.append((self._do_subproject, [self.subproject_name], self.subproject_kwargs)) candidates.append((self._do_subproject, [self.subproject_name], self.subproject_kwargs))
return candidates 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)' self.display_name = self.names[0] if self.names else '(anonymous)'
mods = extract_as_list(kwargs, 'modules') mods = extract_as_list(kwargs, 'modules')
if mods: if mods:
@ -329,7 +332,7 @@ class DependencyFallbacksHolder(InterpreterObject):
func_kwargs['required'] = required and (i == last) func_kwargs['required'] = required and (i == last)
kwargs['required'] = required and (i == last) kwargs['required'] = required and (i == last)
dep = func(kwargs, func_args, func_kwargs) 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 # Override this dependency to have consistent results in subsequent
# dependency lookups. # dependency lookups.
for name in self.names: for name in self.names:
@ -337,7 +340,7 @@ class DependencyFallbacksHolder(InterpreterObject):
identifier = dependencies.get_dep_identifier(name, kwargs) identifier = dependencies.get_dep_identifier(name, kwargs)
if identifier not in self.build.dependency_overrides[for_machine]: if identifier not in self.build.dependency_overrides[for_machine]:
self.build.dependency_overrides[for_machine][identifier] = \ 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 return dep
elif required and (dep or i == last): elif required and (dep or i == last):
# This was the last candidate or the dependency has been cached # This was the last candidate or the dependency has been cached

@ -128,7 +128,6 @@ class Summary:
raise InterpreterException(f'Summary section {section!r} already have key {k!r}') raise InterpreterException(f'Summary section {section!r} already have key {k!r}')
formatted_values = [] formatted_values = []
for i in listify(v): for i in listify(v):
i = unholder(i)
if isinstance(i, bool) and bool_yn: if isinstance(i, bool) and bool_yn:
formatted_values.append(mlog.green('YES') if i else mlog.red('NO')) formatted_values.append(mlog.green('YES') if i else mlog.red('NO'))
elif isinstance(i, (str, int, bool)): elif isinstance(i, (str, int, bool)):
@ -609,20 +608,16 @@ class Interpreter(InterpreterBase, HoldableObject):
if not isinstance(version, str): if not isinstance(version, str):
raise InterpreterException('Version must be a string.') raise InterpreterException('Version must be a string.')
incs = self.extract_incdirs(kwargs) incs = self.extract_incdirs(kwargs)
libs = unholder(extract_as_list(kwargs, 'link_with')) libs = extract_as_list(kwargs, 'link_with')
libs_whole = unholder(extract_as_list(kwargs, 'link_whole')) libs_whole = extract_as_list(kwargs, 'link_whole')
sources = extract_as_list(kwargs, 'sources') sources = extract_as_list(kwargs, 'sources')
sources = unholder(listify(self.source_strings_to_files(sources))) sources = listify(self.source_strings_to_files(sources))
deps = unholder(extract_as_list(kwargs, 'dependencies')) deps = extract_as_list(kwargs, 'dependencies')
compile_args = mesonlib.stringlistify(kwargs.get('compile_args', [])) compile_args = mesonlib.stringlistify(kwargs.get('compile_args', []))
link_args = mesonlib.stringlistify(kwargs.get('link_args', [])) link_args = mesonlib.stringlistify(kwargs.get('link_args', []))
variables = self.extract_variables(kwargs, list_new=True) variables = self.extract_variables(kwargs, list_new=True)
final_deps = [] final_deps = []
for d in deps: for d in deps:
try:
d = d.held_object
except Exception:
pass
if not isinstance(d, (dependencies.Dependency, dependencies.ExternalLibrary, dependencies.InternalDependency)): if not isinstance(d, (dependencies.Dependency, dependencies.ExternalLibrary, dependencies.InternalDependency)):
raise InterpreterException('Dependencies must be external deps') raise InterpreterException('Dependencies must be external deps')
final_deps.append(d) 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() '\ m = 'must be a string, or the output of find_program(), files() '\
'or configure_file(), or a compiler object; not {!r}' 'or configure_file(), or a compiler object; not {!r}'
expanded_args = [] expanded_args = []
if isinstance(cmd, ExternalProgramHolder): if isinstance(cmd, build.Executable):
cmd = cmd.held_object progname = node.args.arguments[0].value
if isinstance(cmd, build.Executable): msg = 'Program {!r} was overridden with the compiled executable {!r}'\
progname = node.args.arguments[0].value ' and therefore cannot be used during configuration'
msg = 'Program {!r} was overridden with the compiled executable {!r}'\ raise InterpreterException(msg.format(progname, cmd.description()))
' and therefore cannot be used during configuration' if isinstance(cmd, ExternalProgram):
raise InterpreterException(msg.format(progname, cmd.description()))
if not cmd.found(): if not cmd.found():
raise InterpreterException(f'command {cmd.get_name()!r} not found or not executable') raise InterpreterException(f'command {cmd.get_name()!r} not found or not executable')
elif isinstance(cmd, CompilerHolder): elif isinstance(cmd, compilers.Compiler):
exelist = cmd.compiler.get_exelist() exelist = cmd.get_exelist()
cmd = exelist[0] cmd = exelist[0]
prog = ExternalProgram(cmd, silent=True) prog = ExternalProgram(cmd, silent=True)
if not prog.found(): if not prog.found():
@ -725,8 +719,8 @@ external dependencies (including libraries) must go to "dependencies".''')
expanded_args.append(a) expanded_args.append(a)
elif isinstance(a, mesonlib.File): elif isinstance(a, mesonlib.File):
expanded_args.append(a.absolute_path(srcdir, builddir)) expanded_args.append(a.absolute_path(srcdir, builddir))
elif isinstance(a, ExternalProgramHolder): elif isinstance(a, ExternalProgram):
expanded_args.append(a.held_object.get_path()) expanded_args.append(a.get_path())
else: else:
raise InterpreterException('Arguments ' + m.format(a)) raise InterpreterException('Arguments ' + m.format(a))
# If any file that was used as an argument to the command # 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 prefix = self.coredata.options[OptionKey('prefix')].value
from ..modules.cmake import CMakeSubprojectOptions from ..modules.cmake import CMakeSubprojectOptions
options = unholder(kwargs.get('options', CMakeSubprojectOptions())) options = kwargs.get('options', CMakeSubprojectOptions())
if not isinstance(options, CMakeSubprojectOptions): if not isinstance(options, CMakeSubprojectOptions):
raise InterpreterException('"options" kwarg must be CMakeSubprojectOptions' raise InterpreterException('"options" kwarg must be CMakeSubprojectOptions'
' object (created by cmake.subproject_options())') ' object (created by cmake.subproject_options())')
@ -1290,14 +1284,14 @@ external dependencies (including libraries) must go to "dependencies".''')
return success return success
def program_from_file_for(self, for_machine, prognames): def program_from_file_for(self, for_machine, prognames):
for p in unholder(prognames): for p in prognames:
if isinstance(p, mesonlib.File): if isinstance(p, mesonlib.File):
continue # Always points to a local (i.e. self generated) file. continue # Always points to a local (i.e. self generated) file.
if not isinstance(p, str): if not isinstance(p, str):
raise InterpreterException('Executable name must be a string') raise InterpreterException('Executable name must be a string')
prog = ExternalProgram.from_bin_list(self.environment, for_machine, p) prog = ExternalProgram.from_bin_list(self.environment, for_machine, p)
if prog.found(): if prog.found():
return ExternalProgramHolder(prog, self.subproject) return prog
return None return None
def program_from_system(self, args, search_dirs, extra_info): 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: if progobj is None:
progobj = self.notfound_program(args) 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')) mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO'))
if required: if required:
m = 'Program {!r} not found' m = 'Program {!r} not found'
@ -1484,7 +1478,7 @@ external dependencies (including libraries) must go to "dependencies".''')
if not_found_message: if not_found_message:
self.message_impl([not_found_message]) self.message_impl([not_found_message])
raise raise
assert isinstance(d, DependencyHolder) assert isinstance(d, Dependency)
if not d.found() and not_found_message: if not d.found() and not_found_message:
self.message_impl([not_found_message]) self.message_impl([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: if 'command' not in kwargs:
raise InterpreterException('Missing "command" keyword argument') raise InterpreterException('Missing "command" keyword argument')
all_args = extract_as_list(kwargs, 'command') all_args = extract_as_list(kwargs, 'command')
deps = unholder(extract_as_list(kwargs, 'depends')) deps = extract_as_list(kwargs, 'depends')
else: else:
raise InterpreterException('Run_target needs at least one positional argument.') raise InterpreterException('Run_target needs at least one positional argument.')
cleaned_args = [] 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)): if not isinstance(i, (str, build.BuildTarget, build.CustomTarget, ExternalProgram, mesonlib.File)):
mlog.debug('Wrong type:', str(i)) mlog.debug('Wrong type:', str(i))
raise InterpreterException('Invalid argument to run_target.') 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.') raise InterpreterException('Depends items must be build targets.')
cleaned_deps.append(d) cleaned_deps.append(d)
env = self.unpack_env_kwarg(kwargs) env = self.unpack_env_kwarg(kwargs)
tg = RunTargetHolder(build.RunTarget(name, cleaned_args, cleaned_deps, self.subdir, self.subproject, env), self) tg = build.RunTarget(name, cleaned_args, cleaned_deps, self.subdir, self.subproject, env)
self.add_target(name, tg.held_object) self.add_target(name, tg)
full_name = (self.subproject, name) full_name = (self.subproject, name)
assert(full_name not in self.build.run_target_names) assert(full_name not in self.build.run_target_names)
self.build.run_target_names.add(full_name) 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] name = args[0]
if not isinstance(name, str): if not isinstance(name, str):
raise InterpreterException('First argument must be a string.') raise InterpreterException('First argument must be a string.')
deps = unholder(listify(args[1:])) deps = listify(args[1:])
for d in deps: for d in deps:
if not isinstance(d, (build.BuildTarget, build.CustomTarget)): if not isinstance(d, (build.BuildTarget, build.CustomTarget)):
raise InterpreterException('Depends items must be build targets.') raise InterpreterException('Depends items must be build targets.')
tg = RunTargetHolder(build.AliasTarget(name, deps, self.subdir, self.subproject), self) tg = build.AliasTarget(name, deps, self.subdir, self.subproject)
self.add_target(name, tg.held_object) self.add_target(name, tg)
return tg return tg
@permittedKwargs({'arguments', 'output', 'depends', 'depfile', 'capture', @permittedKwargs({'arguments', 'output', 'depends', 'depfile', 'capture',
'preserve_path_from'}) 'preserve_path_from'})
@typed_pos_args('generator', (ExecutableHolder, ExternalProgramHolder)) @typed_pos_args('generator', (build.Executable, ExternalProgram))
@typed_kwargs( @typed_kwargs(
'generator', 'generator',
KwargInfo('arguments', ContainerTypeInfo(list, str, allow_empty=False), required=True, listify=True), 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('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('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('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, def func_generator(self, node: mparser.FunctionNode,
args: T.Tuple[T.Union[ExecutableHolder, ExternalProgramHolder]], args: T.Tuple[T.Union[build.Executable, ExternalProgram]],
kwargs: 'kwargs.FuncGenerator') -> GeneratorHolder: kwargs: 'kwargs.FuncGenerator') -> build.Generator:
for rule in kwargs['output']: for rule in kwargs['output']:
if '@BASENAME@' not in rule and '@PLAINNAME@' not in rule: if '@BASENAME@' not in rule and '@PLAINNAME@' not in rule:
raise InvalidArguments('Every element of "output" must contain @BASENAME@ or @PLAINNAME@.') 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: if '@OUTPUT@' in o:
raise InvalidArguments('Tried to use @OUTPUT@ in a rule with more than one output.') 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], **kwargs)
self.generators.append(gen)
gen = build.Generator(args[0].held_object, depends=depends, **kwargs) return gen
holder = GeneratorHolder(gen, self)
self.generators.append(holder)
return holder
@typed_pos_args('benchmark', str, (ExecutableHolder, JarHolder, ExternalProgramHolder, mesonlib.File)) @typed_pos_args('benchmark', str, (ExecutableHolder, JarHolder, ExternalProgramHolder, mesonlib.File))
@typed_kwargs('benchmark', *TEST_KWARGS) @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, return Test(name,
prj, prj,
suite, suite,
exe.held_object, exe,
[d.held_object for d in kwargs['depends']], kwargs['depends'],
kwargs.get('is_parallel', False), kwargs.get('is_parallel', False),
[c.held_object if isinstance(c, ObjectHolder) else c for c in kwargs['args']], kwargs['args'],
env, env,
kwargs['should_fail'], kwargs['should_fail'],
kwargs['timeout'], 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-'): if self.subdir == '' and args[0].startswith('meson-'):
raise InvalidArguments('The "meson-" prefix is reserved and cannot be used for top-level subdir().') 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'): 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.') raise InterpreterException('Object used in if_found does not have a found method.')
if not i.found_method([], {}): if not i.found():
return return
prev_subdir = self.subdir prev_subdir = self.subdir
subdir = os.path.join(prev_subdir, args[0]) 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) os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True)
file_encoding = kwargs.setdefault('encoding', 'utf-8') file_encoding = kwargs.setdefault('encoding', 'utf-8')
missing_variables, confdata_useless = \ 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) fmt, file_encoding)
if missing_variables: if missing_variables:
var_list = ", ".join(map(repr, sorted(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 ' 'copy a file to the build dir, use the \'copy:\' keyword '
'argument added in 0.47.0'.format(ifbase), location=node) 'argument added in 0.47.0'.format(ifbase), location=node)
else: 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() conf.mark_used()
elif 'command' in kwargs: elif 'command' in kwargs:
if len(inputs) > 1: 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: if ":" not in setup_name:
setup_name = (self.subproject if self.subproject else self.build.project_name) + ":" + setup_name setup_name = (self.subproject if self.subproject else self.build.project_name) + ":" + setup_name
try: try:
inp = unholder(extract_as_list(kwargs, 'exe_wrapper')) inp = extract_as_list(kwargs, 'exe_wrapper')
exe_wrapper = [] exe_wrapper = []
for i in inp: for i in inp:
if isinstance(i, str): 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 target.project_version = self.project_version
self.add_stdlib_info(target) self.add_stdlib_info(target)
l = targetholder(target, self) self.add_target(name, target)
self.add_target(name, l.held_object)
self.project_args_frozen = True self.project_args_frozen = True
return l return target
def kwarg_strings_to_includedirs(self, kwargs): def kwarg_strings_to_includedirs(self, kwargs):
if 'd_import_dirs' in kwargs: if 'd_import_dirs' in kwargs:

@ -75,7 +75,6 @@ class MesonMain(MesonInterpreterObject):
script_args = [] # T.List[str] script_args = [] # T.List[str]
new = False new = False
for a in args: for a in args:
a = unholder(a)
if isinstance(a, str): if isinstance(a, str):
script_args.append(a) script_args.append(a)
elif isinstance(a, mesonlib.File): elif isinstance(a, mesonlib.File):
@ -287,7 +286,6 @@ class MesonMain(MesonInterpreterObject):
name, exe = args name, exe = args
if not isinstance(name, str): if not isinstance(name, str):
raise InterpreterException('First argument must be a string') raise InterpreterException('First argument must be a string')
exe = unholder(exe)
if isinstance(exe, mesonlib.File): if isinstance(exe, mesonlib.File):
abspath = exe.absolute_path(self.interpreter.environment.source_dir, abspath = exe.absolute_path(self.interpreter.environment.source_dir,
self.interpreter.environment.build_dir) self.interpreter.environment.build_dir)
@ -307,7 +305,6 @@ class MesonMain(MesonInterpreterObject):
dep = args[1] dep = args[1]
if not isinstance(name, str) or not name: if not isinstance(name, str) or not name:
raise InterpreterException('First argument must be a string and cannot be empty') raise InterpreterException('First argument must be a string and cannot be empty')
dep = unholder(dep)
if not isinstance(dep, dependencies.Dependency): if not isinstance(dep, dependencies.Dependency):
raise InterpreterException('Second argument must be a dependency object') raise InterpreterException('Second argument must be a dependency object')
identifier = dependencies.get_dep_identifier(name, kwargs) identifier = dependencies.get_dep_identifier(name, kwargs)

@ -46,6 +46,7 @@ __all__ = [
'ContainerTypeInfo', 'ContainerTypeInfo',
'KwargInfo', 'KwargInfo',
'typed_kwargs', 'typed_kwargs',
'FeatureCheckBase',
'FeatureNew', 'FeatureNew',
'FeatureDeprecated', 'FeatureDeprecated',
'FeatureNewKwargs', 'FeatureNewKwargs',
@ -60,6 +61,7 @@ __all__ = [
'TYPE_elementary', 'TYPE_elementary',
'TYPE_var', 'TYPE_var',
'TYPE_nvar', 'TYPE_nvar',
'TYPE_kwargs',
'TYPE_nkwargs', 'TYPE_nkwargs',
'TYPE_key_resolver', 'TYPE_key_resolver',
] ]
@ -78,6 +80,7 @@ from .baseobjects import (
TYPE_elementary, TYPE_elementary,
TYPE_var, TYPE_var,
TYPE_nvar, TYPE_nvar,
TYPE_kwargs,
TYPE_nkwargs, TYPE_nkwargs,
TYPE_key_resolver, TYPE_key_resolver,
) )
@ -95,6 +98,7 @@ from .decorators import (
ContainerTypeInfo, ContainerTypeInfo,
KwargInfo, KwargInfo,
typed_kwargs, typed_kwargs,
FeatureCheckBase,
FeatureNew, FeatureNew,
FeatureDeprecated, FeatureDeprecated,
FeatureNewKwargs, FeatureNewKwargs,

@ -131,7 +131,6 @@ __all__ = [
'substitute_values', 'substitute_values',
'substring_is_in_list', 'substring_is_in_list',
'typeslistify', 'typeslistify',
'unholder',
'verbose_git', 'verbose_git',
'version_compare', 'version_compare',
'version_compare_condition_with_min', 'version_compare_condition_with_min',
@ -1246,26 +1245,6 @@ def replace_if_different(dst: str, dst_tmp: str) -> None:
os.unlink(dst_tmp) 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]: def listify(item: T.Any, flatten: bool = True) -> T.List[T.Any]:
''' '''

@ -18,13 +18,12 @@
import os import os
from .. import build from .. import build
from ..mesonlib import unholder, relpath from ..mesonlib import relpath, HoldableObject
import typing as T import typing as T
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
from ..interpreter import Interpreter from ..interpreter import Interpreter
from ..interpreter.interpreterobjects import IncludeDirsHolder, ExternalProgramHolder from ..interpreterbase import TYPE_var, TYPE_kwargs
from ..interpreterbase import TYPE_var, TYPE_nvar, TYPE_nkwargs
from ..programs import ExternalProgram from ..programs import ExternalProgram
class ModuleState: class ModuleState:
@ -61,7 +60,7 @@ class ModuleState:
self.target_machine = interpreter.builtin['target_machine'].held_object self.target_machine = interpreter.builtin['target_machine'].held_object
self.current_node = interpreter.current_node 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: if not include_dirs:
return [] return []
@ -69,7 +68,7 @@ class ModuleState:
builddir = self.environment.get_build_dir() builddir = self.environment.get_build_dir()
dirs_str: T.List[str] = [] dirs_str: T.List[str] = []
for dirs in unholder(include_dirs): for dirs in include_dirs:
if isinstance(dirs, str): if isinstance(dirs, str):
dirs_str += [f'{prefix}{dirs}'] dirs_str += [f'{prefix}{dirs}']
continue continue
@ -89,14 +88,17 @@ class ModuleState:
def find_program(self, prog: T.Union[str, T.List[str]], required: bool = True, def find_program(self, prog: T.Union[str, T.List[str]], required: bool = True,
version_func: T.Optional[T.Callable[['ExternalProgram'], str]] = None, 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) 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 """Base class for all objects returned by modules
""" """
def __init__(self) -> None: 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): class MutableModuleObject(ModuleObject):
pass pass

@ -18,9 +18,9 @@ import typing as T
from . import ExtensionModule, ModuleReturnValue, ModuleObject 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 ..cmake import SingleTargetOptions, TargetOptions, cmake_defines_to_args
from ..interpreter import ConfigurationDataHolder, SubprojectHolder, DependencyHolder from ..interpreter import ConfigurationDataObject, SubprojectHolder
from ..interpreterbase import ( from ..interpreterbase import (
FeatureNew, FeatureNew,
FeatureNewKwargs, FeatureNewKwargs,
@ -32,6 +32,7 @@ from ..interpreterbase import (
noKwargs, noKwargs,
InvalidArguments, InvalidArguments,
InterpreterException,
) )
from ..programs import ExternalProgram from ..programs import ExternalProgram
@ -109,11 +110,11 @@ class CMakeSubproject(ModuleObject):
def dependency(self, state, args, kwargs): def dependency(self, state, args, kwargs):
info = self._args_to_info(args) info = self._args_to_info(args)
orig = self.get_variable(state, [info['dep']], {}) orig = self.get_variable(state, [info['dep']], {})
assert isinstance(orig, DependencyHolder) assert isinstance(orig, dependencies.Dependency)
actual = orig.include_type_method([], {}) actual = orig.include_type
if 'include_type' in kwargs and kwargs['include_type'] != actual: if 'include_type' in kwargs and kwargs['include_type'] != actual:
mlog.debug('Current include type is {}. Converting to requested {}'.format(actual, kwargs['include_type'])) 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 return orig
@noKwargs @noKwargs
@ -351,7 +352,7 @@ class CmakeModule(ExtensionModule):
if 'configuration' not in kwargs: if 'configuration' not in kwargs:
raise mesonlib.MesonException('"configuration" not specified.') raise mesonlib.MesonException('"configuration" not specified.')
conf = kwargs['configuration'] conf = kwargs['configuration']
if not isinstance(conf, ConfigurationDataHolder): if not isinstance(conf, ConfigurationDataObject):
raise mesonlib.MesonException('Argument "configuration" is not of type configuration_data') raise mesonlib.MesonException('Argument "configuration" is not of type configuration_data')
prefix = state.environment.coredata.get_option(mesonlib.OptionKey('prefix')) 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 = PACKAGE_INIT_EXT.replace('@absInstallDir@', abs_install_dir)
extra = extra.replace('@installPrefix@', prefix) 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() conf.mark_used()
conffile = os.path.normpath(inputfile.relative_name()) conffile = os.path.normpath(inputfile.relative_name())
@ -389,7 +390,7 @@ class CmakeModule(ExtensionModule):
raise InterpreterException('"options" cannot be used together with "cmake_options"') raise InterpreterException('"options" cannot be used together with "cmake_options"')
dirname = args[0] dirname = args[0]
subp = self.interpreter.do_subproject(dirname, 'cmake', kwargs) subp = self.interpreter.do_subproject(dirname, 'cmake', kwargs)
if not subp.held_object: if not subp.found():
return subp return subp
return CMakeSubproject(subp, dirname) return CMakeSubproject(subp, dirname)

@ -30,7 +30,7 @@ from . import ExtensionModule
from . import ModuleReturnValue from . import ModuleReturnValue
from ..mesonlib import ( from ..mesonlib import (
MachineChoice, MesonException, OrderedSet, Popen_safe, extract_as_list, MachineChoice, MesonException, OrderedSet, Popen_safe, extract_as_list,
join_args, unholder, join_args, HoldableObject
) )
from ..dependencies import Dependency, PkgConfigDependency, InternalDependency from ..dependencies import Dependency, PkgConfigDependency, InternalDependency
from ..interpreterbase import noPosargs, noKwargs, permittedKwargs, FeatureNew, FeatureNewKwargs, FeatureDeprecatedKwargs from ..interpreterbase import noPosargs, noKwargs, permittedKwargs, FeatureNew, FeatureNewKwargs, FeatureDeprecatedKwargs
@ -39,6 +39,7 @@ from ..build import CustomTarget, CustomTargetIndex, GeneratedList
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
from ..compilers import Compiler from ..compilers import Compiler
from ..interpreter import Interpreter
# gresource compilation is broken due to the way # gresource compilation is broken due to the way
# the resource compiler and Ninja clash about it # 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): def _get_dep(self, state, depname, native=False, required=True):
kwargs = {'native': native, 'required': required} kwargs = {'native': native, 'required': required}
holder = self.interpreter.func_dependency(state.current_node, [depname], kwargs) return self.interpreter.func_dependency(state.current_node, [depname], kwargs)
return holder.held_object
def _get_native_binary(self, state, name, depname, varname, required=True): def _get_native_binary(self, state, name, depname, varname, required=True):
# Look in overrides in case glib/gtk/etc are built as subproject # Look in overrides in case glib/gtk/etc are built as subproject
prog = self.interpreter.program_from_overrides([name], []) prog = self.interpreter.program_from_overrides([name], [])
if prog is not None: if prog is not None:
return unholder(prog) return prog
# Look in machine file # Look in machine file
prog = state.environment.lookup_binary_entry(MachineChoice.HOST, name) prog = state.environment.lookup_binary_entry(MachineChoice.HOST, name)
@ -125,7 +125,7 @@ class GnomeModule(ExtensionModule):
return ExternalProgram(name, value) return ExternalProgram(name, value)
# Normal program lookup # 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'}) @permittedKwargs({'glib_compile_schemas', 'gio_querymodules', 'gtk_update_icon_cache'})
@noPosargs @noPosargs
@ -179,7 +179,7 @@ class GnomeModule(ExtensionModule):
# Validate dependencies # Validate dependencies
subdirs = [] subdirs = []
depends = [] depends = []
for (ii, dep) in enumerate(unholder(dependencies)): for (ii, dep) in enumerate(dependencies):
if isinstance(dep, mesonlib.File): if isinstance(dep, mesonlib.File):
subdirs.append(dep.subdir) subdirs.append(dep.subdir)
elif isinstance(dep, (build.CustomTarget, build.CustomTargetIndex)): elif isinstance(dep, (build.CustomTarget, build.CustomTargetIndex)):
@ -323,7 +323,7 @@ class GnomeModule(ExtensionModule):
subdirs = [] subdirs = []
for resfile in dep_files[:]: for resfile in dep_files[:]:
resbasename = os.path.basename(resfile) resbasename = os.path.basename(resfile)
for dep in unholder(dependencies): for dep in dependencies:
if isinstance(dep, mesonlib.File): if isinstance(dep, mesonlib.File):
if dep.fname != resbasename: if dep.fname != resbasename:
continue continue
@ -399,7 +399,7 @@ class GnomeModule(ExtensionModule):
# require two args in order, such as -framework AVFoundation # require two args in order, such as -framework AVFoundation
external_ldflags_nodedup = [] external_ldflags_nodedup = []
gi_includes = OrderedSet() gi_includes = OrderedSet()
deps = mesonlib.unholder(mesonlib.listify(deps)) deps = mesonlib.listify(deps)
for dep in deps: for dep in deps:
if isinstance(dep, Dependency): if isinstance(dep, Dependency):
@ -409,7 +409,7 @@ class GnomeModule(ExtensionModule):
if isinstance(dep, InternalDependency): if isinstance(dep, InternalDependency):
cflags.update(dep.get_compile_args()) cflags.update(dep.get_compile_args())
cflags.update(state.get_include_args(dep.include_directories)) 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): if isinstance(lib, build.SharedLibrary):
internal_ldflags.update(self._get_link_args(state, lib, depends, include_rpath)) 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, 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.update(extdepflags[2])
external_ldflags_nodedup += extdepflags[3] external_ldflags_nodedup += extdepflags[3]
gi_includes.update(extdepflags[4]) gi_includes.update(extdepflags[4])
for source in unholder(dep.sources): for source in dep.sources:
if isinstance(source, GirTarget): if isinstance(source, GirTarget):
gi_includes.update([os.path.join(state.environment.get_build_dir(), gi_includes.update([os.path.join(state.environment.get_build_dir(),
source.get_subdir())]) source.get_subdir())])
@ -480,9 +480,6 @@ class GnomeModule(ExtensionModule):
return cflags, internal_ldflags, external_ldflags, external_ldflags_nodedup, gi_includes return cflags, internal_ldflags, external_ldflags, external_ldflags_nodedup, gi_includes
def _unwrap_gir_target(self, girtarget, state): def _unwrap_gir_target(self, girtarget, state):
while hasattr(girtarget, 'held_object'):
girtarget = girtarget.held_object
if not isinstance(girtarget, (build.Executable, build.SharedLibrary, if not isinstance(girtarget, (build.Executable, build.SharedLibrary,
build.StaticLibrary)): build.StaticLibrary)):
raise MesonException('Gir target must be an executable or library') raise MesonException('Gir target must be an executable or library')
@ -512,8 +509,6 @@ class GnomeModule(ExtensionModule):
@functools.lru_cache(maxsize=None) @functools.lru_cache(maxsize=None)
def _gir_has_option(self, option) -> bool: def _gir_has_option(self, option) -> bool:
exe = self.giscanner exe = self.giscanner
if hasattr(exe, 'held_object'):
exe = exe.held_object
if isinstance(exe, OverrideProgram): if isinstance(exe, OverrideProgram):
# Handle overridden g-ir-scanner # Handle overridden g-ir-scanner
assert option in ['--extra-library', '--sources-top-dirs'] 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) link_with = mesonlib.extract_as_list(kwargs, 'link_with', pop = True)
for link in link_with: 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) use_gir_args=True)
return ret return ret
@ -549,7 +544,7 @@ class GnomeModule(ExtensionModule):
if 'includes' in kwargs: if 'includes' in kwargs:
includes = mesonlib.extract_as_list(kwargs, 'includes', pop = True) includes = mesonlib.extract_as_list(kwargs, 'includes', pop = True)
for inc in unholder(includes): for inc in includes:
if isinstance(inc, str): if isinstance(inc, str):
ret += [f'--include={inc}'] ret += [f'--include={inc}']
elif isinstance(inc, GirTarget): elif isinstance(inc, GirTarget):
@ -605,7 +600,7 @@ class GnomeModule(ExtensionModule):
def _scan_inc_dirs(self, kwargs): def _scan_inc_dirs(self, kwargs):
ret = mesonlib.extract_as_list(kwargs, 'include_directories', pop = True) ret = mesonlib.extract_as_list(kwargs, 'include_directories', pop = True)
for incd in ret: for incd in ret:
if not isinstance(incd.held_object, (str, build.IncludeDirs)): if not isinstance(incd, (str, build.IncludeDirs)):
raise MesonException( raise MesonException(
'Gir include dirs should be include_directories().') 'Gir include dirs should be include_directories().')
return ret return ret
@ -708,7 +703,7 @@ class GnomeModule(ExtensionModule):
gir_filelist_filename = os.path.join(gir_filelist_dir, f'{ns}_{nsversion}_gir_filelist') 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: 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)): if isinstance(s, (build.CustomTarget, build.CustomTargetIndex)):
for custom_output in s.get_outputs(): for custom_output in s.get_outputs():
gir_filelist.write(os.path.join(state.environment.get_build_dir(), 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 # dependencies and also find the include directories needed for the
# typelib generation custom target below. # typelib generation custom target below.
typelib_includes = [] typelib_includes = []
for dep in unholder(deps): for dep in deps:
# Add a dependency on each GirTarget listed in dependencies and add # Add a dependency on each GirTarget listed in dependencies and add
# the directory where it will be generated to the typelib includes # the directory where it will be generated to the typelib includes
if isinstance(dep, InternalDependency): if isinstance(dep, InternalDependency):
for source in unholder(dep.sources): for source in dep.sources:
if isinstance(source, GirTarget) and source not in depends: if isinstance(source, GirTarget) and source not in depends:
depends.append(source) depends.append(source)
subdir = os.path.join(state.environment.get_build_dir(), subdir = os.path.join(state.environment.get_build_dir(),
@ -846,7 +841,7 @@ class GnomeModule(ExtensionModule):
langs_compilers = self._get_girtargets_langs_compilers(girtargets) langs_compilers = self._get_girtargets_langs_compilers(girtargets)
cflags, internal_ldflags, external_ldflags = self._get_langs_compilers_flags(state, langs_compilers) cflags, internal_ldflags, external_ldflags = self._get_langs_compilers_flags(state, langs_compilers)
deps = self._get_gir_targets_deps(girtargets) 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] deps += [gir_dep]
typelib_includes = self._gather_typelib_includes_and_update_depends(state, deps, depends) typelib_includes = self._gather_typelib_includes_and_update_depends(state, deps, depends)
# ldflags will be misinterpreted by gir scanner (showing # ldflags will be misinterpreted by gir scanner (showing
@ -898,7 +893,7 @@ class GnomeModule(ExtensionModule):
if fatal_warnings: if fatal_warnings:
scan_command.append('--warn-error') 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) 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') src_dirs = mesonlib.extract_as_list(kwargs, 'src_dir')
header_dirs = [] header_dirs = []
for src_dir in src_dirs: for src_dir in src_dirs:
if hasattr(src_dir, 'held_object'): if isinstance(src_dir, HoldableObject):
src_dir = src_dir.held_object
if not isinstance(src_dir, build.IncludeDirs): if not isinstance(src_dir, build.IncludeDirs):
raise MesonException('Invalid keyword argument for src_dir.') raise MesonException('Invalid keyword argument for src_dir.')
for inc_dir in src_dir.get_incdirs(): for inc_dir in src_dir.get_incdirs():
@ -1068,7 +1062,7 @@ class GnomeModule(ExtensionModule):
for tool in ['scan', 'scangobj', 'mkdb', 'mkhtml', 'fixxref']: for tool in ['scan', 'scangobj', 'mkdb', 'mkhtml', 'fixxref']:
program_name = 'gtkdoc-' + tool program_name = 'gtkdoc-' + tool
program = state.find_program(program_name) program = state.find_program(program_name)
path = program.held_object.get_path() path = program.get_path()
args.append(f'--{program_name}={path}') args.append(f'--{program_name}={path}')
if namespace: if namespace:
args.append('--namespace=' + namespace) args.append('--namespace=' + namespace)
@ -1082,7 +1076,7 @@ class GnomeModule(ExtensionModule):
depends = [] depends = []
content_files = [] 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)): if isinstance(s, (build.CustomTarget, build.CustomTargetIndex)):
depends.append(s) depends.append(s)
for o in s.get_outputs(): for o in s.get_outputs():
@ -1134,14 +1128,14 @@ class GnomeModule(ExtensionModule):
def _get_build_args(self, kwargs, state, depends): def _get_build_args(self, kwargs, state, depends):
args = [] args = []
deps = mesonlib.unholder(extract_as_list(kwargs, 'dependencies')) deps = extract_as_list(kwargs, 'dependencies')
cflags = [] cflags = []
cflags.extend(mesonlib.stringlistify(kwargs.pop('c_args', []))) cflags.extend(mesonlib.stringlistify(kwargs.pop('c_args', [])))
deps_cflags, internal_ldflags, external_ldflags, gi_includes = \ deps_cflags, internal_ldflags, external_ldflags, gi_includes = \
self._get_dependencies_flags(deps, state, depends, include_rpath=True) self._get_dependencies_flags(deps, state, depends, include_rpath=True)
inc_dirs = mesonlib.extract_as_list(kwargs, 'include_directories') inc_dirs = mesonlib.extract_as_list(kwargs, 'include_directories')
for incd in inc_dirs: for incd in inc_dirs:
if not isinstance(incd.held_object, (str, build.IncludeDirs)): if not isinstance(incd, (str, build.IncludeDirs)):
raise MesonException( raise MesonException(
'Gir include dirs should be include_directories().') 'Gir include dirs should be include_directories().')
@ -1678,7 +1672,7 @@ G_END_DECLS'''
vapi_includes = [] vapi_includes = []
ret = [] ret = []
remaining_args = [] remaining_args = []
for arg in unholder(arg_list): for arg in arg_list:
if isinstance(arg, InternalDependency): if isinstance(arg, InternalDependency):
targets = [t for t in arg.sources if isinstance(t, VapiTarget)] targets = [t for t in arg.sources if isinstance(t, VapiTarget)]
for target in targets: for target in targets:
@ -1752,11 +1746,11 @@ G_END_DECLS'''
for i in inputs: for i in inputs:
if isinstance(i, str): if isinstance(i, str):
cmd.append(os.path.join(source_dir, i)) cmd.append(os.path.join(source_dir, i))
elif hasattr(i, 'held_object') and isinstance(i.held_object, GirTarget): elif isinstance(i, GirTarget):
link_with += self._get_vapi_link_with(i.held_object) link_with += self._get_vapi_link_with(i)
subdir = os.path.join(state.environment.get_build_dir(), subdir = os.path.join(state.environment.get_build_dir(),
i.held_object.get_subdir()) i.get_subdir())
gir_file = os.path.join(subdir, i.held_object.get_outputs()[0]) gir_file = os.path.join(subdir, i.get_outputs()[0])
cmd.append(gir_file) cmd.append(gir_file)
else: else:
raise MesonException('Input must be a str or GirTarget') raise MesonException('Input must be a str or GirTarget')
@ -1791,4 +1785,10 @@ G_END_DECLS'''
return ModuleReturnValue(rv, created_values) return ModuleReturnValue(rv, created_values)
def initialize(*args, **kwargs): 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

@ -105,7 +105,6 @@ class HotdocTargetBuilder:
self.cmd.extend([option, value]) self.cmd.extend([option, value])
def check_extra_arg_type(self, arg, value): def check_extra_arg_type(self, arg, value):
value = getattr(value, 'held_object', value)
if isinstance(value, list): if isinstance(value, list):
for v in value: for v in value:
self.check_extra_arg_type(arg, v) self.check_extra_arg_type(arg, v)
@ -188,7 +187,6 @@ class HotdocTargetBuilder:
def process_dependencies(self, deps): def process_dependencies(self, deps):
cflags = set() cflags = set()
for dep in mesonlib.listify(ensure_list(deps)): for dep in mesonlib.listify(ensure_list(deps)):
dep = getattr(dep, "held_object", dep)
if isinstance(dep, InternalDependency): if isinstance(dep, InternalDependency):
inc_args = self.state.get_include_args(dep.include_directories) inc_args = self.state.get_include_args(dep.include_directories)
cflags.update([self.replace_dirs_in_string(x) cflags.update([self.replace_dirs_in_string(x)
@ -232,7 +230,6 @@ class HotdocTargetBuilder:
def flatten_config_command(self): def flatten_config_command(self):
cmd = [] cmd = []
for arg in mesonlib.listify(self.cmd, flatten=True): for arg in mesonlib.listify(self.cmd, flatten=True):
arg = getattr(arg, 'held_object', arg)
if isinstance(arg, mesonlib.File): if isinstance(arg, mesonlib.File):
arg = arg.absolute_path(self.state.environment.get_source_dir(), arg = arg.absolute_path(self.state.environment.get_source_dir(),
self.state.environment.get_build_dir()) self.state.environment.get_build_dir())
@ -371,7 +368,7 @@ class HotdocTargetHolder(CustomTargetHolder):
def config_path_method(self, *args, **kwargs): def config_path_method(self, *args, **kwargs):
conf = self.held_object.hotdoc_conf.absolute_path(self.interpreter.environment.source_dir, conf = self.held_object.hotdoc_conf.absolute_path(self.interpreter.environment.source_dir,
self.interpreter.environment.build_dir) self.interpreter.environment.build_dir)
return self.interpreter.holderify(conf) return conf
class HotdocTarget(build.CustomTarget): class HotdocTarget(build.CustomTarget):
@ -422,7 +419,7 @@ class HotDocModule(ExtensionModule):
project_name = args[0] project_name = args[0]
builder = HotdocTargetBuilder(project_name, state, self.hotdoc, self.interpreter, kwargs) builder = HotdocTargetBuilder(project_name, state, self.hotdoc, self.interpreter, kwargs)
target, install_script = builder.make_targets() target, install_script = builder.make_targets()
targets = [HotdocTargetHolder(target, self.interpreter)] targets = [target]
if install_script: if install_script:
targets.append(install_script) targets.append(install_script)
@ -430,4 +427,6 @@ class HotDocModule(ExtensionModule):
def initialize(interpreter): def initialize(interpreter):
return HotDocModule(interpreter) mod = HotDocModule(interpreter)
mod.interpreter.append_holder_map(HotdocTarget, HotdocTargetHolder)
return mod

@ -108,7 +108,8 @@ class I18nModule(ExtensionModule):
kwargs['command'] = command kwargs['command'] = command
inputfile = kwargs['input'] 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) ct = build.CustomTarget(kwargs['output'] + '_merge', state.subdir, state.subproject, kwargs)
else: else:
if isinstance(inputfile, list): if isinstance(inputfile, list):

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import os, types import os
from pathlib import PurePath from pathlib import PurePath
from .. import build from .. import build
@ -22,7 +22,9 @@ from .. import mesonlib
from .. import mlog from .. import mlog
from . import ModuleReturnValue from . import ModuleReturnValue
from . import ExtensionModule 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() already_warned_objs = set()
@ -75,7 +77,7 @@ class DependenciesHelper:
def _process_reqs(self, reqs): def _process_reqs(self, reqs):
'''Returns string names of requirements''' '''Returns string names of requirements'''
processed_reqs = [] processed_reqs = []
for obj in mesonlib.unholder(mesonlib.listify(reqs)): for obj in mesonlib.listify(reqs):
if not isinstance(obj, str): if not isinstance(obj, str):
FeatureNew.single_use('pkgconfig.generate requirement from non-string object', '0.46.0', self.state.subproject) FeatureNew.single_use('pkgconfig.generate requirement from non-string object', '0.46.0', self.state.subproject)
if hasattr(obj, 'generated_pc'): if hasattr(obj, 'generated_pc'):
@ -108,14 +110,13 @@ class DependenciesHelper:
def add_cflags(self, cflags): def add_cflags(self, cflags):
self.cflags += mesonlib.stringlistify(cflags) self.cflags += mesonlib.stringlistify(cflags)
def _process_libs(self, libs, public): def _process_libs(self, libs, public: bool):
libs = mesonlib.unholder(mesonlib.listify(libs)) libs = mesonlib.listify(libs)
libs = [x.get_preferred_library() if isinstance(x, build.BothLibraries) else x for x in libs] libs = [x.get_preferred_library() if isinstance(x, build.BothLibraries) else x for x in libs]
processed_libs = [] processed_libs = []
processed_reqs = [] processed_reqs = []
processed_cflags = [] processed_cflags = []
for obj in libs: for obj in libs:
shared_library_only = getattr(obj, 'shared_library_only', False)
if hasattr(obj, 'pcdep'): if hasattr(obj, 'pcdep'):
pcdeps = mesonlib.listify(obj.pcdep) pcdeps = mesonlib.listify(obj.pcdep)
for d in pcdeps: for d in pcdeps:
@ -488,7 +489,7 @@ class PkgConfigModule(ExtensionModule):
FeatureNew.single_use('pkgconfig.generate implicit version keyword', '0.46.0', state.subproject) FeatureNew.single_use('pkgconfig.generate implicit version keyword', '0.46.0', state.subproject)
elif len(args) == 1: elif len(args) == 1:
FeatureNew.single_use('pkgconfig.generate optional positional argument', '0.46.0', state.subproject) 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)): if not isinstance(mainlib, (build.StaticLibrary, build.SharedLibrary)):
raise mesonlib.MesonException('Pkgconfig_gen first positional argument must be a library object') raise mesonlib.MesonException('Pkgconfig_gen first positional argument must be a library object')
default_name = mainlib.name default_name = mainlib.name

@ -101,7 +101,6 @@ class SourceSet(MutableModuleObject):
if_true = args if_true = args
elif args: elif args:
raise InterpreterException('add_all called with both positional and keyword arguments') raise InterpreterException('add_all called with both positional and keyword arguments')
if_true = mesonlib.unholder(if_true)
keys, dependencies = self.check_conditions(when) keys, dependencies = self.check_conditions(when)
for s in if_true: for s in if_true:
if not isinstance(s, SourceSet): if not isinstance(s, SourceSet):

@ -16,8 +16,7 @@ import typing as T
import re import re
from ..mesonlib import version_compare from ..mesonlib import version_compare
from ..interpreter import CompilerHolder from ..compilers import CudaCompiler, Compiler
from ..compilers import CudaCompiler
from . import ModuleObject from . import ModuleObject
@ -83,7 +82,7 @@ class CudaModule(ModuleObject):
@permittedKwargs(['detected']) @permittedKwargs(['detected'])
def nvcc_arch_flags(self, state: 'ModuleState', 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]: kwargs: T.Dict[str, T.Any]) -> T.List[str]:
nvcc_arch_args = self._validate_nvcc_arch_args(args, kwargs) nvcc_arch_args = self._validate_nvcc_arch_args(args, kwargs)
ret = self._nvcc_arch_flags(*nvcc_arch_args)[0] ret = self._nvcc_arch_flags(*nvcc_arch_args)[0]
@ -91,7 +90,7 @@ class CudaModule(ModuleObject):
@permittedKwargs(['detected']) @permittedKwargs(['detected'])
def nvcc_arch_readable(self, state: 'ModuleState', 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]: kwargs: T.Dict[str, T.Any]) -> T.List[str]:
nvcc_arch_args = self._validate_nvcc_arch_args(args, kwargs) nvcc_arch_args = self._validate_nvcc_arch_args(args, kwargs)
ret = self._nvcc_arch_flags(*nvcc_arch_args)[1] ret = self._nvcc_arch_flags(*nvcc_arch_args)[1]
@ -105,16 +104,12 @@ class CudaModule(ModuleObject):
@staticmethod @staticmethod
def _detected_cc_from_compiler(c): def _detected_cc_from_compiler(c):
if isinstance(c, CompilerHolder):
c = c.compiler
if isinstance(c, CudaCompiler): if isinstance(c, CudaCompiler):
return c.detected_cc return c.detected_cc
return '' return ''
@staticmethod @staticmethod
def _version_from_compiler(c): def _version_from_compiler(c):
if isinstance(c, CompilerHolder):
c = c.compiler
if isinstance(c, CudaCompiler): if isinstance(c, CudaCompiler):
return c.version return c.version
if isinstance(c, str): if isinstance(c, str):

@ -109,7 +109,7 @@ class RustModule(ExtensionModule):
``` ```
""" """
name = args[0] name = args[0]
base_target: BuildTarget = unholder(args[1]) base_target: BuildTarget = args[1]
if not base_target.uses_rust(): if not base_target.uses_rust():
raise InterpreterException('Second positional argument to rustmod.test() must be a rust based target') raise InterpreterException('Second positional argument to rustmod.test() must be a rust based target')
extra_args = kwargs['args'] extra_args = kwargs['args']
@ -129,7 +129,7 @@ class RustModule(ExtensionModule):
del extra_args[i] del extra_args[i]
break 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. # 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()) tkwargs = T.cast('_kwargs.FuncTest', kwargs.copy())
@ -168,7 +168,7 @@ class RustModule(ExtensionModule):
header: 'SourceOutputs' header: 'SourceOutputs'
_deps: T.Sequence['SourceOutputs'] _deps: T.Sequence['SourceOutputs']
try: 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: except KeyError:
raise InvalidArguments('rustmod.bindgen() `input` argument must have at least one element.') raise InvalidArguments('rustmod.bindgen() `input` argument must have at least one element.')
@ -179,7 +179,7 @@ class RustModule(ExtensionModule):
if not isinstance(output, str): if not isinstance(output, str):
raise InvalidArguments('rustmod.bindgen() `output` argument must be a string.') 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', []))) c_args: T.List[str] = stringlistify(listify(kwargs.get('c_args', [])))
bind_args: T.List[str] = stringlistify(listify(kwargs.get('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())]) inc_strs.extend([f'-I{x}' for x in i.to_string_list(state.environment.get_source_dir())])
if self._bindgen_bin is None: if self._bindgen_bin is None:
# there's some bugs in the interpreter typeing. self._bindgen_bin = state.find_program('bindgen')
self._bindgen_bin = state.find_program('bindgen').held_object
name: str name: str
if isinstance(header, File): if isinstance(header, File):

@ -54,11 +54,11 @@ class SimdModule(ExtensionModule):
for key, value in kwargs.items(): for key, value in kwargs.items():
if key not in self.isets and key != 'compiler': if key not in self.isets and key != 'compiler':
basic_kwargs[key] = value basic_kwargs[key] = value
compiler = kwargs['compiler'].compiler compiler = kwargs['compiler']
if not isinstance(compiler, compilers.compilers.Compiler): if not isinstance(compiler, compilers.compilers.Compiler):
raise mesonlib.MesonException('Compiler argument must be a compiler object.') raise mesonlib.MesonException('Compiler argument must be a compiler object.')
cdata = self.interpreter.func_configuration_data(None, [], {}) cdata = self.interpreter.func_configuration_data(None, [], {})
conf = cdata.held_object conf = cdata.conf_data
for iset in self.isets: for iset in self.isets:
if iset not in kwargs: if iset not in kwargs:
continue continue

@ -18,10 +18,9 @@ import re
from .. import mlog from .. import mlog
from .. import mesonlib, build 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 ModuleReturnValue
from . import ExtensionModule from . import ExtensionModule
from ..interpreter import CustomTargetHolder
from ..interpreterbase import permittedKwargs, FeatureNewKwargs, flatten from ..interpreterbase import permittedKwargs, FeatureNewKwargs, flatten
from ..programs import ExternalProgram from ..programs import ExternalProgram
@ -86,11 +85,13 @@ class WindowsModule(ExtensionModule):
wrc_depend_files = extract_as_list(kwargs, 'depend_files', pop = True) wrc_depend_files = extract_as_list(kwargs, 'depend_files', pop = True)
wrc_depends = extract_as_list(kwargs, 'depends', pop = True) wrc_depends = extract_as_list(kwargs, 'depends', pop = True)
for d in wrc_depends: for d in wrc_depends:
if isinstance(d, CustomTargetHolder): if isinstance(d, build.CustomTarget):
extra_args += state.get_include_args([d.outdir_include()]) 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) inc_dirs = extract_as_list(kwargs, 'include_directories', pop = True)
for incd in inc_dirs: 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().') raise MesonException('Resource include dirs should be include_directories().')
extra_args += state.get_include_args(inc_dirs) extra_args += state.get_include_args(inc_dirs)
@ -120,7 +121,6 @@ class WindowsModule(ExtensionModule):
for subsrc in src: for subsrc in src:
add_target(subsrc) add_target(subsrc)
return return
src = unholder(src)
if isinstance(src, str): if isinstance(src, str):
name_formatted = src name_formatted = src

@ -741,17 +741,6 @@ class InternalTests(unittest.TestCase):
self.assertEqual([holder1, 2], listify([holder1, 2])) self.assertEqual([holder1, 2], listify([holder1, 2]))
self.assertEqual([holder1, 2, 3], listify([holder1, 2, [3]])) 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): def test_extract_as_list(self):
extract = mesonbuild.mesonlib.extract_as_list extract = mesonbuild.mesonlib.extract_as_list
# Test sanity # Test sanity

Loading…
Cancel
Save