diff options
Diffstat (limited to 'mesonbuild/coredata.py')
| -rw-r--r-- | mesonbuild/coredata.py | 569 |
1 files changed, 61 insertions, 508 deletions
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 6e67587b2..76da0b67f 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -6,7 +6,7 @@ from __future__ import annotations import copy -from . import mlog, mparser +from . import mlog, mparser, options import pickle, os, uuid import sys from itertools import chain @@ -15,12 +15,10 @@ from collections import OrderedDict, abc from dataclasses import dataclass from .mesonlib import ( - HoldableObject, MesonBugException, + MesonBugException, MesonException, EnvironmentException, MachineChoice, PerMachine, - PerMachineDefaultable, default_libdir, default_libexecdir, - default_prefix, default_datadir, default_includedir, default_infodir, - default_localedir, default_mandir, default_sbindir, default_sysconfdir, - listify_array_value, OptionKey, OptionType, stringlistify, + PerMachineDefaultable, + OptionKey, OptionType, stringlistify, pickle_load ) import ast @@ -56,8 +54,8 @@ if T.TYPE_CHECKING: cross_file: T.List[str] native_file: T.List[str] - OptionDictType = T.Union[T.Dict[str, 'UserOption[T.Any]'], 'OptionsView'] - MutableKeyedOptionDictType = T.Dict['OptionKey', 'UserOption[T.Any]'] + OptionDictType = T.Union[T.Dict[str, 'options.UserOption[T.Any]'], 'OptionsView'] + MutableKeyedOptionDictType = T.Dict['OptionKey', 'options.UserOption[T.Any]'] KeyedOptionDictType = T.Union[MutableKeyedOptionDictType, 'OptionsView'] CompilerCheckCacheKey = T.Tuple[T.Tuple[str, ...], str, FileOrString, T.Tuple[str, ...], CompileCheckMode] # code, args @@ -82,20 +80,11 @@ if stable_version.endswith('.99'): stable_version_array[-2] = str(int(stable_version_array[-2]) + 1) stable_version = '.'.join(stable_version_array) -backendlist = ['ninja', 'vs', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'vs2017', 'vs2019', 'vs2022', 'xcode', 'none'] -genvslitelist = ['vs2022'] -buildtypelist = ['plain', 'debug', 'debugoptimized', 'release', 'minsize', 'custom'] - -DEFAULT_YIELDING = False - -# Can't bind this near the class method it seems, sadly. -_T = T.TypeVar('_T') - def get_genvs_default_buildtype_list() -> list[str]: # just debug, debugoptimized, and release for now # but this should probably be configurable through some extra option, alongside --genvslite. - return buildtypelist[1:-2] + return options.buildtypelist[1:-2] class MesonVersionMismatchException(MesonException): @@ -108,312 +97,6 @@ class MesonVersionMismatchException(MesonException): self.current_version = current_version -class UserOption(T.Generic[_T], HoldableObject): - def __init__(self, name: str, description: str, choices: T.Optional[T.Union[str, T.List[_T]]], - yielding: bool, - deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): - super().__init__() - self.name = name - self.choices = choices - self.description = description - if not isinstance(yielding, bool): - raise MesonException('Value of "yielding" must be a boolean.') - self.yielding = yielding - self.deprecated = deprecated - self.readonly = False - - def listify(self, value: T.Any) -> T.List[T.Any]: - return [value] - - def printable_value(self) -> T.Union[str, int, bool, T.List[T.Union[str, int, bool]]]: - assert isinstance(self.value, (str, int, bool, list)) - return self.value - - # Check that the input is a valid value and return the - # "cleaned" or "native" version. For example the Boolean - # option could take the string "true" and return True. - def validate_value(self, value: T.Any) -> _T: - raise RuntimeError('Derived option class did not override validate_value.') - - def set_value(self, newvalue: T.Any) -> bool: - oldvalue = getattr(self, 'value', None) - self.value = self.validate_value(newvalue) - return self.value != oldvalue - -class UserStringOption(UserOption[str]): - def __init__(self, name: str, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING, - deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): - super().__init__(name, description, None, yielding, deprecated) - self.set_value(value) - - def validate_value(self, value: T.Any) -> str: - if not isinstance(value, str): - raise MesonException(f'The value of option "{self.name}" is "{value}", which is not a string.') - return value - -class UserBooleanOption(UserOption[bool]): - def __init__(self, name: str, description: str, value: bool, yielding: bool = DEFAULT_YIELDING, - deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): - super().__init__(name, description, [True, False], yielding, deprecated) - self.set_value(value) - - def __bool__(self) -> bool: - return self.value - - def validate_value(self, value: T.Any) -> bool: - if isinstance(value, bool): - return value - if not isinstance(value, str): - raise MesonException(f'Option "{self.name}" value {value} cannot be converted to a boolean') - if value.lower() == 'true': - return True - if value.lower() == 'false': - return False - raise MesonException(f'Option "{self.name}" value {value} is not boolean (true or false).') - -class UserIntegerOption(UserOption[int]): - def __init__(self, name: str, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING, - deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): - min_value, max_value, default_value = value - self.min_value = min_value - self.max_value = max_value - c: T.List[str] = [] - if min_value is not None: - c.append('>=' + str(min_value)) - if max_value is not None: - c.append('<=' + str(max_value)) - choices = ', '.join(c) - super().__init__(name, description, choices, yielding, deprecated) - self.set_value(default_value) - - def validate_value(self, value: T.Any) -> int: - if isinstance(value, str): - value = self.toint(value) - if not isinstance(value, int): - raise MesonException(f'Value {value!r} for option "{self.name}" is not an integer.') - if self.min_value is not None and value < self.min_value: - raise MesonException(f'Value {value} for option "{self.name}" is less than minimum value {self.min_value}.') - if self.max_value is not None and value > self.max_value: - raise MesonException(f'Value {value} for option "{self.name}" is more than maximum value {self.max_value}.') - return value - - def toint(self, valuestring: str) -> int: - try: - return int(valuestring) - except ValueError: - raise MesonException(f'Value string "{valuestring}" for option "{self.name}" is not convertible to an integer.') - -class OctalInt(int): - # NinjaBackend.get_user_option_args uses str() to converts it to a command line option - # UserUmaskOption.toint() uses int(str, 8) to convert it to an integer - # So we need to use oct instead of dec here if we do not want values to be misinterpreted. - def __str__(self) -> str: - return oct(int(self)) - -class UserUmaskOption(UserIntegerOption, UserOption[T.Union[str, OctalInt]]): - def __init__(self, name: str, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING, - deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): - super().__init__(name, description, (0, 0o777, value), yielding, deprecated) - self.choices = ['preserve', '0000-0777'] - - def printable_value(self) -> str: - if self.value == 'preserve': - return self.value - return format(self.value, '04o') - - def validate_value(self, value: T.Any) -> T.Union[str, OctalInt]: - if value == 'preserve': - return 'preserve' - return OctalInt(super().validate_value(value)) - - def toint(self, valuestring: T.Union[str, OctalInt]) -> int: - try: - return int(valuestring, 8) - except ValueError as e: - raise MesonException(f'Invalid mode for option "{self.name}" {e}') - -class UserComboOption(UserOption[str]): - def __init__(self, name: str, description: str, choices: T.List[str], value: T.Any, - yielding: bool = DEFAULT_YIELDING, - deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): - super().__init__(name, description, choices, yielding, deprecated) - if not isinstance(self.choices, list): - raise MesonException(f'Combo choices for option "{self.name}" must be an array.') - for i in self.choices: - if not isinstance(i, str): - raise MesonException(f'Combo choice elements for option "{self.name}" must be strings.') - self.set_value(value) - - def validate_value(self, value: T.Any) -> str: - if value not in self.choices: - if isinstance(value, bool): - _type = 'boolean' - elif isinstance(value, (int, float)): - _type = 'number' - else: - _type = 'string' - optionsstring = ', '.join([f'"{item}"' for item in self.choices]) - raise MesonException('Value "{}" (of type "{}") for option "{}" is not one of the choices.' - ' Possible choices are (as string): {}.'.format( - value, _type, self.name, optionsstring)) - return value - -class UserArrayOption(UserOption[T.List[str]]): - def __init__(self, name: str, description: str, value: T.Union[str, T.List[str]], - split_args: bool = False, - allow_dups: bool = False, yielding: bool = DEFAULT_YIELDING, - choices: T.Optional[T.List[str]] = None, - deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): - super().__init__(name, description, choices if choices is not None else [], yielding, deprecated) - self.split_args = split_args - self.allow_dups = allow_dups - self.set_value(value) - - def listify(self, value: T.Any) -> T.List[T.Any]: - try: - return listify_array_value(value, self.split_args) - except MesonException as e: - raise MesonException(f'error in option "{self.name}": {e!s}') - - def validate_value(self, value: T.Union[str, T.List[str]]) -> T.List[str]: - newvalue = self.listify(value) - - if not self.allow_dups and len(set(newvalue)) != len(newvalue): - msg = 'Duplicated values in array option is deprecated. ' \ - 'This will become a hard error in the future.' - mlog.deprecation(msg) - for i in newvalue: - if not isinstance(i, str): - raise MesonException(f'String array element "{newvalue!s}" for option "{self.name}" is not a string.') - if self.choices: - bad = [x for x in newvalue if x not in self.choices] - if bad: - raise MesonException('Value{} "{}" for option "{}" {} not in allowed choices: "{}"'.format( - '' if len(bad) == 1 else 's', - ', '.join(bad), - self.name, - 'is' if len(bad) == 1 else 'are', - ', '.join(self.choices)) - ) - return newvalue - - def extend_value(self, value: T.Union[str, T.List[str]]) -> None: - """Extend the value with an additional value.""" - new = self.validate_value(value) - self.set_value(self.value + new) - - -class UserFeatureOption(UserComboOption): - static_choices = ['enabled', 'disabled', 'auto'] - - def __init__(self, name: str, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING, - deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False): - super().__init__(name, description, self.static_choices, value, yielding, deprecated) - self.name: T.Optional[str] = None # TODO: Refactor options to all store their name - - def is_enabled(self) -> bool: - return self.value == 'enabled' - - def is_disabled(self) -> bool: - return self.value == 'disabled' - - def is_auto(self) -> bool: - return self.value == 'auto' - -class UserStdOption(UserComboOption): - ''' - UserOption specific to c_std and cpp_std options. User can set a list of - STDs in preference order and it selects the first one supported by current - compiler. - - For historical reasons, some compilers (msvc) allowed setting a GNU std and - silently fell back to C std. This is now deprecated. Projects that support - both GNU and MSVC compilers should set e.g. c_std=gnu11,c11. - - This is not using self.deprecated mechanism we already have for project - options because we want to print a warning if ALL values are deprecated, not - if SOME values are deprecated. - ''' - def __init__(self, lang: str, all_stds: T.List[str]) -> None: - self.lang = lang.lower() - self.all_stds = ['none'] + all_stds - # Map a deprecated std to its replacement. e.g. gnu11 -> c11. - self.deprecated_stds: T.Dict[str, str] = {} - opt_name = 'cpp_std' if lang == 'c++' else f'{lang}_std' - super().__init__(opt_name, f'{lang} language standard to use', ['none'], 'none') - - def set_versions(self, versions: T.List[str], gnu: bool = False, gnu_deprecated: bool = False) -> None: - assert all(std in self.all_stds for std in versions) - self.choices += versions - if gnu: - gnu_stds_map = {f'gnu{std[1:]}': std for std in versions} - if gnu_deprecated: - self.deprecated_stds.update(gnu_stds_map) - else: - self.choices += gnu_stds_map.keys() - - def validate_value(self, value: T.Union[str, T.List[str]]) -> str: - try: - candidates = listify_array_value(value) - except MesonException as e: - raise MesonException(f'error in option "{self.name}": {e!s}') - unknown = ','.join(std for std in candidates if std not in self.all_stds) - if unknown: - raise MesonException(f'Unknown option "{self.name}" value {unknown}. Possible values are {self.all_stds}.') - # Check first if any of the candidates are not deprecated - for std in candidates: - if std in self.choices: - return std - # Fallback to a deprecated std if any - for std in candidates: - newstd = self.deprecated_stds.get(std) - if newstd is not None: - mlog.deprecation( - f'None of the values {candidates} are supported by the {self.lang} compiler.\n' + - f'However, the deprecated {std} std currently falls back to {newstd}.\n' + - 'This will be an error in the future.\n' + - 'If the project supports both GNU and MSVC compilers, a value such as\n' + - '"c_std=gnu11,c11" specifies that GNU is preferred but it can safely fallback to plain c11.') - return newstd - raise MesonException(f'None of values {candidates} are supported by the {self.lang.upper()} compiler. ' + - f'Possible values for option "{self.name}" are {self.choices}') - -@dataclass -class OptionsView(abc.Mapping): - '''A view on an options dictionary for a given subproject and with overrides. - ''' - - # TODO: the typing here could be made more explicit using a TypeDict from - # python 3.8 or typing_extensions - options: KeyedOptionDictType - subproject: T.Optional[str] = None - overrides: T.Optional[T.Mapping[OptionKey, T.Union[str, int, bool, T.List[str]]]] = None - - def __getitem__(self, key: OptionKey) -> UserOption: - # FIXME: This is fundamentally the same algorithm than interpreter.get_option_internal(). - # We should try to share the code somehow. - key = key.evolve(subproject=self.subproject) - if not key.is_project(): - opt = self.options.get(key) - if opt is None or opt.yielding: - opt = self.options[key.as_root()] - else: - opt = self.options[key] - if opt.yielding: - opt = self.options.get(key.as_root(), opt) - if self.overrides: - override_value = self.overrides.get(key.as_root()) - if override_value is not None: - opt = copy.copy(opt) - opt.set_value(override_value) - return opt - - def __iter__(self) -> T.Iterator[OptionKey]: - return iter(self.options) - - def __len__(self) -> int: - return len(self.options) - class DependencyCacheType(enum.Enum): OTHER = 0 @@ -664,7 +347,7 @@ class CoreData: # getting the "system default" is always wrong on multiarch # platforms as it gets a value like lib/x86_64-linux-gnu. if self.cross_files: - BUILTIN_OPTIONS[OptionKey('libdir')].default = 'lib' + options.BUILTIN_OPTIONS[OptionKey('libdir')].default = 'lib' def sanitize_prefix(self, prefix: str) -> str: prefix = os.path.expanduser(prefix) @@ -698,7 +381,7 @@ class CoreData: except TypeError: return value if option.name.endswith('dir') and value.is_absolute() and \ - option not in BUILTIN_DIR_NOPREFIX_OPTIONS: + option not in options.BUILTIN_DIR_NOPREFIX_OPTIONS: try: # Try to relativize the path. value = value.relative_to(prefix) @@ -717,15 +400,15 @@ class CoreData: def init_builtins(self, subproject: str) -> None: # Create builtin options with default values - for key, opt in BUILTIN_OPTIONS.items(): + for key, opt in options.BUILTIN_OPTIONS.items(): self.add_builtin_option(self.options, key.evolve(subproject=subproject), opt) for for_machine in iter(MachineChoice): - for key, opt in BUILTIN_OPTIONS_PER_MACHINE.items(): + for key, opt in options.BUILTIN_OPTIONS_PER_MACHINE.items(): self.add_builtin_option(self.options, key.evolve(subproject=subproject, machine=for_machine), opt) @staticmethod def add_builtin_option(opts_map: 'MutableKeyedOptionDictType', key: OptionKey, - opt: 'BuiltinOption') -> None: + opt: 'options.BuiltinOption') -> None: if key.subproject: if opt.yielding: # This option is global and not per-subproject @@ -733,17 +416,17 @@ class CoreData: value = opts_map[key.as_root()].value else: value = None - opts_map[key] = opt.init_option(key, value, default_prefix()) + opts_map[key] = opt.init_option(key, value, options.default_prefix()) def init_backend_options(self, backend_name: str) -> None: if backend_name == 'ninja': - self.options[OptionKey('backend_max_links')] = UserIntegerOption( + self.options[OptionKey('backend_max_links')] = options.UserIntegerOption( 'backend_max_links', 'Maximum number of linker processes to run or 0 for no ' 'limit', (0, None, 0)) elif backend_name.startswith('vs'): - self.options[OptionKey('backend_startup_project')] = UserStringOption( + self.options[OptionKey('backend_startup_project')] = options.UserStringOption( 'backend_startup_project', 'Default project to execute in Visual Studio', '') @@ -881,7 +564,7 @@ class CoreData: @staticmethod def is_per_machine_option(optname: OptionKey) -> bool: - if optname.as_host() in BUILTIN_OPTIONS_PER_MACHINE: + if optname.as_host() in options.BUILTIN_OPTIONS_PER_MACHINE: return True return optname.lang is not None @@ -930,7 +613,7 @@ class CoreData: def copy_build_options_from_regular_ones(self) -> bool: dirty = False assert not self.is_cross_build() - for k in BUILTIN_OPTIONS_PER_MACHINE: + for k in options.BUILTIN_OPTIONS_PER_MACHINE: o = self.options[k] dirty |= self.options[k.as_build()].set_value(o.value) for bk, bv in self.options.items(): @@ -944,21 +627,21 @@ class CoreData: return dirty - def set_options(self, options: T.Dict[OptionKey, T.Any], subproject: str = '', first_invocation: bool = False) -> bool: + def set_options(self, opts_to_set: T.Dict[OptionKey, T.Any], subproject: str = '', first_invocation: bool = False) -> bool: dirty = False if not self.is_cross_build(): - options = {k: v for k, v in options.items() if k.machine is not MachineChoice.BUILD} + opts_to_set = {k: v for k, v in opts_to_set.items() if k.machine is not MachineChoice.BUILD} # Set prefix first because it's needed to sanitize other options pfk = OptionKey('prefix') - if pfk in options: - prefix = self.sanitize_prefix(options[pfk]) + if pfk in opts_to_set: + prefix = self.sanitize_prefix(opts_to_set[pfk]) dirty |= self.options[OptionKey('prefix')].set_value(prefix) - for key in BUILTIN_DIR_NOPREFIX_OPTIONS: - if key not in options: - dirty |= self.options[key].set_value(BUILTIN_OPTIONS[key].prefixed_default(key, prefix)) + for key in options.BUILTIN_DIR_NOPREFIX_OPTIONS: + if key not in opts_to_set: + dirty |= self.options[key].set_value(options.BUILTIN_OPTIONS[key].prefixed_default(key, prefix)) unknown_options: T.List[OptionKey] = [] - for k, v in options.items(): + for k, v in opts_to_set.items(): if k == pfk: continue elif k in self.options: @@ -1255,9 +938,9 @@ def save(obj: CoreData, build_dir: str) -> str: def register_builtin_arguments(parser: argparse.ArgumentParser) -> None: - for n, b in BUILTIN_OPTIONS.items(): + for n, b in options.BUILTIN_OPTIONS.items(): b.add_to_argparse(str(n), parser, '') - for n, b in BUILTIN_OPTIONS_PER_MACHINE.items(): + for n, b in options.BUILTIN_OPTIONS_PER_MACHINE.items(): b.add_to_argparse(str(n), parser, ' (just for host machine)') b.add_to_argparse(str(n.as_build()), parser, ' (just for build machine)') parser.add_argument('-D', action='append', dest='projectoptions', default=[], metavar="option", @@ -1281,185 +964,55 @@ def parse_cmd_line_options(args: SharedCMDOptions) -> None: # Merge builtin options set with --option into the dict. for key in chain( - BUILTIN_OPTIONS.keys(), - (k.as_build() for k in BUILTIN_OPTIONS_PER_MACHINE.keys()), - BUILTIN_OPTIONS_PER_MACHINE.keys(), + options.BUILTIN_OPTIONS.keys(), + (k.as_build() for k in options.BUILTIN_OPTIONS_PER_MACHINE.keys()), + options.BUILTIN_OPTIONS_PER_MACHINE.keys(), ): name = str(key) value = getattr(args, name, None) if value is not None: if key in args.cmd_line_options: - cmdline_name = BuiltinOption.argparse_name_to_arg(name) + cmdline_name = options.BuiltinOption.argparse_name_to_arg(name) raise MesonException( f'Got argument {name} as both -D{name} and {cmdline_name}. Pick one.') args.cmd_line_options[key] = value delattr(args, name) +@dataclass +class OptionsView(abc.Mapping): + '''A view on an options dictionary for a given subproject and with overrides. + ''' -_U = T.TypeVar('_U', bound=UserOption[_T]) - -class BuiltinOption(T.Generic[_T, _U]): - - """Class for a builtin option type. - - There are some cases that are not fully supported yet. - """ - - def __init__(self, opt_type: T.Type[_U], description: str, default: T.Any, yielding: bool = True, *, - choices: T.Any = None, readonly: bool = False): - self.opt_type = opt_type - self.description = description - self.default = default - self.choices = choices - self.yielding = yielding - self.readonly = readonly - - def init_option(self, name: 'OptionKey', value: T.Optional[T.Any], prefix: str) -> _U: - """Create an instance of opt_type and return it.""" - if value is None: - value = self.prefixed_default(name, prefix) - keywords = {'yielding': self.yielding, 'value': value} - if self.choices: - keywords['choices'] = self.choices - o = self.opt_type(name.name, self.description, **keywords) - o.readonly = self.readonly - return o - - def _argparse_action(self) -> T.Optional[str]: - # If the type is a boolean, the presence of the argument in --foo form - # is to enable it. Disabling happens by using -Dfoo=false, which is - # parsed under `args.projectoptions` and does not hit this codepath. - if isinstance(self.default, bool): - return 'store_true' - return None - - def _argparse_choices(self) -> T.Any: - if self.opt_type is UserBooleanOption: - return [True, False] - elif self.opt_type is UserFeatureOption: - return UserFeatureOption.static_choices - return self.choices + # TODO: the typing here could be made more explicit using a TypeDict from + # python 3.8 or typing_extensions + original_options: KeyedOptionDictType + subproject: T.Optional[str] = None + overrides: T.Optional[T.Mapping[OptionKey, T.Union[str, int, bool, T.List[str]]]] = None - @staticmethod - def argparse_name_to_arg(name: str) -> str: - if name == 'warning_level': - return '--warnlevel' + def __getitem__(self, key: OptionKey) -> options.UserOption: + # FIXME: This is fundamentally the same algorithm than interpreter.get_option_internal(). + # We should try to share the code somehow. + key = key.evolve(subproject=self.subproject) + if not key.is_project(): + opt = self.original_options.get(key) + if opt is None or opt.yielding: + opt = self.original_options[key.as_root()] else: - return '--' + name.replace('_', '-') - - def prefixed_default(self, name: 'OptionKey', prefix: str = '') -> T.Any: - if self.opt_type in [UserComboOption, UserIntegerOption]: - return self.default - try: - return BUILTIN_DIR_NOPREFIX_OPTIONS[name][prefix] - except KeyError: - pass - return self.default + opt = self.original_options[key] + if opt.yielding: + opt = self.original_options.get(key.as_root(), opt) + if self.overrides: + override_value = self.overrides.get(key.as_root()) + if override_value is not None: + opt = copy.copy(opt) + opt.set_value(override_value) + return opt - def add_to_argparse(self, name: str, parser: argparse.ArgumentParser, help_suffix: str) -> None: - kwargs = OrderedDict() + def __iter__(self) -> T.Iterator[OptionKey]: + return iter(self.original_options) - c = self._argparse_choices() - b = self._argparse_action() - h = self.description - if not b: - h = '{} (default: {}).'.format(h.rstrip('.'), self.prefixed_default(name)) - else: - kwargs['action'] = b - if c and not b: - kwargs['choices'] = c - kwargs['default'] = argparse.SUPPRESS - kwargs['dest'] = name - - cmdline_name = self.argparse_name_to_arg(name) - parser.add_argument(cmdline_name, help=h + help_suffix, **kwargs) - - -# Update `docs/markdown/Builtin-options.md` after changing the options below -# Also update mesonlib._BUILTIN_NAMES. See the comment there for why this is required. -# Please also update completion scripts in $MESONSRC/data/shell-completions/ -BUILTIN_DIR_OPTIONS: T.Dict['OptionKey', 'BuiltinOption'] = OrderedDict([ - (OptionKey('prefix'), BuiltinOption(UserStringOption, 'Installation prefix', default_prefix())), - (OptionKey('bindir'), BuiltinOption(UserStringOption, 'Executable directory', 'bin')), - (OptionKey('datadir'), BuiltinOption(UserStringOption, 'Data file directory', default_datadir())), - (OptionKey('includedir'), BuiltinOption(UserStringOption, 'Header file directory', default_includedir())), - (OptionKey('infodir'), BuiltinOption(UserStringOption, 'Info page directory', default_infodir())), - (OptionKey('libdir'), BuiltinOption(UserStringOption, 'Library directory', default_libdir())), - (OptionKey('licensedir'), BuiltinOption(UserStringOption, 'Licenses directory', '')), - (OptionKey('libexecdir'), BuiltinOption(UserStringOption, 'Library executable directory', default_libexecdir())), - (OptionKey('localedir'), BuiltinOption(UserStringOption, 'Locale data directory', default_localedir())), - (OptionKey('localstatedir'), BuiltinOption(UserStringOption, 'Localstate data directory', 'var')), - (OptionKey('mandir'), BuiltinOption(UserStringOption, 'Manual page directory', default_mandir())), - (OptionKey('sbindir'), BuiltinOption(UserStringOption, 'System executable directory', default_sbindir())), - (OptionKey('sharedstatedir'), BuiltinOption(UserStringOption, 'Architecture-independent data directory', 'com')), - (OptionKey('sysconfdir'), BuiltinOption(UserStringOption, 'Sysconf data directory', default_sysconfdir())), -]) - -BUILTIN_CORE_OPTIONS: T.Dict['OptionKey', 'BuiltinOption'] = OrderedDict([ - (OptionKey('auto_features'), BuiltinOption(UserFeatureOption, "Override value of all 'auto' features", 'auto')), - (OptionKey('backend'), BuiltinOption(UserComboOption, 'Backend to use', 'ninja', choices=backendlist, - readonly=True)), - (OptionKey('genvslite'), - BuiltinOption( - UserComboOption, - 'Setup multiple buildtype-suffixed ninja-backend build directories, ' - 'and a [builddir]_vs containing a Visual Studio meta-backend with multiple configurations that calls into them', - 'vs2022', - choices=genvslitelist) - ), - (OptionKey('buildtype'), BuiltinOption(UserComboOption, 'Build type to use', 'debug', - choices=buildtypelist)), - (OptionKey('debug'), BuiltinOption(UserBooleanOption, 'Enable debug symbols and other information', True)), - (OptionKey('default_library'), BuiltinOption(UserComboOption, 'Default library type', 'shared', choices=['shared', 'static', 'both'], - yielding=False)), - (OptionKey('errorlogs'), BuiltinOption(UserBooleanOption, "Whether to print the logs from failing tests", True)), - (OptionKey('install_umask'), BuiltinOption(UserUmaskOption, 'Default umask to apply on permissions of installed files', '022')), - (OptionKey('layout'), BuiltinOption(UserComboOption, 'Build directory layout', 'mirror', choices=['mirror', 'flat'])), - (OptionKey('optimization'), BuiltinOption(UserComboOption, 'Optimization level', '0', choices=['plain', '0', 'g', '1', '2', '3', 's'])), - (OptionKey('prefer_static'), BuiltinOption(UserBooleanOption, 'Whether to try static linking before shared linking', False)), - (OptionKey('stdsplit'), BuiltinOption(UserBooleanOption, 'Split stdout and stderr in test logs', True)), - (OptionKey('strip'), BuiltinOption(UserBooleanOption, 'Strip targets on install', False)), - (OptionKey('unity'), BuiltinOption(UserComboOption, 'Unity build', 'off', choices=['on', 'off', 'subprojects'])), - (OptionKey('unity_size'), BuiltinOption(UserIntegerOption, 'Unity block size', (2, None, 4))), - (OptionKey('warning_level'), BuiltinOption(UserComboOption, 'Compiler warning level to use', '1', choices=['0', '1', '2', '3', 'everything'], yielding=False)), - (OptionKey('werror'), BuiltinOption(UserBooleanOption, 'Treat warnings as errors', False, yielding=False)), - (OptionKey('wrap_mode'), BuiltinOption(UserComboOption, 'Wrap mode', 'default', choices=['default', 'nofallback', 'nodownload', 'forcefallback', 'nopromote'])), - (OptionKey('force_fallback_for'), BuiltinOption(UserArrayOption, 'Force fallback for those subprojects', [])), - (OptionKey('vsenv'), BuiltinOption(UserBooleanOption, 'Activate Visual Studio environment', False, readonly=True)), - - # Pkgconfig module - (OptionKey('relocatable', module='pkgconfig'), - BuiltinOption(UserBooleanOption, 'Generate pkgconfig files as relocatable', False)), - - # Python module - (OptionKey('bytecompile', module='python'), - BuiltinOption(UserIntegerOption, 'Whether to compile bytecode', (-1, 2, 0))), - (OptionKey('install_env', module='python'), - BuiltinOption(UserComboOption, 'Which python environment to install to', 'prefix', choices=['auto', 'prefix', 'system', 'venv'])), - (OptionKey('platlibdir', module='python'), - BuiltinOption(UserStringOption, 'Directory for site-specific, platform-specific files.', '')), - (OptionKey('purelibdir', module='python'), - BuiltinOption(UserStringOption, 'Directory for site-specific, non-platform-specific files.', '')), - (OptionKey('allow_limited_api', module='python'), - BuiltinOption(UserBooleanOption, 'Whether to allow use of the Python Limited API', True)), -]) - -BUILTIN_OPTIONS = OrderedDict(chain(BUILTIN_DIR_OPTIONS.items(), BUILTIN_CORE_OPTIONS.items())) - -BUILTIN_OPTIONS_PER_MACHINE: T.Dict['OptionKey', 'BuiltinOption'] = OrderedDict([ - (OptionKey('pkg_config_path'), BuiltinOption(UserArrayOption, 'List of additional paths for pkg-config to search', [])), - (OptionKey('cmake_prefix_path'), BuiltinOption(UserArrayOption, 'List of additional prefixes for cmake to search', [])), -]) - -# Special prefix-dependent defaults for installation directories that reside in -# a path outside of the prefix in FHS and common usage. -BUILTIN_DIR_NOPREFIX_OPTIONS: T.Dict[OptionKey, T.Dict[str, str]] = { - OptionKey('sysconfdir'): {'/usr': '/etc'}, - OptionKey('localstatedir'): {'/usr': '/var', '/usr/local': '/var/local'}, - OptionKey('sharedstatedir'): {'/usr': '/var/lib', '/usr/local': '/var/local/lib'}, - OptionKey('platlibdir', module='python'): {}, - OptionKey('purelibdir', module='python'): {}, -} + def __len__(self) -> int: + return len(self.original_options) FORBIDDEN_TARGET_NAMES = frozenset({ 'clean', |
