diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index fafee86ab..27ce54e20 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -19,6 +19,7 @@ from .toolchain import CMakeToolchain, CMakeExecScope from .traceparser import CMakeTraceParser from .tracetargets import resolve_cmake_trace_targets from .. import mlog, mesonlib +from .. import options from ..mesonlib import MachineChoice, OrderedSet, path_is_in_root, relative_to_if_possible from ..options import OptionKey from ..mesondata import DataFile @@ -533,17 +534,12 @@ class ConverterTarget: @lru_cache(maxsize=None) def _all_lang_stds(self, lang: str) -> 'ImmutableListProtocol[str]': try: - res = self.env.coredata.optstore.get_value_object(OptionKey(f'{lang}_std', machine=MachineChoice.BUILD)).choices + opt = self.env.coredata.optstore.get_value_object(OptionKey(f'{lang}_std', machine=MachineChoice.BUILD)) + assert isinstance(opt, (options.UserStdOption, options.UserComboOption)), 'for mypy' + return opt.choices or [] except KeyError: return [] - # TODO: Get rid of this once we have proper typing for options - assert isinstance(res, list) - for i in res: - assert isinstance(i, str) - - return res - def process_inter_target_dependencies(self) -> None: # Move the dependencies from all TRANSFER_DEPENDENCIES_FROM to the target to_process = list(self.depends) diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index d8ad9f793..4f93ea14e 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -124,7 +124,7 @@ class ClangCCompiler(ClangCStds, ClangCompiler, CCompiler): opts = super().get_options() if self.info.is_windows() or self.info.is_cygwin(): key = self.form_compileropt_key('winlibs') - opts[key] = options.UserArrayOption( + opts[key] = options.UserStringArrayOption( self.make_option_name(key), 'Standard Windows libraries to link against', gnu_winlibs) @@ -257,7 +257,7 @@ class GnuCCompiler(GnuCStds, GnuCompiler, CCompiler): opts = super().get_options() if self.info.is_windows() or self.info.is_cygwin(): key = self.form_compileropt_key('winlibs') - opts[key] = options.UserArrayOption( + opts[key] = options.UserStringArrayOption( self.make_option_name(key), 'Standard Windows libraries to link against', gnu_winlibs) @@ -406,7 +406,7 @@ class VisualStudioLikeCCompilerMixin(CompilerMixinBase): def get_options(self) -> MutableKeyedOptionDictType: opts = super().get_options() key = self.form_compileropt_key('winlibs') - opts[key] = options.UserArrayOption( + opts[key] = options.UserStringArrayOption( self.make_option_name(key), 'Standard Windows libraries to link against', msvc_winlibs) @@ -733,9 +733,7 @@ class MetrowerksCCompilerARM(MetrowerksCompiler, CCompiler): def get_options(self) -> 'MutableKeyedOptionDictType': opts = super().get_options() - c_stds = ['c99'] - key = self.form_compileropt_key('std') - opts[key].choices = ['none'] + c_stds + self._update_language_stds(opts, ['c99']) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -763,9 +761,7 @@ class MetrowerksCCompilerEmbeddedPowerPC(MetrowerksCompiler, CCompiler): def get_options(self) -> 'MutableKeyedOptionDictType': opts = super().get_options() - c_stds = ['c99'] - key = self.form_compileropt_key('std') - opts[key].choices = ['none'] + c_stds + self._update_language_stds(opts, ['c99']) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 1432afb85..5777f19f1 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1359,6 +1359,15 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta): def form_compileropt_key(self, basename: str) -> OptionKey: return OptionKey(f'{self.language}_{basename}', machine=self.for_machine) + def _update_language_stds(self, opts: MutableKeyedOptionDictType, value: T.List[str]) -> None: + key = self.form_compileropt_key('std') + std = opts[key] + assert isinstance(std, (options.UserStdOption, options.UserComboOption)), 'for mypy' + if 'none' not in value: + value = ['none'] + value + std.choices = value + + def get_global_options(lang: str, comp: T.Type[Compiler], for_machine: MachineChoice, @@ -1374,12 +1383,12 @@ def get_global_options(lang: str, comp_options = env.options.get(comp_key, []) link_options = env.options.get(largkey, []) - cargs = options.UserArrayOption( + cargs = options.UserStringArrayOption( f'{lang}_{argkey.name}', description + ' compiler', comp_options, split_args=True, allow_dups=True) - largs = options.UserArrayOption( + largs = options.UserStringArrayOption( f'{lang}_{largkey.name}', description + ' linker', link_options, split_args=True, allow_dups=True) diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 7fa9aa833..80f84b38e 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -243,7 +243,7 @@ class ClangCPPCompiler(_StdCPPLibMixin, ClangCPPStds, ClangCompiler, CPPCompiler self.make_option_name(key), 'C++ exception handling type.', 'default', - ['none', 'default', 'a', 's', 'sc']) + choices=['none', 'default', 'a', 's', 'sc']) key = self.form_compileropt_key('rtti') opts[key] = options.UserBooleanOption( @@ -259,7 +259,7 @@ class ClangCPPCompiler(_StdCPPLibMixin, ClangCPPStds, ClangCompiler, CPPCompiler if self.info.is_windows() or self.info.is_cygwin(): key = self.form_compileropt_key('winlibs') - opts[key] = options.UserArrayOption( + opts[key] = options.UserStringArrayOption( self.make_option_name(key), 'Standard Win libraries to link against', gnu_winlibs) @@ -399,7 +399,7 @@ class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler): self.make_option_name(key), 'C++ exception handling type.', 'default', - ['none', 'default', 'a', 's', 'sc']) + choices=['none', 'default', 'a', 's', 'sc']) key = self.form_compileropt_key('std') std_opt = opts[key] @@ -449,7 +449,7 @@ class GnuCPPCompiler(_StdCPPLibMixin, GnuCPPStds, GnuCompiler, CPPCompiler): self.make_option_name(key), 'C++ exception handling type.', 'default', - ['none', 'default', 'a', 's', 'sc']) + choices=['none', 'default', 'a', 's', 'sc']) key = self.form_compileropt_key('rtti') opts[key] = options.UserBooleanOption( @@ -465,7 +465,7 @@ class GnuCPPCompiler(_StdCPPLibMixin, GnuCPPStds, GnuCompiler, CPPCompiler): if self.info.is_windows() or self.info.is_cygwin(): key = key.evolve(name='cpp_winlibs') - opts[key] = options.UserArrayOption( + opts[key] = options.UserStringArrayOption( self.make_option_name(key), 'Standard Win libraries to link against', gnu_winlibs) @@ -578,7 +578,7 @@ class ElbrusCPPCompiler(ElbrusCompiler, CPPCompiler): self.make_option_name(key), 'C++ exception handling type.', 'default', - ['none', 'default', 'a', 's', 'sc']) + choices=['none', 'default', 'a', 's', 'sc']) key = self.form_compileropt_key('debugstl') opts[key] = options.UserBooleanOption( @@ -661,7 +661,7 @@ class IntelCPPCompiler(IntelGnuLikeCompiler, CPPCompiler): self.make_option_name(key), 'C++ exception handling type.', 'default', - ['none', 'default', 'a', 's', 'sc']) + choices=['none', 'default', 'a', 's', 'sc']) key = self.form_compileropt_key('rtti') opts[key] = options.UserBooleanOption( @@ -691,9 +691,7 @@ class IntelCPPCompiler(IntelGnuLikeCompiler, CPPCompiler): c_stds += ['c++2a'] g_stds += ['gnu++2a'] - std_opt = opts[self.form_compileropt_key('std')] - assert isinstance(std_opt, options.UserStdOption), 'for mypy' - std_opt.set_versions(c_stds + g_stds) + self._update_language_stds(opts, c_stds + g_stds) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -754,7 +752,7 @@ class VisualStudioLikeCPPCompilerMixin(CompilerMixinBase): self.make_option_name(key), 'C++ exception handling type.', 'default', - ['none', 'default', 'a', 's', 'sc']) + choices=['none', 'default', 'a', 's', 'sc']) key = self.form_compileropt_key('rtti') opts[key] = options.UserBooleanOption( @@ -763,7 +761,7 @@ class VisualStudioLikeCPPCompilerMixin(CompilerMixinBase): True) key = self.form_compileropt_key('winlibs') - opts[key] = options.UserArrayOption( + opts[key] = options.UserStringArrayOption( self.make_option_name(key), 'Standard Win libraries to link against', msvc_winlibs) @@ -1040,8 +1038,7 @@ class MetrowerksCPPCompilerARM(MetrowerksCompiler, CPPCompiler): def get_options(self) -> 'MutableKeyedOptionDictType': opts = super().get_options() - key = self.form_compileropt_key('std') - opts[key].choices = ['none'] + self._update_language_stds(opts, []) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -1069,8 +1066,7 @@ class MetrowerksCPPCompilerEmbeddedPowerPC(MetrowerksCompiler, CPPCompiler): def get_options(self) -> 'MutableKeyedOptionDictType': opts = super().get_options() - key = self.form_compileropt_key('std') - opts[key].choices = ['none'] + self._update_language_stds(opts, []) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index aefcc512b..6a49d95ae 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -648,13 +648,12 @@ class CudaCompiler(Compiler): opts = super().get_options() - # XXX: cpp_std is correct, the annotations are wrong key = self.form_compileropt_key('std') opts[key] = options.UserComboOption( self.make_option_name(key), 'C++ language standard to use with CUDA', 'none', - cpp_stds) + choices=cpp_stds) key = self.form_compileropt_key('ccbindir') opts[key] = options.UserStringOption( diff --git a/mesonbuild/compilers/cython.py b/mesonbuild/compilers/cython.py index ba04aea0b..ed0ab31ad 100644 --- a/mesonbuild/compilers/cython.py +++ b/mesonbuild/compilers/cython.py @@ -74,14 +74,14 @@ class CythonCompiler(Compiler): self.make_option_name(key), 'Python version to target', '3', - ['2', '3']) + choices=['2', '3']) key = self.form_compileropt_key('language') opts[key] = options.UserComboOption( self.make_option_name(key), 'Output C or C++ files', 'c', - ['c', 'cpp']) + choices=['c', 'cpp']) return opts diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index b004727b4..72c9a5a97 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -121,7 +121,7 @@ class FortranCompiler(CLikeCompiler, Compiler): self.make_option_name(key), 'Fortran language standard to use', 'none', - ['none']) + choices=['none']) return opts @@ -281,8 +281,7 @@ class GnuFortranCompiler(GnuCompiler, FortranCompiler): fortran_stds += ['f2008'] if version_compare(self.version, '>=8.0.0'): fortran_stds += ['f2018'] - key = self.form_compileropt_key('std') - opts[key].choices = ['none'] + fortran_stds + self._update_language_stds(opts, fortran_stds) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -338,9 +337,7 @@ class ElbrusFortranCompiler(ElbrusCompiler, FortranCompiler): def get_options(self) -> 'MutableKeyedOptionDictType': opts = super().get_options() - fortran_stds = ['f95', 'f2003', 'f2008', 'gnu', 'legacy', 'f2008ts'] - key = self.form_compileropt_key('std') - opts[key].choices = ['none'] + fortran_stds + self._update_language_stds(opts, ['f95', 'f2003', 'f2008', 'gnu', 'legacy', 'f2008ts']) return opts def get_module_outdir_args(self, path: str) -> T.List[str]: @@ -418,8 +415,7 @@ class IntelFortranCompiler(IntelGnuLikeCompiler, FortranCompiler): def get_options(self) -> 'MutableKeyedOptionDictType': opts = super().get_options() - key = self.form_compileropt_key('std') - opts[key].choices = ['none', 'legacy', 'f95', 'f2003', 'f2008', 'f2018'] + self._update_language_stds(opts, ['none', 'legacy', 'f95', 'f2003', 'f2008', 'f2018']) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -473,8 +469,7 @@ class IntelClFortranCompiler(IntelVisualStudioLikeCompiler, FortranCompiler): def get_options(self) -> 'MutableKeyedOptionDictType': opts = super().get_options() - key = self.form_compileropt_key('std') - opts[key].choices = ['none', 'legacy', 'f95', 'f2003', 'f2008', 'f2018'] + self._update_language_stds(opts, ['none', 'legacy', 'f95', 'f2003', 'f2008', 'f2018']) return opts def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py index 7fe16c6f8..aacdc07d7 100644 --- a/mesonbuild/compilers/rust.py +++ b/mesonbuild/compilers/rust.py @@ -241,7 +241,7 @@ class RustCompiler(Compiler): self.make_option_name(key), 'Rust edition to use', 'none', - ['none', '2015', '2018', '2021', '2024']) + choices=['none', '2015', '2018', '2021', '2024']) return opts diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index d295858dc..5469616f8 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -599,7 +599,7 @@ class CoreData: oldval = self.optstore.get_value_object(key) if type(oldval) is not type(value): self.optstore.set_value(key, value.value) - elif oldval.choices != value.choices: + elif oldval.printable_choices() != value.printable_choices(): # If the choices have changed, use the new value, but attempt # to keep the old options. If they are not valid keep the new # defaults but warn. diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py index 3a6343ba1..7c2270edc 100644 --- a/mesonbuild/mconf.py +++ b/mesonbuild/mconf.py @@ -240,7 +240,7 @@ class Conf: printable_value = '' if isinstance(o, options.UserFeatureOption) and o.is_auto(): printable_value = auto.printable_value() - self.add_option(str(root), o.description, printable_value, o.choices) + self.add_option(str(root), o.description, printable_value, o.printable_choices()) def print_conf(self, pager: bool) -> None: if pager: diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index cd68911ce..cf76b6012 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -319,7 +319,7 @@ def list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[s typestr = 'combo' elif isinstance(opt, options.UserIntegerOption): typestr = 'integer' - elif isinstance(opt, options.UserArrayOption): + elif isinstance(opt, options.UserStringArrayOption): typestr = 'array' c = opt.printable_choices() if c: diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index 99efd511e..8c0d1daec 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -213,7 +213,7 @@ class OptionInterpreter: KwargInfo('value', str, default=''), ) def string_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: StringArgs) -> options.UserOption: - return options.UserStringOption(name, description, kwargs['value'], None, *args) + return options.UserStringOption(name, description, kwargs['value'], *args) @typed_kwargs( 'boolean option', @@ -239,7 +239,7 @@ class OptionInterpreter: value = kwargs['value'] if value is None: value = kwargs['choices'][0] - return options.UserComboOption(name, description, value, choices, *args) + return options.UserComboOption(name, description, value, *args, choices) @typed_kwargs( 'integer option', @@ -255,7 +255,7 @@ class OptionInterpreter: ) def integer_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: IntegerArgs) -> options.UserOption: return options.UserIntegerOption( - name, description, kwargs['value'], None, *args, min_value=kwargs['min'], max_value=kwargs['max']) + name, description, kwargs['value'], *args, min_value=kwargs['min'], max_value=kwargs['max']) @typed_kwargs( 'string array option', @@ -270,12 +270,11 @@ class OptionInterpreter: FeatureDeprecated('String value for array option', '1.3.0').use(self.subproject) else: raise mesonlib.MesonException('Value does not define an array: ' + value) - # XXX: the value of choices is correct, the annotation is wrong. - # the annotation will be fixed in a later commit - return options.UserArrayOption(name, description, value, - choices=choices, # type: ignore[arg-type] - yielding=args[0], - deprecated=args[1]) + return options.UserStringArrayOption( + name, description, value, + choices=choices, + yielding=args[0], + deprecated=args[1]) @typed_kwargs( 'feature option', diff --git a/mesonbuild/options.py b/mesonbuild/options.py index a53cb91a4..ae580785e 100644 --- a/mesonbuild/options.py +++ b/mesonbuild/options.py @@ -253,7 +253,6 @@ class UserOption(T.Generic[_T], HoldableObject): name: str description: str value_: dataclasses.InitVar[_T] - choices: T.Optional[T.Union[str, T.List[_T]]] = None yielding: bool = DEFAULT_YIELDING deprecated: DeprecatedType = False readonly: bool = dataclasses.field(default=False, init=False) @@ -269,11 +268,7 @@ class UserOption(T.Generic[_T], HoldableObject): return self.value def printable_choices(self) -> T.Optional[T.List[str]]: - if not self.choices: - return None - if isinstance(self.choices, str): - return [self.choices] - return [str(c) for c in self.choices] + return None # Check that the input is a valid value and return the # "cleaned" or "native" version. For example the Boolean @@ -287,6 +282,17 @@ class UserOption(T.Generic[_T], HoldableObject): return self.value != oldvalue +@dataclasses.dataclass +class EnumeratedUserOption(UserOption[_T]): + + """A generic UserOption that has enumerated values.""" + + choices: T.List[_T] = dataclasses.field(default_factory=list) + + def printable_choices(self) -> T.Optional[T.List[str]]: + return [str(c) for c in self.choices] + + @dataclasses.dataclass class UserStringOption(UserOption[str]): @@ -296,7 +302,7 @@ class UserStringOption(UserOption[str]): return value @dataclasses.dataclass -class UserBooleanOption(UserOption[bool]): +class UserBooleanOption(EnumeratedUserOption[bool]): choices: T.List[bool] = dataclasses.field(default_factory=lambda: [True, False]) @@ -327,7 +333,10 @@ class UserIntegerOption(UserOption[int]): choices.append(f'>= {self.min_value!s}') if self.max_value is not None: choices.append(f'<= {self.max_value!s}') - self.choices = ', '.join(choices) + self.__choices: str = ', '.join(choices) + + def printable_choices(self) -> T.Optional[T.List[str]]: + return [self.__choices] def validate_value(self, value: T.Any) -> int: if isinstance(value, str): @@ -376,7 +385,7 @@ class UserUmaskOption(UserIntegerOption, UserOption[T.Union[str, OctalInt]]): raise MesonException(f'Invalid mode for option "{self.name}" {e}') @dataclasses.dataclass -class UserComboOption(UserOption[str]): +class UserComboOption(EnumeratedUserOption[str]): def validate_value(self, value: T.Any) -> str: if value not in self.choices: @@ -390,15 +399,32 @@ class UserComboOption(UserOption[str]): raise MesonException('Value "{}" (of type "{}") for option "{}" is not one of the choices.' ' Possible choices are (as string): {}.'.format( value, _type, self.name, optionsstring)) + + assert isinstance(value, str), 'for mypy' return value @dataclasses.dataclass -class UserArrayOption(UserOption[T.List[str]]): +class UserArrayOption(UserOption[T.List[_T]]): - value_: dataclasses.InitVar[T.Union[str, T.List[str]]] + value_: dataclasses.InitVar[T.Union[_T, T.List[_T]]] + choices: T.Optional[T.List[_T]] = None split_args: bool = False allow_dups: bool = False + 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) + + def printable_choices(self) -> T.Optional[T.List[str]]: + if self.choices is None: + return None + return [str(c) for c in self.choices] + + +@dataclasses.dataclass +class UserStringArrayOption(UserArrayOption[str]): + def listify(self, value: T.Any) -> T.List[T.Any]: try: return listify_array_value(value, self.split_args) @@ -427,11 +453,6 @@ class UserArrayOption(UserOption[T.List[str]]): ) 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) - @dataclasses.dataclass class UserFeatureOption(UserComboOption): @@ -471,7 +492,7 @@ class UserStdOption(UserComboOption): # 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']) + super().__init__(opt_name, f'{lang} language standard to use', 'none', choices=['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) @@ -637,7 +658,7 @@ BUILTIN_CORE_OPTIONS: T.Dict['OptionKey', 'BuiltinOption'] = OrderedDict([ (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('force_fallback_for'), BuiltinOption(UserStringArrayOption, 'Force fallback for those subprojects', [])), (OptionKey('vsenv'), BuiltinOption(UserBooleanOption, 'Activate Visual Studio environment', False, readonly=True)), # Pkgconfig module @@ -660,8 +681,8 @@ BUILTIN_CORE_OPTIONS: T.Dict['OptionKey', 'BuiltinOption'] = OrderedDict([ 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', [])), + (OptionKey('pkg_config_path'), BuiltinOption(UserStringArrayOption, 'List of additional paths for pkg-config to search', [])), + (OptionKey('cmake_prefix_path'), BuiltinOption(UserStringArrayOption, 'List of additional prefixes for cmake to search', [])), ]) # Special prefix-dependent defaults for installation directories that reside in