aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/interpreter
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/interpreter')
-rw-r--r--mesonbuild/interpreter/compiler.py82
-rw-r--r--mesonbuild/interpreter/dependencyfallbacks.py16
-rw-r--r--mesonbuild/interpreter/interpreter.py92
-rw-r--r--mesonbuild/interpreter/interpreterobjects.py168
-rw-r--r--mesonbuild/interpreter/kwargs.py2
-rw-r--r--mesonbuild/interpreter/mesonmain.py67
-rw-r--r--mesonbuild/interpreter/primitives/array.py37
-rw-r--r--mesonbuild/interpreter/primitives/boolean.py26
-rw-r--r--mesonbuild/interpreter/primitives/dict.py43
-rw-r--r--mesonbuild/interpreter/primitives/integer.py53
-rw-r--r--mesonbuild/interpreter/primitives/range.py7
-rw-r--r--mesonbuild/interpreter/primitives/string.py79
-rw-r--r--mesonbuild/interpreter/type_checking.py25
13 files changed, 335 insertions, 362 deletions
diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py
index 8aeac8a..57e9499 100644
--- a/mesonbuild/interpreter/compiler.py
+++ b/mesonbuild/interpreter/compiler.py
@@ -19,7 +19,7 @@ from ..compilers import SUFFIX_TO_LANG, RunResult
from ..compilers.compilers import CompileCheckMode
from ..interpreterbase import (ObjectHolder, noPosargs, noKwargs,
FeatureNew, FeatureNewKwargs, disablerIfNotFound,
- InterpreterException)
+ InterpreterException, InterpreterObject)
from ..interpreterbase.decorators import ContainerTypeInfo, typed_kwargs, KwargInfo, typed_pos_args
from ..options import OptionKey
from .interpreterobjects import (extract_required_kwarg, extract_search_dirs)
@@ -110,29 +110,28 @@ class _TestMode(enum.Enum):
class TryRunResultHolder(ObjectHolder['RunResult']):
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,
- 'stderr': self.stderr_method,
- })
@noPosargs
@noKwargs
+ @InterpreterObject.method('returncode')
def returncode_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> int:
return self.held_object.returncode
@noPosargs
@noKwargs
+ @InterpreterObject.method('compiled')
def compiled_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
return self.held_object.compiled
@noPosargs
@noKwargs
+ @InterpreterObject.method('stdout')
def stdout_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
return self.held_object.stdout
@noPosargs
@noKwargs
+ @InterpreterObject.method('stderr')
def stderr_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
return self.held_object.stderr
@@ -190,40 +189,6 @@ class CompilerHolder(ObjectHolder['Compiler']):
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,
- 'get_linker_id': self.get_linker_id_method,
- 'compute_int': self.compute_int_method,
- 'sizeof': self.sizeof_method,
- 'get_define': self.get_define_method,
- 'has_define': self.has_define_method,
- 'check_header': self.check_header_method,
- 'has_header': self.has_header_method,
- 'has_header_symbol': self.has_header_symbol_method,
- 'run': self.run_method,
- 'has_function': self.has_function_method,
- 'has_member': self.has_member_method,
- 'has_members': self.has_members_method,
- 'has_type': self.has_type_method,
- 'alignment': self.alignment_method,
- 'version': self.version_method,
- 'cmd_array': self.cmd_array_method,
- 'find_library': self.find_library_method,
- 'has_argument': self.has_argument_method,
- 'has_function_attribute': self.has_func_attribute_method,
- 'get_supported_function_attributes': self.get_supported_function_attributes_method,
- 'has_multi_arguments': self.has_multi_arguments_method,
- 'get_supported_arguments': self.get_supported_arguments_method,
- 'first_supported_argument': self.first_supported_argument_method,
- 'has_link_argument': self.has_link_argument_method,
- 'has_multi_link_arguments': self.has_multi_link_arguments_method,
- 'get_supported_link_arguments': self.get_supported_link_arguments_method,
- 'first_supported_link_argument': self.first_supported_link_argument_method,
- 'symbols_have_underscore_prefix': self.symbols_have_underscore_prefix_method,
- 'get_argument_syntax': self.get_argument_syntax_method,
- 'preprocess': self.preprocess_method,
- })
@property
def compiler(self) -> 'Compiler':
@@ -254,11 +219,13 @@ class CompilerHolder(ObjectHolder['Compiler']):
@noPosargs
@noKwargs
+ @InterpreterObject.method('version')
def version_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
return self.compiler.version
@noPosargs
@noKwargs
+ @InterpreterObject.method('cmd_array')
def cmd_array_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> T.List[str]:
return self.compiler.exelist
@@ -289,6 +256,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
_ARGS_KW,
_DEPENDENCIES_KW,
)
+ @InterpreterObject.method('alignment')
def alignment_method(self, args: T.Tuple[str], kwargs: 'AlignmentKw') -> int:
typename = args[0]
deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=self.compiler.is_cross)
@@ -302,6 +270,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
@typed_pos_args('compiler.run', (str, mesonlib.File))
@typed_kwargs('compiler.run', *_COMPILES_KWS)
+ @InterpreterObject.method('run')
def run_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> 'RunResult':
if self.compiler.language not in {'d', 'c', 'cpp', 'objc', 'objcpp', 'fortran'}:
FeatureNew.single_use(f'compiler.run for {self.compiler.get_display_language()} language',
@@ -338,17 +307,20 @@ class CompilerHolder(ObjectHolder['Compiler']):
@noPosargs
@noKwargs
+ @InterpreterObject.method('get_id')
def get_id_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
return self.compiler.get_id()
@noPosargs
@noKwargs
@FeatureNew('compiler.get_linker_id', '0.53.0')
+ @InterpreterObject.method('get_linker_id')
def get_linker_id_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
return self.compiler.get_linker_id()
@noPosargs
@noKwargs
+ @InterpreterObject.method('symbols_have_underscore_prefix')
def symbols_have_underscore_prefix_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
'''
Check if the compiler prefixes _ (underscore) to global C symbols
@@ -358,6 +330,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
@typed_pos_args('compiler.has_member', str, str)
@typed_kwargs('compiler.has_member', _HAS_REQUIRED_KW, *_COMMON_KWS)
+ @InterpreterObject.method('has_member')
def has_member_method(self, args: T.Tuple[str, str], kwargs: 'HasKW') -> bool:
typename, membername = args
disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
@@ -383,6 +356,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
@typed_pos_args('compiler.has_members', str, varargs=str, min_varargs=1)
@typed_kwargs('compiler.has_members', _HAS_REQUIRED_KW, *_COMMON_KWS)
+ @InterpreterObject.method('has_members')
def has_members_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'HasKW') -> bool:
typename, membernames = args
members = mlog.bold(', '.join([f'"{m}"' for m in membernames]))
@@ -410,6 +384,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
@typed_pos_args('compiler.has_function', str)
@typed_kwargs('compiler.has_function', _HAS_REQUIRED_KW, *_COMMON_KWS)
+ @InterpreterObject.method('has_function')
def has_function_method(self, args: T.Tuple[str], kwargs: 'HasKW') -> bool:
funcname = args[0]
disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
@@ -433,6 +408,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
@typed_pos_args('compiler.has_type', str)
@typed_kwargs('compiler.has_type', _HAS_REQUIRED_KW, *_COMMON_KWS)
+ @InterpreterObject.method('has_type')
def has_type_method(self, args: T.Tuple[str], kwargs: 'HasKW') -> bool:
typename = args[0]
disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
@@ -462,6 +438,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
KwargInfo('guess', (int, NoneType)),
*_COMMON_KWS,
)
+ @InterpreterObject.method('compute_int')
def compute_int_method(self, args: T.Tuple[str], kwargs: 'ComputeIntKW') -> int:
expression = args[0]
extra_args = functools.partial(self._determine_args, kwargs)
@@ -475,6 +452,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
@typed_pos_args('compiler.sizeof', str)
@typed_kwargs('compiler.sizeof', *_COMMON_KWS)
+ @InterpreterObject.method('sizeof')
def sizeof_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> int:
element = args[0]
extra_args = functools.partial(self._determine_args, kwargs)
@@ -489,6 +467,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
@FeatureNew('compiler.get_define', '0.40.0')
@typed_pos_args('compiler.get_define', str)
@typed_kwargs('compiler.get_define', *_COMMON_KWS)
+ @InterpreterObject.method('get_define')
def get_define_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> str:
element = args[0]
extra_args = functools.partial(self._determine_args, kwargs)
@@ -504,6 +483,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
@FeatureNew('compiler.has_define', '1.3.0')
@typed_pos_args('compiler.has_define', str)
@typed_kwargs('compiler.has_define', *_COMMON_KWS)
+ @InterpreterObject.method('has_define')
def has_define_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> bool:
define_name = args[0]
extra_args = functools.partial(self._determine_args, kwargs)
@@ -519,6 +499,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
@typed_pos_args('compiler.compiles', (str, mesonlib.File))
@typed_kwargs('compiler.compiles', *_COMPILES_KWS)
+ @InterpreterObject.method('compiles')
def compiles_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> bool:
code = args[0]
testname = kwargs['name']
@@ -555,6 +536,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
@typed_pos_args('compiler.links', (str, mesonlib.File))
@typed_kwargs('compiler.links', *_COMPILES_KWS)
+ @InterpreterObject.method('links')
def links_method(self, args: T.Tuple['mesonlib.FileOrString'], kwargs: 'CompileKW') -> bool:
code = args[0]
testname = kwargs['name']
@@ -606,6 +588,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
@FeatureNew('compiler.check_header', '0.47.0')
@typed_pos_args('compiler.check_header', str)
@typed_kwargs('compiler.check_header', *_HEADER_KWS)
+ @InterpreterObject.method('check_header')
def check_header_method(self, args: T.Tuple[str], kwargs: 'HeaderKW') -> bool:
hname = args[0]
disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
@@ -648,11 +631,13 @@ class CompilerHolder(ObjectHolder['Compiler']):
@typed_pos_args('compiler.has_header', str)
@typed_kwargs('compiler.has_header', *_HEADER_KWS)
+ @InterpreterObject.method('has_header')
def has_header_method(self, args: T.Tuple[str], kwargs: 'HeaderKW') -> bool:
return self._has_header_impl(args[0], kwargs)
@typed_pos_args('compiler.has_header_symbol', str, str)
@typed_kwargs('compiler.has_header_symbol', *_HEADER_KWS)
+ @InterpreterObject.method('has_header_symbol')
def has_header_symbol_method(self, args: T.Tuple[str, str], kwargs: 'HeaderKW') -> bool:
hname, symbol = args
disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
@@ -692,6 +677,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
KwargInfo('dirs', ContainerTypeInfo(list, str), listify=True, default=[]),
*(k.evolve(name=f'header_{k.name}') for k in _HEADER_KWS)
)
+ @InterpreterObject.method('find_library')
def find_library_method(self, args: T.Tuple[str], kwargs: 'FindLibraryKW') -> 'dependencies.ExternalLibrary':
# TODO add dependencies support?
libname = args[0]
@@ -772,12 +758,14 @@ class CompilerHolder(ObjectHolder['Compiler']):
@typed_pos_args('compiler.has_argument', str)
@typed_kwargs('compiler.has_argument', _HAS_REQUIRED_KW)
+ @InterpreterObject.method('has_argument')
def has_argument_method(self, args: T.Tuple[str], kwargs: 'HasArgumentKW') -> bool:
return self._has_argument_impl([args[0]], kwargs=kwargs)
@typed_pos_args('compiler.has_multi_arguments', varargs=str)
@typed_kwargs('compiler.has_multi_arguments', _HAS_REQUIRED_KW)
@FeatureNew('compiler.has_multi_arguments', '0.37.0')
+ @InterpreterObject.method('has_multi_arguments')
def has_multi_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'HasArgumentKW') -> bool:
return self._has_argument_impl(args[0], kwargs=kwargs)
@@ -788,6 +776,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
KwargInfo('checked', str, default='off', since='0.59.0',
validator=in_set_validator({'warn', 'require', 'off'})),
)
+ @InterpreterObject.method('get_supported_arguments')
def get_supported_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'GetSupportedArgumentKw') -> T.List[str]:
supported_args: T.List[str] = []
checked = kwargs['checked']
@@ -805,6 +794,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
@noKwargs
@typed_pos_args('compiler.first_supported_argument', varargs=str)
+ @InterpreterObject.method('first_supported_argument')
def first_supported_argument_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[str]:
for arg in args[0]:
if self._has_argument_impl([arg]):
@@ -816,18 +806,21 @@ class CompilerHolder(ObjectHolder['Compiler']):
@FeatureNew('compiler.has_link_argument', '0.46.0')
@typed_pos_args('compiler.has_link_argument', str)
@typed_kwargs('compiler.has_link_argument', _HAS_REQUIRED_KW)
+ @InterpreterObject.method('has_link_argument')
def has_link_argument_method(self, args: T.Tuple[str], kwargs: 'HasArgumentKW') -> bool:
return self._has_argument_impl([args[0]], mode=_TestMode.LINKER, kwargs=kwargs)
@FeatureNew('compiler.has_multi_link_argument', '0.46.0')
@typed_pos_args('compiler.has_multi_link_argument', varargs=str)
@typed_kwargs('compiler.has_multi_link_argument', _HAS_REQUIRED_KW)
+ @InterpreterObject.method('has_multi_link_arguments')
def has_multi_link_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'HasArgumentKW') -> bool:
return self._has_argument_impl(args[0], mode=_TestMode.LINKER, kwargs=kwargs)
@FeatureNew('compiler.get_supported_link_arguments', '0.46.0')
@noKwargs
@typed_pos_args('compiler.get_supported_link_arguments', varargs=str)
+ @InterpreterObject.method('get_supported_link_arguments')
def get_supported_link_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[str]:
supported_args: T.List[str] = []
for arg in args[0]:
@@ -835,9 +828,10 @@ class CompilerHolder(ObjectHolder['Compiler']):
supported_args.append(arg)
return supported_args
- @FeatureNew('compiler.first_supported_link_argument_method', '0.46.0')
+ @FeatureNew('compiler.first_supported_link_argument', '0.46.0')
@noKwargs
@typed_pos_args('compiler.first_supported_link_argument', varargs=str)
+ @InterpreterObject.method('first_supported_link_argument')
def first_supported_link_argument_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[str]:
for arg in args[0]:
if self._has_argument_impl([arg], mode=_TestMode.LINKER):
@@ -871,18 +865,21 @@ class CompilerHolder(ObjectHolder['Compiler']):
@FeatureNew('compiler.has_function_attribute', '0.48.0')
@typed_pos_args('compiler.has_function_attribute', str)
@typed_kwargs('compiler.has_function_attribute', _HAS_REQUIRED_KW)
+ @InterpreterObject.method('has_function_attribute')
def has_func_attribute_method(self, args: T.Tuple[str], kwargs: 'HasArgumentKW') -> bool:
return self._has_function_attribute_impl(args[0], kwargs)
@FeatureNew('compiler.get_supported_function_attributes', '0.48.0')
@noKwargs
@typed_pos_args('compiler.get_supported_function_attributes', varargs=str)
+ @InterpreterObject.method('get_supported_function_attributes')
def get_supported_function_attributes_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> T.List[str]:
return [a for a in args[0] if self._has_function_attribute_impl(a)]
- @FeatureNew('compiler.get_argument_syntax_method', '0.49.0')
+ @FeatureNew('compiler.get_argument_syntax', '0.49.0')
@noPosargs
@noKwargs
+ @InterpreterObject.method('get_argument_syntax')
def get_argument_syntax_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
return self.compiler.get_argument_syntax()
@@ -897,6 +894,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
_DEPENDENCIES_KW.evolve(since='1.1.0'),
_DEPENDS_KW.evolve(since='1.4.0'),
)
+ @InterpreterObject.method('preprocess')
def preprocess_method(self, args: T.Tuple[T.List['mesonlib.FileOrString']], kwargs: 'PreprocessKW') -> T.List[build.CustomTargetIndex]:
compiler = self.compiler.get_preprocessor()
_sources: T.List[mesonlib.File] = self.interpreter.source_strings_to_files(args[0])
diff --git a/mesonbuild/interpreter/dependencyfallbacks.py b/mesonbuild/interpreter/dependencyfallbacks.py
index 0ebfe3b..f415026 100644
--- a/mesonbuild/interpreter/dependencyfallbacks.py
+++ b/mesonbuild/interpreter/dependencyfallbacks.py
@@ -4,14 +4,12 @@
from __future__ import annotations
-import copy
-
from .interpreterobjects import extract_required_kwarg
from .. import mlog
from .. import dependencies
from .. import build
from ..wrap import WrapMode
-from ..mesonlib import extract_as_list, stringlistify, version_compare_many, listify
+from ..mesonlib import extract_as_list, stringlistify, version_compare_many
from ..options import OptionKey
from ..dependencies import Dependency, DependencyException, NotFoundDependency
from ..interpreterbase import (MesonInterpreterObject, FeatureNew,
@@ -124,21 +122,17 @@ class DependencyFallbacksHolder(MesonInterpreterObject):
# dependency('foo', static: true) should implicitly add
# default_options: ['default_library=static']
static = kwargs.get('static')
- default_options = func_kwargs.get('default_options', {})
- if static is not None and 'default_library' not in default_options:
+ forced_options = {}
+ if static is not None:
default_library = 'static' if static else 'shared'
mlog.log(f'Building fallback subproject with default_library={default_library}')
- default_options = copy.copy(default_options)
- default_options['default_library'] = default_library
- func_kwargs['default_options'] = default_options
+ forced_options[OptionKey('default_library')] = default_library
# Configure the subproject
subp_name = self.subproject_name
varname = self.subproject_varname
func_kwargs.setdefault('version', [])
- if 'default_options' in kwargs and isinstance(kwargs['default_options'], str):
- func_kwargs['default_options'] = listify(kwargs['default_options'])
- self.interpreter.do_subproject(subp_name, func_kwargs)
+ self.interpreter.do_subproject(subp_name, func_kwargs, forced_options=forced_options)
return self._get_subproject_dep(subp_name, varname, kwargs)
def _get_subproject(self, subp_name: str) -> T.Optional[SubprojectHolder]:
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index bf41bfb..730f3d3 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -115,6 +115,7 @@ if T.TYPE_CHECKING:
from . import kwargs as kwtypes
from ..backend.backends import Backend
from ..interpreterbase.baseobjects import InterpreterObject, TYPE_var, TYPE_kwargs
+ from ..options import OptionDict
from ..programs import OverrideProgram
from .type_checking import SourcesVarargsType
@@ -270,7 +271,7 @@ class Interpreter(InterpreterBase, HoldableObject):
subproject: str = '',
subdir: str = '',
subproject_dir: str = 'subprojects',
- default_project_options: T.Optional[T.Dict[OptionKey, str]] = None,
+ invoker_method_default_options: T.Optional[OptionDict] = None,
ast: T.Optional[mparser.CodeBlockNode] = None,
relaxations: T.Optional[T.Set[InterpreterRuleRelaxation]] = None,
user_defined_options: T.Optional[coredata.SharedCMDOptions] = None,
@@ -295,13 +296,12 @@ class Interpreter(InterpreterBase, HoldableObject):
self.subproject_stack: T.List[str] = []
self.configure_file_outputs: T.Dict[str, int] = {}
# Passed from the outside, only used in subprojects.
- if default_project_options:
- self.default_project_options = default_project_options if isinstance(default_project_options, str) else default_project_options.copy()
- if isinstance(default_project_options, dict):
- pass
+ if invoker_method_default_options:
+ assert isinstance(invoker_method_default_options, dict)
+ self.invoker_method_default_options = invoker_method_default_options
else:
- self.default_project_options = {}
- self.project_default_options: T.List[str] = []
+ self.invoker_method_default_options = {}
+ self.project_default_options: OptionDict = {}
self.build_func_dict()
self.build_holder_map()
self.user_defined_options = user_defined_options
@@ -426,6 +426,7 @@ class Interpreter(InterpreterBase, HoldableObject):
build.Generator: OBJ.GeneratorHolder,
build.GeneratedList: OBJ.GeneratedListHolder,
build.ExtractedObjects: OBJ.GeneratedObjectsHolder,
+ build.OverrideExecutable: OBJ.OverrideExecutableHolder,
build.RunTarget: OBJ.RunTargetHolder,
build.AliasTarget: OBJ.AliasTargetHolder,
build.Headers: OBJ.HeadersHolder,
@@ -868,7 +869,8 @@ class Interpreter(InterpreterBase, HoldableObject):
self.subprojects[subp_name] = sub
return sub
- def do_subproject(self, subp_name: str, kwargs: kwtypes.DoSubproject, force_method: T.Optional[wrap.Method] = None) -> SubprojectHolder:
+ def do_subproject(self, subp_name: str, kwargs: kwtypes.DoSubproject, force_method: T.Optional[wrap.Method] = None,
+ forced_options: T.Optional[OptionDict] = None) -> SubprojectHolder:
if subp_name == 'sub_static':
pass
disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
@@ -879,6 +881,16 @@ class Interpreter(InterpreterBase, HoldableObject):
default_options = kwargs['default_options']
+ # This in practice is only used for default_library. forced_options is the
+ # only case in which a meson.build file overrides the machine file or the
+ # command line.
+ if forced_options:
+ for k, v in forced_options.items():
+ # FIXME: this should have no business poking at augments[],
+ # but set_option() does not do what we want
+ self.coredata.optstore.augments[k.evolve(subproject=subp_name)] = v
+ default_options = {**forced_options, **default_options}
+
if subp_name == '':
raise InterpreterException('Subproject name must not be empty.')
if subp_name[0] == '.':
@@ -930,7 +942,8 @@ class Interpreter(InterpreterBase, HoldableObject):
m += ['method', mlog.bold(method)]
mlog.log(*m, '\n', nested=False)
- methods_map: T.Dict[wrap.Method, T.Callable[[str, str, T.Dict[OptionKey, str, kwtypes.DoSubproject]], SubprojectHolder]] = {
+ methods_map: T.Dict[wrap.Method, T.Callable[[str, str, OptionDict, kwtypes.DoSubproject],
+ SubprojectHolder]] = {
'meson': self._do_subproject_meson,
'cmake': self._do_subproject_cmake,
'cargo': self._do_subproject_cargo,
@@ -952,7 +965,7 @@ class Interpreter(InterpreterBase, HoldableObject):
raise e
def _do_subproject_meson(self, subp_name: str, subdir: str,
- default_options: T.List[str],
+ default_options: OptionDict,
kwargs: kwtypes.DoSubproject,
ast: T.Optional[mparser.CodeBlockNode] = None,
build_def_files: T.Optional[T.List[str]] = None,
@@ -1012,7 +1025,7 @@ class Interpreter(InterpreterBase, HoldableObject):
return self.subprojects[subp_name]
def _do_subproject_cmake(self, subp_name: str, subdir: str,
- default_options: T.List[str],
+ default_options: OptionDict,
kwargs: kwtypes.DoSubproject) -> SubprojectHolder:
from ..cmake import CMakeInterpreter
with mlog.nested(subp_name):
@@ -1039,13 +1052,14 @@ class Interpreter(InterpreterBase, HoldableObject):
return result
def _do_subproject_cargo(self, subp_name: str, subdir: str,
- default_options: T.List[str],
+ default_options: OptionDict,
kwargs: kwtypes.DoSubproject) -> SubprojectHolder:
from .. import cargo
FeatureNew.single_use('Cargo subproject', '1.3.0', self.subproject, location=self.current_node)
mlog.warning('Cargo subproject is an experimental feature and has no backwards compatibility guarantees.',
once=True, location=self.current_node)
if self.environment.cargo is None:
+ self.add_languages(['rust'], True, MachineChoice.HOST)
self.environment.cargo = cargo.Interpreter(self.environment)
with mlog.nested(subp_name):
ast = self.environment.cargo.interpret(subdir)
@@ -1184,23 +1198,34 @@ class Interpreter(InterpreterBase, HoldableObject):
self._load_option_file()
self.project_default_options = kwargs['default_options']
- if isinstance(self.project_default_options, str):
- self.project_default_options = [self.project_default_options]
- assert isinstance(self.project_default_options, (list, dict))
if self.environment.first_invocation or (self.subproject != '' and self.subproject not in self.coredata.initialized_subprojects):
if self.subproject == '':
self.coredata.optstore.initialize_from_top_level_project_call(self.project_default_options,
self.user_defined_options.cmd_line_options,
self.environment.options)
else:
- invoker_method_default_options = self.default_project_options
self.coredata.optstore.initialize_from_subproject_call(self.subproject,
- invoker_method_default_options,
+ self.invoker_method_default_options,
self.project_default_options,
- self.user_defined_options.cmd_line_options)
+ self.user_defined_options.cmd_line_options,
+ self.environment.options)
self.coredata.initialized_subprojects.add(self.subproject)
if not self.is_subproject():
+ # We have to activate VS before adding languages and before calling
+ # self.set_backend() otherwise it wouldn't be able to detect which
+ # vs backend version we need. But after setting default_options in case
+ # the project sets vs backend by default.
+ backend = self.coredata.optstore.get_value_for(OptionKey('backend'))
+ assert backend is None or isinstance(backend, str), 'for mypy'
+ vsenv = self.coredata.optstore.get_value_for(OptionKey('vsenv'))
+ assert isinstance(vsenv, bool), 'for mypy'
+ force_vsenv = vsenv or backend.startswith('vs')
+ mesonlib.setup_vsenv(force_vsenv)
+ self.set_backend()
+
+ if not self.is_subproject():
+ self.coredata.optstore.validate_cmd_line_options(self.user_defined_options.cmd_line_options)
self.build.project_name = proj_name
self.active_projectname = proj_name
@@ -1270,22 +1295,9 @@ class Interpreter(InterpreterBase, HoldableObject):
mlog.log('Project name:', mlog.bold(proj_name))
mlog.log('Project version:', mlog.bold(self.project_version))
- if not self.is_subproject():
- # We have to activate VS before adding languages and before calling
- # self.set_backend() otherwise it wouldn't be able to detect which
- # vs backend version we need. But after setting default_options in case
- # the project sets vs backend by default.
- backend = self.coredata.optstore.get_value_for(OptionKey('backend'))
- assert backend is None or isinstance(backend, str), 'for mypy'
- vsenv = self.coredata.optstore.get_value_for(OptionKey('vsenv'))
- assert isinstance(vsenv, bool), 'for mypy'
- force_vsenv = vsenv or backend.startswith('vs')
- mesonlib.setup_vsenv(force_vsenv)
-
self.add_languages(proj_langs, True, MachineChoice.HOST)
self.add_languages(proj_langs, False, MachineChoice.BUILD)
- self.set_backend()
if not self.is_subproject():
self.check_stdlibs()
@@ -1528,7 +1540,7 @@ class Interpreter(InterpreterBase, HoldableObject):
self.backend.allow_thin_archives[for_machine] = False
else:
# update new values from commandline, if it applies
- self.coredata.process_compiler_options(lang, comp, self.environment, self.subproject)
+ self.coredata.process_compiler_options(lang, comp, self.subproject)
if for_machine == MachineChoice.HOST or self.environment.is_cross_build():
logger_fun = mlog.log
@@ -1589,7 +1601,7 @@ class Interpreter(InterpreterBase, HoldableObject):
def program_from_overrides(self, command_names: T.List[mesonlib.FileOrString],
extra_info: T.List['mlog.TV_Loggable']
- ) -> T.Optional[T.Union[ExternalProgram, OverrideProgram, build.Executable]]:
+ ) -> T.Optional[T.Union[ExternalProgram, OverrideProgram, build.OverrideExecutable]]:
for name in command_names:
if not isinstance(name, str):
continue
@@ -1604,7 +1616,7 @@ class Interpreter(InterpreterBase, HoldableObject):
if isinstance(name, str):
self.build.searched_programs.add(name)
- def add_find_program_override(self, name: str, exe: T.Union[build.Executable, ExternalProgram, 'OverrideProgram']) -> None:
+ def add_find_program_override(self, name: str, exe: T.Union[build.OverrideExecutable, ExternalProgram, 'OverrideProgram']) -> None:
if name in self.build.searched_programs:
raise InterpreterException(f'Tried to override finding of executable "{name}" which has already been found.')
if name in self.build.find_overrides:
@@ -1623,13 +1635,13 @@ class Interpreter(InterpreterBase, HoldableObject):
# the host machine.
def find_program_impl(self, args: T.List[mesonlib.FileOrString],
for_machine: MachineChoice = MachineChoice.HOST,
- default_options: T.Optional[T.Dict[OptionKey, options.ElementaryOptionValues]] = None,
+ default_options: T.Optional[OptionDict] = None,
required: bool = True, silent: bool = True,
wanted: T.Union[str, T.List[str]] = '',
search_dirs: T.Optional[T.List[str]] = None,
version_arg: T.Optional[str] = '',
version_func: T.Optional[ProgramVersionFunc] = None
- ) -> T.Union['ExternalProgram', 'build.Executable', 'OverrideProgram']:
+ ) -> T.Union['ExternalProgram', 'build.OverrideExecutable', 'OverrideProgram']:
args = mesonlib.listify(args)
extra_info: T.List[mlog.TV_Loggable] = []
@@ -1654,7 +1666,7 @@ class Interpreter(InterpreterBase, HoldableObject):
return progobj
def program_lookup(self, args: T.List[mesonlib.FileOrString], for_machine: MachineChoice,
- default_options: T.Optional[T.Dict[OptionKey, options.ElementaryOptionValues]],
+ default_options: T.Optional[OptionDict],
required: bool,
search_dirs: T.Optional[T.List[str]],
wanted: T.Union[str, T.List[str]],
@@ -1722,7 +1734,7 @@ class Interpreter(InterpreterBase, HoldableObject):
return True
def find_program_fallback(self, fallback: str, args: T.List[mesonlib.FileOrString],
- default_options: T.Dict[OptionKey, options.ElementaryOptionValues],
+ default_options: OptionDict,
required: bool, extra_info: T.List[mlog.TV_Loggable]
) -> T.Optional[T.Union[ExternalProgram, build.Executable, OverrideProgram]]:
mlog.log('Fallback to subproject', mlog.bold(fallback), 'which provides program',
@@ -3243,9 +3255,9 @@ class Interpreter(InterpreterBase, HoldableObject):
def build_both_libraries(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Library) -> build.BothLibraries:
shared_lib = self.build_target(node, args, kwargs, build.SharedLibrary)
static_lib = self.build_target(node, args, kwargs, build.StaticLibrary)
- preferred_library = self.coredata.optstore.get_value_for(OptionKey('default_both_libraries'))
+ preferred_library = self.coredata.optstore.get_value_for(OptionKey('default_both_libraries', subproject=self.subproject))
if preferred_library == 'auto':
- preferred_library = self.coredata.optstore.get_value_for(OptionKey('default_library'))
+ preferred_library = self.coredata.optstore.get_value_for(OptionKey('default_library', subproject=self.subproject))
if preferred_library == 'both':
preferred_library = 'shared'
diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py
index a2fadbe..17ba989 100644
--- a/mesonbuild/interpreter/interpreterobjects.py
+++ b/mesonbuild/interpreter/interpreterobjects.py
@@ -15,7 +15,7 @@ from .. import mlog
from ..modules import ModuleReturnValue, ModuleObject, ModuleState, ExtensionModule, NewExtensionModule
from ..backend.backends import TestProtocol
from ..interpreterbase import (
- ContainerTypeInfo, KwargInfo, MesonOperator,
+ ContainerTypeInfo, KwargInfo, InterpreterObject, MesonOperator,
MesonInterpreterObject, ObjectHolder, MutableInterpreterObject,
FeatureNew, FeatureDeprecated,
typed_pos_args, typed_kwargs, typed_operator,
@@ -32,7 +32,7 @@ if T.TYPE_CHECKING:
from . import kwargs
from ..cmake.interpreter import CMakeInterpreter
from ..envconfig import MachineInfo
- from ..interpreterbase import FeatureCheckBase, InterpreterObject, SubProject, TYPE_var, TYPE_kwargs, TYPE_nvar, TYPE_nkwargs
+ from ..interpreterbase import FeatureCheckBase, SubProject, TYPE_var, TYPE_kwargs, TYPE_nvar, TYPE_nkwargs
from .interpreter import Interpreter
from typing_extensions import TypedDict
@@ -97,16 +97,6 @@ class FeatureOptionHolder(ObjectHolder[options.UserFeatureOption]):
auto = T.cast('options.UserFeatureOption', self.env.coredata.optstore.get_value_object_for('auto_features'))
self.held_object = copy.copy(auto)
self.held_object.name = option.name
- self.methods.update({'enabled': self.enabled_method,
- 'disabled': self.disabled_method,
- 'allowed': self.allowed_method,
- 'auto': self.auto_method,
- 'require': self.require_method,
- 'disable_auto_if': self.disable_auto_if_method,
- 'enable_auto_if': self.enable_auto_if_method,
- 'disable_if': self.disable_if_method,
- 'enable_if': self.enable_if_method,
- })
@property
def value(self) -> str:
@@ -124,22 +114,26 @@ class FeatureOptionHolder(ObjectHolder[options.UserFeatureOption]):
@noPosargs
@noKwargs
+ @InterpreterObject.method('enabled')
def enabled_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
return self.value == 'enabled'
@noPosargs
@noKwargs
+ @InterpreterObject.method('disabled')
def disabled_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
return self.value == 'disabled'
@noPosargs
@noKwargs
@FeatureNew('feature_option.allowed()', '0.59.0')
+ @InterpreterObject.method('allowed')
def allowed_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
return self.value != 'disabled'
@noPosargs
@noKwargs
+ @InterpreterObject.method('auto')
def auto_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
return self.value == 'auto'
@@ -160,6 +154,7 @@ class FeatureOptionHolder(ObjectHolder[options.UserFeatureOption]):
'feature_option.require',
_ERROR_MSG_KW,
)
+ @InterpreterObject.method('require')
def require_method(self, args: T.Tuple[bool], kwargs: 'kwargs.FeatureOptionRequire') -> options.UserFeatureOption:
return self._disable_if(not args[0], kwargs['error_message'])
@@ -169,6 +164,7 @@ class FeatureOptionHolder(ObjectHolder[options.UserFeatureOption]):
'feature_option.disable_if',
_ERROR_MSG_KW,
)
+ @InterpreterObject.method('disable_if')
def disable_if_method(self, args: T.Tuple[bool], kwargs: 'kwargs.FeatureOptionRequire') -> options.UserFeatureOption:
return self._disable_if(args[0], kwargs['error_message'])
@@ -178,6 +174,7 @@ class FeatureOptionHolder(ObjectHolder[options.UserFeatureOption]):
'feature_option.enable_if',
_ERROR_MSG_KW,
)
+ @InterpreterObject.method('enable_if')
def enable_if_method(self, args: T.Tuple[bool], kwargs: 'kwargs.FeatureOptionRequire') -> options.UserFeatureOption:
if not args[0]:
return copy.deepcopy(self.held_object)
@@ -192,12 +189,14 @@ class FeatureOptionHolder(ObjectHolder[options.UserFeatureOption]):
@FeatureNew('feature_option.disable_auto_if()', '0.59.0')
@noKwargs
@typed_pos_args('feature_option.disable_auto_if', bool)
+ @InterpreterObject.method('disable_auto_if')
def disable_auto_if_method(self, args: T.Tuple[bool], kwargs: TYPE_kwargs) -> options.UserFeatureOption:
return copy.deepcopy(self.held_object) if self.value != 'auto' or not args[0] else self.as_disabled()
@FeatureNew('feature_option.enable_auto_if()', '1.1.0')
@noKwargs
@typed_pos_args('feature_option.enable_auto_if', bool)
+ @InterpreterObject.method('enable_auto_if')
def enable_auto_if_method(self, args: T.Tuple[bool], kwargs: TYPE_kwargs) -> options.UserFeatureOption:
return self.as_enabled() if self.value == 'auto' and args[0] else copy.deepcopy(self.held_object)
@@ -220,10 +219,6 @@ class RunProcess(MesonInterpreterObject):
raise AssertionError('BUG: RunProcess must be passed an ExternalProgram')
self.capture = capture
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: ExternalProgram,
@@ -271,16 +266,19 @@ class RunProcess(MesonInterpreterObject):
@noPosargs
@noKwargs
+ @InterpreterObject.method('returncode')
def returncode_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> int:
return self.returncode
@noPosargs
@noKwargs
+ @InterpreterObject.method('stdout')
def stdout_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.stdout
@noPosargs
@noKwargs
+ @InterpreterObject.method('stderr')
def stderr_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.stderr
@@ -288,11 +286,6 @@ class EnvironmentVariablesHolder(ObjectHolder[mesonlib.EnvironmentVariables], Mu
def __init__(self, obj: mesonlib.EnvironmentVariables, interpreter: 'Interpreter'):
super().__init__(obj, interpreter)
- self.methods.update({'set': self.set_method,
- 'unset': self.unset_method,
- 'append': self.append_method,
- 'prepend': self.prepend_method,
- })
def __repr__(self) -> str:
repr_str = "<{0}: {1}>"
@@ -310,6 +303,7 @@ class EnvironmentVariablesHolder(ObjectHolder[mesonlib.EnvironmentVariables], Mu
@typed_pos_args('environment.set', str, varargs=str, min_varargs=1)
@typed_kwargs('environment.set', ENV_SEPARATOR_KW)
+ @InterpreterObject.method('set')
def set_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSeparatorKW') -> None:
name, values = args
self.held_object.set(name, values, kwargs['separator'])
@@ -317,11 +311,13 @@ class EnvironmentVariablesHolder(ObjectHolder[mesonlib.EnvironmentVariables], Mu
@FeatureNew('environment.unset', '1.4.0')
@typed_pos_args('environment.unset', str)
@noKwargs
+ @InterpreterObject.method('unset')
def unset_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> None:
self.held_object.unset(args[0])
@typed_pos_args('environment.append', str, varargs=str, min_varargs=1)
@typed_kwargs('environment.append', ENV_SEPARATOR_KW)
+ @InterpreterObject.method('append')
def append_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSeparatorKW') -> None:
name, values = args
self.warn_if_has_name(name)
@@ -329,6 +325,7 @@ class EnvironmentVariablesHolder(ObjectHolder[mesonlib.EnvironmentVariables], Mu
@typed_pos_args('environment.prepend', str, varargs=str, min_varargs=1)
@typed_kwargs('environment.prepend', ENV_SEPARATOR_KW)
+ @InterpreterObject.method('prepend')
def prepend_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'EnvironmentSeparatorKW') -> None:
name, values = args
self.warn_if_has_name(name)
@@ -342,15 +339,6 @@ class ConfigurationDataHolder(ObjectHolder[build.ConfigurationData], MutableInte
def __init__(self, obj: build.ConfigurationData, interpreter: 'Interpreter'):
super().__init__(obj, interpreter)
- self.methods.update({'set': self.set_method,
- 'set10': self.set10_method,
- 'set_quoted': self.set_quoted_method,
- 'has': self.has_method,
- 'get': self.get_method,
- 'keys': self.keys_method,
- 'get_unquoted': self.get_unquoted_method,
- 'merge_from': self.merge_from_method,
- })
def __deepcopy__(self, memo: T.Dict) -> 'ConfigurationDataHolder':
return ConfigurationDataHolder(copy.deepcopy(self.held_object), self.interpreter)
@@ -364,12 +352,14 @@ class ConfigurationDataHolder(ObjectHolder[build.ConfigurationData], MutableInte
@typed_pos_args('configuration_data.set', str, (str, int, bool))
@typed_kwargs('configuration_data.set', _CONF_DATA_SET_KWS)
+ @InterpreterObject.method('set')
def set_method(self, args: T.Tuple[str, T.Union[str, int, bool]], kwargs: 'kwargs.ConfigurationDataSet') -> None:
self.__check_used()
self.held_object.values[args[0]] = (args[1], kwargs['description'])
@typed_pos_args('configuration_data.set_quoted', str, str)
@typed_kwargs('configuration_data.set_quoted', _CONF_DATA_SET_KWS)
+ @InterpreterObject.method('set_quoted')
def set_quoted_method(self, args: T.Tuple[str, str], kwargs: 'kwargs.ConfigurationDataSet') -> None:
self.__check_used()
escaped_val = '\\"'.join(args[1].split('"'))
@@ -377,6 +367,7 @@ class ConfigurationDataHolder(ObjectHolder[build.ConfigurationData], MutableInte
@typed_pos_args('configuration_data.set10', str, (int, bool))
@typed_kwargs('configuration_data.set10', _CONF_DATA_SET_KWS)
+ @InterpreterObject.method('set10')
def set10_method(self, args: T.Tuple[str, T.Union[int, bool]], kwargs: 'kwargs.ConfigurationDataSet') -> None:
self.__check_used()
# bool is a subclass of int, so we need to check for bool explicitly.
@@ -394,12 +385,14 @@ class ConfigurationDataHolder(ObjectHolder[build.ConfigurationData], MutableInte
@typed_pos_args('configuration_data.has', (str, int, bool))
@noKwargs
+ @InterpreterObject.method('has')
def has_method(self, args: T.Tuple[T.Union[str, int, bool]], kwargs: TYPE_kwargs) -> bool:
return args[0] in self.held_object.values
@FeatureNew('configuration_data.get()', '0.38.0')
@typed_pos_args('configuration_data.get', str, optargs=[(str, int, bool)])
@noKwargs
+ @InterpreterObject.method('get')
def get_method(self, args: T.Tuple[str, T.Optional[T.Union[str, int, bool]]],
kwargs: TYPE_kwargs) -> T.Union[str, int, bool]:
name = args[0]
@@ -412,6 +405,7 @@ class ConfigurationDataHolder(ObjectHolder[build.ConfigurationData], MutableInte
@FeatureNew('configuration_data.get_unquoted()', '0.44.0')
@typed_pos_args('configuration_data.get_unquoted', str, optargs=[(str, int, bool)])
@noKwargs
+ @InterpreterObject.method('get_unquoted')
def get_unquoted_method(self, args: T.Tuple[str, T.Optional[T.Union[str, int, bool]]],
kwargs: TYPE_kwargs) -> T.Union[str, int, bool]:
name = args[0]
@@ -431,6 +425,7 @@ class ConfigurationDataHolder(ObjectHolder[build.ConfigurationData], MutableInte
@FeatureNew('configuration_data.keys()', '0.57.0')
@noPosargs
@noKwargs
+ @InterpreterObject.method('keys')
def keys_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[str]:
return sorted(self.keys())
@@ -439,6 +434,7 @@ class ConfigurationDataHolder(ObjectHolder[build.ConfigurationData], MutableInte
@typed_pos_args('configuration_data.merge_from', build.ConfigurationData)
@noKwargs
+ @InterpreterObject.method('merge_from')
def merge_from_method(self, args: T.Tuple[build.ConfigurationData], kwargs: TYPE_kwargs) -> None:
from_object = args[0]
self.held_object.values.update(from_object.values)
@@ -455,31 +451,19 @@ _PARTIAL_DEP_KWARGS = [
class DependencyHolder(ObjectHolder[Dependency]):
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,
- 'name': self.name_method,
- 'get_pkgconfig_variable': self.pkgconfig_method,
- 'get_configtool_variable': self.configtool_method,
- 'get_variable': self.variable_method,
- 'partial_dependency': self.partial_dependency_method,
- 'include_type': self.include_type_method,
- 'as_system': self.as_system_method,
- 'as_link_whole': self.as_link_whole_method,
- 'as_static': self.as_static_method,
- 'as_shared': self.as_shared_method,
- })
def found(self) -> bool:
return self.found_method([], {})
@noPosargs
@noKwargs
+ @InterpreterObject.method('type_name')
def type_name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.type_name
@noPosargs
@noKwargs
+ @InterpreterObject.method('found')
def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
if self.held_object.type_name == 'internal':
return True
@@ -487,11 +471,13 @@ class DependencyHolder(ObjectHolder[Dependency]):
@noPosargs
@noKwargs
+ @InterpreterObject.method('version')
def version_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.get_version()
@noPosargs
@noKwargs
+ @InterpreterObject.method('name')
def name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.get_name()
@@ -503,6 +489,7 @@ class DependencyHolder(ObjectHolder[Dependency]):
KwargInfo('default', str, default=''),
PKGCONFIG_DEFINE_KW.evolve(name='define_variable')
)
+ @InterpreterObject.method('get_pkgconfig_variable')
def pkgconfig_method(self, args: T.Tuple[str], kwargs: 'kwargs.DependencyPkgConfigVar') -> str:
from ..dependencies.pkgconfig import PkgConfigDependency
if not isinstance(self.held_object, PkgConfigDependency):
@@ -521,6 +508,7 @@ class DependencyHolder(ObjectHolder[Dependency]):
'use dependency.get_variable(configtool : ...) instead')
@noKwargs
@typed_pos_args('dependency.get_config_tool_variable', str)
+ @InterpreterObject.method('get_configtool_variable')
def configtool_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> str:
from ..dependencies.configtool import ConfigToolDependency
if not isinstance(self.held_object, ConfigToolDependency):
@@ -533,6 +521,7 @@ class DependencyHolder(ObjectHolder[Dependency]):
@FeatureNew('dependency.partial_dependency', '0.46.0')
@noPosargs
@typed_kwargs('dependency.partial_dependency', *_PARTIAL_DEP_KWARGS)
+ @InterpreterObject.method('partial_dependency')
def partial_dependency_method(self, args: T.List[TYPE_nvar], kwargs: 'kwargs.DependencyMethodPartialDependency') -> Dependency:
pdep = self.held_object.get_partial_dependency(**kwargs)
return pdep
@@ -549,6 +538,7 @@ class DependencyHolder(ObjectHolder[Dependency]):
KwargInfo('default_value', (str, NoneType)),
PKGCONFIG_DEFINE_KW,
)
+ @InterpreterObject.method('get_variable')
def variable_method(self, args: T.Tuple[T.Optional[str]], kwargs: 'kwargs.DependencyGetVariable') -> str:
default_varname = args[0]
if default_varname is not None:
@@ -570,18 +560,21 @@ class DependencyHolder(ObjectHolder[Dependency]):
@FeatureNew('dependency.include_type', '0.52.0')
@noPosargs
@noKwargs
+ @InterpreterObject.method('include_type')
def include_type_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.get_include_type()
@FeatureNew('dependency.as_system', '0.52.0')
@noKwargs
@typed_pos_args('dependency.as_system', optargs=[str])
+ @InterpreterObject.method('as_system')
def as_system_method(self, args: T.Tuple[T.Optional[str]], kwargs: TYPE_kwargs) -> Dependency:
return self.held_object.generate_system_dependency(args[0] or 'system')
@FeatureNew('dependency.as_link_whole', '0.56.0')
@noKwargs
@noPosargs
+ @InterpreterObject.method('as_link_whole')
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')
@@ -594,6 +587,7 @@ class DependencyHolder(ObjectHolder[Dependency]):
'dependency.as_static',
KwargInfo('recursive', bool, default=False),
)
+ @InterpreterObject.method('as_static')
def as_static_method(self, args: T.List[TYPE_var], kwargs: InternalDependencyAsKW) -> Dependency:
if not isinstance(self.held_object, InternalDependency):
raise InterpreterException('as_static method is only supported on declare_dependency() objects')
@@ -605,6 +599,7 @@ class DependencyHolder(ObjectHolder[Dependency]):
'dependency.as_shared',
KwargInfo('recursive', bool, default=False),
)
+ @InterpreterObject.method('as_shared')
def as_shared_method(self, args: T.List[TYPE_var], kwargs: InternalDependencyAsKW) -> Dependency:
if not isinstance(self.held_object, InternalDependency):
raise InterpreterException('as_shared method is only supported on declare_dependency() objects')
@@ -615,13 +610,10 @@ _EXTPROG = T.TypeVar('_EXTPROG', bound=ExternalProgram)
class _ExternalProgramHolder(ObjectHolder[_EXTPROG]):
def __init__(self, ep: _EXTPROG, interpreter: 'Interpreter') -> None:
super().__init__(ep, interpreter)
- self.methods.update({'found': self.found_method,
- 'path': self.path_method,
- 'version': self.version_method,
- 'full_path': self.full_path_method})
@noPosargs
@noKwargs
+ @InterpreterObject.method('found')
def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
return self.found()
@@ -629,12 +621,14 @@ class _ExternalProgramHolder(ObjectHolder[_EXTPROG]):
@noKwargs
@FeatureDeprecated('ExternalProgram.path', '0.55.0',
'use ExternalProgram.full_path() instead')
+ @InterpreterObject.method('path')
def path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self._full_path()
@noPosargs
@noKwargs
@FeatureNew('ExternalProgram.full_path', '0.55.0')
+ @InterpreterObject.method('full_path')
def full_path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self._full_path()
@@ -648,6 +642,7 @@ class _ExternalProgramHolder(ObjectHolder[_EXTPROG]):
@noPosargs
@noKwargs
@FeatureNew('ExternalProgram.version', '0.62.0')
+ @InterpreterObject.method('version')
def version_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
if not self.found():
raise InterpreterException('Unable to get the version of a not-found external program')
@@ -665,25 +660,23 @@ class ExternalProgramHolder(_ExternalProgramHolder[ExternalProgram]):
class ExternalLibraryHolder(ObjectHolder[ExternalLibrary]):
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,
- 'name': self.name_method,
- })
@noPosargs
@noKwargs
+ @InterpreterObject.method('type_name')
def type_name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.type_name
@noPosargs
@noKwargs
+ @InterpreterObject.method('found')
def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
return self.held_object.found()
@FeatureNew('dependency.partial_dependency', '0.46.0')
@noPosargs
@typed_kwargs('dependency.partial_dependency', *_PARTIAL_DEP_KWARGS)
+ @InterpreterObject.method('partial_dependency')
def partial_dependency_method(self, args: T.List[TYPE_nvar], kwargs: 'kwargs.DependencyMethodPartialDependency') -> Dependency:
pdep = self.held_object.get_partial_dependency(**kwargs)
return pdep
@@ -691,6 +684,7 @@ class ExternalLibraryHolder(ObjectHolder[ExternalLibrary]):
@FeatureNew('dependency.name', '1.5.0')
@noPosargs
@noKwargs
+ @InterpreterObject.method('name')
def name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.name
@@ -699,36 +693,34 @@ class ExternalLibraryHolder(ObjectHolder[ExternalLibrary]):
class MachineHolder(ObjectHolder['MachineInfo']):
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,
- 'endian': self.endian_method,
- 'kernel': self.kernel_method,
- 'subsystem': self.subsystem_method,
- })
@noPosargs
@noKwargs
+ @InterpreterObject.method('cpu_family')
def cpu_family_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.cpu_family
@noPosargs
@noKwargs
+ @InterpreterObject.method('cpu')
def cpu_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.cpu
@noPosargs
@noKwargs
+ @InterpreterObject.method('system')
def system_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.system
@noPosargs
@noKwargs
+ @InterpreterObject.method('endian')
def endian_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.endian
@noPosargs
@noKwargs
+ @InterpreterObject.method('kernel')
def kernel_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
if self.held_object.kernel is not None:
return self.held_object.kernel
@@ -736,6 +728,7 @@ class MachineHolder(ObjectHolder['MachineInfo']):
@noPosargs
@noKwargs
+ @InterpreterObject.method('subsystem')
def subsystem_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
if self.held_object.subsystem is not None:
return self.held_object.subsystem
@@ -748,12 +741,11 @@ class IncludeDirsHolder(ObjectHolder[build.IncludeDirs]):
class FileHolder(ObjectHolder[mesonlib.File]):
def __init__(self, file: mesonlib.File, interpreter: 'Interpreter'):
super().__init__(file, interpreter)
- self.methods.update({'full_path': self.full_path_method,
- })
@noPosargs
@noKwargs
@FeatureNew('file.full_path', '1.4.0')
+ @InterpreterObject.method('full_path')
def full_path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.absolute_path(self.env.source_dir, self.env.build_dir)
@@ -836,12 +828,10 @@ class SubprojectHolder(MesonInterpreterObject):
self.subdir = PurePath(subdir).as_posix()
self.cm_interpreter: T.Optional[CMakeInterpreter] = None
self.callstack = callstack
- self.methods.update({'get_variable': self.get_variable_method,
- 'found': self.found_method,
- })
@noPosargs
@noKwargs
+ @InterpreterObject.method('found')
def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
return self.found()
@@ -863,6 +853,7 @@ class SubprojectHolder(MesonInterpreterObject):
@noKwargs
@typed_pos_args('subproject.get_variable', str, optargs=[object])
@noArgsFlattening
+ @InterpreterObject.method('get_variable')
def get_variable_method(self, args: T.Tuple[str, T.Optional[str]], kwargs: TYPE_kwargs) -> T.Union[TYPE_var, InterpreterObject]:
return self.get_variable(args, kwargs)
@@ -905,16 +896,6 @@ _BuildTarget = T.TypeVar('_BuildTarget', bound=T.Union[build.BuildTarget, build.
class BuildTargetHolder(ObjectHolder[_BuildTarget]):
def __init__(self, target: _BuildTarget, interp: 'Interpreter'):
super().__init__(target, interp)
- self.methods.update({'extract_objects': self.extract_objects_method,
- 'extract_all_objects': self.extract_all_objects_method,
- 'name': self.name_method,
- 'get_id': self.get_id_method,
- 'outdir': self.outdir_method,
- 'full_path': self.full_path_method,
- 'path': self.path_method,
- 'found': self.found_method,
- 'private_dir_include': self.private_dir_include_method,
- })
def __repr__(self) -> str:
r = '<{} {}: {}>'
@@ -934,6 +915,7 @@ class BuildTargetHolder(ObjectHolder[_BuildTarget]):
@noPosargs
@noKwargs
+ @InterpreterObject.method('found')
def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
if not (isinstance(self.held_object, build.Executable) and self.held_object.was_returned_by_find_program):
FeatureNew.single_use('BuildTarget.found', '0.59.0', subproject=self.held_object.subproject)
@@ -941,27 +923,32 @@ class BuildTargetHolder(ObjectHolder[_BuildTarget]):
@noPosargs
@noKwargs
+ @InterpreterObject.method('private_dir_include')
def private_dir_include_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> build.IncludeDirs:
return build.IncludeDirs('', [], False, [self.interpreter.backend.get_target_private_dir(self._target_object)])
@noPosargs
@noKwargs
+ @InterpreterObject.method('full_path')
def full_path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.interpreter.backend.get_target_filename_abs(self._target_object)
@noPosargs
@noKwargs
@FeatureDeprecated('BuildTarget.path', '0.55.0', 'Use BuildTarget.full_path instead')
+ @InterpreterObject.method('path')
def path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.interpreter.backend.get_target_filename_abs(self._target_object)
@noPosargs
@noKwargs
+ @InterpreterObject.method('outdir')
def outdir_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.interpreter.backend.get_target_dir(self._target_object)
@noKwargs
@typed_pos_args('extract_objects', varargs=(mesonlib.File, str, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList))
+ @InterpreterObject.method('extract_objects')
def extract_objects_method(self, args: T.Tuple[T.List[T.Union[mesonlib.FileOrString, 'build.GeneratedTypes']]], kwargs: TYPE_nkwargs) -> build.ExtractedObjects:
tobj = self._target_object
unity_value = self.interpreter.coredata.get_option_for_target(tobj, "unity")
@@ -981,6 +968,7 @@ class BuildTargetHolder(ObjectHolder[_BuildTarget]):
''')
)
)
+ @InterpreterObject.method('extract_all_objects')
def extract_all_objects_method(self, args: T.List[TYPE_nvar], kwargs: 'kwargs.BuildTargeMethodExtractAllObjects') -> build.ExtractedObjects:
return self._target_object.extract_all_objects(kwargs['recursive'])
@@ -989,12 +977,14 @@ class BuildTargetHolder(ObjectHolder[_BuildTarget]):
@FeatureDeprecated('BuildTarget.get_id', '1.2.0',
'This was never formally documented and does not seem to have a real world use. ' +
'See https://github.com/mesonbuild/meson/pull/6061')
+ @InterpreterObject.method('get_id')
def get_id_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self._target_object.get_id()
@FeatureNew('name', '0.54.0')
@noPosargs
@noKwargs
+ @InterpreterObject.method('name')
def name_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self._target_object.name
@@ -1010,9 +1000,6 @@ class SharedLibraryHolder(BuildTargetHolder[build.SharedLibrary]):
class BothLibrariesHolder(BuildTargetHolder[build.BothLibraries]):
def __init__(self, libs: build.BothLibraries, interp: 'Interpreter'):
super().__init__(libs, interp)
- self.methods.update({'get_shared_lib': self.get_shared_lib_method,
- 'get_static_lib': self.get_static_lib_method,
- })
def __repr__(self) -> str:
r = '<{} {}: {}, {}: {}>'
@@ -1022,6 +1009,7 @@ class BothLibrariesHolder(BuildTargetHolder[build.BothLibraries]):
@noPosargs
@noKwargs
+ @InterpreterObject.method('get_shared_lib')
def get_shared_lib_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> build.SharedLibrary:
lib = copy.copy(self.held_object.shared)
lib.both_lib = None
@@ -1029,6 +1017,7 @@ class BothLibrariesHolder(BuildTargetHolder[build.BothLibraries]):
@noPosargs
@noKwargs
+ @InterpreterObject.method('get_static_lib')
def get_static_lib_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> build.StaticLibrary:
lib = copy.copy(self.held_object.static)
lib.both_lib = None
@@ -1043,12 +1032,11 @@ class JarHolder(BuildTargetHolder[build.Jar]):
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,
- })
@FeatureNew('custom_target[i].full_path', '0.54.0')
@noPosargs
@noKwargs
+ @InterpreterObject.method('full_path')
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)
@@ -1058,13 +1046,6 @@ _CT = T.TypeVar('_CT', bound=build.CustomTarget)
class _CustomTargetHolder(ObjectHolder[_CT]):
def __init__(self, target: _CT, interp: 'Interpreter'):
super().__init__(target, interp)
- self.methods.update({'full_path': self.full_path_method,
- 'to_list': self.to_list_method,
- })
-
- self.operators.update({
- MesonOperator.INDEX: self.op_index,
- })
def __repr__(self) -> str:
r = '<{} {}: {}>'
@@ -1073,12 +1054,14 @@ class _CustomTargetHolder(ObjectHolder[_CT]):
@noPosargs
@noKwargs
+ @InterpreterObject.method('full_path')
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
@noKwargs
+ @InterpreterObject.method('to_list')
def to_list_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[build.CustomTargetIndex]:
result = []
for i in self.held_object:
@@ -1087,6 +1070,7 @@ class _CustomTargetHolder(ObjectHolder[_CT]):
@noKwargs
@typed_operator(MesonOperator.INDEX, int)
+ @InterpreterObject.operator(MesonOperator.INDEX)
def op_index(self, other: int) -> build.CustomTargetIndex:
try:
return self.held_object[other]
@@ -1108,7 +1092,6 @@ class GeneratedListHolder(ObjectHolder[build.GeneratedList]):
class GeneratorHolder(ObjectHolder[build.Generator]):
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, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList))
@typed_kwargs(
@@ -1117,6 +1100,7 @@ class GeneratorHolder(ObjectHolder[build.Generator]):
KwargInfo('extra_args', ContainerTypeInfo(list, str), listify=True, default=[]),
ENV_KW.evolve(since='1.3.0')
)
+ @InterpreterObject.method('process')
def process_method(self,
args: T.Tuple[T.List[T.Union[str, mesonlib.File, 'build.GeneratedTypes']]],
kwargs: 'kwargs.GeneratorProcess') -> build.GeneratedList:
@@ -1142,3 +1126,11 @@ class StructuredSourcesHolder(ObjectHolder[build.StructuredSources]):
def __init__(self, sources: build.StructuredSources, interp: 'Interpreter'):
super().__init__(sources, interp)
+
+class OverrideExecutableHolder(BuildTargetHolder[build.OverrideExecutable]):
+ @noPosargs
+ @noKwargs
+ @FeatureNew('OverrideExecutable.version', '1.9.0')
+ @InterpreterObject.method('version')
+ def version_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
+ return self.held_object.get_version(self.interpreter)
diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py
index fb34bbb..d741aab 100644
--- a/mesonbuild/interpreter/kwargs.py
+++ b/mesonbuild/interpreter/kwargs.py
@@ -321,7 +321,7 @@ class Subproject(ExtractRequired):
class DoSubproject(ExtractRequired):
- default_options: T.List[str]
+ default_options: T.Union[T.List[str], T.Dict[str, options.ElementaryOptionValues], str]
version: T.List[str]
cmake_options: T.List[str]
options: T.Optional[CMakeSubprojectOptions]
diff --git a/mesonbuild/interpreter/mesonmain.py b/mesonbuild/interpreter/mesonmain.py
index 8ede691..602575c 100644
--- a/mesonbuild/interpreter/mesonmain.py
+++ b/mesonbuild/interpreter/mesonmain.py
@@ -18,7 +18,7 @@ from ..programs import OverrideProgram, ExternalProgram
from ..interpreter.type_checking import ENV_KW, ENV_METHOD_KW, ENV_SEPARATOR_KW, env_convertor_with_method
from ..interpreterbase import (MesonInterpreterObject, FeatureNew, FeatureDeprecated,
typed_pos_args, noArgsFlattening, noPosargs, noKwargs,
- typed_kwargs, KwargInfo, InterpreterException)
+ typed_kwargs, KwargInfo, InterpreterException, InterpreterObject)
from .primitives import MesonVersionString
from .type_checking import NATIVE_KW, NoneType
@@ -55,38 +55,6 @@ class MesonMain(MesonInterpreterObject):
super().__init__(subproject=interpreter.subproject)
self.build = build
self.interpreter = interpreter
- self.methods.update({'add_devenv': self.add_devenv_method,
- 'add_dist_script': self.add_dist_script_method,
- 'add_install_script': self.add_install_script_method,
- 'add_postconf_script': self.add_postconf_script_method,
- 'backend': self.backend_method,
- 'build_options': self.build_options_method,
- 'build_root': self.build_root_method,
- 'can_run_host_binaries': self.can_run_host_binaries_method,
- 'current_source_dir': self.current_source_dir_method,
- 'current_build_dir': self.current_build_dir_method,
- 'get_compiler': self.get_compiler_method,
- 'get_cross_property': self.get_cross_property_method,
- 'get_external_property': self.get_external_property_method,
- 'global_build_root': self.global_build_root_method,
- 'global_source_root': self.global_source_root_method,
- 'has_exe_wrapper': self.has_exe_wrapper_method,
- 'has_external_property': self.has_external_property_method,
- 'install_dependency_manifest': self.install_dependency_manifest_method,
- 'is_cross_build': self.is_cross_build_method,
- 'is_subproject': self.is_subproject_method,
- 'is_unity': self.is_unity_method,
- 'override_dependency': self.override_dependency_method,
- 'override_find_program': self.override_find_program_method,
- 'project_build_root': self.project_build_root_method,
- 'project_license': self.project_license_method,
- 'project_license_files': self.project_license_files_method,
- 'project_name': self.project_name_method,
- 'project_source_root': self.project_source_root_method,
- 'project_version': self.project_version_method,
- 'source_root': self.source_root_method,
- 'version': self.version_method,
- })
def _find_source_script(
self, name: str, prog: T.Union[str, mesonlib.File, build.Executable, ExternalProgram],
@@ -157,6 +125,7 @@ class MesonMain(MesonInterpreterObject):
KwargInfo('install_tag', (str, NoneType), since='0.60.0'),
KwargInfo('dry_run', bool, default=False, since='1.1.0'),
)
+ @InterpreterObject.method('add_install_script')
def add_install_script_method(
self,
args: T.Tuple[T.Union[str, mesonlib.File, build.Executable, ExternalProgram],
@@ -175,6 +144,7 @@ class MesonMain(MesonInterpreterObject):
varargs=(str, mesonlib.File, ExternalProgram)
)
@noKwargs
+ @InterpreterObject.method('add_postconf_script')
def add_postconf_script_method(
self,
args: T.Tuple[T.Union[str, mesonlib.File, ExternalProgram],
@@ -191,6 +161,7 @@ class MesonMain(MesonInterpreterObject):
)
@noKwargs
@FeatureNew('meson.add_dist_script', '0.48.0')
+ @InterpreterObject.method('add_dist_script')
def add_dist_script_method(
self,
args: T.Tuple[T.Union[str, mesonlib.File, ExternalProgram],
@@ -208,6 +179,7 @@ class MesonMain(MesonInterpreterObject):
@noPosargs
@noKwargs
+ @InterpreterObject.method('current_source_dir')
def current_source_dir_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
src = self.interpreter.environment.source_dir
sub = self.interpreter.subdir
@@ -217,6 +189,7 @@ class MesonMain(MesonInterpreterObject):
@noPosargs
@noKwargs
+ @InterpreterObject.method('current_build_dir')
def current_build_dir_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
src = self.interpreter.environment.build_dir
sub = self.interpreter.subdir
@@ -226,24 +199,28 @@ class MesonMain(MesonInterpreterObject):
@noPosargs
@noKwargs
+ @InterpreterObject.method('backend')
def backend_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
return self.interpreter.backend.name
@noPosargs
@noKwargs
@FeatureDeprecated('meson.source_root', '0.56.0', 'use meson.project_source_root() or meson.global_source_root() instead.')
+ @InterpreterObject.method('source_root')
def source_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
return self.interpreter.environment.source_dir
@noPosargs
@noKwargs
@FeatureDeprecated('meson.build_root', '0.56.0', 'use meson.project_build_root() or meson.global_build_root() instead.')
+ @InterpreterObject.method('build_root')
def build_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
return self.interpreter.environment.build_dir
@noPosargs
@noKwargs
@FeatureNew('meson.project_source_root', '0.56.0')
+ @InterpreterObject.method('project_source_root')
def project_source_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
src = self.interpreter.environment.source_dir
sub = self.interpreter.root_subdir
@@ -254,6 +231,7 @@ class MesonMain(MesonInterpreterObject):
@noPosargs
@noKwargs
@FeatureNew('meson.project_build_root', '0.56.0')
+ @InterpreterObject.method('project_build_root')
def project_build_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
src = self.interpreter.environment.build_dir
sub = self.interpreter.root_subdir
@@ -264,24 +242,28 @@ class MesonMain(MesonInterpreterObject):
@noPosargs
@noKwargs
@FeatureNew('meson.global_source_root', '0.58.0')
+ @InterpreterObject.method('global_source_root')
def global_source_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
return self.interpreter.environment.source_dir
@noPosargs
@noKwargs
@FeatureNew('meson.global_build_root', '0.58.0')
+ @InterpreterObject.method('global_build_root')
def global_build_root_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
return self.interpreter.environment.build_dir
@noPosargs
@noKwargs
@FeatureDeprecated('meson.has_exe_wrapper', '0.55.0', 'use meson.can_run_host_binaries instead.')
+ @InterpreterObject.method('has_exe_wrapper')
def has_exe_wrapper_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
return self._can_run_host_binaries_impl()
@noPosargs
@noKwargs
@FeatureNew('meson.can_run_host_binaries', '0.55.0')
+ @InterpreterObject.method('can_run_host_binaries')
def can_run_host_binaries_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
return self._can_run_host_binaries_impl()
@@ -294,11 +276,13 @@ class MesonMain(MesonInterpreterObject):
@noPosargs
@noKwargs
+ @InterpreterObject.method('is_cross_build')
def is_cross_build_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
return self.build.environment.is_cross_build()
@typed_pos_args('meson.get_compiler', str)
@typed_kwargs('meson.get_compiler', NATIVE_KW)
+ @InterpreterObject.method('get_compiler')
def get_compiler_method(self, args: T.Tuple[str], kwargs: 'NativeKW') -> 'Compiler':
cname = args[0]
for_machine = kwargs['native']
@@ -310,23 +294,27 @@ class MesonMain(MesonInterpreterObject):
@noPosargs
@noKwargs
+ @InterpreterObject.method('is_unity')
def is_unity_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
optval = self.interpreter.environment.coredata.optstore.get_value_for(OptionKey('unity'))
return optval == 'on' or (optval == 'subprojects' and self.interpreter.is_subproject())
@noPosargs
@noKwargs
+ @InterpreterObject.method('is_subproject')
def is_subproject_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
return self.interpreter.is_subproject()
@typed_pos_args('meson.install_dependency_manifest', str)
@noKwargs
+ @InterpreterObject.method('install_dependency_manifest')
def install_dependency_manifest_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> None:
self.build.dep_manifest_name = args[0]
@FeatureNew('meson.override_find_program', '0.46.0')
@typed_pos_args('meson.override_find_program', str, (mesonlib.File, ExternalProgram, build.Executable))
@noKwargs
+ @InterpreterObject.method('override_find_program')
def override_find_program_method(self, args: T.Tuple[str, T.Union[mesonlib.File, ExternalProgram, build.Executable]], kwargs: 'TYPE_kwargs') -> None:
name, exe = args
if isinstance(exe, mesonlib.File):
@@ -335,6 +323,8 @@ class MesonMain(MesonInterpreterObject):
if not os.path.exists(abspath):
raise InterpreterException(f'Tried to override {name} with a file that does not exist.')
exe = OverrideProgram(name, self.interpreter.project_version, command=[abspath])
+ elif isinstance(exe, build.Executable):
+ exe = build.OverrideExecutable(exe, self.interpreter.project_version)
self.interpreter.add_find_program_override(name, exe)
@typed_kwargs(
@@ -344,6 +334,7 @@ class MesonMain(MesonInterpreterObject):
)
@typed_pos_args('meson.override_dependency', str, dependencies.Dependency)
@FeatureNew('meson.override_dependency', '0.54.0')
+ @InterpreterObject.method('override_dependency')
def override_dependency_method(self, args: T.Tuple[str, dependencies.Dependency], kwargs: 'FuncOverrideDependency') -> None:
name, dep = args
if not name:
@@ -409,28 +400,33 @@ class MesonMain(MesonInterpreterObject):
@noPosargs
@noKwargs
+ @InterpreterObject.method('project_version')
def project_version_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
return self.build.dep_manifest[self.interpreter.active_projectname].version
@FeatureNew('meson.project_license()', '0.45.0')
@noPosargs
@noKwargs
+ @InterpreterObject.method('project_license')
def project_license_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> T.List[str]:
return self.build.dep_manifest[self.interpreter.active_projectname].license
@FeatureNew('meson.project_license_files()', '1.1.0')
@noPosargs
@noKwargs
+ @InterpreterObject.method('project_license_files')
def project_license_files_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[mesonlib.File]:
return [l[1] for l in self.build.dep_manifest[self.interpreter.active_projectname].license_files]
@noPosargs
@noKwargs
+ @InterpreterObject.method('version')
def version_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> MesonVersionString:
return MesonVersionString(self.interpreter.coredata.version)
@noPosargs
@noKwargs
+ @InterpreterObject.method('project_name')
def project_name_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
return self.interpreter.active_projectname
@@ -447,6 +443,7 @@ class MesonMain(MesonInterpreterObject):
@FeatureDeprecated('meson.get_cross_property', '0.58.0', 'Use meson.get_external_property() instead')
@typed_pos_args('meson.get_cross_property', str, optargs=[object])
@noKwargs
+ @InterpreterObject.method('get_cross_property')
def get_cross_property_method(self, args: T.Tuple[str, T.Optional[object]], kwargs: 'TYPE_kwargs') -> object:
propname, fallback = args
return self.__get_external_property_impl(propname, fallback, MachineChoice.HOST)
@@ -455,6 +452,7 @@ class MesonMain(MesonInterpreterObject):
@FeatureNew('meson.get_external_property', '0.54.0')
@typed_pos_args('meson.get_external_property', str, optargs=[object])
@typed_kwargs('meson.get_external_property', NATIVE_KW)
+ @InterpreterObject.method('get_external_property')
def get_external_property_method(self, args: T.Tuple[str, T.Optional[object]], kwargs: 'NativeKW') -> object:
propname, fallback = args
return self.__get_external_property_impl(propname, fallback, kwargs['native'])
@@ -462,6 +460,7 @@ class MesonMain(MesonInterpreterObject):
@FeatureNew('meson.has_external_property', '0.58.0')
@typed_pos_args('meson.has_external_property', str)
@typed_kwargs('meson.has_external_property', NATIVE_KW)
+ @InterpreterObject.method('has_external_property')
def has_external_property_method(self, args: T.Tuple[str], kwargs: 'NativeKW') -> bool:
prop_name = args[0]
return prop_name in self.interpreter.environment.properties[kwargs['native']]
@@ -469,6 +468,7 @@ class MesonMain(MesonInterpreterObject):
@FeatureNew('add_devenv', '0.58.0')
@typed_kwargs('environment', ENV_METHOD_KW, ENV_SEPARATOR_KW.evolve(since='0.62.0'))
@typed_pos_args('add_devenv', (str, list, dict, mesonlib.EnvironmentVariables))
+ @InterpreterObject.method('add_devenv')
def add_devenv_method(self, args: T.Tuple[T.Union[str, list, dict, mesonlib.EnvironmentVariables]],
kwargs: 'AddDevenvKW') -> None:
env = args[0]
@@ -482,6 +482,7 @@ class MesonMain(MesonInterpreterObject):
@noPosargs
@noKwargs
@FeatureNew('meson.build_options', '1.1.0')
+ @InterpreterObject.method('build_options')
def build_options_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
options = self.interpreter.user_defined_options
if options is None:
diff --git a/mesonbuild/interpreter/primitives/array.py b/mesonbuild/interpreter/primitives/array.py
index b42ddea..ff520a2 100644
--- a/mesonbuild/interpreter/primitives/array.py
+++ b/mesonbuild/interpreter/primitives/array.py
@@ -5,9 +5,10 @@ from __future__ import annotations
import typing as T
from ...interpreterbase import (
- ObjectHolder,
+ InterpreterObject,
IterableObject,
MesonOperator,
+ ObjectHolder,
typed_operator,
noKwargs,
noPosargs,
@@ -22,31 +23,16 @@ from ...interpreterbase import (
from ...mparser import PlusAssignmentNode
if T.TYPE_CHECKING:
- # Object holders need the actual interpreter
- from ...interpreter import Interpreter
from ...interpreterbase import TYPE_kwargs
class ArrayHolder(ObjectHolder[T.List[TYPE_var]], IterableObject):
- def __init__(self, obj: T.List[TYPE_var], interpreter: 'Interpreter') -> None:
- super().__init__(obj, interpreter)
- self.methods.update({
- 'contains': self.contains_method,
- 'length': self.length_method,
- 'get': self.get_method,
- })
-
- self.trivial_operators.update({
- MesonOperator.EQUALS: (list, lambda x: self.held_object == x),
- MesonOperator.NOT_EQUALS: (list, lambda x: self.held_object != x),
- MesonOperator.IN: (object, lambda x: x in self.held_object),
- MesonOperator.NOT_IN: (object, lambda x: x not in self.held_object),
- })
-
- # Use actual methods for functions that require additional checks
- self.operators.update({
- MesonOperator.PLUS: self.op_plus,
- MesonOperator.INDEX: self.op_index,
- })
+ # Operators that only require type checks
+ TRIVIAL_OPERATORS = {
+ MesonOperator.EQUALS: (list, lambda obj, x: obj.held_object == x),
+ MesonOperator.NOT_EQUALS: (list, lambda obj, x: obj.held_object != x),
+ MesonOperator.IN: (object, lambda obj, x: x in obj.held_object),
+ MesonOperator.NOT_IN: (object, lambda obj, x: x not in obj.held_object),
+ }
def display_name(self) -> str:
return 'array'
@@ -63,6 +49,7 @@ class ArrayHolder(ObjectHolder[T.List[TYPE_var]], IterableObject):
@noArgsFlattening
@noKwargs
@typed_pos_args('array.contains', object)
+ @InterpreterObject.method('contains')
def contains_method(self, args: T.Tuple[object], kwargs: TYPE_kwargs) -> bool:
def check_contains(el: T.List[TYPE_var]) -> bool:
for element in el:
@@ -77,12 +64,14 @@ class ArrayHolder(ObjectHolder[T.List[TYPE_var]], IterableObject):
@noKwargs
@noPosargs
+ @InterpreterObject.method('length')
def length_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> int:
return len(self.held_object)
@noArgsFlattening
@noKwargs
@typed_pos_args('array.get', int, optargs=[object])
+ @InterpreterObject.method('get')
def get_method(self, args: T.Tuple[int, T.Optional[TYPE_var]], kwargs: TYPE_kwargs) -> TYPE_var:
index = args[0]
if index < -len(self.held_object) or index >= len(self.held_object):
@@ -92,6 +81,7 @@ class ArrayHolder(ObjectHolder[T.List[TYPE_var]], IterableObject):
return self.held_object[index]
@typed_operator(MesonOperator.PLUS, object)
+ @InterpreterObject.operator(MesonOperator.PLUS)
def op_plus(self, other: TYPE_var) -> T.List[TYPE_var]:
if not isinstance(other, list):
if not isinstance(self.current_node, PlusAssignmentNode):
@@ -101,6 +91,7 @@ class ArrayHolder(ObjectHolder[T.List[TYPE_var]], IterableObject):
return self.held_object + other
@typed_operator(MesonOperator.INDEX, int)
+ @InterpreterObject.operator(MesonOperator.INDEX)
def op_index(self, other: int) -> TYPE_var:
try:
return self.held_object[other]
diff --git a/mesonbuild/interpreter/primitives/boolean.py b/mesonbuild/interpreter/primitives/boolean.py
index 4b49caf..eb01b9f 100644
--- a/mesonbuild/interpreter/primitives/boolean.py
+++ b/mesonbuild/interpreter/primitives/boolean.py
@@ -3,8 +3,9 @@
from __future__ import annotations
from ...interpreterbase import (
- ObjectHolder,
+ InterpreterObject,
MesonOperator,
+ ObjectHolder,
typed_pos_args,
noKwargs,
noPosargs,
@@ -15,35 +16,28 @@ from ...interpreterbase import (
import typing as T
if T.TYPE_CHECKING:
- # Object holders need the actual interpreter
- from ...interpreter import Interpreter
from ...interpreterbase import TYPE_var, TYPE_kwargs
class BooleanHolder(ObjectHolder[bool]):
- def __init__(self, obj: bool, interpreter: 'Interpreter') -> None:
- super().__init__(obj, interpreter)
- self.methods.update({
- 'to_int': self.to_int_method,
- 'to_string': self.to_string_method,
- })
-
- self.trivial_operators.update({
- MesonOperator.BOOL: (None, lambda x: self.held_object),
- MesonOperator.NOT: (None, lambda x: not self.held_object),
- MesonOperator.EQUALS: (bool, lambda x: self.held_object == x),
- MesonOperator.NOT_EQUALS: (bool, lambda x: self.held_object != x),
- })
+ TRIVIAL_OPERATORS = {
+ MesonOperator.BOOL: (None, lambda obj, x: obj.held_object),
+ MesonOperator.NOT: (None, lambda obj, x: not obj.held_object),
+ MesonOperator.EQUALS: (bool, lambda obj, x: obj.held_object == x),
+ MesonOperator.NOT_EQUALS: (bool, lambda obj, x: obj.held_object != x),
+ }
def display_name(self) -> str:
return 'bool'
@noKwargs
@noPosargs
+ @InterpreterObject.method('to_int')
def to_int_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> int:
return 1 if self.held_object else 0
@noKwargs
@typed_pos_args('bool.to_string', optargs=[str, str])
+ @InterpreterObject.method('to_string')
def to_string_method(self, args: T.Tuple[T.Optional[str], T.Optional[str]], kwargs: TYPE_kwargs) -> str:
true_str = args[0] or 'true'
false_str = args[1] or 'false'
diff --git a/mesonbuild/interpreter/primitives/dict.py b/mesonbuild/interpreter/primitives/dict.py
index ab4c15f..d641fa8 100644
--- a/mesonbuild/interpreter/primitives/dict.py
+++ b/mesonbuild/interpreter/primitives/dict.py
@@ -5,9 +5,10 @@ from __future__ import annotations
import typing as T
from ...interpreterbase import (
- ObjectHolder,
+ InterpreterObject,
IterableObject,
MesonOperator,
+ ObjectHolder,
typed_operator,
noKwargs,
noPosargs,
@@ -20,34 +21,20 @@ from ...interpreterbase import (
)
if T.TYPE_CHECKING:
- # Object holders need the actual interpreter
- from ...interpreter import Interpreter
from ...interpreterbase import TYPE_kwargs
class DictHolder(ObjectHolder[T.Dict[str, TYPE_var]], IterableObject):
- def __init__(self, obj: T.Dict[str, TYPE_var], interpreter: 'Interpreter') -> None:
- super().__init__(obj, interpreter)
- self.methods.update({
- 'has_key': self.has_key_method,
- 'keys': self.keys_method,
- 'get': self.get_method,
- })
-
- self.trivial_operators.update({
- # Arithmetic
- MesonOperator.PLUS: (dict, lambda x: {**self.held_object, **x}),
-
- # Comparison
- MesonOperator.EQUALS: (dict, lambda x: self.held_object == x),
- MesonOperator.NOT_EQUALS: (dict, lambda x: self.held_object != x),
- MesonOperator.IN: (str, lambda x: x in self.held_object),
- MesonOperator.NOT_IN: (str, lambda x: x not in self.held_object),
- })
-
- # Use actual methods for functions that require additional checks
- self.operators.update({
- MesonOperator.INDEX: self.op_index,
- })
+ # Operators that only require type checks
+ TRIVIAL_OPERATORS = {
+ # Arithmetic
+ MesonOperator.PLUS: (dict, lambda obj, x: {**obj.held_object, **x}),
+
+ # Comparison
+ MesonOperator.EQUALS: (dict, lambda obj, x: obj.held_object == x),
+ MesonOperator.NOT_EQUALS: (dict, lambda obj, x: obj.held_object != x),
+ MesonOperator.IN: (str, lambda obj, x: x in obj.held_object),
+ MesonOperator.NOT_IN: (str, lambda obj, x: x not in obj.held_object),
+ }
def display_name(self) -> str:
return 'dict'
@@ -63,17 +50,20 @@ class DictHolder(ObjectHolder[T.Dict[str, TYPE_var]], IterableObject):
@noKwargs
@typed_pos_args('dict.has_key', str)
+ @InterpreterObject.method('has_key')
def has_key_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool:
return args[0] in self.held_object
@noKwargs
@noPosargs
+ @InterpreterObject.method('keys')
def keys_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[str]:
return sorted(self.held_object)
@noArgsFlattening
@noKwargs
@typed_pos_args('dict.get', str, optargs=[object])
+ @InterpreterObject.method('get')
def get_method(self, args: T.Tuple[str, T.Optional[TYPE_var]], kwargs: TYPE_kwargs) -> TYPE_var:
if args[0] in self.held_object:
return self.held_object[args[0]]
@@ -82,6 +72,7 @@ class DictHolder(ObjectHolder[T.Dict[str, TYPE_var]], IterableObject):
raise InvalidArguments(f'Key {args[0]!r} is not in the dictionary.')
@typed_operator(MesonOperator.INDEX, str)
+ @InterpreterObject.operator(MesonOperator.INDEX)
def op_index(self, other: str) -> TYPE_var:
if other not in self.held_object:
raise InvalidArguments(f'Key {other} is not in the dictionary.')
diff --git a/mesonbuild/interpreter/primitives/integer.py b/mesonbuild/interpreter/primitives/integer.py
index cdf2355..c59ea6e 100644
--- a/mesonbuild/interpreter/primitives/integer.py
+++ b/mesonbuild/interpreter/primitives/integer.py
@@ -3,47 +3,33 @@
from __future__ import annotations
from ...interpreterbase import (
- FeatureBroken, InvalidArguments, MesonOperator, ObjectHolder, KwargInfo,
+ InterpreterObject, MesonOperator, ObjectHolder,
+ FeatureBroken, InvalidArguments, KwargInfo,
noKwargs, noPosargs, typed_operator, typed_kwargs
)
import typing as T
if T.TYPE_CHECKING:
- # Object holders need the actual interpreter
- from ...interpreter import Interpreter
from ...interpreterbase import TYPE_var, TYPE_kwargs
class IntegerHolder(ObjectHolder[int]):
- def __init__(self, obj: int, interpreter: 'Interpreter') -> None:
- super().__init__(obj, interpreter)
- self.methods.update({
- 'is_even': self.is_even_method,
- 'is_odd': self.is_odd_method,
- 'to_string': self.to_string_method,
- })
+ # Operators that only require type checks
+ TRIVIAL_OPERATORS = {
+ # Arithmetic
+ MesonOperator.UMINUS: (None, lambda obj, x: -obj.held_object),
+ MesonOperator.PLUS: (int, lambda obj, x: obj.held_object + x),
+ MesonOperator.MINUS: (int, lambda obj, x: obj.held_object - x),
+ MesonOperator.TIMES: (int, lambda obj, x: obj.held_object * x),
- self.trivial_operators.update({
- # Arithmetic
- MesonOperator.UMINUS: (None, lambda x: -self.held_object),
- MesonOperator.PLUS: (int, lambda x: self.held_object + x),
- MesonOperator.MINUS: (int, lambda x: self.held_object - x),
- MesonOperator.TIMES: (int, lambda x: self.held_object * x),
-
- # Comparison
- MesonOperator.EQUALS: (int, lambda x: self.held_object == x),
- MesonOperator.NOT_EQUALS: (int, lambda x: self.held_object != x),
- MesonOperator.GREATER: (int, lambda x: self.held_object > x),
- MesonOperator.LESS: (int, lambda x: self.held_object < x),
- MesonOperator.GREATER_EQUALS: (int, lambda x: self.held_object >= x),
- MesonOperator.LESS_EQUALS: (int, lambda x: self.held_object <= x),
- })
-
- # Use actual methods for functions that require additional checks
- self.operators.update({
- MesonOperator.DIV: self.op_div,
- MesonOperator.MOD: self.op_mod,
- })
+ # Comparison
+ MesonOperator.EQUALS: (int, lambda obj, x: obj.held_object == x),
+ MesonOperator.NOT_EQUALS: (int, lambda obj, x: obj.held_object != x),
+ MesonOperator.GREATER: (int, lambda obj, x: obj.held_object > x),
+ MesonOperator.LESS: (int, lambda obj, x: obj.held_object < x),
+ MesonOperator.GREATER_EQUALS: (int, lambda obj, x: obj.held_object >= x),
+ MesonOperator.LESS_EQUALS: (int, lambda obj, x: obj.held_object <= x),
+ }
def display_name(self) -> str:
return 'int'
@@ -57,11 +43,13 @@ class IntegerHolder(ObjectHolder[int]):
@noKwargs
@noPosargs
+ @InterpreterObject.method('is_even')
def is_even_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
return self.held_object % 2 == 0
@noKwargs
@noPosargs
+ @InterpreterObject.method('is_odd')
def is_odd_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
return self.held_object % 2 != 0
@@ -70,16 +58,19 @@ class IntegerHolder(ObjectHolder[int]):
KwargInfo('fill', int, default=0, since='1.3.0')
)
@noPosargs
+ @InterpreterObject.method('to_string')
def to_string_method(self, args: T.List[TYPE_var], kwargs: T.Dict[str, T.Any]) -> str:
return str(self.held_object).zfill(kwargs['fill'])
@typed_operator(MesonOperator.DIV, int)
+ @InterpreterObject.operator(MesonOperator.DIV)
def op_div(self, other: int) -> int:
if other == 0:
raise InvalidArguments('Tried to divide by 0')
return self.held_object // other
@typed_operator(MesonOperator.MOD, int)
+ @InterpreterObject.operator(MesonOperator.MOD)
def op_mod(self, other: int) -> int:
if other == 0:
raise InvalidArguments('Tried to divide by 0')
diff --git a/mesonbuild/interpreter/primitives/range.py b/mesonbuild/interpreter/primitives/range.py
index 23d5617..1aceb68 100644
--- a/mesonbuild/interpreter/primitives/range.py
+++ b/mesonbuild/interpreter/primitives/range.py
@@ -5,8 +5,9 @@ from __future__ import annotations
import typing as T
from ...interpreterbase import (
- MesonInterpreterObject,
+ InterpreterObject,
IterableObject,
+ MesonInterpreterObject,
MesonOperator,
InvalidArguments,
)
@@ -18,10 +19,8 @@ class RangeHolder(MesonInterpreterObject, IterableObject):
def __init__(self, start: int, stop: int, step: int, *, subproject: 'SubProject') -> None:
super().__init__(subproject=subproject)
self.range = range(start, stop, step)
- self.operators.update({
- MesonOperator.INDEX: self.op_index,
- })
+ @InterpreterObject.operator(MesonOperator.INDEX)
def op_index(self, other: int) -> int:
try:
return self.range[other]
diff --git a/mesonbuild/interpreter/primitives/string.py b/mesonbuild/interpreter/primitives/string.py
index a224dfa..49dd716 100644
--- a/mesonbuild/interpreter/primitives/string.py
+++ b/mesonbuild/interpreter/primitives/string.py
@@ -9,8 +9,9 @@ import typing as T
from ...mesonlib import version_compare, version_compare_many
from ...interpreterbase import (
- ObjectHolder,
+ InterpreterObject,
MesonOperator,
+ ObjectHolder,
FeatureNew,
typed_operator,
noArgsFlattening,
@@ -24,73 +25,47 @@ from ...interpreterbase import (
if T.TYPE_CHECKING:
- # Object holders need the actual interpreter
- from ...interpreter import Interpreter
from ...interpreterbase import TYPE_var, TYPE_kwargs
class StringHolder(ObjectHolder[str]):
- def __init__(self, obj: str, interpreter: 'Interpreter') -> None:
- super().__init__(obj, interpreter)
- self.methods.update({
- 'contains': self.contains_method,
- 'startswith': self.startswith_method,
- 'endswith': self.endswith_method,
- 'format': self.format_method,
- 'join': self.join_method,
- 'replace': self.replace_method,
- 'split': self.split_method,
- 'splitlines': self.splitlines_method,
- 'strip': self.strip_method,
- 'substring': self.substring_method,
- 'to_int': self.to_int_method,
- 'to_lower': self.to_lower_method,
- 'to_upper': self.to_upper_method,
- 'underscorify': self.underscorify_method,
- 'version_compare': self.version_compare_method,
- })
-
- self.trivial_operators.update({
- # Arithmetic
- MesonOperator.PLUS: (str, lambda x: self.held_object + x),
-
- # Comparison
- MesonOperator.EQUALS: (str, lambda x: self.held_object == x),
- MesonOperator.NOT_EQUALS: (str, lambda x: self.held_object != x),
- MesonOperator.GREATER: (str, lambda x: self.held_object > x),
- MesonOperator.LESS: (str, lambda x: self.held_object < x),
- MesonOperator.GREATER_EQUALS: (str, lambda x: self.held_object >= x),
- MesonOperator.LESS_EQUALS: (str, lambda x: self.held_object <= x),
- })
-
- # Use actual methods for functions that require additional checks
- self.operators.update({
- MesonOperator.DIV: self.op_div,
- MesonOperator.INDEX: self.op_index,
- MesonOperator.IN: self.op_in,
- MesonOperator.NOT_IN: self.op_notin,
- })
+ TRIVIAL_OPERATORS = {
+ # Arithmetic
+ MesonOperator.PLUS: (str, lambda obj, x: obj.held_object + x),
+
+ # Comparison
+ MesonOperator.EQUALS: (str, lambda obj, x: obj.held_object == x),
+ MesonOperator.NOT_EQUALS: (str, lambda obj, x: obj.held_object != x),
+ MesonOperator.GREATER: (str, lambda obj, x: obj.held_object > x),
+ MesonOperator.LESS: (str, lambda obj, x: obj.held_object < x),
+ MesonOperator.GREATER_EQUALS: (str, lambda obj, x: obj.held_object >= x),
+ MesonOperator.LESS_EQUALS: (str, lambda obj, x: obj.held_object <= x),
+ }
def display_name(self) -> str:
return 'str'
@noKwargs
@typed_pos_args('str.contains', str)
+ @InterpreterObject.method('contains')
def contains_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool:
return self.held_object.find(args[0]) >= 0
@noKwargs
@typed_pos_args('str.startswith', str)
+ @InterpreterObject.method('startswith')
def startswith_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool:
return self.held_object.startswith(args[0])
@noKwargs
@typed_pos_args('str.endswith', str)
+ @InterpreterObject.method('endswith')
def endswith_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool:
return self.held_object.endswith(args[0])
@noArgsFlattening
@noKwargs
@typed_pos_args('str.format', varargs=object)
+ @InterpreterObject.method('format')
def format_method(self, args: T.Tuple[T.List[TYPE_var]], kwargs: TYPE_kwargs) -> str:
arg_strings: T.List[str] = []
for arg in args[0]:
@@ -111,27 +86,32 @@ class StringHolder(ObjectHolder[str]):
@noKwargs
@noPosargs
@FeatureNew('str.splitlines', '1.2.0')
+ @InterpreterObject.method('splitlines')
def splitlines_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[str]:
return self.held_object.splitlines()
@noKwargs
@typed_pos_args('str.join', varargs=str)
+ @InterpreterObject.method('join')
def join_method(self, args: T.Tuple[T.List[str]], kwargs: TYPE_kwargs) -> str:
return self.held_object.join(args[0])
@noKwargs
@FeatureNew('str.replace', '0.58.0')
@typed_pos_args('str.replace', str, str)
+ @InterpreterObject.method('replace')
def replace_method(self, args: T.Tuple[str, str], kwargs: TYPE_kwargs) -> str:
return self.held_object.replace(args[0], args[1])
@noKwargs
@typed_pos_args('str.split', optargs=[str])
+ @InterpreterObject.method('split')
def split_method(self, args: T.Tuple[T.Optional[str]], kwargs: TYPE_kwargs) -> T.List[str]:
return self.held_object.split(args[0])
@noKwargs
@typed_pos_args('str.strip', optargs=[str])
+ @InterpreterObject.method('strip')
def strip_method(self, args: T.Tuple[T.Optional[str]], kwargs: TYPE_kwargs) -> str:
if args[0]:
FeatureNew.single_use('str.strip with a positional argument', '0.43.0', self.subproject, location=self.current_node)
@@ -140,6 +120,7 @@ class StringHolder(ObjectHolder[str]):
@noKwargs
@FeatureNew('str.substring', '0.56.0')
@typed_pos_args('str.substring', optargs=[int, int])
+ @InterpreterObject.method('substring')
def substring_method(self, args: T.Tuple[T.Optional[int], T.Optional[int]], kwargs: TYPE_kwargs) -> str:
start = args[0] if args[0] is not None else 0
end = args[1] if args[1] is not None else len(self.held_object)
@@ -147,6 +128,7 @@ class StringHolder(ObjectHolder[str]):
@noKwargs
@noPosargs
+ @InterpreterObject.method('to_int')
def to_int_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> int:
try:
return int(self.held_object)
@@ -155,20 +137,24 @@ class StringHolder(ObjectHolder[str]):
@noKwargs
@noPosargs
+ @InterpreterObject.method('to_lower')
def to_lower_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.lower()
@noKwargs
@noPosargs
+ @InterpreterObject.method('to_upper')
def to_upper_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.held_object.upper()
@noKwargs
@noPosargs
+ @InterpreterObject.method('underscorify')
def underscorify_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return re.sub(r'[^a-zA-Z0-9]', '_', self.held_object)
@noKwargs
+ @InterpreterObject.method('version_compare')
@typed_pos_args('str.version_compare', varargs=str, min_varargs=1)
def version_compare_method(self, args: T.Tuple[T.List[str]], kwargs: TYPE_kwargs) -> bool:
if len(args[0]) > 1:
@@ -181,10 +167,12 @@ class StringHolder(ObjectHolder[str]):
@FeatureNew('/ with string arguments', '0.49.0')
@typed_operator(MesonOperator.DIV, str)
+ @InterpreterObject.operator(MesonOperator.DIV)
def op_div(self, other: str) -> str:
return self._op_div(self.held_object, other)
@typed_operator(MesonOperator.INDEX, int)
+ @InterpreterObject.operator(MesonOperator.INDEX)
def op_index(self, other: int) -> str:
try:
return self.held_object[other]
@@ -193,11 +181,13 @@ class StringHolder(ObjectHolder[str]):
@FeatureNew('"in" string operator', '1.0.0')
@typed_operator(MesonOperator.IN, str)
+ @InterpreterObject.operator(MesonOperator.IN)
def op_in(self, other: str) -> bool:
return other in self.held_object
@FeatureNew('"not in" string operator', '1.0.0')
@typed_operator(MesonOperator.NOT_IN, str)
+ @InterpreterObject.operator(MesonOperator.NOT_IN)
def op_notin(self, other: str) -> bool:
return other not in self.held_object
@@ -208,6 +198,7 @@ class MesonVersionString(str):
class MesonVersionStringHolder(StringHolder):
@noKwargs
@typed_pos_args('str.version_compare', str)
+ @InterpreterObject.method('version_compare')
def version_compare_method(self, args: T.Tuple[str], kwargs: TYPE_kwargs) -> bool:
self.interpreter.tmp_meson_version = args[0]
return version_compare(self.held_object, args[0])
@@ -221,6 +212,7 @@ class DependencyVariableString(str):
pass
class DependencyVariableStringHolder(StringHolder):
+ @InterpreterObject.operator(MesonOperator.DIV)
def op_div(self, other: str) -> T.Union[str, DependencyVariableString]:
ret = super().op_div(other)
if '..' in other:
@@ -243,6 +235,7 @@ class OptionString(str):
class OptionStringHolder(StringHolder):
held_object: OptionString
+ @InterpreterObject.operator(MesonOperator.DIV)
def op_div(self, other: str) -> T.Union[str, OptionString]:
ret = super().op_div(other)
name = self._op_div(self.held_object.optname, other)
diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py
index 78938ba..fbe3e3e 100644
--- a/mesonbuild/interpreter/type_checking.py
+++ b/mesonbuild/interpreter/type_checking.py
@@ -11,10 +11,10 @@ from .. import compilers
from ..build import (CustomTarget, BuildTarget,
CustomTargetIndex, ExtractedObjects, GeneratedList, IncludeDirs,
BothLibraries, SharedLibrary, StaticLibrary, Jar, Executable, StructuredSources)
-from ..options import UserFeatureOption
+from ..options import OptionKey, UserFeatureOption
from ..dependencies import Dependency, InternalDependency
from ..interpreterbase.decorators import KwargInfo, ContainerTypeInfo
-from ..mesonlib import (File, FileMode, MachineChoice, listify, has_path_sep,
+from ..mesonlib import (File, FileMode, MachineChoice, has_path_sep, listify, stringlistify,
EnvironmentVariables)
from ..programs import ExternalProgram
@@ -293,11 +293,22 @@ COMMAND_KW: KwargInfo[T.List[T.Union[str, BuildTarget, CustomTarget, CustomTarge
)
-OVERRIDE_OPTIONS_KW: KwargInfo[T.Union[str, T.Dict[str, ElementaryOptionValues], T.List[str]]] = KwargInfo(
+def _override_options_convertor(raw: T.Union[str, T.List[str], T.Dict[str, ElementaryOptionValues]]) -> T.Dict[str, ElementaryOptionValues]:
+ if isinstance(raw, dict):
+ return raw
+ raw = stringlistify(raw)
+ output: T.Dict[str, ElementaryOptionValues] = {}
+ for each in raw:
+ k, v = split_equal_string(each)
+ output[k] = v
+ return output
+
+OVERRIDE_OPTIONS_KW: KwargInfo[T.Union[str, T.List[str], T.Dict[str, ElementaryOptionValues]]] = KwargInfo(
'override_options',
(str, ContainerTypeInfo(list, str), ContainerTypeInfo(dict, (str, int, bool, list))),
default={},
validator=_options_validator,
+ convertor=_override_options_convertor,
since_values={dict: '1.2.0'},
)
@@ -394,7 +405,13 @@ INCLUDE_DIRECTORIES: KwargInfo[T.List[T.Union[str, IncludeDirs]]] = KwargInfo(
default=[],
)
-DEFAULT_OPTIONS = OVERRIDE_OPTIONS_KW.evolve(name='default_options')
+def _default_options_convertor(raw: T.Union[str, T.List[str], T.Dict[str, ElementaryOptionValues]]) -> T.Dict[OptionKey, ElementaryOptionValues]:
+ d = _override_options_convertor(raw)
+ return {OptionKey.from_string(k): v for k, v in d.items()}
+
+DEFAULT_OPTIONS = OVERRIDE_OPTIONS_KW.evolve(
+ name='default_options',
+ convertor=_default_options_convertor)
ENV_METHOD_KW = KwargInfo('method', str, default='set', since='0.62.0',
validator=in_set_validator({'set', 'prepend', 'append'}))