modules/cmake: add type annotations for subproject method

This will be used to handle the interpreter subproject as well
pull/10043/head
Dylan Baker 3 years ago
parent 5e4ea9f0f4
commit f4ae32c2ad
  1. 30
      mesonbuild/interpreter/dependencyfallbacks.py
  2. 43
      mesonbuild/modules/cmake.py

@ -105,14 +105,14 @@ class DependencyFallbacksHolder(MesonInterpreterObject):
def _do_subproject(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: TYPE_nkwargs) -> T.Optional[Dependency]:
if self.forcefallback:
mlog.log('Looking for a fallback subproject for the dependency',
mlog.bold(self.display_name), 'because:\nUse of fallback dependencies is forced.')
mlog.bold(self._display_name), 'because:\nUse of fallback dependencies is forced.')
elif self.nofallback:
mlog.log('Not looking for a fallback subproject for the dependency',
mlog.bold(self.display_name), 'because:\nUse of fallback dependencies is disabled.')
mlog.bold(self._display_name), 'because:\nUse of fallback dependencies is disabled.')
return None
else:
mlog.log('Looking for a fallback subproject for the dependency',
mlog.bold(self.display_name))
mlog.bold(self._display_name))
# dependency('foo', static: true) should implicitly add
# default_options: ['default_library=static']
@ -141,7 +141,7 @@ class DependencyFallbacksHolder(MesonInterpreterObject):
# Verify the subproject is found
subproject = self._get_subproject(subp_name)
if not subproject:
mlog.log('Dependency', mlog.bold(self.display_name), 'from subproject',
mlog.log('Dependency', mlog.bold(self._display_name), 'from subproject',
mlog.bold(subp_name), 'found:', mlog.red('NO'),
mlog.blue('(subproject failed to configure)'))
return None
@ -167,27 +167,27 @@ class DependencyFallbacksHolder(MesonInterpreterObject):
# Legacy: Use the variable name if provided instead of relying on the
# subproject to override one of our dependency names
if not varname:
mlog.warning(f'Subproject {subp_name!r} did not override {self.display_name!r} dependency and no variable name specified')
mlog.log('Dependency', mlog.bold(self.display_name), 'from subproject',
mlog.warning(f'Subproject {subp_name!r} did not override {self._display_name!r} dependency and no variable name specified')
mlog.log('Dependency', mlog.bold(self._display_name), 'from subproject',
mlog.bold(subproject.subdir), 'found:', mlog.red('NO'))
return self._notfound_dependency()
var_dep = self._get_subproject_variable(subproject, varname) or self._notfound_dependency()
if not var_dep.found():
mlog.log('Dependency', mlog.bold(self.display_name), 'from subproject',
mlog.log('Dependency', mlog.bold(self._display_name), 'from subproject',
mlog.bold(subproject.subdir), 'found:', mlog.red('NO'))
return var_dep
wanted = stringlistify(kwargs.get('version', []))
found = var_dep.get_version()
if not self._check_version(wanted, found):
mlog.log('Dependency', mlog.bold(self.display_name), 'from subproject',
mlog.log('Dependency', mlog.bold(self._display_name), 'from subproject',
mlog.bold(subproject.subdir), 'found:', mlog.red('NO'),
'found', mlog.normal_cyan(found), 'but need:',
mlog.bold(', '.join([f"'{e}'" for e in wanted])))
return self._notfound_dependency()
mlog.log('Dependency', mlog.bold(self.display_name), 'from subproject',
mlog.log('Dependency', mlog.bold(self._display_name), 'from subproject',
mlog.bold(subproject.subdir), 'found:', mlog.green('YES'),
mlog.normal_cyan(found) if found else None)
return var_dep
@ -209,7 +209,7 @@ class DependencyFallbacksHolder(MesonInterpreterObject):
# have explicitly called meson.override_dependency() with a not-found
# dep.
if not cached_dep.found():
mlog.log('Dependency', mlog.bold(self.display_name),
mlog.log('Dependency', mlog.bold(self._display_name),
'found:', mlog.red('NO'), *info)
return cached_dep
else:
@ -231,7 +231,7 @@ class DependencyFallbacksHolder(MesonInterpreterObject):
return self._notfound_dependency()
if found_vers:
info = [mlog.normal_cyan(found_vers), *info]
mlog.log('Dependency', mlog.bold(self.display_name),
mlog.log('Dependency', mlog.bold(self._display_name),
'found:', mlog.green('YES'), *info)
return cached_dep
return None
@ -298,14 +298,14 @@ class DependencyFallbacksHolder(MesonInterpreterObject):
return candidates
def lookup(self, kwargs: TYPE_nkwargs, force_fallback: bool = False) -> Dependency:
self.display_name = self.names[0] if self.names else '(anonymous)'
self._display_name = self.names[0] if self.names else '(anonymous)'
mods = extract_as_list(kwargs, 'modules')
if mods:
self.display_name += ' (modules: {})'.format(', '.join(str(i) for i in mods))
self._display_name += ' (modules: {})'.format(', '.join(str(i) for i in mods))
disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
if disabled:
mlog.log('Dependency', mlog.bold(self.display_name), 'skipped: feature', mlog.bold(feature), 'disabled')
mlog.log('Dependency', mlog.bold(self._display_name), 'skipped: feature', mlog.bold(feature), 'disabled')
return self._notfound_dependency()
# Check if usage of the subproject fallback is forced
@ -359,7 +359,7 @@ class DependencyFallbacksHolder(MesonInterpreterObject):
# This was the last candidate or the dependency has been cached
# as not-found, or cached dependency version does not match,
# otherwise func() would have returned None instead.
raise DependencyException(f'Dependency {self.display_name!r} is required but not found.')
raise DependencyException(f'Dependency {self._display_name!r} is required but not found.')
elif dep:
# Same as above, but the dependency is not required.
return dep

@ -11,6 +11,8 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations
import re
import os, os.path, pathlib
import shutil
@ -21,11 +23,10 @@ from . import ExtensionModule, ModuleReturnValue, ModuleObject
from .. import build, mesonlib, mlog, dependencies
from ..cmake import SingleTargetOptions, TargetOptions, cmake_defines_to_args
from ..interpreter import SubprojectHolder
from ..interpreter.type_checking import NoneType, in_set_validator
from ..interpreter.type_checking import REQUIRED_KW, NoneType, in_set_validator
from ..interpreterbase import (
FeatureNew,
FeatureNewKwargs,
FeatureDeprecatedKwargs,
stringArgs,
permittedKwargs,
@ -35,6 +36,7 @@ from ..interpreterbase import (
InvalidArguments,
InterpreterException,
typed_pos_args,
typed_kwargs,
KwargInfo,
ContainerTypeInfo,
@ -43,6 +45,9 @@ from ..interpreterbase import (
if T.TYPE_CHECKING:
from typing_extensions import TypedDict
from . import ModuleState
from ..interpreter import kwargs
class WriteBasicPackageVersionFile(TypedDict):
arch_independent: bool
@ -58,6 +63,12 @@ if T.TYPE_CHECKING:
install_dir: T.Optional[str]
name: str
class Subproject(kwargs.ExtractRequired):
options: T.Optional[CMakeSubprojectOptions]
cmake_options: T.List[str]
COMPATIBILITIES = ['AnyNewerVersion', 'SameMajorVersion', 'SameMinorVersion', 'ExactVersion']
# Taken from https://github.com/Kitware/CMake/blob/master/Modules/CMakePackageConfigHelpers.cmake
@ -91,7 +102,7 @@ endmacro()
'''
class CMakeSubproject(ModuleObject):
def __init__(self, subp, pv):
def __init__(self, subp: SubprojectHolder):
assert isinstance(subp, SubprojectHolder)
assert hasattr(subp, 'cm_interpreter')
super().__init__()
@ -400,20 +411,28 @@ class CmakeModule(ExtensionModule):
return res
@FeatureNew('subproject', '0.51.0')
@FeatureNewKwargs('subproject', '0.55.0', ['options'])
@FeatureDeprecatedKwargs('subproject', '0.55.0', ['cmake_options'])
@permittedKwargs({'cmake_options', 'required', 'options'})
@stringArgs
def subproject(self, state, args, kwargs):
if len(args) != 1:
raise InterpreterException('Subproject takes exactly one argument')
if 'cmake_options' in kwargs and 'options' in kwargs:
@typed_pos_args('cmake.subproject', str)
@typed_kwargs(
'cmake.subproject',
REQUIRED_KW,
KwargInfo('options', (CMakeSubprojectOptions, NoneType), since='0.55.0'),
KwargInfo(
'cmake_options',
ContainerTypeInfo(list, str),
default=[],
listify=True,
deprecated='0.55.0',
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:
raise InterpreterException('"options" cannot be used together with "cmake_options"')
dirname = args[0]
subp = self.interpreter.do_subproject(dirname, 'cmake', kwargs)
if not subp.found():
return subp
return CMakeSubproject(subp, dirname)
return CMakeSubproject(subp)
@FeatureNew('subproject_options', '0.55.0')
@noKwargs

Loading…
Cancel
Save