diff options
-rw-r--r-- | mesonbuild/interpreter/dependencyfallbacks.py | 5 | ||||
-rw-r--r-- | mesonbuild/interpreter/interpreter.py | 55 | ||||
-rw-r--r-- | mesonbuild/interpreter/kwargs.py | 15 | ||||
-rw-r--r-- | mesonbuild/modules/cmake.py | 13 | ||||
-rw-r--r-- | test cases/failing/120 subproject version conflict/test.json | 2 | ||||
-rw-r--r-- | test cases/failing/21 subver/test.json | 2 |
6 files changed, 67 insertions, 25 deletions
diff --git a/mesonbuild/interpreter/dependencyfallbacks.py b/mesonbuild/interpreter/dependencyfallbacks.py index 8a0d351..e029854 100644 --- a/mesonbuild/interpreter/dependencyfallbacks.py +++ b/mesonbuild/interpreter/dependencyfallbacks.py @@ -4,7 +4,7 @@ from .. import mlog from .. import dependencies from .. import build from ..wrap import WrapMode -from ..mesonlib import OptionKey, extract_as_list, stringlistify, version_compare_many +from ..mesonlib import OptionKey, extract_as_list, stringlistify, version_compare_many, listify from ..dependencies import Dependency, DependencyException, NotFoundDependency from ..interpreterbase import (MesonInterpreterObject, FeatureNew, InterpreterException, InvalidArguments, @@ -131,6 +131,9 @@ class DependencyFallbacksHolder(MesonInterpreterObject): # 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, 'meson', func_kwargs) return self._get_subproject_dep(subp_name, varname, kwargs) diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 943f49e..1f778c8 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -799,8 +799,21 @@ external dependencies (including libraries) must go to "dependencies".''') @FeatureNewKwargs('subproject', '0.38.0', ['default_options']) @permittedKwargs({'version', 'default_options', 'required'}) @typed_pos_args('subproject', str) - def func_subproject(self, nodes: mparser.BaseNode, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> SubprojectHolder: - return self.do_subproject(args[0], 'meson', kwargs) + @typed_kwargs( + 'subproject', + REQUIRED_KW, + DEFAULT_OPTIONS.evolve(since='0.38.0'), + KwargInfo('version', ContainerTypeInfo(list, str), default=[], listify=True), + ) + def func_subproject(self, nodes: mparser.BaseNode, args: T.Tuple[str], kwargs_: kwargs.Subproject) -> SubprojectHolder: + kw: kwargs.DoSubproject = { + 'required': kwargs_['required'], + 'default_options': kwargs_['default_options'], + 'version': kwargs_['version'], + 'options': None, + 'cmake_options': [], + } + return self.do_subproject(args[0], 'meson', kw) def disabled_subproject(self, subp_name: str, disabled_feature: T.Optional[str] = None, exception: T.Optional[mesonlib.MesonException] = None) -> SubprojectHolder: @@ -810,14 +823,13 @@ external dependencies (including libraries) must go to "dependencies".''') self.coredata.initialized_subprojects.add(subp_name) return sub - def do_subproject(self, subp_name: str, method: Literal['meson', 'cmake'], kwargs) -> SubprojectHolder: + def do_subproject(self, subp_name: str, method: Literal['meson', 'cmake'], kwargs: kwargs.DoSubproject) -> SubprojectHolder: disabled, required, feature = extract_required_kwarg(kwargs, self.subproject) if disabled: mlog.log('Subproject', mlog.bold(subp_name), ':', 'skipped: feature', mlog.bold(feature), 'disabled') return self.disabled_subproject(subp_name, disabled_feature=feature) - default_options = mesonlib.stringlistify(kwargs.get('default_options', [])) - default_options = coredata.create_options_dict(default_options, subp_name) + default_options = coredata.create_options_dict(kwargs['default_options'], subp_name) if subp_name == '': raise InterpreterException('Subproject name must not be empty.') @@ -838,7 +850,7 @@ external dependencies (including libraries) must go to "dependencies".''') subproject = self.subprojects[subp_name] if required and not subproject.found(): raise InterpreterException(f'Subproject "{subproject.subdir}" required but not found.') - if 'version' in kwargs: + if kwargs['version']: pv = self.build.subprojects[subp_name] wanted = kwargs['version'] if pv == 'undefined' or not mesonlib.version_compare_many(pv, wanted)[0]: @@ -885,7 +897,9 @@ external dependencies (including libraries) must go to "dependencies".''') return self.disabled_subproject(subp_name, exception=e) raise e - def _do_subproject_meson(self, subp_name: str, subdir: str, default_options, kwargs, + def _do_subproject_meson(self, subp_name: str, subdir: str, + default_options: T.Dict[OptionKey, str], + kwargs: kwargs.DoSubproject, ast: T.Optional[mparser.CodeBlockNode] = None, build_def_files: T.Optional[T.List[str]] = None, is_translated: bool = False) -> SubprojectHolder: @@ -914,7 +928,7 @@ external dependencies (including libraries) must go to "dependencies".''') mlog.log() - if 'version' in kwargs: + if kwargs['version']: pv = subi.project_version wanted = kwargs['version'] if pv == 'undefined' or not mesonlib.version_compare_many(pv, wanted)[0]: @@ -932,19 +946,16 @@ external dependencies (including libraries) must go to "dependencies".''') self.coredata.initialized_subprojects.add(subp_name) return self.subprojects[subp_name] - def _do_subproject_cmake(self, subp_name: str, subdir: str, subdir_abs: str, default_options, kwargs): + def _do_subproject_cmake(self, subp_name: str, subdir: str, subdir_abs: str, + default_options: T.Dict[OptionKey, str], + kwargs: kwargs.DoSubproject) -> SubprojectHolder: with mlog.nested(subp_name): new_build = self.build.copy() prefix = self.coredata.options[OptionKey('prefix')].value from ..modules.cmake import CMakeSubprojectOptions - options = kwargs.get('options', CMakeSubprojectOptions()) - if not isinstance(options, CMakeSubprojectOptions): - raise InterpreterException('"options" kwarg must be CMakeSubprojectOptions' - ' object (created by cmake.subproject_options())') - - cmake_options = mesonlib.stringlistify(kwargs.get('cmake_options', [])) - cmake_options += options.cmake_options + options = kwargs['options'] or CMakeSubprojectOptions() + cmake_options = kwargs['cmake_options'] + options.cmake_options cm_int = CMakeInterpreter(new_build, Path(subdir), Path(subdir_abs), Path(prefix), new_build.environment, self.backend) cm_int.initialise(cmake_options) cm_int.analyse() @@ -1501,7 +1512,7 @@ external dependencies (including libraries) must go to "dependencies".''') progobj.was_returned_by_find_program = True return progobj - def program_lookup(self, args, for_machine, required, search_dirs, extra_info): + def program_lookup(self, args, for_machine, required: bool, search_dirs, extra_info): progobj = self.program_from_overrides(args, extra_info) if progobj: return progobj @@ -1524,10 +1535,16 @@ external dependencies (including libraries) must go to "dependencies".''') return progobj - def find_program_fallback(self, fallback, args, required, extra_info): + def find_program_fallback(self, fallback: str, args, required: bool, extra_info): mlog.log('Fallback to subproject', mlog.bold(fallback), 'which provides program', mlog.bold(' '.join(args))) - sp_kwargs = {'required': required} + sp_kwargs: kwargs.DoSubproject = { + 'required': required, + 'default_options': [], + 'version': [], + 'cmake_options': [], + 'options': None, + } self.do_subproject(fallback, 'meson', sp_kwargs) return self.program_from_overrides(args, extra_info) diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 981f50d..f2460ac 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -12,6 +12,7 @@ from .. import build from .. import coredata from ..compilers import Compiler from ..mesonlib import MachineChoice, File, FileMode, FileOrString, OptionKey +from ..modules.cmake import CMakeSubprojectOptions from ..programs import ExternalProgram @@ -293,3 +294,17 @@ class ConfigureFile(TypedDict): command: T.Optional[T.List[T.Union[build.Executable, ExternalProgram, Compiler, File, str]]] input: T.List[FileOrString] configuration: T.Optional[T.Union[T.Dict[str, T.Union[str, int, bool]], build.ConfigurationData]] + + +class Subproject(ExtractRequired): + + default_options: T.List[str] + version: T.List[str] + + +class DoSubproject(ExtractRequired): + + default_options: T.List[str] + version: T.List[str] + cmake_options: T.List[str] + options: T.Optional[CMakeSubprojectOptions] diff --git a/mesonbuild/modules/cmake.py b/mesonbuild/modules/cmake.py index f996087..a58ad54 100644 --- a/mesonbuild/modules/cmake.py +++ b/mesonbuild/modules/cmake.py @@ -425,11 +425,18 @@ class CmakeModule(ExtensionModule): deprecated_message='Use options instead', ), ) - def subproject(self, state: ModuleState, args: T.Tuple[str], kwargs: Subproject) -> T.Union[SubprojectHolder, CMakeSubproject]: - if kwargs['cmake_options'] and kwargs['options'] is not None: + def subproject(self, state: ModuleState, args: T.Tuple[str], kwargs_: Subproject) -> T.Union[SubprojectHolder, CMakeSubproject]: + if kwargs_['cmake_options'] and kwargs_['options'] is not None: raise InterpreterException('"options" cannot be used together with "cmake_options"') dirname = args[0] - subp = self.interpreter.do_subproject(dirname, 'cmake', kwargs) + kw: kwargs.DoSubproject = { + 'required': kwargs_['required'], + 'options': kwargs_['options'], + 'cmake_options': kwargs_['cmake_options'], + 'default_options': [], + 'version': [], + } + subp = self.interpreter.do_subproject(dirname, 'cmake', kw) if not subp.found(): return subp return CMakeSubproject(subp) diff --git a/test cases/failing/120 subproject version conflict/test.json b/test cases/failing/120 subproject version conflict/test.json index 5d445e5..7807d68 100644 --- a/test cases/failing/120 subproject version conflict/test.json +++ b/test cases/failing/120 subproject version conflict/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/120 subproject version conflict/meson.build:4:0: ERROR: Subproject B version is 100 but 1 required." + "line": "test cases/failing/120 subproject version conflict/meson.build:4:0: ERROR: Subproject B version is 100 but ['1'] required." } ] } diff --git a/test cases/failing/21 subver/test.json b/test cases/failing/21 subver/test.json index f8cfd3a..a197b36 100644 --- a/test cases/failing/21 subver/test.json +++ b/test cases/failing/21 subver/test.json @@ -1,7 +1,7 @@ { "stdout": [ { - "line": "test cases/failing/21 subver/meson.build:3:0: ERROR: Subproject foo version is 1.0.0 but >1.0.0 required." + "line": "test cases/failing/21 subver/meson.build:3:0: ERROR: Subproject foo version is 1.0.0 but ['>1.0.0'] required." } ] } |