interpreter: use typed_kwargs for subproject()

pull/10043/head
Dylan Baker 3 years ago
parent 71c65392a8
commit 4a2058cb83
  1. 5
      mesonbuild/interpreter/dependencyfallbacks.py
  2. 55
      mesonbuild/interpreter/interpreter.py
  3. 15
      mesonbuild/interpreter/kwargs.py
  4. 13
      mesonbuild/modules/cmake.py
  5. 2
      test cases/failing/120 subproject version conflict/test.json
  6. 2
      test cases/failing/21 subver/test.json

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

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

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

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

@ -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."
}
]
}

@ -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."
}
]
}

Loading…
Cancel
Save