parent
631b38577e
commit
5365d9a842
31 changed files with 713 additions and 667 deletions
@ -0,0 +1,480 @@ |
|||||||
|
# SPDX-License-Identifier: Apache-2.0 |
||||||
|
# Copyright 2013-2024 Contributors to the The Meson project |
||||||
|
|
||||||
|
from collections import OrderedDict |
||||||
|
from itertools import chain |
||||||
|
import argparse |
||||||
|
|
||||||
|
from .mesonlib import ( |
||||||
|
HoldableObject, |
||||||
|
OptionKey, |
||||||
|
default_prefix, |
||||||
|
default_datadir, |
||||||
|
default_includedir, |
||||||
|
default_infodir, |
||||||
|
default_libdir, |
||||||
|
default_libexecdir, |
||||||
|
default_localedir, |
||||||
|
default_mandir, |
||||||
|
default_sbindir, |
||||||
|
default_sysconfdir, |
||||||
|
MesonException, |
||||||
|
listify_array_value, |
||||||
|
) |
||||||
|
|
||||||
|
from . import mlog |
||||||
|
|
||||||
|
import typing as T |
||||||
|
|
||||||
|
DEFAULT_YIELDING = False |
||||||
|
|
||||||
|
# Can't bind this near the class method it seems, sadly. |
||||||
|
_T = T.TypeVar('_T') |
||||||
|
|
||||||
|
backendlist = ['ninja', 'vs', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'vs2017', 'vs2019', 'vs2022', 'xcode', 'none'] |
||||||
|
genvslitelist = ['vs2022'] |
||||||
|
buildtypelist = ['plain', 'debug', 'debugoptimized', 'release', 'minsize', 'custom'] |
||||||
|
|
||||||
|
|
||||||
|
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 |
||||||
|
|
||||||
|
_U = T.TypeVar('_U', bound=UserOption[_T]) |
||||||
|
|
||||||
|
|
||||||
|
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}') |
||||||
|
|
||||||
|
|
||||||
|
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 |
||||||
|
|
||||||
|
@staticmethod |
||||||
|
def argparse_name_to_arg(name: str) -> str: |
||||||
|
if name == 'warning_level': |
||||||
|
return '--warnlevel' |
||||||
|
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 |
||||||
|
|
||||||
|
def add_to_argparse(self, name: str, parser: argparse.ArgumentParser, help_suffix: str) -> None: |
||||||
|
kwargs = OrderedDict() |
||||||
|
|
||||||
|
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'): {}, |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
class OptionStore: |
||||||
|
def __init__(self): |
||||||
|
# This class will hold all options for a given build directory |
||||||
|
self.dummy = None |
Loading…
Reference in new issue