aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/interpreter
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.com>2023-03-02 11:59:28 -0500
committerXavier Claessens <xclaesse@gmail.com>2023-08-05 07:14:08 -0400
commite01d53b816c9fba25a068039e62d8ac9e5e2a971 (patch)
tree7905b8adc6c81750daa160cccbe7738e636e59a5 /mesonbuild/interpreter
parent50baf3c626267252a2d943a49d8e7c0402e23218 (diff)
downloadmeson-e01d53b816c9fba25a068039e62d8ac9e5e2a971.zip
meson-e01d53b816c9fba25a068039e62d8ac9e5e2a971.tar.gz
meson-e01d53b816c9fba25a068039e62d8ac9e5e2a971.tar.bz2
compiler: Add required keyword to has_* methods
add the "required" keyword to the functions has_function has_type has_member has_members has_argument has_multi_arguments has_link_argument has_multi_link_argument has_function_attribute Co-authored-by: Milan Hauth <milahu@gmail.com>
Diffstat (limited to 'mesonbuild/interpreter')
-rw-r--r--mesonbuild/interpreter/compiler.py140
1 files changed, 100 insertions, 40 deletions
diff --git a/mesonbuild/interpreter/compiler.py b/mesonbuild/interpreter/compiler.py
index 52737c4..4345874 100644
--- a/mesonbuild/interpreter/compiler.py
+++ b/mesonbuild/interpreter/compiler.py
@@ -31,6 +31,7 @@ if T.TYPE_CHECKING:
from ..interpreterbase import TYPE_var, TYPE_kwargs
from .kwargs import ExtractRequired, ExtractSearchDirs
from .interpreter.interpreter import SourceOutputs
+ from ..mlog import TV_LoggableList
from typing_extensions import TypedDict, Literal
@@ -69,6 +70,12 @@ if T.TYPE_CHECKING:
class HeaderKW(CommonKW, ExtractRequired):
pass
+ class HasKW(CommonKW, ExtractRequired):
+ pass
+
+ class HasArgumentKW(ExtractRequired):
+ pass
+
class FindLibraryKW(ExtractRequired, ExtractSearchDirs):
disabler: bool
@@ -165,6 +172,7 @@ _COMMON_KWS: T.List[KwargInfo] = [_ARGS_KW, _DEPENDENCIES_KW, _INCLUDE_DIRS_KW,
_COMPILES_KWS: T.List[KwargInfo] = [_NAME_KW, _ARGS_KW, _DEPENDENCIES_KW, _INCLUDE_DIRS_KW, _NO_BUILTIN_ARGS_KW]
_HEADER_KWS: T.List[KwargInfo] = [REQUIRED_KW.evolve(since='0.50.0', default=False), *_COMMON_KWS]
+_HAS_REQUIRED_KW = REQUIRED_KW.evolve(since='1.1.0', default=False)
class CompilerHolder(ObjectHolder['Compiler']):
preprocess_uid: T.Dict[str, itertools.count] = collections.defaultdict(itertools.count)
@@ -325,9 +333,13 @@ class CompilerHolder(ObjectHolder['Compiler']):
return self.compiler.symbols_have_underscore_prefix(self.environment)
@typed_pos_args('compiler.has_member', str, str)
- @typed_kwargs('compiler.has_member', *_COMMON_KWS)
- def has_member_method(self, args: T.Tuple[str, str], kwargs: 'CommonKW') -> bool:
+ @typed_kwargs('compiler.has_member', _HAS_REQUIRED_KW, *_COMMON_KWS)
+ 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)
+ if disabled:
+ mlog.log('Type', mlog.bold(typename, True), 'has member', mlog.bold(membername, True), 'skipped: feature', mlog.bold(feature), 'disabled')
+ return False
extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
deps, msg = self._determine_dependencies(kwargs['dependencies'])
had, cached = self.compiler.has_members(typename, [membername], kwargs['prefix'],
@@ -335,7 +347,9 @@ class CompilerHolder(ObjectHolder['Compiler']):
extra_args=extra_args,
dependencies=deps)
cached_msg = mlog.blue('(cached)') if cached else ''
- if had:
+ if required and not had:
+ raise InterpreterException(f'{self.compiler.get_display_language()} member {membername!r} of type {typename!r} not usable')
+ elif had:
hadtxt = mlog.green('YES')
else:
hadtxt = mlog.red('NO')
@@ -344,9 +358,14 @@ class CompilerHolder(ObjectHolder['Compiler']):
return had
@typed_pos_args('compiler.has_members', str, varargs=str, min_varargs=1)
- @typed_kwargs('compiler.has_members', *_COMMON_KWS)
- def has_members_method(self, args: T.Tuple[str, T.List[str]], kwargs: 'CommonKW') -> bool:
+ @typed_kwargs('compiler.has_members', _HAS_REQUIRED_KW, *_COMMON_KWS)
+ 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]))
+ disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
+ if disabled:
+ mlog.log('Type', mlog.bold(typename, True), 'has members', members, 'skipped: feature', mlog.bold(feature), 'disabled')
+ return False
extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
deps, msg = self._determine_dependencies(kwargs['dependencies'])
had, cached = self.compiler.has_members(typename, membernames, kwargs['prefix'],
@@ -354,26 +373,34 @@ class CompilerHolder(ObjectHolder['Compiler']):
extra_args=extra_args,
dependencies=deps)
cached_msg = mlog.blue('(cached)') if cached else ''
- if had:
+ if required and not had:
+ # print members as array: ['member1', 'member2']
+ raise InterpreterException(f'{self.compiler.get_display_language()} members {membernames!r} of type {typename!r} not usable')
+ elif had:
hadtxt = mlog.green('YES')
else:
hadtxt = mlog.red('NO')
- members = mlog.bold(', '.join([f'"{m}"' for m in membernames]))
mlog.log('Checking whether type', mlog.bold(typename, True),
'has members', members, msg, hadtxt, cached_msg)
return had
@typed_pos_args('compiler.has_function', str)
- @typed_kwargs('compiler.has_function', *_COMMON_KWS)
- def has_function_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> bool:
+ @typed_kwargs('compiler.has_function', _HAS_REQUIRED_KW, *_COMMON_KWS)
+ 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)
+ if disabled:
+ mlog.log('Has function', mlog.bold(funcname, True), 'skipped: feature', mlog.bold(feature), 'disabled')
+ return False
extra_args = self._determine_args(kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
deps, msg = self._determine_dependencies(kwargs['dependencies'], compile_only=False)
had, cached = self.compiler.has_function(funcname, kwargs['prefix'], self.environment,
extra_args=extra_args,
dependencies=deps)
cached_msg = mlog.blue('(cached)') if cached else ''
- if had:
+ if required and not had:
+ raise InterpreterException(f'{self.compiler.get_display_language()} function {funcname!r} not usable')
+ elif had:
hadtxt = mlog.green('YES')
else:
hadtxt = mlog.red('NO')
@@ -381,15 +408,21 @@ class CompilerHolder(ObjectHolder['Compiler']):
return had
@typed_pos_args('compiler.has_type', str)
- @typed_kwargs('compiler.has_type', *_COMMON_KWS)
- def has_type_method(self, args: T.Tuple[str], kwargs: 'CommonKW') -> bool:
+ @typed_kwargs('compiler.has_type', _HAS_REQUIRED_KW, *_COMMON_KWS)
+ 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)
+ if disabled:
+ mlog.log('Has type', mlog.bold(typename, True), 'skipped: feature', mlog.bold(feature), 'disabled')
+ return False
extra_args = functools.partial(self._determine_args, kwargs['no_builtin_args'], kwargs['include_directories'], kwargs['args'])
deps, msg = self._determine_dependencies(kwargs['dependencies'])
had, cached = self.compiler.has_type(typename, kwargs['prefix'], self.environment,
extra_args=extra_args, dependencies=deps)
cached_msg = mlog.blue('(cached)') if cached else ''
- if had:
+ if required and not had:
+ raise InterpreterException(f'{self.compiler.get_display_language()} type {typename!r} not usable')
+ elif had:
hadtxt = mlog.green('YES')
else:
hadtxt = mlog.red('NO')
@@ -646,33 +679,46 @@ class CompilerHolder(ObjectHolder['Compiler']):
return lib
def _has_argument_impl(self, arguments: T.Union[str, T.List[str]],
- mode: _TestMode = _TestMode.COMPILER) -> bool:
+ mode: _TestMode = _TestMode.COMPILER,
+ kwargs: T.Optional['ExtractRequired'] = None) -> bool:
"""Shared implementation for methods checking compiler and linker arguments."""
# This simplifies the callers
if isinstance(arguments, str):
arguments = [arguments]
- test = self.compiler.has_multi_link_arguments if mode is _TestMode.LINKER else self.compiler.has_multi_arguments
- result, cached = test(arguments, self.environment)
- cached_msg = mlog.blue('(cached)') if cached else ''
- mlog.log(
+ logargs: TV_LoggableList = [
'Compiler for',
self.compiler.get_display_language(),
'supports{}'.format(' link' if mode is _TestMode.LINKER else ''),
'arguments {}:'.format(' '.join(arguments)),
+ ]
+ kwargs = kwargs or {'required': False}
+ disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
+ if disabled:
+ logargs += ['skipped: feature', mlog.bold(feature), 'disabled']
+ mlog.log(*logargs)
+ return False
+ test = self.compiler.has_multi_link_arguments if mode is _TestMode.LINKER else self.compiler.has_multi_arguments
+ result, cached = test(arguments, self.environment)
+ if required and not result:
+ logargs += ['not usable']
+ raise InterpreterException(*logargs)
+ logargs += [
mlog.green('YES') if result else mlog.red('NO'),
- cached_msg)
+ mlog.blue('(cached)') if cached else '',
+ ]
+ mlog.log(*logargs)
return result
- @noKwargs
@typed_pos_args('compiler.has_argument', str)
- def has_argument_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool:
- return self._has_argument_impl([args[0]])
+ @typed_kwargs('compiler.has_argument', _HAS_REQUIRED_KW)
+ def has_argument_method(self, args: T.Tuple[str], kwargs: 'HasArgumentKW') -> bool:
+ return self._has_argument_impl([args[0]], kwargs=kwargs)
- @noKwargs
@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')
- def has_multi_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> bool:
- return self._has_argument_impl(args[0])
+ def has_multi_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'HasArgumentKW') -> bool:
+ return self._has_argument_impl(args[0], kwargs=kwargs)
@FeatureNew('compiler.get_supported_arguments', '0.43.0')
@typed_pos_args('compiler.get_supported_arguments', varargs=str)
@@ -707,16 +753,16 @@ class CompilerHolder(ObjectHolder['Compiler']):
return []
@FeatureNew('compiler.has_link_argument', '0.46.0')
- @noKwargs
@typed_pos_args('compiler.has_link_argument', str)
- def has_link_argument_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool:
- return self._has_argument_impl([args[0]], mode=_TestMode.LINKER)
+ @typed_kwargs('compiler.has_link_argument', _HAS_REQUIRED_KW)
+ 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')
- @noKwargs
@typed_pos_args('compiler.has_multi_link_argument', varargs=str)
- def has_multi_link_arguments_method(self, args: T.Tuple[T.List[str]], kwargs: 'TYPE_kwargs') -> bool:
- return self._has_argument_impl(args[0], mode=_TestMode.LINKER)
+ @typed_kwargs('compiler.has_multi_link_argument', _HAS_REQUIRED_KW)
+ 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
@@ -739,19 +785,33 @@ class CompilerHolder(ObjectHolder['Compiler']):
mlog.log('First supported link argument:', mlog.red('None'))
return []
- def _has_function_attribute_impl(self, attr: str) -> bool:
+ def _has_function_attribute_impl(self, attr: str, kwargs: T.Optional['ExtractRequired'] = None) -> bool:
"""Common helper for function attribute testing."""
- result, cached = self.compiler.has_func_attribute(attr, self.environment)
- cached_msg = mlog.blue('(cached)') if cached else ''
- h = mlog.green('YES') if result else mlog.red('NO')
- mlog.log(f'Compiler for {self.compiler.get_display_language()} supports function attribute {attr}:', h, cached_msg)
- return result
+ logargs: TV_LoggableList = [
+ f'Compiler for {self.compiler.get_display_language()} supports function attribute {attr}:',
+ ]
+ kwargs = kwargs or {'required': False}
+ disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False)
+ if disabled:
+ logargs += ['skipped: feature', mlog.bold(feature), 'disabled']
+ mlog.log(*logargs)
+ return False
+ had, cached = self.compiler.has_func_attribute(attr, self.environment)
+ if required and not had:
+ logargs += ['not usable']
+ raise InterpreterException(*logargs)
+ logargs += [
+ mlog.green('YES') if had else mlog.red('NO'),
+ mlog.blue('(cached)') if cached else ''
+ ]
+ mlog.log(*logargs)
+ return had
@FeatureNew('compiler.has_function_attribute', '0.48.0')
- @noKwargs
@typed_pos_args('compiler.has_function_attribute', str)
- def has_func_attribute_method(self, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> bool:
- return self._has_function_attribute_impl(args[0])
+ @typed_kwargs('compiler.has_function_attribute', _HAS_REQUIRED_KW)
+ 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