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