interpreter: allow default_options and override_options as a dict

pull/11896/head
Dylan Baker 2 years ago
parent d0cbda99a3
commit be20e0809f
  1. 5
      docs/markdown/snippets/option_dict.md
  2. 3
      docs/yaml/functions/_build_target_base.yaml
  3. 3
      docs/yaml/functions/dependency.yaml
  4. 4
      docs/yaml/functions/project.yaml
  5. 12
      docs/yaml/functions/subproject.yaml
  6. 13
      mesonbuild/interpreter/dependencyfallbacks.py
  7. 25
      mesonbuild/interpreter/interpreter.py
  8. 8
      mesonbuild/interpreter/kwargs.py
  9. 37
      mesonbuild/interpreter/type_checking.py
  10. 2
      mesonbuild/modules/cmake.py

@ -0,0 +1,5 @@
## default_options and override_options may now be dictionaries
Instead of passing them as `default_options : ['key=value']`, they can now be
passed as `default_options : {'key': 'value'}`, and the same for
`override_options`.

@ -228,12 +228,13 @@ kwargs:
Set this to `[]`, or omit the keyword argument for the default behaviour.
override_options:
type: list[str]
type: list[str] | dict[str]
since: 0.40.0
description: |
takes an array of strings in the same format as `project`'s `default_options`
overriding the values of these options
for this target only.
*(since 1.2.0)*: A dictionary may now be passed.
gnu_symbol_visibility:
type: str

@ -78,7 +78,7 @@ varargs:
kwargs:
default_options:
type: list[str]
type: list[str] | dict[str]
since: 0.38.0
description: |
An array of default option values
@ -86,6 +86,7 @@ kwargs:
(like `default_options` in [[project]], they only have
effect when Meson is run for the first time, and command line
arguments override any default options in build files)
*(since 1.2.0)*: A dictionary may now be passed.
allow_fallback:
type: bool

@ -38,7 +38,7 @@ varargs:
kwargs:
default_options:
type: list[str]
type: list[str] | dict[str]
description: |
Accepts strings in the form `key=value`
which have the same format as options to `meson configure`.
@ -54,6 +54,8 @@ kwargs:
environment variable is not used. Consider using
[[add_project_arguments()]] instead.
*(since 1.2.0)*: A dictionary may now be passed.
version:
type: str | file
description: |

@ -12,8 +12,9 @@ description: |
that override those set in the subproject's `meson.options`
(like `default_options` in `project`, they only have effect when
Meson is run for the first time, and command line arguments override
any default options in build files). *(since 0.54.0)*: `default_library`
built-in option can also be overridden.
any default options in build files).
*(since 0.54.0)*: `default_library` built-in option can also be overridden.
*(since 1.2.0)*: A dictionary may be passed instead of array.
- `version`: works just like the same as in `dependency`.
It specifies what version the subproject should be, as an example `>=1.0.1`
- `required` *(since 0.48.0)*: By default, `required` is `true` and
@ -41,15 +42,16 @@ posargs:
kwargs:
default_options:
type: list[str]
type: list[str] | dict[str]
since: 0.37.0
description: |
An array of default option values
that override those set in the subproject's `meson.options`
(like `default_options` in [[project]], they only have effect when
Meson is run for the first time, and command line arguments override
any default options in build files). *(since 0.54.0)*: `default_library`
built-in option can also be overridden.
any default options in build files).
*(since 0.54.0)*: `default_library` built-in option can also be overridden.
*(since 1.2.0)*: A dictionary may now be passed.
version:
type: str

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

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

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

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

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

Loading…
Cancel
Save