aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Mensinger <daniel@mensinger-ka.de>2021-06-17 00:27:39 +0200
committerDaniel Mensinger <daniel@mensinger-ka.de>2021-06-18 23:48:33 +0200
commit7c757dff71c031ae02ecc358a69a213a5db4051a (patch)
tree5e7892f0eaa302749440f53b859ff281a2d2584e
parent34c28dc92cb4f28e32e633297e4b8a737228aae5 (diff)
downloadmeson-7c757dff71c031ae02ecc358a69a213a5db4051a.zip
meson-7c757dff71c031ae02ecc358a69a213a5db4051a.tar.gz
meson-7c757dff71c031ae02ecc358a69a213a5db4051a.tar.bz2
holders: Fix the remaining code to respect the holder changes
-rw-r--r--mesonbuild/ast/interpreter.py9
-rw-r--r--mesonbuild/build.py2
-rw-r--r--mesonbuild/interpreter/compiler.py28
-rw-r--r--mesonbuild/interpreter/interpreter.py193
-rw-r--r--mesonbuild/interpreter/interpreterobjects.py548
-rw-r--r--mesonbuild/interpreter/kwargs.py30
-rw-r--r--mesonbuild/interpreter/mesonmain.py23
-rw-r--r--mesonbuild/modules/python.py54
-rw-r--r--mesonbuild/modules/qt.py73
-rw-r--r--mesonbuild/modules/sourceset.py9
-rw-r--r--mesonbuild/modules/unstable_external_project.py3
-rw-r--r--mesonbuild/modules/unstable_rust.py29
-rwxr-xr-xrun_mypy.py3
-rw-r--r--test cases/common/178 bothlibraries/meson.build3
-rw-r--r--test cases/native/9 override with exe/meson.build2
15 files changed, 510 insertions, 499 deletions
diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py
index 26447ce..b9dfc7b 100644
--- a/mesonbuild/ast/interpreter.py
+++ b/mesonbuild/ast/interpreter.py
@@ -76,6 +76,9 @@ class MockRunTarget(MesonInterpreterObject):
ADD_SOURCE = 0
REMOVE_SOURCE = 1
+_T = T.TypeVar('_T')
+_V = T.TypeVar('_V')
+
class AstInterpreter(InterpreterBase):
def __init__(self, source_root: str, subdir: str, subproject: str, visitors: T.Optional[T.List[AstVisitor]] = None):
super().__init__(source_root, subdir, subproject)
@@ -141,6 +144,12 @@ class AstInterpreter(InterpreterBase):
'range': self.func_do_nothing,
})
+ def _unholder_args(self, args: _T, kwargs: _V) -> T.Tuple[_T, _V]:
+ return args, kwargs
+
+ def _holderify(self, res: _T) -> _T:
+ return res
+
def func_do_nothing(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> bool:
return True
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 47ac954..414a4f8 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -40,7 +40,7 @@ from .compilers import (
is_known_suffix
)
from .linkers import StaticLinker
-from .interpreterbase import FeatureNew, TYPE_nkwargs, TYPE_nvar
+from .interpreterbase import FeatureNew
if T.TYPE_CHECKING:
from ._typing import ImmutableListProtocol, ImmutableSetProtocol
diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py
index b67cc88..bf32be3 100644
--- a/mesonbuild/interpreter/compiler.py
+++ b/mesonbuild/interpreter/compiler.py
@@ -1,7 +1,6 @@
import functools
-from .interpreterobjects import (IncludeDirsHolder, ExternalLibraryHolder,
- extract_required_kwarg, extract_search_dirs)
+from .interpreterobjects import (extract_required_kwarg, extract_search_dirs)
from .. import mesonlib
from .. import mlog
@@ -14,12 +13,12 @@ import typing as T
import os
if T.TYPE_CHECKING:
- from ..environment import Environment
+ from ..interpreter import Interpreter
from ..compilers import Compiler, RunResult
class TryRunResultHolder(ObjectHolder['RunResult']):
- def __init__(self, res: 'RunResult'):
- super().__init__(res)
+ def __init__(self, res: 'RunResult', interpreter: 'Interpreter'):
+ super().__init__(res, interpreter)
self.methods.update({'returncode': self.returncode_method,
'compiled': self.compiled_method,
'stdout': self.stdout_method,
@@ -65,9 +64,9 @@ find_library_permitted_kwargs = {
find_library_permitted_kwargs |= {'header_' + k for k in header_permitted_kwargs}
class CompilerHolder(ObjectHolder['Compiler']):
- def __init__(self, compiler: 'Compiler', env: 'Environment', subproject: str):
- super().__init__(compiler, subproject=subproject)
- self.environment = env
+ def __init__(self, compiler: 'Compiler', interpreter: 'Interpreter'):
+ super().__init__(compiler, interpreter)
+ self.environment = self.env
self.methods.update({'compiles': self.compiles_method,
'links': self.links_method,
'get_id': self.get_id_method,
@@ -144,9 +143,10 @@ class CompilerHolder(ObjectHolder['Compiler']):
args = []
incdirs = mesonlib.extract_as_list(kwargs, 'include_directories')
for i in incdirs:
- if not isinstance(i, IncludeDirsHolder):
+ from ..build import IncludeDirs
+ if not isinstance(i, IncludeDirs):
raise InterpreterException('Include directories argument must be an include_directories object.')
- for idir in i.held_object.to_string_list(self.environment.get_source_dir()):
+ for idir in i.to_string_list(self.environment.get_source_dir()):
args += self.compiler.get_include_args(idir, False)
if not nobuiltins:
opts = self.environment.coredata.options
@@ -162,7 +162,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
final_deps = []
while deps:
next_deps = []
- for d in mesonlib.unholder(mesonlib.listify(deps)):
+ for d in mesonlib.listify(deps):
if not isinstance(d, dependencies.Dependency) or d.is_built():
raise InterpreterException('Dependencies must be external dependencies')
final_deps.append(d)
@@ -223,7 +223,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
else:
h = mlog.red('NO (%d)' % result.returncode)
mlog.log('Checking if', mlog.bold(testname, True), msg, 'runs:', h)
- return TryRunResultHolder(result)
+ return result
@noPosargs
@permittedKwargs({})
@@ -614,7 +614,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
self.environment,
self.compiler.language,
silent=True)
- return ExternalLibraryHolder(lib, self.subproject)
+ return lib
@FeatureNewKwargs('compiler.find_library', '0.51.0', ['static'])
@FeatureNewKwargs('compiler.find_library', '0.50.0', ['has_headers'])
@@ -659,7 +659,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
libtype, libname))
lib = dependencies.ExternalLibrary(libname, linkargs, self.environment,
self.compiler.language)
- return ExternalLibraryHolder(lib, self.subproject)
+ return lib
@permittedKwargs({})
def has_argument_method(self, args: T.Sequence[str], kwargs) -> bool:
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index 1f72d4c..be17c9a 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -66,11 +66,11 @@ if T.TYPE_CHECKING:
from . import kwargs
# Input source types passed to Targets
- SourceInputs = T.Union[FileHolder, GeneratedListHolder, TargetHolder,
- CustomTargetIndexHolder, GeneratedObjectsHolder, str]
+ SourceInputs = T.Union[mesonlib.File, build.GeneratedList, build.BuildTarget,
+ build.CustomTargetIndex, build.CustomTarget, build.GeneratedList, str]
# Input source types passed to the build.Target5 classes
SourceOutputs = T.Union[mesonlib.File, build.GeneratedList,
- build.BuildTarget, build.CustomTargetIndex,
+ build.BuildTarget, build.CustomTargetIndex, build.CustomTarget,
build.GeneratedList]
@@ -191,7 +191,7 @@ known_build_target_kwargs = (
)
TEST_KWARGS: T.List[KwargInfo] = [
- KwargInfo('args', ContainerTypeInfo(list, (str, mesonlib.File, TargetHolder)),
+ KwargInfo('args', ContainerTypeInfo(list, (str, mesonlib.File, build.Target)),
listify=True, default=[]),
KwargInfo('should_fail', bool, default=False),
KwargInfo('timeout', int, default=30),
@@ -201,11 +201,11 @@ TEST_KWARGS: T.List[KwargInfo] = [
default='exitcode',
validator=lambda x: 'value must be one of "exitcode", "tap", "gtest", "rust"' if x not in {'exitcode', 'tap', 'gtest', 'rust'} else None,
since_values={'gtest': '0.55.0', 'rust': '0.57.0'}),
- KwargInfo('depends', ContainerTypeInfo(list, (CustomTargetHolder, BuildTargetHolder)),
+ KwargInfo('depends', ContainerTypeInfo(list, (build.CustomTarget, build.BuildTarget)),
listify=True, default=[], since='0.46.0'),
KwargInfo('priority', int, default=0, since='0.52.0'),
# TODO: env needs reworks of the way the environment variable holder itself works probably
- KwargInfo('env', (EnvironmentVariablesHolder, list, dict, str)),
+ KwargInfo('env', (EnvironmentVariablesObject, list, dict, str)),
KwargInfo('suite', ContainerTypeInfo(list, str), listify=True, default=['']), # yes, a list of empty string
]
@@ -235,7 +235,7 @@ class Interpreter(InterpreterBase, HoldableObject):
def __init__(
self,
- build: build.Build,
+ _build: build.Build,
backend: T.Optional[Backend] = None,
subproject: str = '',
subdir: str = '',
@@ -246,10 +246,10 @@ class Interpreter(InterpreterBase, HoldableObject):
ast: T.Optional[mparser.CodeBlockNode] = None,
is_translated: bool = False,
) -> None:
- super().__init__(build.environment.get_source_dir(), subdir, subproject)
+ super().__init__(_build.environment.get_source_dir(), subdir, subproject)
self.an_unpicklable_object = mesonlib.an_unpicklable_object
- self.build = build
- self.environment = build.environment
+ self.build = _build
+ self.environment = self.build.environment
self.coredata = self.environment.get_coredata()
self.backend = backend
self.summary = {}
@@ -268,12 +268,12 @@ class Interpreter(InterpreterBase, HoldableObject):
elif ast is not None:
self.ast = ast
self.sanity_check_ast()
- self.builtin.update({'meson': MesonMain(build, self)})
- self.generators: T.List['GeneratorHolder'] = []
+ self.builtin.update({'meson': MesonMain(self.build, self)})
+ self.generators: T.List[build.Generator] = []
self.processed_buildfiles = set() # type: T.Set[str]
self.project_args_frozen = False
self.global_args_frozen = False # implies self.project_args_frozen
- self.subprojects = {}
+ self.subprojects: T.Dict[str, SubprojectHolder] = {}
self.subproject_stack = []
self.configure_file_outputs = {}
# Passed from the outside, only used in subprojects.
@@ -283,6 +283,7 @@ class Interpreter(InterpreterBase, HoldableObject):
self.default_project_options = {}
self.project_default_options = {}
self.build_func_dict()
+ self.build_holder_map()
# build_def_files needs to be defined before parse_project is called
#
@@ -309,11 +310,11 @@ class Interpreter(InterpreterBase, HoldableObject):
assert self.build.environment.machines.target.cpu is not None
self.builtin['build_machine'] = \
- MachineHolder(self.build.environment.machines.build)
+ OBJ.MachineHolder(self.build.environment.machines.build, self)
self.builtin['host_machine'] = \
- MachineHolder(self.build.environment.machines.host)
+ OBJ.MachineHolder(self.build.environment.machines.host, self)
self.builtin['target_machine'] = \
- MachineHolder(self.build.environment.machines.target)
+ OBJ.MachineHolder(self.build.environment.machines.target, self)
# TODO: Why is this in interpreter.py and not CoreData or Environment?
def get_non_matching_default_options(self) -> T.Iterator[T.Tuple[str, str, coredata.UserOption]]:
@@ -564,7 +565,7 @@ class Interpreter(InterpreterBase, HoldableObject):
mlog.warning('Module %s has no backwards or forwards compatibility and might not exist in future releases.' % modname, location=node)
modname = 'unstable_' + plainname
self.import_module(modname)
- return ModuleObjectHolder(self.modules[modname], self)
+ return self.modules[modname]
@stringArgs
@noKwargs
@@ -628,7 +629,7 @@ external dependencies (including libraries) must go to "dependencies".''')
dep = dependencies.InternalDependency(version, incs, compile_args,
link_args, libs, libs_whole, sources, final_deps,
variables)
- return DependencyHolder(dep, self.subproject)
+ return dep
@noKwargs
def func_assert(self, node, args, kwargs):
@@ -668,7 +669,11 @@ external dependencies (including libraries) must go to "dependencies".''')
def func_run_command(self, node, args, kwargs):
return self.run_command_impl(node, args, kwargs)
- def run_command_impl(self, node, args, kwargs, in_builddir=False):
+ def run_command_impl(self,
+ node: mparser.BaseNode,
+ args: T.Sequence[TYPE_nvar],
+ kwargs: TYPE_nkwargs,
+ in_builddir: bool = False) -> RunProcess:
if len(args) < 1:
raise InterpreterException('Not enough arguments')
cmd, *cargs = args
@@ -748,10 +753,16 @@ external dependencies (including libraries) must go to "dependencies".''')
if len(args) != 1:
raise InterpreterException('Subproject takes exactly one argument')
subp_name = args[0]
- return self.do_subproject(subp_name, 'meson', kwargs)
+ subp = self.do_subproject(subp_name, 'meson', kwargs)
+ # Update the holder maps from the subproject. Additional entries to the
+ # holder maps can be added through imported Meson modules
+ if isinstance(subp.held_object, Interpreter):
+ self.holder_map.update(subp.held_object.holder_map)
+ self.bound_holder_map.update(subp.held_object.bound_holder_map)
+ return subp
def disabled_subproject(self, subp_name, disabled_feature=None, exception=None):
- sub = SubprojectHolder(None, os.path.join(self.subproject_dir, subp_name),
+ sub = SubprojectHolder(NullSubprojectInterpreter(), os.path.join(self.subproject_dir, subp_name),
disabled_feature=disabled_feature, exception=exception)
self.subprojects[subp_name] = sub
self.coredata.initialized_subprojects.add(subp_name)
@@ -836,6 +847,8 @@ external dependencies (including libraries) must go to "dependencies".''')
subi = Interpreter(new_build, self.backend, subp_name, subdir, self.subproject_dir,
self.modules, default_options, ast=ast, is_translated=is_translated)
subi.subprojects = self.subprojects
+ subi.holder_map.update(self.holder_map)
+ subi.bound_holder_map.update(self.bound_holder_map)
subi.subproject_stack = self.subproject_stack + [subp_name]
current_active = self.active_projectname
@@ -958,7 +971,8 @@ external dependencies (including libraries) must go to "dependencies".''')
'options of other subprojects.')
opt = self.get_option_internal(optname)
if isinstance(opt, coredata.UserFeatureOption):
- return FeatureOptionHolder(self.environment, optname, opt)
+ opt.name = optname
+ return opt
elif isinstance(opt, coredata.UserOption):
return opt.value
return opt
@@ -974,7 +988,7 @@ external dependencies (including libraries) must go to "dependencies".''')
raise InterpreterException('configuration_data first argument must be a dictionary')
else:
initial_values = {}
- return ConfigurationDataHolder(self.subproject, initial_values)
+ return ConfigurationDataObject(self.subproject, initial_values)
def set_backend(self):
# The backend is already set when parsing subprojects
@@ -1318,10 +1332,9 @@ external dependencies (including libraries) must go to "dependencies".''')
extprog = ExternalProgram(exename, search_dir=search_dir,
extra_search_dirs=extra_search_dirs,
silent=True)
- progobj = ExternalProgramHolder(extprog, self.subproject)
- if progobj.found():
- extra_info.append(f"({' '.join(progobj.get_command())})")
- return progobj
+ if extprog.found():
+ extra_info.append(f"({' '.join(extprog.get_command())})")
+ return extprog
def program_from_overrides(self, command_names, extra_info):
for name in command_names:
@@ -1330,7 +1343,7 @@ external dependencies (including libraries) must go to "dependencies".''')
if name in self.build.find_overrides:
exe = self.build.find_overrides[name]
extra_info.append(mlog.blue('(overridden)'))
- return ExternalProgramHolder(exe, self.subproject, self.backend)
+ return exe
return None
def store_name_lookups(self, command_names):
@@ -1348,7 +1361,7 @@ external dependencies (including libraries) must go to "dependencies".''')
self.build.find_overrides[name] = exe
def notfound_program(self, args):
- return ExternalProgramHolder(NonExistingExternalProgram(' '.join(args)), self.subproject)
+ return NonExistingExternalProgram(' '.join(args))
# TODO update modules to always pass `for_machine`. It is bad-form to assume
# the host machine.
@@ -1372,22 +1385,28 @@ external dependencies (including libraries) must go to "dependencies".''')
if wanted:
if version_func:
version = version_func(progobj)
- else:
+ elif isinstance(progobj, build.Executable):
+ interp = self
+ if progobj.subproject:
+ interp = self.subprojects[progobj.subproject].held_object
+ assert isinstance(interp, Interpreter)
+ version = interp.project_version
+ elif isinstance(progobj, ExternalProgram):
version = progobj.get_version(self)
is_found, not_found, found = mesonlib.version_compare_many(version, wanted)
if not is_found:
- mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.red('NO'),
+ mlog.log('Program', mlog.bold(progobj.name), 'found:', mlog.red('NO'),
'found', mlog.normal_cyan(version), 'but need:',
mlog.bold(', '.join([f"'{e}'" for e in not_found])), *extra_info)
if required:
m = 'Invalid version of program, need {!r} {!r} found {!r}.'
- raise InterpreterException(m.format(progobj.get_name(), not_found, version))
+ raise InterpreterException(m.format(progobj.name, not_found, version))
return self.notfound_program(args)
extra_info.insert(0, mlog.normal_cyan(version))
# Only store successful lookups
self.store_name_lookups(args)
- mlog.log('Program', mlog.bold(progobj.get_name()), 'found:', mlog.green('YES'), *extra_info)
+ mlog.log('Program', mlog.bold(progobj.name), 'found:', mlog.green('YES'), *extra_info)
return progobj
def program_lookup(self, args, for_machine, required, search_dirs, extra_info):
@@ -1407,7 +1426,7 @@ external dependencies (including libraries) must go to "dependencies".''')
progobj = self.program_from_system(args, search_dirs, extra_info)
if progobj is None and args[0].endswith('python3'):
prog = ExternalProgram('python3', mesonlib.python_command, silent=True)
- progobj = ExternalProgramHolder(prog, self.subproject) if prog.found() else None
+ progobj = prog if prog.found() else None
if progobj is None and fallback and required:
progobj = self.find_program_fallback(fallback, args, required, extra_info)
@@ -1485,10 +1504,12 @@ external dependencies (including libraries) must go to "dependencies".''')
# Ensure the correct include type
if 'include_type' in kwargs:
wanted = kwargs['include_type']
- actual = d.include_type_method([], {})
+ if not isinstance(wanted, str):
+ raise InvalidArguments('The `include_type` kwarg must be a string')
+ actual = d.get_include_type()
if wanted != actual:
mlog.debug(f'Current include type of {names[0]} is {actual}. Converting to requested {wanted}')
- d = d.as_system_method([wanted], {})
+ d = d.generate_system_dependency(wanted)
return d
@FeatureNew('disabler', '0.44.0')
@@ -1502,16 +1523,16 @@ external dependencies (including libraries) must go to "dependencies".''')
@FeatureDeprecatedKwargs('executable', '0.56.0', ['gui_app'], extra_message="Use 'win_subsystem' instead.")
@permittedKwargs(build.known_exe_kwargs)
def func_executable(self, node, args, kwargs):
- return self.build_target(node, args, kwargs, ExecutableHolder)
+ return self.build_target(node, args, kwargs, build.Executable)
@permittedKwargs(build.known_stlib_kwargs)
def func_static_lib(self, node, args, kwargs):
- return self.build_target(node, args, kwargs, StaticLibraryHolder)
+ return self.build_target(node, args, kwargs, build.StaticLibrary)
@permittedKwargs(build.known_shlib_kwargs)
def func_shared_lib(self, node, args, kwargs):
- holder = self.build_target(node, args, kwargs, SharedLibraryHolder)
- holder.held_object.shared_library_only = True
+ holder = self.build_target(node, args, kwargs, build.SharedLibrary)
+ holder.shared_library_only = True
return holder
@permittedKwargs(known_library_kwargs)
@@ -1521,7 +1542,7 @@ external dependencies (including libraries) must go to "dependencies".''')
@FeatureNew('shared_module', '0.37.0')
@permittedKwargs(build.known_shmod_kwargs)
def func_shared_module(self, node, args, kwargs):
- return self.build_target(node, args, kwargs, SharedModuleHolder)
+ return self.build_target(node, args, kwargs, build.SharedModule)
@permittedKwargs(known_library_kwargs)
def func_library(self, node, args, kwargs):
@@ -1529,7 +1550,7 @@ external dependencies (including libraries) must go to "dependencies".''')
@permittedKwargs(build.known_jar_kwargs)
def func_jar(self, node, args, kwargs):
- return self.build_target(node, args, kwargs, JarHolder)
+ return self.build_target(node, args, kwargs, build.Jar)
@FeatureNewKwargs('build_target', '0.40.0', ['link_whole', 'override_options'])
@permittedKwargs(known_build_target_kwargs)
@@ -1538,21 +1559,21 @@ external dependencies (including libraries) must go to "dependencies".''')
raise InterpreterException('Missing target_type keyword argument')
target_type = kwargs.pop('target_type')
if target_type == 'executable':
- return self.build_target(node, args, kwargs, ExecutableHolder)
+ return self.build_target(node, args, kwargs, build.Executable)
elif target_type == 'shared_library':
- return self.build_target(node, args, kwargs, SharedLibraryHolder)
+ return self.build_target(node, args, kwargs, build.SharedLibrary)
elif target_type == 'shared_module':
FeatureNew('build_target(target_type: \'shared_module\')',
'0.51.0').use(self.subproject)
- return self.build_target(node, args, kwargs, SharedModuleHolder)
+ return self.build_target(node, args, kwargs, build.SharedModule)
elif target_type == 'static_library':
- return self.build_target(node, args, kwargs, StaticLibraryHolder)
+ return self.build_target(node, args, kwargs, build.StaticLibrary)
elif target_type == 'both_libraries':
return self.build_both_libraries(node, args, kwargs)
elif target_type == 'library':
return self.build_library(node, args, kwargs)
elif target_type == 'jar':
- return self.build_target(node, args, kwargs, JarHolder)
+ return self.build_target(node, args, kwargs, build.Jar)
else:
raise InterpreterException('Unknown target_type.')
@@ -1634,8 +1655,8 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
if 'command' in kwargs and isinstance(kwargs['command'], list) and kwargs['command']:
if isinstance(kwargs['command'][0], str):
kwargs['command'][0] = self.func_find_program(node, kwargs['command'][0], {})
- tg = CustomTargetHolder(build.CustomTarget(name, self.subdir, self.subproject, kwargs, backend=self.backend), self)
- self.add_target(name, tg.held_object)
+ tg = build.CustomTarget(name, self.subdir, self.subproject, kwargs, backend=self.backend)
+ self.add_target(name, tg)
return tg
@FeatureNewKwargs('run_target', '0.57.0', ['env'])
@@ -1721,36 +1742,36 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
self.generators.append(gen)
return gen
- @typed_pos_args('benchmark', str, (ExecutableHolder, JarHolder, ExternalProgramHolder, mesonlib.File))
+ @typed_pos_args('benchmark', str, (build.Executable, build.Jar, ExternalProgram, mesonlib.File))
@typed_kwargs('benchmark', *TEST_KWARGS)
def func_benchmark(self, node: mparser.BaseNode,
- args: T.Tuple[str, T.Union[ExecutableHolder, JarHolder, ExternalProgramHolder, mesonlib.File]],
+ args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File]],
kwargs: 'kwargs.FuncBenchmark') -> None:
self.add_test(node, args, kwargs, False)
- @typed_pos_args('test', str, (ExecutableHolder, JarHolder, ExternalProgramHolder, mesonlib.File))
+ @typed_pos_args('test', str, (build.Executable, build.Jar, ExternalProgram, mesonlib.File))
@typed_kwargs('benchmark', *TEST_KWARGS, KwargInfo('is_parallel', bool, default=True))
def func_test(self, node: mparser.BaseNode,
- args: T.Tuple[str, T.Union[ExecutableHolder, JarHolder, ExternalProgramHolder, mesonlib.File]],
+ args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File]],
kwargs: 'kwargs.FuncTest') -> None:
self.add_test(node, args, kwargs, True)
- def unpack_env_kwarg(self, kwargs: T.Union[EnvironmentVariablesHolder, T.Dict[str, str], T.List[str]]) -> build.EnvironmentVariables:
- envlist = kwargs.get('env', EnvironmentVariablesHolder())
- if isinstance(envlist, EnvironmentVariablesHolder):
- env = envlist.held_object
+ def unpack_env_kwarg(self, kwargs: T.Union[EnvironmentVariablesObject, T.Dict[str, str], T.List[str]]) -> build.EnvironmentVariables:
+ envlist = kwargs.get('env', EnvironmentVariablesObject())
+ if isinstance(envlist, EnvironmentVariablesObject):
+ env = envlist.vars
elif isinstance(envlist, dict):
FeatureNew.single_use('environment dictionary', '0.52.0', self.subproject)
- env = EnvironmentVariablesHolder(envlist)
- env = env.held_object
+ env = EnvironmentVariablesObject(envlist)
+ env = env.vars
else:
# Convert from array to environment object
- env = EnvironmentVariablesHolder(envlist)
- env = env.held_object
+ env = EnvironmentVariablesObject(envlist)
+ env = env.vars
return env
def make_test(self, node: mparser.BaseNode,
- args: T.Tuple[str, T.Union[ExecutableHolder, JarHolder, ExternalProgramHolder, mesonlib.File]],
+ args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File]],
kwargs: 'kwargs.BaseTest') -> Test:
name = args[0]
if ':' in name:
@@ -1816,7 +1837,7 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
h = build.Headers(source_files, install_subdir, install_dir, install_mode, self.subproject)
self.build.headers.append(h)
- return HeadersHolder(h)
+ return h
@FeatureNewKwargs('install_man', '0.47.0', ['install_mode'])
@FeatureNewKwargs('install_man', '0.58.0', ['locale'])
@@ -1839,7 +1860,7 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
m = build.Man(sources, custom_install_dir, custom_install_mode, self.subproject, locale)
self.build.man.append(m)
- return ManHolder(m)
+ return m
@FeatureNewKwargs('subdir', '0.44.0', ['if_found'])
@permittedKwargs({'if_found'})
@@ -1937,8 +1958,8 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
'"rename" and "sources" argument lists must be the same length if "rename" is given. '
f'Rename has {len(rename)} elements and sources has {len(sources)}.')
- data = DataHolder(build.Data(sources, install_dir, install_mode, self.subproject, rename))
- self.build.data.append(data.held_object)
+ data = build.Data(sources, install_dir, install_mode, self.subproject, rename)
+ self.build.data.append(data)
return data
@FeatureNewKwargs('install_subdir', '0.42.0', ['exclude_files', 'exclude_directories'])
@@ -1986,7 +2007,7 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
install_mode = self._get_kwarg_install_mode(kwargs)
idir = build.InstallDir(self.subdir, subdir, install_dir, install_mode, exclude, strip_directory, self.subproject)
self.build.install_dirs.append(idir)
- return InstallDirHolder(idir)
+ return idir
@FeatureNewKwargs('configure_file', '0.47.0', ['copy', 'output_format', 'install_mode', 'encoding'])
@FeatureNewKwargs('configure_file', '0.46.0', ['format'])
@@ -2083,8 +2104,8 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
conf = kwargs['configuration']
if isinstance(conf, dict):
FeatureNew.single_use('configure_file.configuration dictionary', '0.49.0', self.subproject)
- conf = ConfigurationDataHolder(self.subproject, conf)
- elif not isinstance(conf, ConfigurationDataHolder):
+ conf = ConfigurationDataObject(self.subproject, conf)
+ elif not isinstance(conf, ConfigurationDataObject):
raise InterpreterException('Argument "configuration" is not of type configuration_data')
mlog.log('Configuring', mlog.bold(output), 'using configuration')
if len(inputs) > 1:
@@ -2180,13 +2201,13 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
return mesonlib.File.from_built_file(self.subdir, output)
def extract_incdirs(self, kwargs):
- prospectives = unholder(extract_as_list(kwargs, 'include_directories'))
+ prospectives = extract_as_list(kwargs, 'include_directories')
result = []
for p in prospectives:
if isinstance(p, build.IncludeDirs):
result.append(p)
elif isinstance(p, str):
- result.append(self.build_incdir_object([p]).held_object)
+ result.append(self.build_incdir_object([p]))
else:
raise InterpreterException('Include directory objects can only be created from strings or include directories.')
return result
@@ -2196,7 +2217,7 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
def func_include_directories(self, node, args, kwargs):
return self.build_incdir_object(args, kwargs.get('is_system', False))
- def build_incdir_object(self, incdir_strings: T.List[str], is_system: bool = False) -> IncludeDirsHolder:
+ def build_incdir_object(self, incdir_strings: T.List[str], is_system: bool = False) -> build.IncludeDirs:
if not isinstance(is_system, bool):
raise InvalidArguments('Is_system must be boolean.')
src_root = self.environment.get_source_dir()
@@ -2251,7 +2272,7 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
absdir_build = os.path.join(absbase_build, a)
if not os.path.isdir(absdir_src) and not os.path.isdir(absdir_build):
raise InvalidArguments('Include dir %s does not exist.' % a)
- i = IncludeDirsHolder(build.IncludeDirs(self.subdir, incdir_strings, is_system))
+ i = build.IncludeDirs(self.subdir, incdir_strings, is_system)
return i
@permittedKwargs({'exe_wrapper', 'gdb', 'timeout_multiplier', 'env', 'is_default',
@@ -2392,7 +2413,7 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
raise InterpreterException('environment first argument must be a dictionary or a list')
else:
initial_values = {}
- return EnvironmentVariablesHolder(initial_values, self.subproject)
+ return EnvironmentVariablesObject(initial_values, self.subproject)
@stringArgs
@noKwargs
@@ -2477,10 +2498,10 @@ Try setting b_lundef to false instead.'''.format(self.coredata.options[OptionKey
results.append(mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, s))
elif isinstance(s, mesonlib.File):
results.append(s)
- elif isinstance(s, (GeneratedListHolder, TargetHolder,
- CustomTargetIndexHolder,
- GeneratedObjectsHolder)):
- results.append(unholder(s))
+ elif isinstance(s, (build.GeneratedList, build.BuildTarget,
+ build.CustomTargetIndex, build.CustomTarget,
+ build.GeneratedList)):
+ results.append(s)
else:
raise InterpreterException(f'Source item is {s!r} instead of '
'string or File-type object')
@@ -2554,7 +2575,7 @@ Try setting b_lundef to false instead.'''.format(self.coredata.options[OptionKey
else:
raise InterpreterException('Unknown default_library value: %s.', default_library)
- def build_target(self, node, args, kwargs, targetholder):
+ def build_target(self, node, args, kwargs, targetclass):
@FeatureNewKwargs('build target', '0.42.0', ['rust_crate_type', 'build_rpath', 'implicit_include_directories'])
@FeatureNewKwargs('build target', '0.41.0', ['rust_args'])
@FeatureNewKwargs('build target', '0.40.0', ['build_by_default'])
@@ -2578,18 +2599,8 @@ Try setting b_lundef to false instead.'''.format(self.coredata.options[OptionKey
ef = extract_as_list(kwargs, 'extra_files')
kwargs['extra_files'] = self.source_strings_to_files(ef)
self.check_sources_exist(os.path.join(self.source_root, self.subdir), sources)
- if targetholder == ExecutableHolder:
- targetclass = build.Executable
- elif targetholder == SharedLibraryHolder:
- targetclass = build.SharedLibrary
- elif targetholder == SharedModuleHolder:
- targetclass = build.SharedModule
- elif targetholder == StaticLibraryHolder:
- targetclass = build.StaticLibrary
- elif targetholder == JarHolder:
- targetclass = build.Jar
- else:
- mlog.debug('Unknown target type:', str(targetholder))
+ if targetclass not in {build.Executable, build.SharedLibrary, build.SharedModule, build.StaticLibrary, build.Jar}:
+ mlog.debug('Unknown target type:', str(targetclass))
raise RuntimeError('Unreachable code')
self.kwarg_strings_to_includedirs(kwargs)
diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py
index c0eecca..7c4e75e 100644
--- a/mesonbuild/interpreter/interpreterobjects.py
+++ b/mesonbuild/interpreter/interpreterobjects.py
@@ -1,8 +1,8 @@
import os
import shlex
import subprocess
-import re
import copy
+import textwrap
from pathlib import Path, PurePath
@@ -33,22 +33,22 @@ if T.TYPE_CHECKING:
from ..envconfig import MachineInfo
-def extract_required_kwarg(kwargs: 'kwargs.ExtractRequired', subproject: str,
- feature_check: T.Optional['FeatureCheckBase'] = None,
+def extract_required_kwarg(kwargs: 'kwargs.ExtractRequired',
+ subproject: str,
+ feature_check: T.Optional[FeatureCheckBase] = None,
default: bool = True) -> T.Tuple[bool, bool, T.Optional[str]]:
val = kwargs.get('required', default)
disabled = False
required = False
feature: T.Optional[str] = None
- if isinstance(val, FeatureOptionHolder):
+ if isinstance(val, coredata.UserFeatureOption):
if not feature_check:
feature_check = FeatureNew('User option "feature"', '0.47.0')
feature_check.use(subproject)
- option = val.held_object
feature = val.name
- if option.is_disabled():
+ if val.is_disabled():
disabled = True
- elif option.is_enabled():
+ elif val.is_enabled():
required = True
elif isinstance(val, bool):
required = val
@@ -62,9 +62,9 @@ def extract_required_kwarg(kwargs: 'kwargs.ExtractRequired', subproject: str,
return disabled, required, feature
-def extract_search_dirs(kwargs):
- search_dirs = mesonlib.stringlistify(kwargs.get('dirs', []))
- search_dirs = [Path(d).expanduser() for d in search_dirs]
+def extract_search_dirs(kwargs: T.Dict[str, T.Any]) -> T.List[str]:
+ search_dirs_str = mesonlib.stringlistify(kwargs.get('dirs', []))
+ search_dirs = [Path(d).expanduser() for d in search_dirs_str]
for d in search_dirs:
if mesonlib.is_windows() and d.root.startswith('\\'):
# a Unix-path starting with `/` that is not absolute on Windows.
@@ -75,12 +75,12 @@ def extract_search_dirs(kwargs):
return list(map(str, search_dirs))
class FeatureOptionHolder(ObjectHolder[coredata.UserFeatureOption]):
- def __init__(self, env: 'Environment', name: str, option: coredata.UserFeatureOption):
- super().__init__(option)
+ def __init__(self, option: coredata.UserFeatureOption, interpreter: 'Interpreter'):
+ super().__init__(option, interpreter)
if option and option.is_auto():
# TODO: we need to case here because options is not a TypedDict
- self.held_object = T.cast(coredata.UserFeatureOption, env.coredata.options[OptionKey('auto_features')])
- self.name = name
+ self.held_object = T.cast(coredata.UserFeatureOption, self.env.coredata.options[OptionKey('auto_features')])
+ self.held_object.name = option.name
self.methods.update({'enabled': self.enabled_method,
'disabled': self.disabled_method,
'allowed': self.allowed_method,
@@ -90,34 +90,36 @@ class FeatureOptionHolder(ObjectHolder[coredata.UserFeatureOption]):
})
@property
- def value(self):
+ def value(self) -> str:
return 'disabled' if not self.held_object else self.held_object.value
- def as_disabled(self):
- return FeatureOptionHolder(None, self.name, None)
+ def as_disabled(self) -> coredata.UserFeatureOption:
+ disabled = copy.deepcopy(self.held_object)
+ disabled.value = 'disabled'
+ return disabled
@noPosargs
- @permittedKwargs({})
- def enabled_method(self, args, kwargs):
+ @noKwargs
+ def enabled_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
return self.value == 'enabled'
@noPosargs
- @permittedKwargs({})
- def disabled_method(self, args, kwargs):
+ @noKwargs
+ def disabled_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
return self.value == 'disabled'
@noPosargs
- @permittedKwargs({})
- def allowed_method(self, args, kwargs):
+ @noKwargs
+ def allowed_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
return not self.value == 'disabled'
@noPosargs
- @permittedKwargs({})
- def auto_method(self, args, kwargs):
+ @noKwargs
+ def auto_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
return self.value == 'auto'
@permittedKwargs({'error_message'})
- def require_method(self, args, kwargs):
+ def require_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> coredata.UserFeatureOption:
if len(args) != 1:
raise InvalidArguments('Expected 1 argument, got %d.' % (len(args), ))
if not isinstance(args[0], bool):
@@ -126,38 +128,57 @@ class FeatureOptionHolder(ObjectHolder[coredata.UserFeatureOption]):
if error_message and not isinstance(error_message, str):
raise InterpreterException("Error message must be a string.")
if args[0]:
- return self
+ return copy.deepcopy(self.held_object)
+ assert isinstance(error_message, str)
if self.value == 'enabled':
- prefix = 'Feature {} cannot be enabled'.format(self.name)
+ prefix = 'Feature {} cannot be enabled'.format(self.held_object.name)
prefix = prefix + ': ' if error_message else ''
raise InterpreterException(prefix + error_message)
return self.as_disabled()
- @permittedKwargs({})
- def disable_auto_if_method(self, args, kwargs):
+ @noKwargs
+ def disable_auto_if_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> coredata.UserFeatureOption:
if len(args) != 1:
raise InvalidArguments('Expected 1 argument, got %d.' % (len(args), ))
if not isinstance(args[0], bool):
raise InvalidArguments('boolean argument expected.')
- return self if self.value != 'auto' or not args[0] else self.as_disabled()
+ return copy.deepcopy(self.held_object) if self.value != 'auto' or not args[0] else self.as_disabled()
class RunProcess(MesonInterpreterObject):
- def __init__(self, cmd, args, env, source_dir, build_dir, subdir, mesonintrospect, in_builddir=False, check=False, capture=True):
+ def __init__(self,
+ cmd: ExternalProgram,
+ args: T.List[str],
+ env: build.EnvironmentVariables,
+ source_dir: str,
+ build_dir: str,
+ subdir: str,
+ mesonintrospect: T.List[str],
+ in_builddir: bool = False,
+ check: bool = False,
+ capture: bool = True) -> None:
super().__init__()
if not isinstance(cmd, ExternalProgram):
raise AssertionError('BUG: RunProcess must be passed an ExternalProgram')
self.capture = capture
- pc, self.stdout, self.stderr = self.run_command(cmd, args, env, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check)
- self.returncode = pc.returncode
+ self.returncode, self.stdout, self.stderr = self.run_command(cmd, args, env, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check)
self.methods.update({'returncode': self.returncode_method,
'stdout': self.stdout_method,
'stderr': self.stderr_method,
})
- def run_command(self, cmd, args, env, source_dir, build_dir, subdir, mesonintrospect, in_builddir, check=False):
+ def run_command(self,
+ cmd: ExternalProgram,
+ args: T.List[str],
+ env: build.EnvironmentVariables,
+ source_dir: str,
+ build_dir: str,
+ subdir: str,
+ mesonintrospect: T.List[str],
+ in_builddir: bool,
+ check: bool = False) -> T.Tuple[int, str, str]:
command_array = cmd.get_command() + args
menv = {'MESON_SOURCE_ROOT': source_dir,
'MESON_BUILD_ROOT': build_dir,
@@ -188,28 +209,33 @@ class RunProcess(MesonInterpreterObject):
if check and p.returncode != 0:
raise InterpreterException('Command "{}" failed with status {}.'.format(' '.join(command_array), p.returncode))
- return p, o, e
+ return p.returncode, o, e
except FileNotFoundError:
raise InterpreterException('Could not execute command "%s".' % ' '.join(command_array))
@noPosargs
- @permittedKwargs({})
- def returncode_method(self, args, kwargs):
+ @noKwargs
+ def returncode_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> int:
return self.returncode
@noPosargs
- @permittedKwargs({})
- def stdout_method(self, args, kwargs):
+ @noKwargs
+ def stdout_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.stdout
@noPosargs
- @permittedKwargs({})
- def stderr_method(self, args, kwargs):
+ @noKwargs
+ def stderr_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.stderr
-class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder[build.EnvironmentVariables]):
- def __init__(self, initial_values=None, subproject: str = ''):
- super().__init__(build.EnvironmentVariables(), subproject=subproject)
+# TODO: Parsing the initial values should be either done directly in the
+# `Interpreter` or in `build.EnvironmentVariables`. This way, this class
+# can be converted into a pure object holder.
+class EnvironmentVariablesObject(MutableInterpreterObject, MesonInterpreterObject):
+ # TODO: Move the type cheking for initial_values out of this class and replace T.Any
+ def __init__(self, initial_values: T.Optional[T.Any] = None, subproject: str = ''):
+ super().__init__(subproject=subproject)
+ self.vars = build.EnvironmentVariables()
self.methods.update({'set': self.set_method,
'append': self.append_method,
'prepend': self.prepend_method,
@@ -232,18 +258,18 @@ class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder[build.En
def __repr__(self) -> str:
repr_str = "<{0}: {1}>"
- return repr_str.format(self.__class__.__name__, self.held_object.envvars)
+ return repr_str.format(self.__class__.__name__, self.vars.envvars)
def unpack_separator(self, kwargs: T.Dict[str, T.Any]) -> str:
separator = kwargs.get('separator', os.pathsep)
if not isinstance(separator, str):
- raise InterpreterException("EnvironmentVariablesHolder methods 'separator'"
+ raise InterpreterException("EnvironmentVariablesObject methods 'separator'"
" argument needs to be a string.")
return separator
def warn_if_has_name(self, name: str) -> None:
# Multiple append/prepend operations was not supported until 0.58.0.
- if self.held_object.has_name(name):
+ if self.vars.has_name(name):
m = f'Overriding previous value of environment variable {name!r} with a new one'
FeatureNew('0.58.0', m).use(self.subproject)
@@ -253,7 +279,7 @@ class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder[build.En
def set_method(self, args: T.Tuple[str, T.List[str]], kwargs: T.Dict[str, T.Any]) -> None:
name, values = args
separator = self.unpack_separator(kwargs)
- self.held_object.set(name, values, separator)
+ self.vars.set(name, values, separator)
@stringArgs
@permittedKwargs({'separator'})
@@ -262,7 +288,7 @@ class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder[build.En
name, values = args
separator = self.unpack_separator(kwargs)
self.warn_if_has_name(name)
- self.held_object.append(name, values, separator)
+ self.vars.append(name, values, separator)
@stringArgs
@permittedKwargs({'separator'})
@@ -271,13 +297,14 @@ class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder[build.En
name, values = args
separator = self.unpack_separator(kwargs)
self.warn_if_has_name(name)
- self.held_object.prepend(name, values, separator)
+ self.vars.prepend(name, values, separator)
-class ConfigurationDataHolder(MutableInterpreterObject, ObjectHolder[build.ConfigurationData]):
- def __init__(self, subproject: str, initial_values=None):
+class ConfigurationDataObject(MutableInterpreterObject, MesonInterpreterObject):
+ def __init__(self, subproject: str, initial_values: T.Optional[T.Dict[str, T.Any]] = None) -> None:
self.used = False # These objects become immutable after use in configure_file.
- super().__init__(build.ConfigurationData(), subproject=subproject)
+ super().__init__(subproject=subproject)
+ self.conf_data = build.ConfigurationData()
self.methods.update({'set': self.set_method,
'set10': self.set10_method,
'set_quoted': self.set_quoted_method,
@@ -291,15 +318,15 @@ class ConfigurationDataHolder(MutableInterpreterObject, ObjectHolder[build.Confi
for k, v in initial_values.items():
self.set_method([k, v], {})
elif initial_values:
- raise AssertionError('Unsupported ConfigurationDataHolder initial_values')
+ raise AssertionError('Unsupported ConfigurationDataObject initial_values')
- def is_used(self):
+ def is_used(self) -> bool:
return self.used
- def mark_used(self):
+ def mark_used(self) -> None:
self.used = True
- def validate_args(self, args, kwargs):
+ def validate_args(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.Tuple[str, T.Union[str, int, bool], T.Optional[str]]:
if len(args) == 1 and isinstance(args[0], list) and len(args[0]) == 2:
mlog.deprecation('Passing a list as the single argument to '
'configuration_data.set is deprecated. This will '
@@ -323,85 +350,101 @@ class ConfigurationDataHolder(MutableInterpreterObject, ObjectHolder[build.Confi
if desc is not None and not isinstance(desc, str):
raise InterpreterException('Description must be a string.')
- return name, val, desc
+ # TODO: Remove the cast once we get rid of the deprecation
+ return name, T.cast(T.Union[str, bool, int], val), desc
@noArgsFlattening
- def set_method(self, args, kwargs):
+ def set_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> None:
(name, val, desc) = self.validate_args(args, kwargs)
- self.held_object.values[name] = (val, desc)
+ self.conf_data.values[name] = (val, desc)
- def set_quoted_method(self, args, kwargs):
+ def set_quoted_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> None:
(name, val, desc) = self.validate_args(args, kwargs)
if not isinstance(val, str):
raise InterpreterException("Second argument to set_quoted must be a string.")
escaped_val = '\\"'.join(val.split('"'))
- self.held_object.values[name] = ('"' + escaped_val + '"', desc)
+ self.conf_data.values[name] = ('"' + escaped_val + '"', desc)
- def set10_method(self, args, kwargs):
+ def set10_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> None:
(name, val, desc) = self.validate_args(args, kwargs)
if val:
- self.held_object.values[name] = (1, desc)
+ self.conf_data.values[name] = (1, desc)
else:
- self.held_object.values[name] = (0, desc)
+ self.conf_data.values[name] = (0, desc)
- def has_method(self, args, kwargs):
- return args[0] in self.held_object.values
+ def has_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
+ return args[0] in self.conf_data.values
@FeatureNew('configuration_data.get()', '0.38.0')
@noArgsFlattening
- def get_method(self, args, kwargs):
+ def get_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.Union[str, int, bool]:
if len(args) < 1 or len(args) > 2:
raise InterpreterException('Get method takes one or two arguments.')
+ if not isinstance(args[0], str):
+ raise InterpreterException('The variable name must be a string.')
name = args[0]
- if name in self.held_object:
- return self.held_object.get(name)[0]
+ if name in self.conf_data:
+ return self.conf_data.get(name)[0]
if len(args) > 1:
- return args[1]
+ # Assertion does not work because setting other values is still
+ # supported, but deprecated. Use T.cast in the meantime (even though
+ # this is a lie).
+ # TODO: Fix this once the deprecation is removed
+ # assert isinstance(args[1], (int, str, bool))
+ return T.cast(T.Union[str, int, bool], args[1])
raise InterpreterException('Entry %s not in configuration data.' % name)
@FeatureNew('configuration_data.get_unquoted()', '0.44.0')
- def get_unquoted_method(self, args, kwargs):
+ def get_unquoted_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.Union[str, int, bool]:
if len(args) < 1 or len(args) > 2:
raise InterpreterException('Get method takes one or two arguments.')
+ if not isinstance(args[0], str):
+ raise InterpreterException('The variable name must be a string.')
name = args[0]
- if name in self.held_object:
- val = self.held_object.get(name)[0]
+ if name in self.conf_data:
+ val = self.conf_data.get(name)[0]
elif len(args) > 1:
+ assert isinstance(args[1], (str, int, bool))
val = args[1]
else:
raise InterpreterException('Entry %s not in configuration data.' % name)
- if val[0] == '"' and val[-1] == '"':
+ if isinstance(val, str) and val[0] == '"' and val[-1] == '"':
return val[1:-1]
return val
- def get(self, name):
- return self.held_object.values[name] # (val, desc)
+ def get(self, name: str) -> T.Tuple[T.Union[str, int, bool], T.Optional[str]]:
+ return self.conf_data.values[name]
@FeatureNew('configuration_data.keys()', '0.57.0')
@noPosargs
- def keys_method(self, args, kwargs):
+ def keys_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[str]:
return sorted(self.keys())
- def keys(self):
- return self.held_object.values.keys()
+ def keys(self) -> T.List[str]:
+ return list(self.conf_data.values.keys())
- def merge_from_method(self, args, kwargs):
+ def merge_from_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> None:
if len(args) != 1:
raise InterpreterException('Merge_from takes one positional argument.')
- from_object = args[0]
- if not isinstance(from_object, ConfigurationDataHolder):
+ from_object_holder = args[0]
+ if not isinstance(from_object_holder, ConfigurationDataObject):
raise InterpreterException('Merge_from argument must be a configuration data object.')
- from_object = from_object.held_object
+ from_object = from_object_holder.conf_data
for k, v in from_object.values.items():
- self.held_object.values[k] = v
+ self.conf_data.values[k] = v
+
-permitted_partial_dependency_kwargs = {
- 'compile_args', 'link_args', 'links', 'includes', 'sources'
-}
+_PARTIAL_DEP_KWARGS = [
+ KwargInfo('compile_args', bool, default=False),
+ KwargInfo('link_args', bool, default=False),
+ KwargInfo('links', bool, default=False),
+ KwargInfo('includes', bool, default=False),
+ KwargInfo('sources', bool, default=False),
+]
class DependencyHolder(ObjectHolder[Dependency]):
- def __init__(self, dep: Dependency, subproject: str):
- super().__init__(dep, subproject=subproject)
+ def __init__(self, dep: Dependency, interpreter: 'Interpreter'):
+ super().__init__(dep, interpreter)
self.methods.update({'found': self.found_method,
'type_name': self.type_name_method,
'version': self.version_method,
@@ -415,35 +458,35 @@ class DependencyHolder(ObjectHolder[Dependency]):
'as_link_whole': self.as_link_whole_method,
})
- def found(self):
+ def found(self) -> bool:
return self.found_method([], {})
@noPosargs
- @permittedKwargs({})
- def type_name_method(self, args, kwargs):
+ @noKwargs
+ def type_name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.type_name
@noPosargs
- @permittedKwargs({})
- def found_method(self, args, kwargs):
+ @noKwargs
+ def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
if self.held_object.type_name == 'internal':
return True
return self.held_object.found()
@noPosargs
- @permittedKwargs({})
- def version_method(self, args, kwargs):
+ @noKwargs
+ def version_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.get_version()
@noPosargs
- @permittedKwargs({})
- def name_method(self, args, kwargs):
+ @noKwargs
+ def name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.get_name()
@FeatureDeprecated('Dependency.get_pkgconfig_variable', '0.56.0',
'use Dependency.get_variable(pkgconfig : ...) instead')
@permittedKwargs({'define_variable', 'default'})
- def pkgconfig_method(self, args, kwargs):
+ def pkgconfig_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
args = listify(args)
if len(args) != 1:
raise InterpreterException('get_pkgconfig_variable takes exactly one argument.')
@@ -455,8 +498,8 @@ class DependencyHolder(ObjectHolder[Dependency]):
@FeatureNew('dep.get_configtool_variable', '0.44.0')
@FeatureDeprecated('Dependency.get_configtool_variable', '0.56.0',
'use Dependency.get_variable(configtool : ...) instead')
- @permittedKwargs({})
- def configtool_method(self, args, kwargs):
+ @noKwargs
+ def configtool_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
args = listify(args)
if len(args) != 1:
raise InterpreterException('get_configtool_variable takes exactly one argument.')
@@ -467,16 +510,16 @@ class DependencyHolder(ObjectHolder[Dependency]):
@FeatureNew('dep.partial_dependency', '0.46.0')
@noPosargs
- @permittedKwargs(permitted_partial_dependency_kwargs)
- def partial_dependency_method(self, args, kwargs):
+ @typed_kwargs('dep.partial_dependency', *_PARTIAL_DEP_KWARGS)
+ def partial_dependency_method(self, args: T.List[TYPE_nvar], kwargs: 'kwargs.DependencyMethodPartialDependency') -> Dependency:
pdep = self.held_object.get_partial_dependency(**kwargs)
- return DependencyHolder(pdep, self.subproject)
+ return pdep
@FeatureNew('dep.get_variable', '0.51.0')
@typed_pos_args('dep.get_variable', optargs=[str])
@permittedKwargs({'cmake', 'pkgconfig', 'configtool', 'internal', 'default_value', 'pkgconfig_define'})
@FeatureNewKwargs('dep.get_variable', '0.54.0', ['internal'])
- def variable_method(self, args: T.Tuple[T.Optional[str]], kwargs: T.Dict[str, T.Any]) -> str:
+ def variable_method(self, args: T.Tuple[T.Optional[str]], kwargs: T.Dict[str, T.Any]) -> T.Union[str, T.List[str]]:
default_varname = args[0]
if default_varname is not None:
FeatureNew('0.58.0', 'Positional argument to dep.get_variable()').use(self.subproject)
@@ -486,129 +529,102 @@ class DependencyHolder(ObjectHolder[Dependency]):
@FeatureNew('dep.include_type', '0.52.0')
@noPosargs
- @permittedKwargs({})
- def include_type_method(self, args, kwargs):
+ @noKwargs
+ def include_type_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.get_include_type()
@FeatureNew('dep.as_system', '0.52.0')
- @permittedKwargs({})
- def as_system_method(self, args, kwargs):
+ @noKwargs
+ def as_system_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> Dependency:
args = listify(args)
new_is_system = 'system'
if len(args) > 1:
raise InterpreterException('as_system takes only one optional value')
if len(args) == 1:
+ if not isinstance(args[0], str):
+ raise InterpreterException('as_system takes exactly one string parameter')
new_is_system = args[0]
new_dep = self.held_object.generate_system_dependency(new_is_system)
- return DependencyHolder(new_dep, self.subproject)
+ return new_dep
@FeatureNew('dep.as_link_whole', '0.56.0')
- @permittedKwargs({})
+ @noKwargs
@noPosargs
- def as_link_whole_method(self, args, kwargs):
+ def as_link_whole_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> Dependency:
if not isinstance(self.held_object, InternalDependency):
raise InterpreterException('as_link_whole method is only supported on declare_dependency() objects')
new_dep = self.held_object.generate_link_whole_dependency()
- return DependencyHolder(new_dep, self.subproject)
+ return new_dep
class ExternalProgramHolder(ObjectHolder[ExternalProgram]):
- def __init__(self, ep: ExternalProgram, subproject: str, backend=None):
- super().__init__(ep, subproject=subproject)
- self.backend = backend
+ def __init__(self, ep: ExternalProgram, interpreter: 'Interpreter') -> None:
+ super().__init__(ep, interpreter)
self.methods.update({'found': self.found_method,
'path': self.path_method,
'full_path': self.full_path_method})
@noPosargs
- @permittedKwargs({})
- def found_method(self, args, kwargs):
+ @noKwargs
+ def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
return self.found()
@noPosargs
- @permittedKwargs({})
+ @noKwargs
@FeatureDeprecated('ExternalProgram.path', '0.55.0',
'use ExternalProgram.full_path() instead')
- def path_method(self, args, kwargs):
+ def path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self._full_path()
@noPosargs
- @permittedKwargs({})
+ @noKwargs
@FeatureNew('ExternalProgram.full_path', '0.55.0')
- def full_path_method(self, args, kwargs):
+ def full_path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self._full_path()
- def _full_path(self):
+ def _full_path(self) -> str:
exe = self.held_object
+ # TODO: How is this case even possible? Why can this hold a build.Executable?
if isinstance(exe, build.Executable):
- return self.backend.get_target_filename_abs(exe)
+ assert self.interpreter.backend is not None
+ return self.interpreter.backend.get_target_filename_abs(exe)
+ if not self.found():
+ raise InterpreterException('Unable to get the path of a not-found external program')
+ path = exe.get_path()
+ assert path is not None
return exe.get_path()
- def found(self):
+ def found(self) -> bool:
return isinstance(self.held_object, build.Executable) or self.held_object.found()
- def get_command(self):
- return self.held_object.get_command()
-
- def get_name(self):
- exe = self.held_object
- if isinstance(exe, build.Executable):
- return exe.name
- return exe.get_name()
-
class ExternalLibraryHolder(ObjectHolder[ExternalLibrary]):
- def __init__(self, el: ExternalLibrary, subproject: str):
- super().__init__(el, subproject=subproject)
+ def __init__(self, el: ExternalLibrary, interpreter: 'Interpreter'):
+ super().__init__(el, interpreter)
self.methods.update({'found': self.found_method,
'type_name': self.type_name_method,
'partial_dependency': self.partial_dependency_method,
})
- def found(self):
- return self.held_object.found()
-
@noPosargs
- @permittedKwargs({})
- def type_name_method(self, args, kwargs):
+ @noKwargs
+ def type_name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.type_name
@noPosargs
- @permittedKwargs({})
- def found_method(self, args, kwargs):
- return self.found()
-
- def get_name(self):
- return self.held_object.name
-
- def get_compile_args(self):
- return self.held_object.get_compile_args()
-
- def get_link_args(self):
- return self.held_object.get_link_args()
-
- def get_exe_args(self):
- return self.held_object.get_exe_args()
+ @noKwargs
+ def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
+ return self.held_object.found()
@FeatureNew('dep.partial_dependency', '0.46.0')
@noPosargs
- @permittedKwargs(permitted_partial_dependency_kwargs)
- def partial_dependency_method(self, args, kwargs):
+ @typed_kwargs('dep.partial_dependency', *_PARTIAL_DEP_KWARGS)
+ def partial_dependency_method(self, args: T.List[TYPE_nvar], kwargs: 'kwargs.DependencyMethodPartialDependency') -> Dependency:
pdep = self.held_object.get_partial_dependency(**kwargs)
- return DependencyHolder(pdep, self.subproject)
-
-
-class GeneratedListHolder(ObjectHolder[build.GeneratedList]):
- def __init__(self, arg1: 'build.GeneratedList'):
- super().__init__(arg1)
-
- def __repr__(self) -> str:
- r = '<{}: {!r}>'
- return r.format(self.__class__.__name__, self.held_object.get_outputs())
-
+ return pdep
# A machine that's statically known from the cross file
class MachineHolder(ObjectHolder['MachineInfo']):
- def __init__(self, machine_info: 'MachineInfo'):
- super().__init__(machine_info)
+ def __init__(self, machine_info: 'MachineInfo', interpreter: 'Interpreter'):
+ super().__init__(machine_info, interpreter)
self.methods.update({'system': self.system_method,
'cpu': self.cpu_method,
'cpu_family': self.cpu_family_method,
@@ -616,88 +632,45 @@ class MachineHolder(ObjectHolder['MachineInfo']):
})
@noPosargs
- @permittedKwargs({})
- def cpu_family_method(self, args: T.List[TYPE_var], kwargs: TYPE_nkwargs) -> str:
+ @noKwargs
+ def cpu_family_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.cpu_family
@noPosargs
- @permittedKwargs({})
- def cpu_method(self, args: T.List[TYPE_var], kwargs: TYPE_nkwargs) -> str:
+ @noKwargs
+ def cpu_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.cpu
@noPosargs
- @permittedKwargs({})
- def system_method(self, args: T.List[TYPE_var], kwargs: TYPE_nkwargs) -> str:
+ @noKwargs
+ def system_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.system
@noPosargs
- @permittedKwargs({})
- def endian_method(self, args: T.List[TYPE_var], kwargs: TYPE_nkwargs) -> str:
+ @noKwargs
+ def endian_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.endian
class IncludeDirsHolder(ObjectHolder[build.IncludeDirs]):
- def __init__(self, idobj: build.IncludeDirs):
- super().__init__(idobj)
+ pass
class FileHolder(ObjectHolder[mesonlib.File]):
- def __init__(self, fobj: mesonlib.File):
- super().__init__(fobj)
+ pass
class HeadersHolder(ObjectHolder[build.Headers]):
- def __init__(self, obj: build.Headers):
- super().__init__(obj)
-
- def set_install_subdir(self, subdir):
- self.held_object.install_subdir = subdir
-
- def get_install_subdir(self):
- return self.held_object.install_subdir
-
- def get_sources(self):
- return self.held_object.sources
-
- def get_custom_install_dir(self):
- return self.held_object.custom_install_dir
-
- def get_custom_install_mode(self):
- return self.held_object.custom_install_mode
+ pass
class DataHolder(ObjectHolder[build.Data]):
- def __init__(self, data: build.Data):
- super().__init__(data)
-
- def get_source_subdir(self):
- return self.held_object.source_subdir
-
- def get_sources(self):
- return self.held_object.sources
-
- def get_install_dir(self):
- return self.held_object.install_dir
+ pass
-class InstallDirHolder(ObjectHolder[build.IncludeDirs]):
- def __init__(self, obj: build.InstallDir):
- super().__init__(obj)
+class InstallDirHolder(ObjectHolder[build.InstallDir]):
+ pass
class ManHolder(ObjectHolder[build.Man]):
- def __init__(self, obj: build.Man):
- super().__init__(obj)
-
- def get_custom_install_dir(self) -> T.Optional[str]:
- return self.held_object.custom_install_dir
-
- def get_custom_install_mode(self) -> T.Optional[FileMode]:
- return self.held_object.custom_install_mode
-
- def locale(self) -> T.Optional[str]:
- return self.held_object.locale
-
- def get_sources(self) -> T.List[mesonlib.File]:
- return self.held_object.sources
+ pass
class GeneratedObjectsHolder(ObjectHolder[build.ExtractedObjects]):
- def __init__(self, held_object: build.ExtractedObjects):
- super().__init__(held_object)
+ pass
class Test(MesonInterpreterObject):
def __init__(self, name: str, project: str, suite: T.List[str], exe: build.Executable,
@@ -720,17 +693,27 @@ class Test(MesonInterpreterObject):
self.protocol = TestProtocol.from_str(protocol)
self.priority = priority
- def get_exe(self):
+ def get_exe(self) -> build.Executable:
return self.exe
- def get_name(self):
+ def get_name(self) -> str:
return self.name
-class SubprojectHolder(ObjectHolder[T.Optional['Interpreter']]):
+class NullSubprojectInterpreter(HoldableObject):
+ pass
- def __init__(self, subinterpreter: T.Optional['Interpreter'], subdir: str, warnings=0, disabled_feature=None,
- exception=None):
- super().__init__(subinterpreter)
+# TODO: This should really be an `ObjectHolder`, but the additional stuff in this
+# class prevents this. Thus, this class should be split into a pure
+# `ObjectHolder` and a class specifically for stroing in `Interpreter`.
+class SubprojectHolder(MesonInterpreterObject):
+
+ def __init__(self, subinterpreter: T.Union['Interpreter', NullSubprojectInterpreter],
+ subdir: str,
+ warnings: int = 0,
+ disabled_feature: T.Optional[str] = None,
+ exception: T.Optional[MesonException] = None) -> None:
+ super().__init__()
+ self.held_object = subinterpreter
self.warnings = warnings
self.disabled_feature = disabled_feature
self.exception = exception
@@ -740,20 +723,20 @@ class SubprojectHolder(ObjectHolder[T.Optional['Interpreter']]):
})
@noPosargs
- @permittedKwargs({})
- def found_method(self, args, kwargs):
+ @noKwargs
+ def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
return self.found()
- def found(self):
- return self.held_object is not None
+ def found(self) -> bool:
+ return not isinstance(self.held_object, NullSubprojectInterpreter)
- @permittedKwargs({})
+ @noKwargs
@noArgsFlattening
@unholder_return
def get_variable_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.Union[TYPE_var, InterpreterObject]:
if len(args) < 1 or len(args) > 2:
raise InterpreterException('Get_variable takes one or two arguments.')
- if not self.found():
+ if isinstance(self.held_object, NullSubprojectInterpreter): # == not self.found()
raise InterpreterException('Subproject "%s" disabled can\'t get_variable on it.' % (self.subdir))
varname = args[0]
if not isinstance(varname, str):
@@ -768,12 +751,8 @@ class SubprojectHolder(ObjectHolder[T.Optional['Interpreter']]):
raise InvalidArguments(f'Requested variable "{varname}" not found.')
-class ModuleObjectHolder(ObjectHolder['ModuleObject']):
- def __init__(self, modobj: 'ModuleObject', interpreter: 'Interpreter'):
- super().__init__(modobj)
- self.interpreter = interpreter
-
- def method_call(self, method_name, args, kwargs):
+class ModuleObjectHolder(ObjectHolder[ModuleObject]):
+ def method_call(self, method_name: str, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> TYPE_var:
modobj = self.held_object
method = modobj.methods.get(method_name)
if not method:
@@ -791,10 +770,10 @@ class ModuleObjectHolder(ObjectHolder['ModuleObject']):
if isinstance(ret, ModuleReturnValue):
self.interpreter.process_new_values(ret.new_objects)
ret = ret.return_value
- return self.interpreter.holderify(ret)
+ return ret
class MutableModuleObjectHolder(ModuleObjectHolder, MutableInterpreterObject):
- def __deepcopy__(self, memo):
+ def __deepcopy__(self, memo: T.Dict[int, T.Any]) -> 'MutableModuleObjectHolder':
# Deepcopy only held object, not interpreter
modobj = copy.deepcopy(self.held_object, memo)
return MutableModuleObjectHolder(modobj, self.interpreter)
@@ -916,7 +895,7 @@ class SharedModuleHolder(BuildTargetHolder[build.SharedModule]):
class JarHolder(BuildTargetHolder[build.Jar]):
pass
-class CustomTargetIndexHolder(TargetHolder[build.CustomTargetIndex]):
+class CustomTargetIndexHolder(ObjectHolder[build.CustomTargetIndex]):
def __init__(self, target: build.CustomTargetIndex, interp: 'Interpreter'):
super().__init__(target, interp)
self.methods.update({'full_path': self.full_path_method,
@@ -924,74 +903,69 @@ class CustomTargetIndexHolder(TargetHolder[build.CustomTargetIndex]):
@FeatureNew('custom_target[i].full_path', '0.54.0')
@noPosargs
- @permittedKwargs({})
- def full_path_method(self, args, kwargs):
+ @noKwargs
+ def full_path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+ assert self.interpreter.backend is not None
return self.interpreter.backend.get_target_filename_abs(self.held_object)
-class CustomTargetHolder(TargetHolder[build.CustomTarget]):
+class CustomTargetHolder(ObjectHolder[build.CustomTarget]):
def __init__(self, target: 'build.CustomTarget', interp: 'Interpreter'):
super().__init__(target, interp)
self.methods.update({'full_path': self.full_path_method,
'to_list': self.to_list_method,
})
- def __repr__(self):
+ def __repr__(self) -> str:
r = '<{} {}: {}>'
h = self.held_object
return r.format(self.__class__.__name__, h.get_id(), h.command)
@noPosargs
- @permittedKwargs({})
- def full_path_method(self, args, kwargs):
+ @noKwargs
+ def full_path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.interpreter.backend.get_target_filename_abs(self.held_object)
@FeatureNew('custom_target.to_list', '0.54.0')
@noPosargs
- @permittedKwargs({})
- def to_list_method(self, args, kwargs):
+ @noKwargs
+ def to_list_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[build.CustomTargetIndex]:
result = []
for i in self.held_object:
- result.append(CustomTargetIndexHolder(i, self.interpreter))
+ result.append(i)
return result
- def __getitem__(self, index):
- return CustomTargetIndexHolder(self.held_object[index], self.interpreter)
+ def __getitem__(self, index: int) -> build.CustomTargetIndex:
+ return self.held_object[index]
- def __setitem__(self, index, value): # lgtm[py/unexpected-raise-in-special-method]
+ def __setitem__(self, index: int, value: T.Any) -> None: # lgtm[py/unexpected-raise-in-special-method]
raise InterpreterException('Cannot set a member of a CustomTarget')
- def __delitem__(self, index): # lgtm[py/unexpected-raise-in-special-method]
+ def __delitem__(self, index: int) -> None: # lgtm[py/unexpected-raise-in-special-method]
raise InterpreterException('Cannot delete a member of a CustomTarget')
- def outdir_include(self):
- return IncludeDirsHolder(build.IncludeDirs('', [], False,
- [os.path.join('@BUILD_ROOT@', self.interpreter.backend.get_target_dir(self.held_object))]))
-
-class RunTargetHolder(TargetHolder):
- def __init__(self, target, interp):
- super().__init__(target, interp)
+class RunTargetHolder(ObjectHolder[build.RunTarget]):
+ pass
- def __repr__(self):
- r = '<{} {}: {}>'
- h = self.held_object
- return r.format(self.__class__.__name__, h.get_id(), h.command)
+class AliasTargetHolder(ObjectHolder[build.AliasTarget]):
+ pass
+class GeneratedListHolder(ObjectHolder[build.GeneratedList]):
+ pass
class GeneratorHolder(ObjectHolder[build.Generator]):
-
- def __init__(self, gen: 'build.Generator', interpreter: 'Interpreter'):
- self().__init__(self, gen, interpreter.subproject)
- self.interpreter = interpreter
+ def __init__(self, gen: build.Generator, interpreter: 'Interpreter'):
+ super().__init__(gen, interpreter)
self.methods.update({'process': self.process_method})
- @typed_pos_args('generator.process', min_varargs=1, varargs=(str, mesonlib.File, CustomTargetHolder, CustomTargetIndexHolder, GeneratedListHolder))
+ @typed_pos_args('generator.process', min_varargs=1, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList))
@typed_kwargs(
'generator.process',
KwargInfo('preserve_path_from', str, since='0.45.0'),
KwargInfo('extra_args', ContainerTypeInfo(list, str), listify=True, default=[]),
)
- def process_method(self, args: T.Tuple[T.List[T.Union[str, mesonlib.File, CustomTargetHolder, CustomTargetIndexHolder, GeneratedListHolder]]],
- kwargs: 'kwargs.GeneratorProcess') -> GeneratedListHolder:
+ def process_method(self,
+ args: T.Tuple[T.List[T.Union[str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]]],
+ kwargs: 'kwargs.GeneratorProcess') -> build.GeneratedList:
preserve_path_from = kwargs['preserve_path_from']
if preserve_path_from is not None:
preserve_path_from = os.path.normpath(preserve_path_from)
@@ -999,12 +973,12 @@ class GeneratorHolder(ObjectHolder[build.Generator]):
# This is a bit of a hack. Fix properly before merging.
raise InvalidArguments('Preserve_path_from must be an absolute path for now. Sorry.')
- if any(isinstance(a, (CustomTargetHolder, CustomTargetIndexHolder, GeneratedListHolder)) for a in args[0]):
+ if any(isinstance(a, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)) for a in args[0]):
FeatureNew.single_use(
f'Calling generator.process with CustomTaget or Index of CustomTarget.',
'0.57.0', self.interpreter.subproject)
- gl = self.held_object.process_files(mesonlib.unholder(args[0]), self.interpreter,
+ gl = self.held_object.process_files(args[0], self.interpreter,
preserve_path_from, extra_args=kwargs['extra_args'])
- return GeneratedListHolder(gl)
+ return gl
diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py
index 9734caa..1cc2082 100644
--- a/mesonbuild/interpreter/kwargs.py
+++ b/mesonbuild/interpreter/kwargs.py
@@ -4,15 +4,14 @@
"""Keyword Argument type annotations."""
+from mesonbuild import coredata
import typing as T
from typing_extensions import TypedDict, Literal
+from .. import build
from ..mesonlib import MachineChoice, File
-from .interpreterobjects import (
- BuildTargetHolder, CustomTargetHolder, EnvironmentVariablesHolder,
- FeatureOptionHolder, TargetHolder
-)
+from .interpreterobjects import EnvironmentVariablesObject
class FuncAddProjectArgs(TypedDict):
@@ -34,13 +33,13 @@ class BaseTest(TypedDict):
"""Shared base for the Rust module."""
- args: T.List[T.Union[str, File, TargetHolder]]
+ args: T.List[T.Union[str, File, build.Target]]
should_fail: bool
timeout: int
workdir: T.Optional[str]
- depends: T.List[T.Union[CustomTargetHolder, BuildTargetHolder]]
+ depends: T.List[T.Union[build.CustomTarget, build.BuildTarget]]
priority: int
- env: T.Union[EnvironmentVariablesHolder, T.List[str], T.Dict[str, str], str]
+ env: T.Union[EnvironmentVariablesObject, T.List[str], T.Dict[str, str], str]
suite: T.List[str]
@@ -70,7 +69,7 @@ class ExtractRequired(TypedDict):
a boolean or a feature option should inherit it's arguments from this class.
"""
- required: T.Union[bool, 'FeatureOptionHolder']
+ required: T.Union[bool, coredata.UserFeatureOption]
class FuncGenerator(TypedDict):
@@ -81,7 +80,7 @@ class FuncGenerator(TypedDict):
output: T.List[str]
depfile: bool
capture: bool
- depends: T.List[T.Union['BuildTargetHolder', 'CustomTargetHolder']]
+ depends: T.List[T.Union[build.BuildTarget, build.CustomTarget]]
class GeneratorProcess(TypedDict):
@@ -90,3 +89,16 @@ class GeneratorProcess(TypedDict):
preserve_path_from: T.Optional[str]
extra_args: T.List[str]
+
+class DependencyMethodPartialDependency(TypedDict):
+
+ """ Keyword Arguments for the dep.partial_dependency methods """
+
+ compile_args: bool
+ link_args: bool
+ links: bool
+ includes: bool
+ sources: bool
+
+class BuildTargeMethodExtractAllObjects(TypedDict):
+ recursive: bool
diff --git a/mesonbuild/interpreter/mesonmain.py b/mesonbuild/interpreter/mesonmain.py
index dbd0ade..c3cc0d2 100644
--- a/mesonbuild/interpreter/mesonmain.py
+++ b/mesonbuild/interpreter/mesonmain.py
@@ -5,16 +5,15 @@ from .. import dependencies
from .. import build
from .. import mlog
-from ..mesonlib import unholder, MachineChoice, OptionKey
+from ..mesonlib import MachineChoice, OptionKey
from ..programs import OverrideProgram, ExternalProgram
from ..interpreterbase import (MesonInterpreterObject, FeatureNewKwargs, FeatureNew, FeatureDeprecated,
typed_pos_args, permittedKwargs, noArgsFlattening, noPosargs, noKwargs,
MesonVersionString, InterpreterException)
-from .compiler import CompilerHolder
from .interpreterobjects import (ExecutableHolder, ExternalProgramHolder,
CustomTargetHolder, CustomTargetIndexHolder,
- EnvironmentVariablesHolder)
+ EnvironmentVariablesObject)
import typing as T
@@ -57,11 +56,11 @@ class MesonMain(MesonInterpreterObject):
'add_devenv': self.add_devenv_method,
})
- def _find_source_script(self, prog: T.Union[str, mesonlib.File, ExecutableHolder], args):
+ def _find_source_script(self, prog: T.Union[str, mesonlib.File, build.Executable, ExternalProgram], args):
- if isinstance(prog, (ExecutableHolder, ExternalProgramHolder)):
- return self.interpreter.backend.get_executable_serialisation([unholder(prog)] + args)
- found = self.interpreter.func_find_program({}, prog, {}).held_object
+ if isinstance(prog, (build.Executable, ExternalProgram)):
+ return self.interpreter.backend.get_executable_serialisation([prog] + args)
+ found = self.interpreter.func_find_program({}, prog, {})
es = self.interpreter.backend.get_executable_serialisation([found] + args)
es.subproject = self.interpreter.subproject
return es
@@ -254,7 +253,7 @@ class MesonMain(MesonInterpreterObject):
for_machine = self.interpreter.machine_from_native_kwarg(kwargs)
clist = self.interpreter.coredata.compilers[for_machine]
if cname in clist:
- return CompilerHolder(clist[cname], self.build.environment, self.interpreter.subproject)
+ return clist[cname]
raise InterpreterException(f'Tried to access compiler for language "{cname}", not specified for {for_machine.get_lower_case_name()} machine.')
@noPosargs
@@ -375,9 +374,9 @@ class MesonMain(MesonInterpreterObject):
@FeatureNew('add_devenv', '0.58.0')
@noKwargs
- @typed_pos_args('add_devenv', (str, list, dict, EnvironmentVariablesHolder))
- def add_devenv_method(self, args: T.Union[str, list, dict, EnvironmentVariablesHolder], kwargs: T.Dict[str, T.Any]) -> None:
+ @typed_pos_args('add_devenv', (str, list, dict, EnvironmentVariablesObject))
+ def add_devenv_method(self, args: T.Union[str, list, dict, EnvironmentVariablesObject], kwargs: T.Dict[str, T.Any]) -> None:
env = args[0]
if isinstance(env, (str, list, dict)):
- env = EnvironmentVariablesHolder(env)
- self.build.devenv.append(env.held_object)
+ env = EnvironmentVariablesObject(env)
+ self.build.devenv.append(env.vars)
diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py
index f3bcfab..46fd27b 100644
--- a/mesonbuild/modules/python.py
+++ b/mesonbuild/modules/python.py
@@ -50,6 +50,7 @@ class PythonDependency(SystemDependency):
self.variables = python_holder.variables
self.paths = python_holder.paths
self.link_libpython = python_holder.link_libpython
+ self.info: T.Optional[T.Dict[str, str]] = None
if mesonlib.version_compare(self.version, '>= 3.0'):
self.major_version = 3
else:
@@ -278,12 +279,20 @@ print (json.dumps ({
}))
'''
+class PythonExternalProgram(ExternalProgram):
+ def __init__(self, name: str, command: T.Optional[T.List[str]] = None, ext_prog: T.Optional[ExternalProgram] = None):
+ if ext_prog is None:
+ super().__init__(name, command=command, silent=True)
+ else:
+ self.name = ext_prog.name
+ self.command = ext_prog.command
+ self.path = ext_prog.path
+ self.info: T.Dict[str, str] = {}
class PythonInstallation(ExternalProgramHolder):
- def __init__(self, interpreter, python, info):
- ExternalProgramHolder.__init__(self, python, interpreter.subproject)
- self.interpreter = interpreter
- self.subproject = self.interpreter.subproject
+ def __init__(self, python, interpreter):
+ ExternalProgramHolder.__init__(self, python, interpreter)
+ info = python.info
prefix = self.interpreter.environment.coredata.get_option(mesonlib.OptionKey('prefix'))
self.variables = info['variables']
self.paths = info['paths']
@@ -325,11 +334,10 @@ class PythonInstallation(ExternalProgramHolder):
# behavior. See https://github.com/mesonbuild/meson/issues/4117
if not self.link_libpython:
new_deps = []
- for holder in mesonlib.extract_as_list(kwargs, 'dependencies'):
- dep = holder.held_object
+ for dep in mesonlib.extract_as_list(kwargs, 'dependencies'):
if isinstance(dep, PythonDependency):
- holder = self.interpreter.holderify(dep.get_partial_dependency(compile_args=True))
- new_deps.append(holder)
+ dep = dep.get_partial_dependency(compile_args=True)
+ new_deps.append(dep)
kwargs['dependencies'] = new_deps
suffix = self.variables.get('EXT_SUFFIX') or self.variables.get('SO') or self.variables.get('.so')
@@ -360,7 +368,7 @@ class PythonInstallation(ExternalProgramHolder):
dep = PythonDependency(self, self.interpreter.environment, kwargs)
if required and not dep.found():
raise mesonlib.MesonException('Python dependency not found')
- return self.interpreter.holderify(dep)
+ return dep
@permittedKwargs(['pure', 'subdir'])
def install_sources_method(self, args, kwargs):
@@ -377,7 +385,7 @@ class PythonInstallation(ExternalProgramHolder):
else:
kwargs['install_dir'] = os.path.join(self.platlib_install_path, subdir)
- return self.interpreter.holderify(self.interpreter.func_install_data(None, args, kwargs))
+ return self.interpreter.func_install_data(None, args, kwargs)
@noPosargs
@permittedKwargs(['pure', 'subdir'])
@@ -519,25 +527,26 @@ class PythonModule(ExtensionModule):
if disabled:
mlog.log('Program', name_or_path or 'python', 'found:', mlog.red('NO'), '(disabled by:', mlog.bold(feature), ')')
- return ExternalProgramHolder(NonExistingExternalProgram(), state.subproject)
+ return NonExistingExternalProgram()
if not name_or_path:
- python = ExternalProgram('python3', mesonlib.python_command, silent=True)
+ python = PythonExternalProgram('python3', mesonlib.python_command)
else:
- python = ExternalProgram.from_entry('python3', name_or_path)
+ tmp_python = ExternalProgram.from_entry('python3', name_or_path)
+ python = PythonExternalProgram('python3', ext_prog=tmp_python)
if not python.found() and mesonlib.is_windows():
pythonpath = self._get_win_pythonpath(name_or_path)
if pythonpath is not None:
name_or_path = pythonpath
- python = ExternalProgram(name_or_path, silent=True)
+ python = PythonExternalProgram(name_or_path)
# Last ditch effort, python2 or python3 can be named python
# on various platforms, let's not give up just yet, if an executable
# named python is available and has a compatible version, let's use
# it
if not python.found() and name_or_path in ['python2', 'python3']:
- python = ExternalProgram('python', silent=True)
+ python = PythonExternalProgram('python')
if python.found() and want_modules:
for mod in want_modules:
@@ -566,11 +575,11 @@ class PythonModule(ExtensionModule):
if not python.found():
if required:
raise mesonlib.MesonException('{} not found'.format(name_or_path or 'python'))
- res = ExternalProgramHolder(NonExistingExternalProgram(), state.subproject)
+ return NonExistingExternalProgram()
elif missing_modules:
if required:
raise mesonlib.MesonException('{} is missing modules: {}'.format(name_or_path or 'python', ', '.join(missing_modules)))
- res = ExternalProgramHolder(NonExistingExternalProgram(), state.subproject)
+ return NonExistingExternalProgram()
else:
# Sanity check, we expect to have something that at least quacks in tune
try:
@@ -586,14 +595,17 @@ class PythonModule(ExtensionModule):
mlog.debug(stderr)
if isinstance(info, dict) and 'version' in info and self._check_version(name_or_path, info['version']):
- res = PythonInstallation(self.interpreter, python, info)
+ python.info = info
+ return python
else:
- res = ExternalProgramHolder(NonExistingExternalProgram(), state.subproject)
if required:
raise mesonlib.MesonException(f'{python} is not a valid python or it is missing setuptools')
+ return NonExistingExternalProgram()
- return res
+ raise mesonlib.MesonBugException('Unreachable code was reached (PythonModule.find_installation).')
def initialize(*args, **kwargs):
- return PythonModule(*args, **kwargs)
+ mod = PythonModule(*args, **kwargs)
+ mod.interpreter.append_holder_map(PythonExternalProgram, PythonInstallation)
+ return mod
diff --git a/mesonbuild/modules/qt.py b/mesonbuild/modules/qt.py
index 8c673de..ae45e4d 100644
--- a/mesonbuild/modules/qt.py
+++ b/mesonbuild/modules/qt.py
@@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from mesonbuild import coredata
import os
import shutil
import typing as T
@@ -20,21 +21,19 @@ import xml.etree.ElementTree as ET
from . import ModuleReturnValue, ExtensionModule
from .. import build
-from .. import mesonlib
from .. import mlog
-from ..dependencies import find_external_dependency
+from ..dependencies import find_external_dependency, Dependency, ExternalLibrary
+from ..mesonlib import MesonException, File, FileOrString, version_compare, Popen_safe
+from . import ModuleReturnValue, ExtensionModule
from ..interpreter import extract_required_kwarg
-from ..interpreter.interpreterobjects import DependencyHolder, ExternalLibraryHolder, IncludeDirsHolder, FeatureOptionHolder, GeneratedListHolder
from ..interpreterbase import ContainerTypeInfo, FeatureDeprecated, KwargInfo, noPosargs, FeatureNew, typed_kwargs
-from ..mesonlib import MesonException, File
-from ..programs import NonExistingExternalProgram
+from ..programs import ExternalProgram, NonExistingExternalProgram
if T.TYPE_CHECKING:
from . import ModuleState
from ..dependencies.qt import QtPkgConfigDependency, QmakeQtDependency
from ..interpreter import Interpreter
from ..interpreter import kwargs
- from ..programs import ExternalProgram
QtDependencyType = T.Union[QtPkgConfigDependency, QmakeQtDependency]
@@ -45,7 +44,7 @@ if T.TYPE_CHECKING:
"""Keyword arguments for the Resource Compiler method."""
name: T.Optional[str]
- sources: T.List[mesonlib.FileOrString]
+ sources: T.List[FileOrString]
extra_args: T.List[str]
method: str
@@ -53,7 +52,7 @@ if T.TYPE_CHECKING:
"""Keyword arguments for the Ui Compiler method."""
- sources: T.List[mesonlib.FileOrString]
+ sources: T.List[FileOrString]
extra_args: T.List[str]
method: str
@@ -61,25 +60,25 @@ if T.TYPE_CHECKING:
"""Keyword arguments for the Moc Compiler method."""
- sources: T.List[mesonlib.FileOrString]
- headers: T.List[mesonlib.FileOrString]
+ sources: T.List[FileOrString]
+ headers: T.List[FileOrString]
extra_args: T.List[str]
method: str
- include_directories: T.List[T.Union[str, IncludeDirsHolder]]
- dependencies: T.List[T.Union[DependencyHolder, ExternalLibraryHolder]]
+ include_directories: T.List[T.Union[str, build.IncludeDirs]]
+ dependencies: T.List[T.Union[Dependency, ExternalLibrary]]
class PreprocessKwArgs(TypedDict):
- sources: T.List[mesonlib.FileOrString]
- moc_sources: T.List[mesonlib.FileOrString]
- moc_headers: T.List[mesonlib.FileOrString]
- qresources: T.List[mesonlib.FileOrString]
- ui_files: T.List[mesonlib.FileOrString]
+ sources: T.List[FileOrString]
+ moc_sources: T.List[FileOrString]
+ moc_headers: T.List[FileOrString]
+ qresources: T.List[FileOrString]
+ ui_files: T.List[FileOrString]
moc_extra_arguments: T.List[str]
rcc_extra_arguments: T.List[str]
uic_extra_arguments: T.List[str]
- include_directories: T.List[T.Union[str, IncludeDirsHolder]]
- dependencies: T.List[T.Union[DependencyHolder, ExternalLibraryHolder]]
+ include_directories: T.List[T.Union[str, build.IncludeDirs]]
+ dependencies: T.List[T.Union[Dependency, ExternalLibrary]]
method: str
class HasToolKwArgs(kwargs.ExtractRequired):
@@ -104,10 +103,10 @@ class QtBaseModule(ExtensionModule):
def __init__(self, interpreter: 'Interpreter', qt_version: int = 5):
ExtensionModule.__init__(self, interpreter)
self.qt_version = qt_version
- self.moc: 'ExternalProgram' = NonExistingExternalProgram('moc')
- self.uic: 'ExternalProgram' = NonExistingExternalProgram('uic')
- self.rcc: 'ExternalProgram' = NonExistingExternalProgram('rcc')
- self.lrelease: 'ExternalProgram' = NonExistingExternalProgram('lrelease')
+ self.moc: ExternalProgram = NonExistingExternalProgram('moc')
+ self.uic: ExternalProgram = NonExistingExternalProgram('uic')
+ self.rcc: ExternalProgram = NonExistingExternalProgram('rcc')
+ self.lrelease: ExternalProgram = NonExistingExternalProgram('lrelease')
self.methods.update({
'has_tools': self.has_tools,
'preprocess': self.preprocess,
@@ -141,14 +140,14 @@ class QtBaseModule(ExtensionModule):
if name == 'lrelease':
arg = ['-version']
- elif mesonlib.version_compare(qt_dep.version, '>= 5'):
+ elif version_compare(qt_dep.version, '>= 5'):
arg = ['--version']
else:
arg = ['-v']
# Ensure that the version of qt and each tool are the same
- def get_version(p: 'ExternalProgram') -> str:
- _, out, err = mesonlib.Popen_safe(p.get_command() + arg)
+ def get_version(p: ExternalProgram) -> str:
+ _, out, err = Popen_safe(p.get_command() + arg)
if b.startswith('lrelease') or not qt_dep.version.startswith('4'):
care = out
else:
@@ -157,7 +156,7 @@ class QtBaseModule(ExtensionModule):
p = state.find_program(b, required=False,
version_func=get_version,
- wanted=wanted).held_object
+ wanted=wanted)
if p.found():
setattr(self, name, p)
@@ -172,7 +171,7 @@ class QtBaseModule(ExtensionModule):
if qt.found():
# Get all tools and then make sure that they are the right version
self.compilers_detect(state, qt)
- if mesonlib.version_compare(qt.version, '>=5.14.0'):
+ if version_compare(qt.version, '>=5.14.0'):
self._rcc_supports_depfiles = True
else:
mlog.warning('rcc dependencies will not work properly until you move to Qt >= 5.14:',
@@ -185,7 +184,7 @@ class QtBaseModule(ExtensionModule):
self.lrelease = NonExistingExternalProgram(name='lrelease' + suffix)
@staticmethod
- def _qrc_nodes(state: 'ModuleState', rcc_file: 'mesonlib.FileOrString') -> T.Tuple[str, T.List[str]]:
+ def _qrc_nodes(state: 'ModuleState', rcc_file: 'FileOrString') -> T.Tuple[str, T.List[str]]:
abspath: str
if isinstance(rcc_file, str):
abspath = os.path.join(state.environment.source_dir, state.subdir, rcc_file)
@@ -210,7 +209,7 @@ class QtBaseModule(ExtensionModule):
except Exception:
raise MesonException(f'Unable to parse resource file {abspath}')
- def _parse_qrc_deps(self, state: 'ModuleState', rcc_file: 'mesonlib.FileOrString') -> T.List[File]:
+ def _parse_qrc_deps(self, state: 'ModuleState', rcc_file: 'FileOrString') -> T.List[File]:
rcc_dirname, nodes = self._qrc_nodes(state, rcc_file)
result: T.List[File] = []
for resource_path in nodes:
@@ -243,7 +242,7 @@ class QtBaseModule(ExtensionModule):
@noPosargs
@typed_kwargs(
'qt.has_tools',
- KwargInfo('required', (bool, FeatureOptionHolder), default=False),
+ KwargInfo('required', (bool, coredata.UserFeatureOption), default=False),
KwargInfo('method', str, default='auto'),
)
def has_tools(self, state: 'ModuleState', args: T.Tuple, kwargs: 'HasToolKwArgs') -> bool:
@@ -351,7 +350,7 @@ class QtBaseModule(ExtensionModule):
kwargs['extra_args'] + ['-o', '@OUTPUT@', '@INPUT@'],
['ui_@BASENAME@.h'],
name=f'Qt{self.qt_version} ui')
- out = GeneratedListHolder(gen.process_files(kwargs['sources'], state))
+ out = gen.process_files(kwargs['sources'], state)
return ModuleReturnValue(out, [out])
@FeatureNew('qt.compile_moc', '0.59.0')
@@ -362,8 +361,8 @@ class QtBaseModule(ExtensionModule):
KwargInfo('headers', ContainerTypeInfo(list, (File, str)), listify=True, default=[]),
KwargInfo('extra_args', ContainerTypeInfo(list, str), listify=True, default=[]),
KwargInfo('method', str, default='auto'),
- KwargInfo('include_directories', ContainerTypeInfo(list, (IncludeDirsHolder, str)), listify=True, default=[]),
- KwargInfo('dependencies', ContainerTypeInfo(list, (DependencyHolder, ExternalLibraryHolder)), listify=True, default=[]),
+ KwargInfo('include_directories', ContainerTypeInfo(list, (build.IncludeDirs, str)), listify=True, default=[]),
+ KwargInfo('dependencies', ContainerTypeInfo(list, (Dependency, ExternalLibrary)), listify=True, default=[]),
)
def compile_moc(self, state: 'ModuleState', args: T.Tuple, kwargs: 'MocCompilerKwArgs') -> ModuleReturnValue:
self._detect_tools(state, kwargs['method'])
@@ -378,7 +377,7 @@ class QtBaseModule(ExtensionModule):
inc = state.get_include_args(include_dirs=kwargs['include_directories'])
compile_args: T.List[str] = []
for dep in kwargs['dependencies']:
- compile_args.extend([a for a in dep.held_object.get_all_compile_args() if a.startswith(('-I', '-D'))])
+ compile_args.extend([a for a in dep.get_all_compile_args() if a.startswith(('-I', '-D'))])
output: T.List[build.GeneratedList] = []
@@ -408,8 +407,8 @@ class QtBaseModule(ExtensionModule):
KwargInfo('rcc_extra_arguments', ContainerTypeInfo(list, str), listify=True, default=[], since='0.49.0'),
KwargInfo('uic_extra_arguments', ContainerTypeInfo(list, str), listify=True, default=[], since='0.49.0'),
KwargInfo('method', str, default='auto'),
- KwargInfo('include_directories', ContainerTypeInfo(list, (IncludeDirsHolder, str)), listify=True, default=[]),
- KwargInfo('dependencies', ContainerTypeInfo(list, (DependencyHolder, ExternalLibraryHolder)), listify=True, default=[]),
+ KwargInfo('include_directories', ContainerTypeInfo(list, (build.IncludeDirs, str)), listify=True, default=[]),
+ KwargInfo('dependencies', ContainerTypeInfo(list, (Dependency, ExternalLibrary)), listify=True, default=[]),
)
def preprocess(self, state: 'ModuleState', args: T.List[T.Union[str, File]], kwargs: 'PreprocessKwArgs') -> ModuleReturnValue:
_sources = args[1:]
diff --git a/mesonbuild/modules/sourceset.py b/mesonbuild/modules/sourceset.py
index eea3dbd..ba8b300 100644
--- a/mesonbuild/modules/sourceset.py
+++ b/mesonbuild/modules/sourceset.py
@@ -14,16 +14,13 @@
from collections import namedtuple
from .. import mesonlib
+from .. import build
from ..mesonlib import listify, OrderedSet
from . import ExtensionModule, ModuleObject, MutableModuleObject
from ..interpreterbase import (
noPosargs, noKwargs, permittedKwargs,
InterpreterException, InvalidArguments, InvalidCode, FeatureNew,
)
-from ..interpreter import (
- GeneratedListHolder, CustomTargetHolder,
- CustomTargetIndexHolder
-)
SourceSetRule = namedtuple('SourceSetRule', 'keys sources if_false sourcesets dependencies extra_deps')
SourceFiles = namedtuple('SourceFiles', 'sources dependencies')
@@ -49,8 +46,8 @@ class SourceSet(MutableModuleObject):
deps = []
for x in arg:
if isinstance(x, (str, mesonlib.File,
- GeneratedListHolder, CustomTargetHolder,
- CustomTargetIndexHolder)):
+ build.GeneratedList, build.CustomTarget,
+ build.CustomTargetIndex)):
sources.append(x)
elif hasattr(x, 'found'):
if not allow_deps:
diff --git a/mesonbuild/modules/unstable_external_project.py b/mesonbuild/modules/unstable_external_project.py
index f10c7aa..e997f6a 100644
--- a/mesonbuild/modules/unstable_external_project.py
+++ b/mesonbuild/modules/unstable_external_project.py
@@ -22,7 +22,6 @@ from ..mesonlib import (MesonException, Popen_safe, MachineChoice,
get_variable_regex, do_replacement, extract_as_list)
from ..interpreterbase import InterpreterException, FeatureNew
from ..interpreterbase import permittedKwargs, typed_pos_args
-from ..interpreter import DependencyHolder
from ..compilers.compilers import CFLAGS_MAPPING, CEXE_MAPPING
from ..dependencies import InternalDependency, PkgConfigDependency
from ..mesonlib import OptionKey
@@ -237,7 +236,7 @@ class ExternalProject(ModuleObject):
variables = []
dep = InternalDependency(version, incdir, compile_args, link_args, libs,
libs_whole, sources, final_deps, variables)
- return DependencyHolder(dep, self.subproject)
+ return dep
class ExternalProjectModule(ExtensionModule):
diff --git a/mesonbuild/modules/unstable_rust.py b/mesonbuild/modules/unstable_rust.py
index e5af2d7..995370a 100644
--- a/mesonbuild/modules/unstable_rust.py
+++ b/mesonbuild/modules/unstable_rust.py
@@ -19,15 +19,11 @@ from . import ExtensionModule, ModuleReturnValue
from .. import mlog
from ..build import BuildTarget, CustomTargetIndex, Executable, GeneratedList, InvalidArguments, IncludeDirs, CustomTarget
from ..interpreter.interpreter import TEST_KWARGS
-from ..interpreter.interpreterobjects import (
- BuildTargetHolder,
- CustomTargetHolder,
- DependencyHolder,
- ExecutableHolder,
- ExternalLibraryHolder,
-)
from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, permittedKwargs, FeatureNew, typed_kwargs, typed_pos_args, noPosargs
-from ..mesonlib import stringlistify, unholder, listify, typeslistify, File
+from ..mesonlib import stringlistify, listify, typeslistify, File
+from ..dependencies import Dependency, ExternalLibrary
+from ..interpreterbase import InterpreterException, permittedKwargs, FeatureNew, typed_pos_args, noPosargs
+from ..mesonlib import stringlistify, listify, typeslistify, File
if T.TYPE_CHECKING:
from . import ModuleState
@@ -38,7 +34,7 @@ if T.TYPE_CHECKING:
class FuncTest(_kwargs.BaseTest):
- dependencies: T.List[T.Union[DependencyHolder, ExternalLibraryHolder]]
+ dependencies: T.List[T.Union[Dependency, ExternalLibrary]]
is_parallel: bool
@@ -55,18 +51,18 @@ class RustModule(ExtensionModule):
'bindgen': self.bindgen,
})
- @typed_pos_args('rust.test', str, BuildTargetHolder)
+ @typed_pos_args('rust.test', str, BuildTarget)
@typed_kwargs(
'rust.test',
*TEST_KWARGS,
KwargInfo('is_parallel', bool, default=False),
KwargInfo(
'dependencies',
- ContainerTypeInfo(list, (DependencyHolder, ExternalLibraryHolder)),
+ ContainerTypeInfo(list, (Dependency, ExternalLibrary)),
listify=True,
default=[]),
)
- def test(self, state: 'ModuleState', args: T.Tuple[str, BuildTargetHolder], kwargs: 'FuncTest') -> ModuleReturnValue:
+ def test(self, state: 'ModuleState', args: T.Tuple[str, BuildTarget], kwargs: 'FuncTest') -> ModuleReturnValue:
"""Generate a rust test target from a given rust target.
Rust puts it's unitests inside it's main source files, unlike most
@@ -151,11 +147,10 @@ class RustModule(ExtensionModule):
new_target_kwargs
)
- e = ExecutableHolder(new_target, self.interpreter)
test = self.interpreter.make_test(
- self.interpreter.current_node, (name, e), tkwargs)
+ self.interpreter.current_node, (name, new_target), tkwargs)
- return ModuleReturnValue(None, [e, test])
+ return ModuleReturnValue(None, [new_target, test])
@noPosargs
@permittedKwargs({'input', 'output', 'include_directories', 'c_args', 'args'})
@@ -184,7 +179,7 @@ class RustModule(ExtensionModule):
bind_args: T.List[str] = stringlistify(listify(kwargs.get('args', [])))
# Split File and Target dependencies to add pass to CustomTarget
- depends: T.List[T.Union[GeneratedList, BuildTarget, CustomTargetIndex]] = []
+ depends: T.List[T.Union[GeneratedList, BuildTarget, CustomTargetIndex, CustomTarget]] = []
depend_files: T.List[File] = []
for d in _deps:
if isinstance(d, File):
@@ -225,7 +220,7 @@ class RustModule(ExtensionModule):
backend=state.backend,
)
- return ModuleReturnValue([target], [CustomTargetHolder(target, self.interpreter)])
+ return ModuleReturnValue([target], [target])
def initialize(*args: T.List, **kwargs: T.Dict) -> RustModule:
diff --git a/run_mypy.py b/run_mypy.py
index 982a3ae..e780adf 100755
--- a/run_mypy.py
+++ b/run_mypy.py
@@ -11,7 +11,7 @@ from mesonbuild.mesonlib import version_compare
modules = [
# fully typed submodules
- 'mesonbuild/ast',
+ # 'mesonbuild/ast',
'mesonbuild/cmake',
'mesonbuild/compilers',
'mesonbuild/dependencies',
@@ -23,6 +23,7 @@ modules = [
'mesonbuild/arglist.py',
# 'mesonbuild/coredata.py',
'mesonbuild/envconfig.py',
+ 'mesonbuild/interpreter/interpreterobjects.py',
'mesonbuild/linkers.py',
'mesonbuild/mcompile.py',
'mesonbuild/mdevenv.py',
diff --git a/test cases/common/178 bothlibraries/meson.build b/test cases/common/178 bothlibraries/meson.build
index 0bfba76..d52158d 100644
--- a/test cases/common/178 bothlibraries/meson.build
+++ b/test cases/common/178 bothlibraries/meson.build
@@ -20,6 +20,9 @@ exe_static2 = executable('prog-static2', 'main.c',
link_with : both_libs2.get_static_lib())
exe_both2 = executable('prog-both2', 'main.c', link_with : both_libs2)
+# Ensure that calling the build target methods also works
+assert(both_libs.name() == 'mylib')
+
test('runtest-shared-2', exe_shared2)
test('runtest-static-2', exe_static2)
test('runtest-both-2', exe_both2)
diff --git a/test cases/native/9 override with exe/meson.build b/test cases/native/9 override with exe/meson.build
index 62d2f32..5275532 100644
--- a/test cases/native/9 override with exe/meson.build
+++ b/test cases/native/9 override with exe/meson.build
@@ -1,4 +1,4 @@
-project('myexe', 'c')
+project('myexe', 'c', version: '0.1')
sub = subproject('sub')
prog = find_program('foobar', version : '>= 2.0', required : false)