From be20e0809f3cee518a49f4c22ce3ca19319ebb33 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 1 Mar 2023 12:21:56 -0800 Subject: interpreter: allow default_options and override_options as a dict --- mesonbuild/interpreter/dependencyfallbacks.py | 13 +++++----- mesonbuild/interpreter/interpreter.py | 25 +++++++++++++----- mesonbuild/interpreter/kwargs.py | 8 +++--- mesonbuild/interpreter/type_checking.py | 37 ++++++++++++--------------- mesonbuild/modules/cmake.py | 2 +- 5 files changed, 47 insertions(+), 38 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/interpreter/dependencyfallbacks.py b/mesonbuild/interpreter/dependencyfallbacks.py index 79ca884..7ef1527 100644 --- a/mesonbuild/interpreter/dependencyfallbacks.py +++ b/mesonbuild/interpreter/dependencyfallbacks.py @@ -19,7 +19,7 @@ if T.TYPE_CHECKING: class DependencyFallbacksHolder(MesonInterpreterObject): def __init__(self, interpreter: 'Interpreter', names: T.List[str], allow_fallback: T.Optional[bool] = None, - default_options: T.Optional[T.List[str]] = None) -> None: + default_options: T.Optional[T.Dict[OptionKey, str]] = None) -> None: super().__init__(subproject=interpreter.subproject) self.interpreter = interpreter self.subproject = interpreter.subproject @@ -30,7 +30,7 @@ class DependencyFallbacksHolder(MesonInterpreterObject): self.allow_fallback = allow_fallback self.subproject_name: T.Optional[str] = None self.subproject_varname: T.Optional[str] = None - self.subproject_kwargs = {'default_options': default_options or []} + self.subproject_kwargs = {'default_options': default_options or {}} self.names: T.List[str] = [] self.forcefallback: bool = False self.nofallback: bool = False @@ -114,12 +114,11 @@ class DependencyFallbacksHolder(MesonInterpreterObject): # dependency('foo', static: true) should implicitly add # default_options: ['default_library=static'] static = kwargs.get('static') - default_options = stringlistify(func_kwargs.get('default_options', [])) - if static is not None and not any('default_library' in i for i in default_options): + default_options = func_kwargs.get('default_options', {}) + if static is not None and 'default_library' not in default_options: default_library = 'static' if static else 'shared' - opt = f'default_library={default_library}' - mlog.log(f'Building fallback subproject with {opt}') - default_options.append(opt) + mlog.log(f'Building fallback subproject with default_library={default_library}') + default_options[OptionKey('default_library')] = default_library func_kwargs['default_options'] = default_options # Configure the subproject diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 5908bec..c5e25d3 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -80,6 +80,7 @@ from .type_checking import ( INSTALL_TAG_KW, LANGUAGE_KW, NATIVE_KW, + OVERRIDE_OPTIONS_KW, PRESERVE_PATH_KW, REQUIRED_KW, SOURCES_KW, @@ -890,7 +891,7 @@ class Interpreter(InterpreterBase, HoldableObject): mlog.log('Subproject', mlog.bold(subp_name), ':', 'skipped: feature', mlog.bold(feature), 'disabled') return self.disabled_subproject(subp_name, disabled_feature=feature) - default_options = coredata.create_options_dict(kwargs['default_options'], subp_name) + default_options = {k.evolve(subproject=subp_name): v for k, v in kwargs['default_options'].items()} if subp_name == '': raise InterpreterException('Subproject name must not be empty.') @@ -1196,13 +1197,17 @@ class Interpreter(InterpreterBase, HoldableObject): self.coredata.update_project_options(oi.options) self.add_build_def_file(option_file) + if self.subproject: + self.project_default_options = {k.evolve(subproject=self.subproject): v + for k, v in kwargs['default_options'].items()} + else: + self.project_default_options = kwargs['default_options'] + # Do not set default_options on reconfigure otherwise it would override # values previously set from command line. That means that changing # default_options in a project will trigger a reconfigure but won't # have any effect. - self.project_default_options = coredata.create_options_dict( - kwargs['default_options'], self.subproject) - + # # If this is the first invocation we always need to initialize # builtins, if this is a subproject that is new in a re-invocation we # need to initialize builtins for that @@ -1694,7 +1699,7 @@ class Interpreter(InterpreterBase, HoldableObject): mlog.bold(' '.join(args))) sp_kwargs: kwtypes.DoSubproject = { 'required': required, - 'default_options': [], + 'default_options': {}, 'version': [], 'cmake_options': [], 'options': None, @@ -1739,10 +1744,10 @@ class Interpreter(InterpreterBase, HoldableObject): @FeatureNewKwargs('dependency', '0.50.0', ['not_found_message', 'cmake_module_path', 'cmake_args']) @FeatureNewKwargs('dependency', '0.49.0', ['disabler']) @FeatureNewKwargs('dependency', '0.40.0', ['method']) - @FeatureNewKwargs('dependency', '0.38.0', ['default_options']) @disablerIfNotFound @permittedKwargs(permitted_dependency_kwargs) @typed_pos_args('dependency', varargs=str, min_varargs=1) + @typed_kwargs('dependency', DEFAULT_OPTIONS.evolve(since='0.38.0'), allow_unknown=True) def func_dependency(self, node: mparser.BaseNode, args: T.Tuple[T.List[str]], kwargs) -> Dependency: # Replace '' by empty list of names names = [n for n in args[0] if n] @@ -1794,6 +1799,7 @@ class Interpreter(InterpreterBase, HoldableObject): @FeatureDeprecatedKwargs('executable', '0.56.0', ['gui_app'], extra_message="Use 'win_subsystem' instead.") @permittedKwargs(build.known_exe_kwargs) @typed_pos_args('executable', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('executable', OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_executable(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs) -> build.Executable: @@ -1801,6 +1807,7 @@ class Interpreter(InterpreterBase, HoldableObject): @permittedKwargs(build.known_stlib_kwargs) @typed_pos_args('static_library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('static_library', OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_static_lib(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs) -> build.StaticLibrary: @@ -1808,6 +1815,7 @@ class Interpreter(InterpreterBase, HoldableObject): @permittedKwargs(build.known_shlib_kwargs) @typed_pos_args('shared_library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('shared_library', OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_shared_lib(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs) -> build.SharedLibrary: @@ -1817,6 +1825,7 @@ class Interpreter(InterpreterBase, HoldableObject): @permittedKwargs(known_library_kwargs) @typed_pos_args('both_libraries', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('both_libraries', OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_both_lib(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs) -> build.BothLibraries: @@ -1825,6 +1834,7 @@ class Interpreter(InterpreterBase, HoldableObject): @FeatureNew('shared_module', '0.37.0') @permittedKwargs(build.known_shmod_kwargs) @typed_pos_args('shared_module', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('shared_module', OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_shared_module(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs) -> build.SharedModule: @@ -1832,6 +1842,7 @@ class Interpreter(InterpreterBase, HoldableObject): @permittedKwargs(known_library_kwargs) @typed_pos_args('library', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('library', OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_library(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs) -> build.Executable: @@ -1839,6 +1850,7 @@ class Interpreter(InterpreterBase, HoldableObject): @permittedKwargs(build.known_jar_kwargs) @typed_pos_args('jar', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('jar', OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_jar(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[T.Union[str, mesonlib.File, build.GeneratedTypes]]], kwargs) -> build.Jar: @@ -1847,6 +1859,7 @@ class Interpreter(InterpreterBase, HoldableObject): @FeatureNewKwargs('build_target', '0.40.0', ['link_whole', 'override_options']) @permittedKwargs(known_build_target_kwargs) @typed_pos_args('build_target', str, varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList, build.StructuredSources, build.ExtractedObjects, build.BuildTarget)) + @typed_kwargs('build_target', OVERRIDE_OPTIONS_KW, allow_unknown=True) def func_build_target(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[BuildTargetSource]], kwargs) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary, diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 3c1cb00..972b0f3 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -12,7 +12,7 @@ from typing_extensions import TypedDict, Literal, Protocol from .. import build from .. import coredata from ..compilers import Compiler -from ..mesonlib import MachineChoice, File, FileMode, FileOrString +from ..mesonlib import MachineChoice, File, FileMode, FileOrString, OptionKey from ..modules.cmake import CMakeSubprojectOptions from ..programs import ExternalProgram @@ -203,7 +203,7 @@ class Project(TypedDict): version: T.Optional[FileOrString] meson_version: T.Optional[str] - default_options: T.List[str] + default_options: T.Dict[OptionKey, str] license: T.List[str] subproject_dir: str @@ -298,13 +298,13 @@ class ConfigureFile(TypedDict): class Subproject(ExtractRequired): - default_options: T.List[str] + default_options: T.Dict[OptionKey, str] version: T.List[str] class DoSubproject(ExtractRequired): - default_options: T.List[str] + default_options: T.Dict[OptionKey, str] version: T.List[str] cmake_options: T.List[str] options: T.Optional[CMakeSubprojectOptions] diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index 2d2b916..e950da0 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -281,21 +281,25 @@ COMMAND_KW: KwargInfo[T.List[T.Union[str, BuildTarget, CustomTarget, CustomTarge default=[], ) -def _override_options_convertor(raw: T.List[str]) -> T.Dict[OptionKey, str]: - output: T.Dict[OptionKey, str] = {} - for each in raw: - k, v = split_equal_string(each) - output[OptionKey.from_string(k)] = v - return output - - -OVERRIDE_OPTIONS_KW: KwargInfo[T.List[str]] = KwargInfo( +def _override_options_convertor(raw: T.Union[str, T.List[str], T.Dict[str, str]]) -> T.Dict[OptionKey, str]: + if isinstance(raw, str): + raw = [raw] + if isinstance(raw, list): + output: T.Dict[OptionKey, str] = {} + for each in raw: + k, v = split_equal_string(each) + output[OptionKey.from_string(k)] = v + return output + return {OptionKey.from_string(k): v for k, v in raw.items()} + + +OVERRIDE_OPTIONS_KW: KwargInfo[T.Union[str, T.Dict[str, str], T.List[str]]] = KwargInfo( 'override_options', - ContainerTypeInfo(list, str), - listify=True, - default=[], + (str, ContainerTypeInfo(list, str), ContainerTypeInfo(dict, str)), + default={}, validator=_options_validator, convertor=_override_options_convertor, + since_values={dict: '1.2.0'}, ) @@ -385,14 +389,7 @@ INCLUDE_DIRECTORIES: KwargInfo[T.List[T.Union[str, IncludeDirs]]] = KwargInfo( default=[], ) -# for cases like default_options and override_options -DEFAULT_OPTIONS: KwargInfo[T.List[str]] = KwargInfo( - 'default_options', - ContainerTypeInfo(list, str), - listify=True, - default=[], - validator=_options_validator, -) +DEFAULT_OPTIONS = OVERRIDE_OPTIONS_KW.evolve(name='default_options') ENV_METHOD_KW = KwargInfo('method', str, default='set', since='0.62.0', validator=in_set_validator({'set', 'prepend', 'append'})) diff --git a/mesonbuild/modules/cmake.py b/mesonbuild/modules/cmake.py index 25129e6..d37c832 100644 --- a/mesonbuild/modules/cmake.py +++ b/mesonbuild/modules/cmake.py @@ -431,7 +431,7 @@ class CmakeModule(ExtensionModule): 'required': kwargs_['required'], 'options': kwargs_['options'], 'cmake_options': kwargs_['cmake_options'], - 'default_options': [], + 'default_options': {}, 'version': [], } subp = self.interpreter.do_subproject(dirname, 'cmake', kw) -- cgit v1.1