holders: Fix the remaining code to respect the holder changes

pull/8903/head
Daniel Mensinger 4 years ago
parent 34c28dc92c
commit 7c757dff71
  1. 9
      mesonbuild/ast/interpreter.py
  2. 2
      mesonbuild/build.py
  3. 28
      mesonbuild/interpreter/compiler.py
  4. 193
      mesonbuild/interpreter/interpreter.py
  5. 548
      mesonbuild/interpreter/interpreterobjects.py
  6. 30
      mesonbuild/interpreter/kwargs.py
  7. 23
      mesonbuild/interpreter/mesonmain.py
  8. 54
      mesonbuild/modules/python.py
  9. 73
      mesonbuild/modules/qt.py
  10. 9
      mesonbuild/modules/sourceset.py
  11. 3
      mesonbuild/modules/unstable_external_project.py
  12. 29
      mesonbuild/modules/unstable_rust.py
  13. 3
      run_mypy.py
  14. 3
      test cases/common/178 bothlibraries/meson.build
  15. 2
      test cases/native/9 override with exe/meson.build

@ -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

@ -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

@ -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:

@ -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)

@ -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

@ -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

@ -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)

@ -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

@ -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:]

@ -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:

@ -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):

@ -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:

@ -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',

@ -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)

@ -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)

Loading…
Cancel
Save