Merge pull request #13307 from mesonbuild/optstorerefactor

Convert OptionStore from a dict to a full class with named methods
This commit is contained in:
Jussi Pakkanen 2024-06-14 19:25:18 +03:00 committed by GitHub
commit ce889d6870
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
43 changed files with 443 additions and 354 deletions

View File

@ -182,7 +182,7 @@ class IntrospectionInterpreter(AstInterpreter):
if self.subproject:
options = {}
for k in comp.get_options():
v = copy.copy(self.coredata.options[k])
v = copy.copy(self.coredata.optstore.get_value_object(k))
k = k.evolve(subproject=self.subproject)
options[k] = v
self.coredata.add_compiler_options(options, lang, for_machine, self.environment, self.subproject)

View File

@ -962,7 +962,7 @@ class Backend:
def target_uses_pch(self, target: build.BuildTarget) -> bool:
try:
return T.cast('bool', target.get_option(OptionKey('b_pch')))
except KeyError:
except (KeyError, AttributeError):
return False
@staticmethod

View File

@ -623,7 +623,7 @@ class NinjaBackend(backends.Backend):
outfile.write('# Do not edit by hand.\n\n')
outfile.write('ninja_required_version = 1.8.2\n\n')
num_pools = self.environment.coredata.options[OptionKey('backend_max_links')].value
num_pools = self.environment.coredata.optstore.get_value('backend_max_links')
if num_pools > 0:
outfile.write(f'''pool link_pool
depth = {num_pools}
@ -656,8 +656,8 @@ class NinjaBackend(backends.Backend):
self.generate_dist()
mlog.log_timestamp("Dist generated")
key = OptionKey('b_coverage')
if (key in self.environment.coredata.options and
self.environment.coredata.options[key].value):
if (key in self.environment.coredata.optstore and
self.environment.coredata.optstore.get_value(key)):
gcovr_exe, gcovr_version, lcov_exe, lcov_version, genhtml_exe, llvm_cov_exe = environment.find_coverage_tools(self.environment.coredata)
mlog.debug(f'Using {gcovr_exe} ({gcovr_version}), {lcov_exe} and {llvm_cov_exe} for code coverage')
if gcovr_exe or (lcov_exe and genhtml_exe):
@ -1991,7 +1991,7 @@ class NinjaBackend(backends.Backend):
buildtype = target.get_option(OptionKey('buildtype'))
crt = target.get_option(OptionKey('b_vscrt'))
args += rustc.get_crt_link_args(crt, buildtype)
except KeyError:
except (KeyError, AttributeError):
pass
if mesonlib.version_compare(rustc.version, '>= 1.67.0'):
@ -2295,7 +2295,7 @@ class NinjaBackend(backends.Backend):
return options
def generate_static_link_rules(self):
num_pools = self.environment.coredata.options[OptionKey('backend_max_links')].value
num_pools = self.environment.coredata.optstore.get_value('backend_max_links')
if 'java' in self.environment.coredata.compilers.host:
self.generate_java_link()
for for_machine in MachineChoice:
@ -2343,7 +2343,7 @@ class NinjaBackend(backends.Backend):
self.add_rule(NinjaRule(rule, cmdlist, args, description, **options, extra=pool))
def generate_dynamic_link_rules(self):
num_pools = self.environment.coredata.options[OptionKey('backend_max_links')].value
num_pools = self.environment.coredata.optstore.get_value('backend_max_links')
for for_machine in MachineChoice:
complist = self.environment.coredata.compilers[for_machine]
for langname, compiler in complist.items():
@ -3605,7 +3605,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
def get_user_option_args(self):
cmds = []
for (k, v) in self.environment.coredata.options.items():
for k, v in self.environment.coredata.optstore.items():
if k.is_project():
cmds.append('-D' + str(k) + '=' + (v.value if isinstance(v.value, str) else str(v.value).lower()))
# The order of these arguments must be the same between runs of Meson
@ -3734,8 +3734,8 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
if ctlist:
elem.add_dep(self.generate_custom_target_clean(ctlist))
if OptionKey('b_coverage') in self.environment.coredata.options and \
self.environment.coredata.options[OptionKey('b_coverage')].value:
if OptionKey('b_coverage') in self.environment.coredata.optstore and \
self.environment.coredata.optstore.get_value('b_coverage'):
self.generate_gcov_clean()
elem.add_dep('clean-gcda')
elem.add_dep('clean-gcno')

View File

@ -532,7 +532,7 @@ class Vs2010Backend(backends.Backend):
replace_if_different(sln_filename, sln_filename_tmp)
def generate_projects(self, vslite_ctx: dict = None) -> T.List[Project]:
startup_project = self.environment.coredata.options[OptionKey('backend_startup_project')].value
startup_project = self.environment.coredata.optstore.get_value('backend_startup_project')
projlist: T.List[Project] = []
startup_idx = 0
for (i, (name, target)) in enumerate(self.build.targets.items()):

View File

@ -533,7 +533,7 @@ class Target(HoldableObject, metaclass=abc.ABCMeta):
for k, v in overrides.items()}
else:
ovr = {}
self.options = coredata.OptionsView(self.environment.coredata.options, self.subproject, ovr)
self.options = coredata.OptionsView(self.environment.coredata.optstore, self.subproject, ovr)
# XXX: this should happen in the interpreter
if has_path_sep(self.name):
# Fix failing test 53 when this becomes an error.
@ -664,7 +664,7 @@ class Target(HoldableObject, metaclass=abc.ABCMeta):
def get_option(self, key: 'OptionKey') -> T.Union[str, int, bool]:
# TODO: if it's possible to annotate get_option or validate_option_value
# in the future we might be able to remove the cast here
return T.cast('T.Union[str, int, bool]', self.options[key].value)
return T.cast('T.Union[str, int, bool]', self.options.get_value(key))
@staticmethod
def parse_overrides(kwargs: T.Dict[str, T.Any]) -> T.Dict[OptionKey, str]:
@ -1242,8 +1242,8 @@ class BuildTarget(Target):
k = OptionKey(option)
if kwargs.get(arg) is not None:
val = T.cast('bool', kwargs[arg])
elif k in self.environment.coredata.options:
val = self.environment.coredata.options[k].value
elif k in self.environment.coredata.optstore:
val = self.environment.coredata.optstore.get_value(k)
else:
val = False
@ -1930,8 +1930,8 @@ class Executable(BuildTarget):
compilers: T.Dict[str, 'Compiler'],
kwargs):
key = OptionKey('b_pie')
if 'pie' not in kwargs and key in environment.coredata.options:
kwargs['pie'] = environment.coredata.options[key].value
if 'pie' not in kwargs and key in environment.coredata.optstore:
kwargs['pie'] = environment.coredata.optstore.get_value(key)
super().__init__(name, subdir, subproject, for_machine, sources, structured_sources, objects,
environment, compilers, kwargs)
self.win_subsystem = kwargs.get('win_subsystem') or 'console'

View File

@ -27,11 +27,11 @@ from .. import coredata, options
if T.TYPE_CHECKING:
from types import ModuleType
from typing import Any
from . import manifest
from .. import mparser
from ..environment import Environment
from ..coredata import KeyedOptionDictType
# tomllib is present in python 3.11, before that it is a pypi module called tomli,
# we try to import tomllib, then tomli,
@ -700,7 +700,7 @@ def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CR
]
def interpret(subp_name: str, subdir: str, env: Environment) -> T.Tuple[mparser.CodeBlockNode, KeyedOptionDictType]:
def interpret(subp_name: str, subdir: str, env: Environment) -> T.Tuple[mparser.CodeBlockNode, dict[OptionKey, options.UserOption[Any]]]:
# subp_name should be in the form "foo-0.1-rs"
package_name = subp_name.rsplit('-', 2)[0]
manifests = _load_manifests(os.path.join(env.source_dir, subdir))

View File

@ -51,9 +51,9 @@ blacklist_cmake_defs = [
]
def cmake_is_debug(env: 'Environment') -> bool:
if OptionKey('b_vscrt') in env.coredata.options:
if OptionKey('b_vscrt') in env.coredata.optstore:
is_debug = env.coredata.get_option(OptionKey('buildtype')) == 'debug'
if env.coredata.options[OptionKey('b_vscrt')].value in {'mdd', 'mtd'}:
if env.coredata.optstore.get_value('b_vscrt') in {'mdd', 'mtd'}:
is_debug = True
return is_debug
else:

View File

@ -51,7 +51,7 @@ class CMakeExecutor:
self.cmakebin = None
return
self.prefix_paths = self.environment.coredata.options[OptionKey('cmake_prefix_path', machine=self.for_machine)].value
self.prefix_paths = self.environment.coredata.optstore.get_value(OptionKey('cmake_prefix_path', machine=self.for_machine))
if self.prefix_paths:
self.extra_cmake_args += ['-DCMAKE_PREFIX_PATH={}'.format(';'.join(self.prefix_paths))]

View File

@ -532,7 +532,7 @@ class ConverterTarget:
@lru_cache(maxsize=None)
def _all_lang_stds(self, lang: str) -> 'ImmutableListProtocol[str]':
try:
res = self.env.coredata.options[OptionKey('std', machine=MachineChoice.BUILD, lang=lang)].choices
res = self.env.coredata.optstore.get_value_object(OptionKey('std', machine=MachineChoice.BUILD, lang=lang)).choices
except KeyError:
return []

View File

@ -165,16 +165,16 @@ class ClangCCompiler(_ClangCStds, ClangCompiler, CCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
args.append('-std=' + std.value)
std = options.get_value(key)
if std != 'none':
args.append('-std=' + std)
return args
def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
if self.info.is_windows() or self.info.is_cygwin():
# without a typedict mypy can't understand this.
key = self.form_langopt_key('winlibs')
libs = options[key].value.copy()
libs = options.get_value(key).copy()
assert isinstance(libs, list)
for l in libs:
assert isinstance(l, str)
@ -258,9 +258,9 @@ class ArmclangCCompiler(ArmclangCompiler, CCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
args.append('-std=' + std.value)
std = options.get_value(key)
if std != 'none':
args.append('-std=' + std)
return args
def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
@ -318,16 +318,16 @@ class GnuCCompiler(GnuCompiler, CCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
args.append('-std=' + std.value)
std = options.get_value(key)
if std != 'none':
args.append('-std=' + std)
return args
def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
if self.info.is_windows() or self.info.is_cygwin():
# without a typeddict mypy can't figure this out
key = self.form_langopt_key('winlibs')
libs: T.List[str] = options[key].value.copy()
libs: T.List[str] = options.get_value(key).copy()
assert isinstance(libs, list)
for l in libs:
assert isinstance(l, str)
@ -432,9 +432,9 @@ class IntelCCompiler(IntelGnuLikeCompiler, CCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
args.append('-std=' + std.value)
std = options.get_value(key)
if std != 'none':
args.append('-std=' + std)
return args
@ -461,7 +461,7 @@ class VisualStudioLikeCCompilerMixin(CompilerMixinBase):
def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
# need a TypeDict to make this work
key = self.form_langopt_key('winlibs')
libs = options[key].value.copy()
libs = options.get_value(key).copy()
assert isinstance(libs, list)
for l in libs:
assert isinstance(l, str)
@ -498,11 +498,11 @@ class VisualStudioCCompiler(MSVCCompiler, VisualStudioLikeCCompilerMixin, CCompi
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
key = self.form_langopt_key('std')
std = options[key]
std = options.get_value(key)
# As of MVSC 16.8, /std:c11 and /std:c17 are the only valid C standard options.
if std.value in {'c11'}:
if std == 'c11':
args.append('/std:c11')
elif std.value in {'c17', 'c18'}:
elif std in {'c17', 'c18'}:
args.append('/std:c17')
return args
@ -519,7 +519,7 @@ class ClangClCCompiler(_ClangCStds, ClangClCompiler, VisualStudioLikeCCompilerMi
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
key = self.form_langopt_key('std')
std = options[key].value
std = options.get_value(key)
if std != "none":
return [f'/clang:-std={std}']
return []
@ -541,7 +541,10 @@ class IntelClCCompiler(IntelVisualStudioLikeCompiler, VisualStudioLikeCCompilerM
def get_options(self) -> 'MutableKeyedOptionDictType':
opts = super().get_options()
key = self.form_langopt_key('std')
std_opt = opts[key]
# To shut up mypy.
if isinstance(opts, dict):
raise RuntimeError('This is a transitory issue that should not happen. Please report with full backtrace.')
std_opt = opts.get_value_object(key)
assert isinstance(std_opt, options.UserStdOption), 'for mypy'
std_opt.set_versions(['c89', 'c99', 'c11'])
return opts
@ -549,11 +552,11 @@ class IntelClCCompiler(IntelVisualStudioLikeCompiler, VisualStudioLikeCCompilerM
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
key = self.form_langopt_key('std')
std = options[key]
if std.value == 'c89':
std = options.get_value(key)
if std == 'c89':
mlog.log("ICL doesn't explicitly implement c89, setting the standard to 'none', which is close.", once=True)
elif std.value != 'none':
args.append('/Qstd:' + std.value)
elif std != 'none':
args.append('/Qstd:' + std)
return args
@ -583,9 +586,9 @@ class ArmCCompiler(ArmCompiler, CCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
args.append('--' + std.value)
std = options.get_value(key)
if std != 'none':
args.append('--' + std)
return args
@ -616,10 +619,10 @@ class CcrxCCompiler(CcrxCompiler, CCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
key = self.form_langopt_key('std')
std = options[key]
if std.value == 'c89':
std = options.get_value(key)
if std == 'c89':
args.append('-lang=c')
elif std.value == 'c99':
elif std == 'c99':
args.append('-lang=c99')
return args
@ -664,10 +667,10 @@ class Xc16CCompiler(Xc16Compiler, CCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
std = options.get_value(key)
if std != 'none':
args.append('-ansi')
args.append('-std=' + std.value)
args.append('-std=' + std)
return args
def get_compile_only_args(self) -> T.List[str]:
@ -748,9 +751,9 @@ class TICCompiler(TICompiler, CCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
args.append('--' + std.value)
std = options.get_value(key)
if std != 'none':
args.append('--' + std)
return args
class C2000CCompiler(TICCompiler):
@ -784,10 +787,10 @@ class MetrowerksCCompilerARM(MetrowerksCompiler, CCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
std = options.get_value(key)
if std != 'none':
args.append('-lang')
args.append(std.value)
args.append(std)
return args
class MetrowerksCCompilerEmbeddedPowerPC(MetrowerksCompiler, CCompiler):
@ -814,7 +817,7 @@ class MetrowerksCCompilerEmbeddedPowerPC(MetrowerksCompiler, CCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
args.append('-lang ' + std.value)
std = options.get_value(key)
if std != 'none':
args.append('-lang ' + std)
return args

View File

@ -25,6 +25,7 @@ from ..mesonlib import (
from ..arglist import CompilerArgs
if T.TYPE_CHECKING:
from typing import Any
from ..build import BuildTarget, DFeatures
from ..coredata import MutableKeyedOptionDictType, KeyedOptionDictType
from ..envconfig import MachineInfo
@ -247,14 +248,14 @@ BASE_OPTIONS: T.Mapping[OptionKey, BaseOption] = {
choices=MSCRT_VALS + ['from_buildtype', 'static_from_buildtype']),
}
base_options: KeyedOptionDictType = {key: base_opt.init_option(key) for key, base_opt in BASE_OPTIONS.items()}
base_options = {key: base_opt.init_option(key) for key, base_opt in BASE_OPTIONS.items()}
def option_enabled(boptions: T.Set[OptionKey], options: 'KeyedOptionDictType',
option: OptionKey) -> bool:
try:
if option not in boptions:
return False
ret = options[option].value
ret = options.get_value(option)
assert isinstance(ret, bool), 'must return bool' # could also be str
return ret
except KeyError:
@ -264,8 +265,8 @@ def option_enabled(boptions: T.Set[OptionKey], options: 'KeyedOptionDictType',
def get_option_value(options: 'KeyedOptionDictType', opt: OptionKey, fallback: '_T') -> '_T':
"""Get the value of an option, or the fallback value."""
try:
v: '_T' = options[opt].value
except KeyError:
v: '_T' = options.get_value(opt)
except (KeyError, AttributeError):
return fallback
assert isinstance(v, type(fallback)), f'Should have {type(fallback)!r} but was {type(v)!r}'
@ -279,52 +280,52 @@ def are_asserts_disabled(options: KeyedOptionDictType) -> bool:
:param options: OptionDictionary
:return: whether to disable assertions or not
"""
return (options[OptionKey('b_ndebug')].value == 'true' or
(options[OptionKey('b_ndebug')].value == 'if-release' and
options[OptionKey('buildtype')].value in {'release', 'plain'}))
return (options.get_value('b_ndebug') == 'true' or
(options.get_value('b_ndebug') == 'if-release' and
options.get_value('buildtype') in {'release', 'plain'}))
def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler', env: 'Environment') -> T.List[str]:
args: T.List[str] = []
try:
if options[OptionKey('b_lto')].value:
if options.get_value(OptionKey('b_lto')):
args.extend(compiler.get_lto_compile_args(
threads=get_option_value(options, OptionKey('b_lto_threads'), 0),
mode=get_option_value(options, OptionKey('b_lto_mode'), 'default')))
except KeyError:
except (KeyError, AttributeError):
pass
try:
args += compiler.get_colorout_args(options[OptionKey('b_colorout')].value)
except KeyError:
args += compiler.get_colorout_args(options.get_value(OptionKey('b_colorout')))
except (KeyError, AttributeError):
pass
try:
args += compiler.sanitizer_compile_args(options[OptionKey('b_sanitize')].value)
except KeyError:
args += compiler.sanitizer_compile_args(options.get_value(OptionKey('b_sanitize')))
except (KeyError, AttributeError):
pass
try:
pgo_val = options[OptionKey('b_pgo')].value
pgo_val = options.get_value(OptionKey('b_pgo'))
if pgo_val == 'generate':
args.extend(compiler.get_profile_generate_args())
elif pgo_val == 'use':
args.extend(compiler.get_profile_use_args())
except KeyError:
except (KeyError, AttributeError):
pass
try:
if options[OptionKey('b_coverage')].value:
if options.get_value(OptionKey('b_coverage')):
args += compiler.get_coverage_args()
except KeyError:
except (KeyError, AttributeError):
pass
try:
args += compiler.get_assert_args(are_asserts_disabled(options), env)
except KeyError:
except (KeyError, AttributeError):
pass
# This does not need a try...except
if option_enabled(compiler.base_options, options, OptionKey('b_bitcode')):
args.append('-fembed-bitcode')
try:
crt_val = options[OptionKey('b_vscrt')].value
buildtype = options[OptionKey('buildtype')].value
try:
crt_val = options.get_value(OptionKey('b_vscrt'))
buildtype = options.get_value(OptionKey('buildtype'))
args += compiler.get_crt_compile_args(crt_val, buildtype)
except AttributeError:
pass
@ -336,8 +337,8 @@ def get_base_link_args(options: 'KeyedOptionDictType', linker: 'Compiler',
is_shared_module: bool, build_dir: str) -> T.List[str]:
args: T.List[str] = []
try:
if options[OptionKey('b_lto')].value:
if options[OptionKey('werror')].value:
if options.get_value('b_lto'):
if options.get_value('werror'):
args.extend(linker.get_werror_args())
thinlto_cache_dir = None
@ -349,24 +350,24 @@ def get_base_link_args(options: 'KeyedOptionDictType', linker: 'Compiler',
threads=get_option_value(options, OptionKey('b_lto_threads'), 0),
mode=get_option_value(options, OptionKey('b_lto_mode'), 'default'),
thinlto_cache_dir=thinlto_cache_dir))
except KeyError:
except (KeyError, AttributeError):
pass
try:
args += linker.sanitizer_link_args(options[OptionKey('b_sanitize')].value)
except KeyError:
args += linker.sanitizer_link_args(options.get_value('b_sanitize'))
except (KeyError, AttributeError):
pass
try:
pgo_val = options[OptionKey('b_pgo')].value
pgo_val = options.get_value('b_pgo')
if pgo_val == 'generate':
args.extend(linker.get_profile_generate_args())
elif pgo_val == 'use':
args.extend(linker.get_profile_use_args())
except KeyError:
except (KeyError, AttributeError):
pass
try:
if options[OptionKey('b_coverage')].value:
if options.get_value('b_coverage'):
args += linker.get_coverage_link_args()
except KeyError:
except (KeyError, AttributeError):
pass
as_needed = option_enabled(linker.base_options, options, OptionKey('b_asneeded'))
@ -390,9 +391,9 @@ def get_base_link_args(options: 'KeyedOptionDictType', linker: 'Compiler',
args.extend(linker.get_allow_undefined_link_args())
try:
crt_val = options[OptionKey('b_vscrt')].value
buildtype = options[OptionKey('buildtype')].value
try:
crt_val = options.get_value(OptionKey('b_vscrt'))
buildtype = options.get_value(OptionKey('buildtype'))
args += linker.get_crt_link_args(crt_val, buildtype)
except AttributeError:
pass
@ -1357,7 +1358,7 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta):
def get_global_options(lang: str,
comp: T.Type[Compiler],
for_machine: MachineChoice,
env: 'Environment') -> 'KeyedOptionDictType':
env: 'Environment') -> 'dict[OptionKey, options.UserOption[Any]]':
"""Retrieve options that apply to all compilers for a given language."""
description = f'Extra arguments passed to the {lang}'
argkey = OptionKey('args', lang=lang, machine=for_machine)
@ -1387,6 +1388,6 @@ def get_global_options(lang: str,
# autotools compatibility.
largs.extend_value(comp_options)
opts: 'KeyedOptionDictType' = {argkey: cargs, largkey: largs}
opts: 'dict[OptionKey, options.UserOption[Any]]' = {argkey: cargs, largkey: largs}
return opts

View File

@ -278,15 +278,15 @@ class ClangCPPCompiler(_StdCPPLibMixin, ClangCompiler, CPPCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args: T.List[str] = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
args.append(self._find_best_cpp_std(std.value))
std = options.get_value(key)
if std != 'none':
args.append(self._find_best_cpp_std(std))
key = self.form_langopt_key('eh')
non_msvc_eh_options(options[key].value, args)
non_msvc_eh_options(options.get_value(key), args)
key = self.form_langopt_key('debugstl')
if options[key].value:
if options.get_value(key):
args.append('-D_GLIBCXX_DEBUG=1')
# We can't do _LIBCPP_DEBUG because it's unreliable unless libc++ was built with it too:
@ -296,7 +296,7 @@ class ClangCPPCompiler(_StdCPPLibMixin, ClangCompiler, CPPCompiler):
args.append('-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG')
key = self.form_langopt_key('rtti')
if not options[key].value:
if not options.get_value(key):
args.append('-fno-rtti')
return args
@ -305,7 +305,7 @@ class ClangCPPCompiler(_StdCPPLibMixin, ClangCompiler, CPPCompiler):
if self.info.is_windows() or self.info.is_cygwin():
# without a typedict mypy can't understand this.
key = self.form_langopt_key('winlibs')
libs = options[key].value.copy()
libs = options.get_value(key).copy()
assert isinstance(libs, list)
for l in libs:
assert isinstance(l, str)
@ -365,9 +365,9 @@ class EmscriptenCPPCompiler(EmscriptenMixin, ClangCPPCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args: T.List[str] = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
args.append(self._find_best_cpp_std(std.value))
std = options.get_value(key)
if std != 'none':
args.append(self._find_best_cpp_std(std))
return args
@ -409,12 +409,12 @@ class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args: T.List[str] = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
args.append('-std=' + std.value)
std = options.get_value(key)
if std != 'none':
args.append('-std=' + std)
key = self.form_langopt_key('eh')
non_msvc_eh_options(options[key].value, args)
non_msvc_eh_options(options.get_value(key), args)
return args
@ -483,16 +483,16 @@ class GnuCPPCompiler(_StdCPPLibMixin, GnuCompiler, CPPCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args: T.List[str] = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
args.append(self._find_best_cpp_std(std.value))
std = options.get_value(key)
if std != 'none':
args.append(self._find_best_cpp_std(std))
non_msvc_eh_options(options[key.evolve('eh')].value, args)
non_msvc_eh_options(options.get_value(key.evolve('eh')), args)
if not options[key.evolve('rtti')].value:
if not options.get_value(key.evolve('rtti')):
args.append('-fno-rtti')
if options[key.evolve('debugstl')].value:
if options.get_value(key.evolve('debugstl')):
args.append('-D_GLIBCXX_DEBUG=1')
return args
@ -500,7 +500,7 @@ class GnuCPPCompiler(_StdCPPLibMixin, GnuCompiler, CPPCompiler):
if self.info.is_windows() or self.info.is_cygwin():
# without a typedict mypy can't understand this.
key = self.form_langopt_key('winlibs')
libs = options[key].value.copy()
libs = options.get_value(key).copy()
assert isinstance(libs, list)
for l in libs:
assert isinstance(l, str)
@ -616,15 +616,15 @@ class ElbrusCPPCompiler(ElbrusCompiler, CPPCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args: T.List[str] = []
key = self.form_langopt_key('std')
std = options[key]
std = options.get_value(key)
if std.value != 'none':
args.append(self._find_best_cpp_std(std.value))
key = self.form_langopt_key('eh')
non_msvc_eh_options(options[key].value, args)
non_msvc_eh_options(options.get_value(key), args)
key = self.form_langopt_key('debugstl')
if options[key].value:
if options.get_value(key):
args.append('-D_GLIBCXX_DEBUG=1')
return args
@ -688,18 +688,18 @@ class IntelCPPCompiler(IntelGnuLikeCompiler, CPPCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args: T.List[str] = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
std = options.get_value(key)
if std != 'none':
remap_cpp03 = {
'c++03': 'c++98',
'gnu++03': 'gnu++98'
}
args.append('-std=' + remap_cpp03.get(std.value, std.value))
if options[key.evolve('eh')].value == 'none':
args.append('-std=' + remap_cpp03.get(std.value, std))
if options.get_value(key.evolve('eh')) == 'none':
args.append('-fno-exceptions')
if not options[key.evolve('rtti')].value:
if not options.get_value(key.evolve('rtti')):
args.append('-fno-rtti')
if options[key.evolve('debugstl')].value:
if options.get_value(key.evolve('debugstl')):
args.append('-D_GLIBCXX_DEBUG=1')
return args
@ -733,7 +733,7 @@ class VisualStudioLikeCPPCompilerMixin(CompilerMixinBase):
def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
# need a typeddict for this
key = self.form_langopt_key('winlibs')
return T.cast('T.List[str]', options[key].value[:])
return T.cast('T.List[str]', options.get_value(key)[:])
def _get_options_impl(self, opts: 'MutableKeyedOptionDictType', cpp_stds: T.List[str]) -> 'MutableKeyedOptionDictType':
key = self.form_langopt_key('std')
@ -762,18 +762,18 @@ class VisualStudioLikeCPPCompilerMixin(CompilerMixinBase):
args: T.List[str] = []
key = self.form_langopt_key('std')
eh = options[self.form_langopt_key('eh')]
if eh.value == 'default':
eh = options.get_value(self.form_langopt_key('eh'))
if eh == 'default':
args.append('/EHsc')
elif eh.value == 'none':
elif eh == 'none':
args.append('/EHs-c-')
else:
args.append('/EH' + eh.value)
args.append('/EH' + eh)
if not options[self.form_langopt_key('rtti')].value:
if not options.get_value(self.form_langopt_key('rtti')):
args.append('/GR-')
permissive, ver = self.VC_VERSION_MAP[options[key].value]
permissive, ver = self.VC_VERSION_MAP[options.get_value(key)]
if ver is not None:
args.append(f'/std:c++{ver}')
@ -801,7 +801,7 @@ class CPP11AsCPP14Mixin(CompilerMixinBase):
# (i.e., after VS2015U3)
# if one is using anything before that point, one cannot set the standard.
key = self.form_langopt_key('std')
if options[key].value in {'vc++11', 'c++11'}:
if options.get_value(key) in {'vc++11', 'c++11'}:
mlog.warning(self.id, 'does not support C++11;',
'attempting best effort; setting the standard to C++14',
once=True, fatal=False)
@ -809,10 +809,10 @@ class CPP11AsCPP14Mixin(CompilerMixinBase):
# deepcopy since we're messing with members, and we can't simply
# copy the members because the option proxy doesn't support it.
options = copy.deepcopy(options)
if options[key].value == 'vc++11':
options[key].value = 'vc++14'
if options.get_value(key) == 'vc++11':
options.set_value(key, 'vc++14')
else:
options[key].value = 'c++14'
options.set_value(key, 'c++14')
return super().get_option_compile_args(options)
@ -848,10 +848,10 @@ class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixi
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
key = self.form_langopt_key('std')
if options[key].value != 'none' and version_compare(self.version, '<19.00.24210'):
if options.get_value(key) != 'none' and version_compare(self.version, '<19.00.24210'):
mlog.warning('This version of MSVC does not support cpp_std arguments', fatal=False)
options = copy.copy(options)
options[key].value = 'none'
options.set_value(key, 'none')
args = super().get_option_compile_args(options)
@ -924,10 +924,10 @@ class ArmCPPCompiler(ArmCompiler, CPPCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args: T.List[str] = []
key = self.form_langopt_key('std')
std = options[key]
if std.value == 'c++11':
std = options.get_value(key)
if std == 'c++11':
args.append('--cpp11')
elif std.value == 'c++03':
elif std == 'c++03':
args.append('--cpp')
return args
@ -986,9 +986,9 @@ class TICPPCompiler(TICompiler, CPPCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args: T.List[str] = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
args.append('--' + std.value)
std = options.get_value(key)
if std != 'none':
args.append('--' + std)
return args
def get_always_args(self) -> T.List[str]:
@ -1027,10 +1027,10 @@ class MetrowerksCPPCompilerARM(MetrowerksCompiler, CPPCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args: T.List[str] = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
std = options.get_value(key)
if std != 'none':
args.append('-lang')
args.append(std.value)
args.append(std)
return args
class MetrowerksCPPCompilerEmbeddedPowerPC(MetrowerksCompiler, CPPCompiler):
@ -1056,7 +1056,7 @@ class MetrowerksCPPCompilerEmbeddedPowerPC(MetrowerksCompiler, CPPCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args: T.List[str] = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
args.append('-lang ' + std.value)
std = options.get_value(key)
if std != 'none':
args.append('-lang ' + std)
return args

View File

@ -13,7 +13,7 @@ from .. import options
from .. import mlog
from ..mesonlib import (
EnvironmentException, Popen_safe,
is_windows, LibType, version_compare,
is_windows, LibType, version_compare, OptionKey
)
from .compilers import Compiler
@ -549,7 +549,7 @@ class CudaCompiler(Compiler):
# Use the -ccbin option, if available, even during sanity checking.
# Otherwise, on systems where CUDA does not support the default compiler,
# NVCC becomes unusable.
flags += self.get_ccbin_args(env.coredata.options)
flags += self.get_ccbin_args(env.coredata.optstore)
# If cross-compiling, we can't run the sanity check, only compile it.
if env.need_exe_wrapper(self.for_machine) and not env.has_exe_wrapper():
@ -655,16 +655,17 @@ class CudaCompiler(Compiler):
''),
)
def _to_host_compiler_options(self, options: 'KeyedOptionDictType') -> 'KeyedOptionDictType':
def _to_host_compiler_options(self, master_options: 'KeyedOptionDictType') -> 'KeyedOptionDictType':
"""
Convert an NVCC Option set to a host compiler's option set.
"""
# We must strip the -std option from the host compiler option set, as NVCC has
# its own -std flag that may not agree with the host compiler's.
host_options = {key: options.get(key, opt) for key, opt in self.host_compiler.get_options().items()}
std_key = self.form_langopt_key('std')
host_options = {key: master_options.get(key, opt) for key, opt in self.host_compiler.get_options().items()}
std_key = OptionKey('std', machine=self.for_machine, lang=self.host_compiler.language)
overrides = {std_key: 'none'}
# To shut up mypy.
return coredata.OptionsView(host_options, overrides=overrides)
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
@ -674,9 +675,9 @@ class CudaCompiler(Compiler):
# and attempting to use it will result in a warning: https://stackoverflow.com/a/51272091/741027
if not is_windows():
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
args.append('--std=' + std.value)
std = options.get_value(key)
if std != 'none':
args.append('--std=' + std)
return args + self._to_host_flags(self.host_compiler.get_option_compile_args(self._to_host_compiler_options(options)))
@ -792,9 +793,9 @@ class CudaCompiler(Compiler):
def get_dependency_link_args(self, dep: 'Dependency') -> T.List[str]:
return self._to_host_flags(super().get_dependency_link_args(dep), _Phase.LINKER)
def get_ccbin_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
def get_ccbin_args(self, ccoptions: 'KeyedOptionDictType') -> T.List[str]:
key = self.form_langopt_key('ccbindir')
ccbindir = options[key].value
ccbindir = ccoptions.get_value(key)
if isinstance(ccbindir, str) and ccbindir != '':
return [self._shield_nvcc_list_arg('-ccbin='+ccbindir, False)]
else:

View File

@ -84,10 +84,10 @@ class CythonCompiler(Compiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args: T.List[str] = []
key = self.form_langopt_key('version')
version = options[key]
args.append(f'-{version.value}')
version = options.get_value(key)
args.append(f'-{version}')
key = self.form_langopt_key('language')
lang = options[key]
if lang.value == 'cpp':
lang = options.get_value(key)
if lang == 'cpp':
args.append('--cplus')
return args

View File

@ -154,9 +154,9 @@ class GnuFortranCompiler(GnuCompiler, FortranCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args: T.List[str] = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
args.append('-std=' + std.value)
std = options.get_value(key)
if std != 'none':
args.append('-std=' + std)
return args
def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
@ -291,10 +291,10 @@ class IntelFortranCompiler(IntelGnuLikeCompiler, FortranCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args: T.List[str] = []
key = self.form_langopt_key('std')
std = options[key]
std = options.get_value(key)
stds = {'legacy': 'none', 'f95': 'f95', 'f2003': 'f03', 'f2008': 'f08', 'f2018': 'f18'}
if std.value != 'none':
args.append('-stand=' + stds[std.value])
if std != 'none':
args.append('-stand=' + stds[std])
return args
def get_preprocess_only_args(self) -> T.List[str]:
@ -346,10 +346,10 @@ class IntelClFortranCompiler(IntelVisualStudioLikeCompiler, FortranCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args: T.List[str] = []
key = self.form_langopt_key('std')
std = options[key]
std = options.get_value(key)
stds = {'legacy': 'none', 'f95': 'f95', 'f2003': 'f03', 'f2008': 'f08', 'f2018': 'f18'}
if std.value != 'none':
args.append('/stand:' + stds[std.value])
if std != 'none':
args.append('/stand:' + stds[std])
return args
def get_werror_args(self) -> T.List[str]:

View File

@ -26,7 +26,7 @@ from ... import arglist
from ... import mesonlib
from ... import mlog
from ...linkers.linkers import GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker
from ...mesonlib import LibType, OptionKey
from ...mesonlib import LibType
from .. import compilers
from ..compilers import CompileCheckMode
from .visualstudio import VisualStudioLikeCompiler
@ -376,8 +376,8 @@ class CLikeCompiler(Compiler):
# linking with static libraries since MSVC won't select a CRT for
# us in that case and will error out asking us to pick one.
try:
crt_val = env.coredata.options[OptionKey('b_vscrt')].value
buildtype = env.coredata.options[OptionKey('buildtype')].value
crt_val = env.coredata.optstore.get_value('b_vscrt')
buildtype = env.coredata.optstore.get_value('buildtype')
cargs += self.get_crt_compile_args(crt_val, buildtype)
except (KeyError, AttributeError):
pass

View File

@ -84,9 +84,9 @@ class ElbrusCompiler(GnuLikeCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args: T.List[str] = []
std = options[OptionKey('std', lang=self.language, machine=self.for_machine)]
if std.value != 'none':
args.append('-std=' + std.value)
std = options.get_value(OptionKey('std', lang=self.language, machine=self.for_machine))
if std != 'none':
args.append('-std=' + std)
return args
def openmp_flags(self) -> T.List[str]:

View File

@ -51,7 +51,7 @@ class EmscriptenMixin(Compiler):
def thread_link_flags(self, env: 'Environment') -> T.List[str]:
args = ['-pthread']
count: int = env.coredata.options[OptionKey('thread_count', lang=self.language, machine=self.for_machine)].value
count: int = env.coredata.optstore.get_value(OptionKey('thread_count', lang=self.language, machine=self.for_machine))
if count:
args.append(f'-sPTHREAD_POOL_SIZE={count}')
return args

View File

@ -90,9 +90,9 @@ class ClangObjCCompiler(ClangCompiler, ObjCCompiler):
def get_option_compile_args(self, options: 'coredata.KeyedOptionDictType') -> T.List[str]:
args = []
std = options[OptionKey('std', machine=self.for_machine, lang='c')]
if std.value != 'none':
args.append('-std=' + std.value)
std = options.get_value(OptionKey('std', machine=self.for_machine, lang='c'))
if std != 'none':
args.append('-std=' + std)
return args
class AppleClangObjCCompiler(ClangObjCCompiler):

View File

@ -92,9 +92,9 @@ class ClangObjCPPCompiler(ClangCompiler, ObjCPPCompiler):
def get_option_compile_args(self, options: 'coredata.KeyedOptionDictType') -> T.List[str]:
args = []
std = options[OptionKey('std', machine=self.for_machine, lang='cpp')]
if std.value != 'none':
args.append('-std=' + std.value)
std = options.get_value(OptionKey('std', machine=self.for_machine, lang='cpp'))
if std != 'none':
args.append('-std=' + std)
return args

View File

@ -173,9 +173,9 @@ class RustCompiler(Compiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
key = self.form_langopt_key('std')
std = options[key]
if std.value != 'none':
args.append('--edition=' + std.value)
std = options.get_value(key)
if std != 'none':
args.append('--edition=' + std)
return args
def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]:

View File

@ -32,6 +32,7 @@ import typing as T
if T.TYPE_CHECKING:
from typing_extensions import Protocol
from typing import Any
from . import dependencies
from .compilers.compilers import Compiler, CompileResult, RunResult, CompileCheckMode
@ -40,6 +41,7 @@ if T.TYPE_CHECKING:
from .mesonlib import FileOrString
from .cmake.traceparser import CMakeCacheEntry
from .interpreterbase import SubProject
from .options import UserOption
class SharedCMDOptions(Protocol):
@ -58,7 +60,7 @@ if T.TYPE_CHECKING:
OptionDictType = T.Union[T.Dict[str, 'options.UserOption[T.Any]'], 'OptionsView']
MutableKeyedOptionDictType = T.Dict['OptionKey', 'options.UserOption[T.Any]']
KeyedOptionDictType = T.Union[MutableKeyedOptionDictType, 'OptionsView']
KeyedOptionDictType = T.Union['options.OptionStore', 'OptionsView']
CompilerCheckCacheKey = T.Tuple[T.Tuple[str, ...], str, FileOrString, T.Tuple[str, ...], CompileCheckMode]
# code, args
RunCheckCacheKey = T.Tuple[str, T.Tuple[str, ...]]
@ -150,8 +152,8 @@ class DependencyCache:
def __calculate_subkey(self, type_: DependencyCacheType) -> T.Tuple[str, ...]:
data: T.Dict[DependencyCacheType, T.List[str]] = {
DependencyCacheType.PKG_CONFIG: stringlistify(self.__builtins[self.__pkg_conf_key].value),
DependencyCacheType.CMAKE: stringlistify(self.__builtins[self.__cmake_key].value),
DependencyCacheType.PKG_CONFIG: stringlistify(self.__builtins.get_value(self.__pkg_conf_key)),
DependencyCacheType.CMAKE: stringlistify(self.__builtins.get_value(self.__cmake_key)),
DependencyCacheType.OTHER: [],
}
assert type_ in data, 'Someone forgot to update subkey calculations for a new type'
@ -241,7 +243,7 @@ _V = T.TypeVar('_V')
class CoreData:
def __init__(self, options: SharedCMDOptions, scratch_dir: str, meson_command: T.List[str]):
def __init__(self, cmd_options: SharedCMDOptions, scratch_dir: str, meson_command: T.List[str]):
self.lang_guids = {
'default': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942',
'c': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942',
@ -255,8 +257,8 @@ class CoreData:
self.meson_command = meson_command
self.target_guids = {}
self.version = version
self.options: 'MutableKeyedOptionDictType' = {}
self.cross_files = self.__load_config_files(options, scratch_dir, 'cross')
self.optstore = options.OptionStore()
self.cross_files = self.__load_config_files(cmd_options, scratch_dir, 'cross')
self.compilers: PerMachine[T.Dict[str, Compiler]] = PerMachine(OrderedDict(), OrderedDict())
# Stores the (name, hash) of the options file, The name will be either
@ -272,8 +274,8 @@ class CoreData:
# For host == build configurations these caches should be the same.
self.deps: PerMachine[DependencyCache] = PerMachineDefaultable.default(
self.is_cross_build(),
DependencyCache(self.options, MachineChoice.BUILD),
DependencyCache(self.options, MachineChoice.HOST))
DependencyCache(self.optstore, MachineChoice.BUILD),
DependencyCache(self.optstore, MachineChoice.HOST))
self.compiler_check_cache: T.Dict['CompilerCheckCacheKey', 'CompileResult'] = OrderedDict()
self.run_check_cache: T.Dict['RunCheckCacheKey', 'RunResult'] = OrderedDict()
@ -282,18 +284,18 @@ class CoreData:
self.cmake_cache: PerMachine[CMakeStateCache] = PerMachine(CMakeStateCache(), CMakeStateCache())
# Only to print a warning if it changes between Meson invocations.
self.config_files = self.__load_config_files(options, scratch_dir, 'native')
self.config_files = self.__load_config_files(cmd_options, scratch_dir, 'native')
self.builtin_options_libdir_cross_fixup()
self.init_builtins('')
@staticmethod
def __load_config_files(options: SharedCMDOptions, scratch_dir: str, ftype: str) -> T.List[str]:
def __load_config_files(cmd_options: SharedCMDOptions, scratch_dir: str, ftype: str) -> T.List[str]:
# Need to try and make the passed filenames absolute because when the
# files are parsed later we'll have chdir()d.
if ftype == 'cross':
filenames = options.cross_file
filenames = cmd_options.cross_file
else:
filenames = options.native_file
filenames = cmd_options.native_file
if not filenames:
return []
@ -403,10 +405,10 @@ class CoreData:
def init_builtins(self, subproject: str) -> None:
# Create builtin options with default values
for key, opt in options.BUILTIN_OPTIONS.items():
self.add_builtin_option(self.options, key.evolve(subproject=subproject), opt)
self.add_builtin_option(self.optstore, key.evolve(subproject=subproject), opt)
for for_machine in iter(MachineChoice):
for key, opt in options.BUILTIN_OPTIONS_PER_MACHINE.items():
self.add_builtin_option(self.options, key.evolve(subproject=subproject, machine=for_machine), opt)
self.add_builtin_option(self.optstore, key.evolve(subproject=subproject, machine=for_machine), opt)
@staticmethod
def add_builtin_option(opts_map: 'MutableKeyedOptionDictType', key: OptionKey,
@ -415,33 +417,33 @@ class CoreData:
if opt.yielding:
# This option is global and not per-subproject
return
value = opts_map[key.as_root()].value
value = opts_map.get_value(key.as_root())
else:
value = None
opts_map[key] = opt.init_option(key, value, options.default_prefix())
opts_map.add_system_option(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')] = options.UserIntegerOption(
self.optstore.add_system_option('backend_max_links', options.UserIntegerOption(
'backend_max_links',
'Maximum number of linker processes to run or 0 for no '
'limit',
(0, None, 0))
(0, None, 0)))
elif backend_name.startswith('vs'):
self.options[OptionKey('backend_startup_project')] = options.UserStringOption(
self.optstore.add_system_option('backend_startup_project', options.UserStringOption(
'backend_startup_project',
'Default project to execute in Visual Studio',
'')
''))
def get_option(self, key: OptionKey) -> T.Union[T.List[str], str, int, bool]:
try:
v = self.options[key].value
v = self.optstore.get_value(key)
return v
except KeyError:
pass
try:
v = self.options[key.as_root()]
v = self.optstore.get_value_object(key.as_root())
if v.yielding:
return v.value
except KeyError:
@ -455,11 +457,11 @@ class CoreData:
if key.name == 'prefix':
value = self.sanitize_prefix(value)
else:
prefix = self.options[OptionKey('prefix')].value
prefix = self.optstore.get_value('prefix')
value = self.sanitize_dir_option_value(prefix, key, value)
try:
opt = self.options[key]
opt = self.optstore.get_value_object(key)
except KeyError:
raise MesonException(f'Tried to set unknown builtin option {str(key)}')
@ -510,7 +512,7 @@ class CoreData:
def get_nondefault_buildtype_args(self) -> T.List[T.Union[T.Tuple[str, str, str], T.Tuple[str, bool, bool]]]:
result: T.List[T.Union[T.Tuple[str, str, str], T.Tuple[str, bool, bool]]] = []
value = self.options[OptionKey('buildtype')].value
value = self.optstore.get_value('buildtype')
if value == 'plain':
opt = 'plain'
debug = False
@ -529,8 +531,8 @@ class CoreData:
else:
assert value == 'custom'
return []
actual_opt = self.options[OptionKey('optimization')].value
actual_debug = self.options[OptionKey('debug')].value
actual_opt = self.optstore.get_value('optimization')
actual_debug = self.optstore.get_value('debug')
if actual_opt != opt:
result.append(('optimization', actual_opt, opt))
if actual_debug != debug:
@ -559,8 +561,8 @@ class CoreData:
assert value == 'custom'
return False
dirty |= self.options[OptionKey('optimization')].set_value(opt)
dirty |= self.options[OptionKey('debug')].set_value(debug)
dirty |= self.optstore.set_value('optimization', opt)
dirty |= self.optstore.set_value('debug', debug)
return dirty
@ -572,30 +574,32 @@ class CoreData:
def get_external_args(self, for_machine: MachineChoice, lang: str) -> T.List[str]:
# mypy cannot analyze type of OptionKey
return T.cast('T.List[str]', self.options[OptionKey('args', machine=for_machine, lang=lang)].value)
key = OptionKey('args', machine=for_machine, lang=lang)
return T.cast('T.List[str]', self.optstore.get_value(key))
def get_external_link_args(self, for_machine: MachineChoice, lang: str) -> T.List[str]:
# mypy cannot analyze type of OptionKey
return T.cast('T.List[str]', self.options[OptionKey('link_args', machine=for_machine, lang=lang)].value)
key = OptionKey('link_args', machine=for_machine, lang=lang)
return T.cast('T.List[str]', self.optstore.get_value(key))
def update_project_options(self, options: 'MutableKeyedOptionDictType', subproject: SubProject) -> None:
for key, value in options.items():
def update_project_options(self, project_options: 'MutableKeyedOptionDictType', subproject: SubProject) -> None:
for key, value in project_options.items():
if not key.is_project():
continue
if key not in self.options:
self.options[key] = value
if key not in self.optstore:
self.optstore.add_project_option(key, value)
continue
if key.subproject != subproject:
raise MesonBugException(f'Tried to set an option for subproject {key.subproject} from {subproject}!')
oldval = self.options[key]
oldval = self.optstore.get_value_object(key)
if type(oldval) is not type(value):
self.options[key] = value
self.optstore.set_value(key, value.value)
elif oldval.choices != value.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.
self.options[key] = value
self.optstore.set_value_object(key, value)
try:
value.set_value(oldval.value)
except MesonException:
@ -603,9 +607,9 @@ class CoreData:
fatal=False)
# Find any extranious keys for this project and remove them
for key in self.options.keys() - options.keys():
for key in self.optstore.keys() - project_options.keys():
if key.is_project() and key.subproject == subproject:
del self.options[key]
self.optstore.remove(key)
def is_cross_build(self, when_building_for: MachineChoice = MachineChoice.HOST) -> bool:
if when_building_for == MachineChoice.BUILD:
@ -616,13 +620,13 @@ class CoreData:
dirty = False
assert not self.is_cross_build()
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():
o = self.optstore.get_value_object(k)
dirty |= self.optstore.set_value(k.as_build(), o.value)
for bk, bv in self.optstore.items():
if bk.machine is MachineChoice.BUILD:
hk = bk.as_host()
try:
hv = self.options[hk]
hv = self.optstore.get_value_object(hk)
dirty |= bv.set_value(hv.value)
except KeyError:
continue
@ -637,16 +641,16 @@ class CoreData:
pfk = OptionKey('prefix')
if pfk in opts_to_set:
prefix = self.sanitize_prefix(opts_to_set[pfk])
dirty |= self.options[OptionKey('prefix')].set_value(prefix)
dirty |= self.optstore.set_value('prefix', 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))
dirty |= self.optstore.set_value(key, options.BUILTIN_OPTIONS[key].prefixed_default(key, prefix))
unknown_options: T.List[OptionKey] = []
for k, v in opts_to_set.items():
if k == pfk:
continue
elif k in self.options:
elif k in self.optstore:
dirty |= self.set_option(k, v, first_invocation)
elif k.machine != MachineChoice.BUILD and k.type != OptionType.COMPILER:
unknown_options.append(k)
@ -690,7 +694,7 @@ class CoreData:
# Always test this using the HOST machine, as many builtin options
# are not valid for the BUILD machine, but the yielding value does
# not differ between them even when they are valid for both.
if subproject and k.is_builtin() and self.options[k.evolve(subproject='', machine=MachineChoice.HOST)].yielding:
if subproject and k.is_builtin() and self.optstore.get_value_object(k.evolve(subproject='', machine=MachineChoice.HOST)).yielding:
continue
# Skip base, compiler, and backend options, they are handled when
# adding languages and setting backend.
@ -703,23 +707,23 @@ class CoreData:
self.set_options(options, subproject=subproject, first_invocation=env.first_invocation)
def add_compiler_options(self, options: MutableKeyedOptionDictType, lang: str, for_machine: MachineChoice,
def add_compiler_options(self, c_options: MutableKeyedOptionDictType, lang: str, for_machine: MachineChoice,
env: Environment, subproject: str) -> None:
for k, o in options.items():
for k, o in c_options.items():
value = env.options.get(k)
if value is not None:
o.set_value(value)
if not subproject:
self.options[k] = o # override compiler option on reconfigure
self.options.setdefault(k, o)
self.optstore.set_value_object(k, o) # override compiler option on reconfigure
self.optstore.setdefault(k, o)
if subproject:
sk = k.evolve(subproject=subproject)
value = env.options.get(sk) or value
if value is not None:
o.set_value(value)
self.options[sk] = o # override compiler option on reconfigure
self.options.setdefault(sk, o)
self.optstore.set_value_object(sk, o) # override compiler option on reconfigure
self.optstore.setdefault(sk, o)
def add_lang_args(self, lang: str, comp: T.Type['Compiler'],
for_machine: MachineChoice, env: 'Environment') -> None:
@ -727,8 +731,8 @@ class CoreData:
from .compilers import compilers
# These options are all new at this point, because the compiler is
# responsible for adding its own options, thus calling
# `self.options.update()`` is perfectly safe.
self.options.update(compilers.get_global_options(lang, comp, for_machine, env))
# `self.optstore.update()`` is perfectly safe.
self.optstore.update(compilers.get_global_options(lang, comp, for_machine, env))
def process_compiler_options(self, lang: str, comp: Compiler, env: Environment, subproject: str) -> None:
from . import compilers
@ -741,20 +745,20 @@ class CoreData:
skey = key.evolve(subproject=subproject)
else:
skey = key
if skey not in self.options:
self.options[skey] = copy.deepcopy(compilers.base_options[key])
if skey not in self.optstore:
self.optstore.add_system_option(skey, copy.deepcopy(compilers.base_options[key]))
if skey in env.options:
self.options[skey].set_value(env.options[skey])
self.optstore.set_value(skey, env.options[skey])
enabled_opts.append(skey)
elif subproject and key in env.options:
self.options[skey].set_value(env.options[key])
self.optstore.set_value(skey, env.options[key])
enabled_opts.append(skey)
if subproject and key not in self.options:
self.options[key] = copy.deepcopy(self.options[skey])
if subproject and key not in self.optstore:
self.optstore.add_system_option(key, copy.deepcopy(self.optstore.get_value_object(skey)))
elif skey in env.options:
self.options[skey].set_value(env.options[skey])
self.optstore.set_value(skey, env.options[skey])
elif subproject and key in env.options:
self.options[skey].set_value(env.options[key])
self.optstore.set_value(skey, env.options[key])
self.emit_base_options_warnings(enabled_opts)
def emit_base_options_warnings(self, enabled_opts: T.List[OptionKey]) -> None:
@ -894,7 +898,7 @@ class OptionsView(abc.Mapping):
# TODO: the typing here could be made more explicit using a TypeDict from
# python 3.8 or typing_extensions
original_options: KeyedOptionDictType
original_options: T.Union[KeyedOptionDictType, 'dict[OptionKey, UserOption[Any]]']
subproject: T.Optional[str] = None
overrides: T.Optional[T.Mapping[OptionKey, T.Union[str, int, bool, T.List[str]]]] = None
@ -905,7 +909,15 @@ class OptionsView(abc.Mapping):
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()]
key2 = key.as_root()
# This hack goes away once wi start using OptionStore
# to hold overrides.
if isinstance(self.original_options, options.OptionStore):
if key2 not in self.original_options:
raise KeyError
opt = self.original_options.get_value_object(key2)
else:
opt = self.original_options[key2]
else:
opt = self.original_options[key]
if opt.yielding:
@ -917,6 +929,16 @@ class OptionsView(abc.Mapping):
opt.set_value(override_value)
return opt
def get_value(self, key: T.Union[str, OptionKey]):
if isinstance(key, str):
key = OptionKey(key)
return self[key].value
def set_value(self, key: T.Union[str, OptionKey], value: T.Union[str, int, bool, T.List[str]]):
if isinstance(key, str):
key = OptionKey(key)
self.overrides[key] = value
def __iter__(self) -> T.Iterator[OptionKey]:
return iter(self.original_options)

View File

@ -580,8 +580,8 @@ class BoostDependency(SystemDependency):
# MSVC is very picky with the library tags
vscrt = ''
try:
crt_val = self.env.coredata.options[mesonlib.OptionKey('b_vscrt')].value
buildtype = self.env.coredata.options[mesonlib.OptionKey('buildtype')].value
crt_val = self.env.coredata.optstore.get_value('b_vscrt')
buildtype = self.env.coredata.optstore.get_value('buildtype')
vscrt = self.clib_compiler.get_crt_compile_args(crt_val, buildtype)[0]
except (KeyError, IndexError, AttributeError):
pass

View File

@ -238,7 +238,7 @@ class PkgConfigCLI(PkgConfigInterface):
def _get_env(self, uninstalled: bool = False) -> EnvironmentVariables:
env = EnvironmentVariables()
key = OptionKey('pkg_config_path', machine=self.for_machine)
extra_paths: T.List[str] = self.env.coredata.options[key].value[:]
extra_paths: T.List[str] = self.env.coredata.optstore.get_value(key)[:]
if uninstalled:
uninstalled_path = Path(self.env.get_build_dir(), 'meson-uninstalled').as_posix()
if uninstalled_path not in extra_paths:
@ -397,7 +397,7 @@ class PkgConfigDependency(ExternalDependency):
#
# Only prefix_libpaths are reordered here because there should not be
# too many system_libpaths to cause library version issues.
pkg_config_path: T.List[str] = self.env.coredata.options[OptionKey('pkg_config_path', machine=self.for_machine)].value
pkg_config_path: T.List[str] = self.env.coredata.optstore.get_value(OptionKey('pkg_config_path', machine=self.for_machine))
pkg_config_path = self._convert_mingw_paths(pkg_config_path)
prefix_libpaths = OrderedSet(sort_libpaths(list(prefix_libpaths), pkg_config_path))
system_libpaths: OrderedSet[str] = OrderedSet()

View File

@ -233,8 +233,8 @@ class _PythonDependencyBase(_Base):
# `debugoptimized` buildtype may not set debug=True currently, see gh-11645
is_debug_build = debug or buildtype == 'debug'
vscrt_debug = False
if mesonlib.OptionKey('b_vscrt') in self.env.coredata.options:
vscrt = self.env.coredata.options[mesonlib.OptionKey('b_vscrt')].value
if mesonlib.OptionKey('b_vscrt') in self.env.coredata.optstore:
vscrt = self.env.coredata.optstore.get_value('b_vscrt')
if vscrt in {'mdd', 'mtd', 'from_buildtype', 'static_from_buildtype'}:
vscrt_debug = True
if is_debug_build and vscrt_debug and not self.variables.get('Py_DEBUG'):

View File

@ -297,8 +297,8 @@ class QmakeQtDependency(_QtBase, ConfigToolDependency, metaclass=abc.ABCMeta):
# Use the buildtype by default, but look at the b_vscrt option if the
# compiler supports it.
is_debug = self.env.coredata.get_option(mesonlib.OptionKey('buildtype')) == 'debug'
if mesonlib.OptionKey('b_vscrt') in self.env.coredata.options:
if self.env.coredata.options[mesonlib.OptionKey('b_vscrt')].value in {'mdd', 'mtd'}:
if mesonlib.OptionKey('b_vscrt') in self.env.coredata.optstore:
if self.env.coredata.optstore.get_value('b_vscrt') in {'mdd', 'mtd'}:
is_debug = True
modules_lib_suffix = _get_modules_lib_suffix(self.version, self.env.machines[self.for_machine], is_debug)

View File

@ -520,7 +520,7 @@ class Environment:
log_dir = 'meson-logs'
info_dir = 'meson-info'
def __init__(self, source_dir: str, build_dir: str, options: coredata.SharedCMDOptions) -> None:
def __init__(self, source_dir: str, build_dir: str, cmd_options: coredata.SharedCMDOptions) -> None:
self.source_dir = source_dir
self.build_dir = build_dir
# Do not try to create build directories when build_dir is none.
@ -536,26 +536,26 @@ class Environment:
self.coredata: coredata.CoreData = coredata.load(self.get_build_dir(), suggest_reconfigure=False)
self.first_invocation = False
except FileNotFoundError:
self.create_new_coredata(options)
self.create_new_coredata(cmd_options)
except coredata.MesonVersionMismatchException as e:
# This is routine, but tell the user the update happened
mlog.log('Regenerating configuration from scratch:', str(e))
coredata.read_cmd_line_file(self.build_dir, options)
self.create_new_coredata(options)
coredata.read_cmd_line_file(self.build_dir, cmd_options)
self.create_new_coredata(cmd_options)
except MesonException as e:
# If we stored previous command line options, we can recover from
# a broken/outdated coredata.
if os.path.isfile(coredata.get_cmd_line_file(self.build_dir)):
mlog.warning('Regenerating configuration from scratch.', fatal=False)
mlog.log('Reason:', mlog.red(str(e)))
coredata.read_cmd_line_file(self.build_dir, options)
self.create_new_coredata(options)
coredata.read_cmd_line_file(self.build_dir, cmd_options)
self.create_new_coredata(cmd_options)
else:
raise MesonException(f'{str(e)} Try regenerating using "meson setup --wipe".')
else:
# Just create a fresh coredata in this case
self.scratch_dir = ''
self.create_new_coredata(options)
self.create_new_coredata(cmd_options)
## locally bind some unfrozen configuration
@ -627,7 +627,7 @@ class Environment:
self.cmakevars = cmakevars.default_missing()
# Command line options override those from cross/native files
self.options.update(options.cmd_line_options)
self.options.update(cmd_options.cmd_line_options)
# Take default value from env if not set in cross/native files or command line.
self._set_default_options_from_env()

View File

@ -270,7 +270,7 @@ class CompilerHolder(ObjectHolder['Compiler']):
for idir in i.to_string_list(self.environment.get_source_dir(), self.environment.get_build_dir()):
args.extend(self.compiler.get_include_args(idir, False))
if not kwargs['no_builtin_args']:
opts = coredata.OptionsView(self.environment.coredata.options, self.subproject)
opts = coredata.OptionsView(self.environment.coredata.optstore, self.subproject)
args += self.compiler.get_option_compile_args(opts)
if mode is CompileCheckMode.LINK:
args.extend(self.compiler.get_option_link_args(opts))

View File

@ -1013,7 +1013,7 @@ class Interpreter(InterpreterBase, HoldableObject):
kwargs: kwtypes.DoSubproject) -> SubprojectHolder:
from ..cmake import CMakeInterpreter
with mlog.nested(subp_name):
prefix = self.coredata.options[OptionKey('prefix')].value
prefix = self.coredata.optstore.get_value('prefix')
from ..modules.cmake import CMakeSubprojectOptions
options = kwargs.get('options') or CMakeSubprojectOptions()
@ -1052,7 +1052,7 @@ class Interpreter(InterpreterBase, HoldableObject):
key = OptionKey.from_string(optname).evolve(subproject=self.subproject)
if not key.is_project():
for opts in [self.coredata.options, compilers.base_options]:
for opts in [self.coredata.optstore, compilers.base_options]:
v = opts.get(key)
if v is None or v.yielding:
v = opts.get(key.as_root())
@ -1061,9 +1061,9 @@ class Interpreter(InterpreterBase, HoldableObject):
return v
try:
opt = self.coredata.options[key]
if opt.yielding and key.subproject and key.as_root() in self.coredata.options:
popt = self.coredata.options[key.as_root()]
opt = self.coredata.optstore.get_value_object(key)
if opt.yielding and key.subproject and key.as_root() in self.coredata.optstore:
popt = self.coredata.optstore.get_value_object(key.as_root())
if type(opt) is type(popt):
opt = popt
else:
@ -1543,7 +1543,7 @@ class Interpreter(InterpreterBase, HoldableObject):
if self.subproject:
options = {}
for k in comp.get_options():
v = copy.copy(self.coredata.options[k])
v = copy.copy(self.coredata.optstore.get_value_object(k))
k = k.evolve(subproject=self.subproject)
options[k] = v
self.coredata.add_compiler_options(options, lang, for_machine, self.environment, self.subproject)
@ -3041,13 +3041,13 @@ class Interpreter(InterpreterBase, HoldableObject):
break
def check_clang_asan_lundef(self) -> None:
if OptionKey('b_lundef') not in self.coredata.options:
if OptionKey('b_lundef') not in self.coredata.optstore:
return
if OptionKey('b_sanitize') not in self.coredata.options:
if OptionKey('b_sanitize') not in self.coredata.optstore:
return
if (self.coredata.options[OptionKey('b_lundef')].value and
self.coredata.options[OptionKey('b_sanitize')].value != 'none'):
value = self.coredata.options[OptionKey('b_sanitize')].value
if (self.coredata.optstore.get_value('b_lundef') and
self.coredata.optstore.get_value('b_sanitize') != 'none'):
value = self.coredata.optstore.get_value('b_sanitize')
mlog.warning(textwrap.dedent(f'''\
Trying to use {value} sanitizer on Clang with b_lundef.
This will probably not work.

View File

@ -24,7 +24,7 @@ from ..interpreterbase import (
from ..interpreter.type_checking import NoneType, ENV_KW, ENV_SEPARATOR_KW, PKGCONFIG_DEFINE_KW
from ..dependencies import Dependency, ExternalLibrary, InternalDependency
from ..programs import ExternalProgram
from ..mesonlib import HoldableObject, OptionKey, listify, Popen_safe
from ..mesonlib import HoldableObject, listify, Popen_safe
import typing as T
@ -90,7 +90,7 @@ class FeatureOptionHolder(ObjectHolder[options.UserFeatureOption]):
super().__init__(option, interpreter)
if option and option.is_auto():
# TODO: we need to cast here because options is not a TypedDict
auto = T.cast('options.UserFeatureOption', self.env.coredata.options[OptionKey('auto_features')])
auto = T.cast('options.UserFeatureOption', self.env.coredata.optstore.get_value_object('auto_features'))
self.held_object = copy.copy(auto)
self.held_object.name = option.name
self.methods.update({'enabled': self.enabled_method,

View File

@ -25,6 +25,8 @@ from .optinterpreter import OptionInterpreter
if T.TYPE_CHECKING:
from typing_extensions import Protocol
from typing import Any
from .options import UserOption
import argparse
class CMDOptions(coredata.SharedCMDOptions, Protocol):
@ -186,7 +188,7 @@ class Conf:
items = [l[i] if l[i] else ' ' * four_column[i] for i in range(4)]
mlog.log(*items)
def split_options_per_subproject(self, options: 'coredata.KeyedOptionDictType') -> T.Dict[str, 'coredata.MutableKeyedOptionDictType']:
def split_options_per_subproject(self, options: 'T.Union[dict[OptionKey, UserOption[Any]], coredata.KeyedOptionDictType]') -> T.Dict[str, 'coredata.MutableKeyedOptionDictType']:
result: T.Dict[str, 'coredata.MutableKeyedOptionDictType'] = {}
for k, o in options.items():
if k.subproject:
@ -224,16 +226,16 @@ class Conf:
self._add_line(mlog.normal_yellow(section + ':'), '', '', '')
self.print_margin = 2
def print_options(self, title: str, opts: 'coredata.KeyedOptionDictType') -> None:
def print_options(self, title: str, opts: 'T.Union[dict[OptionKey, UserOption[Any]], coredata.KeyedOptionDictType]') -> None:
if not opts:
return
if title:
self.add_title(title)
auto = T.cast('options.UserFeatureOption', self.coredata.options[OptionKey('auto_features')])
auto = T.cast('options.UserFeatureOption', self.coredata.optstore.get_value_object('auto_features'))
for k, o in sorted(opts.items()):
printable_value = o.printable_value()
root = k.as_root()
if o.yielding and k.subproject and root in self.coredata.options:
if o.yielding and k.subproject and root in self.coredata.optstore:
printable_value = '<inherited from main project>'
if isinstance(o, options.UserFeatureOption) and o.is_auto():
printable_value = auto.printable_value()
@ -264,7 +266,7 @@ class Conf:
test_options: 'coredata.MutableKeyedOptionDictType' = {}
core_options: 'coredata.MutableKeyedOptionDictType' = {}
module_options: T.Dict[str, 'coredata.MutableKeyedOptionDictType'] = collections.defaultdict(dict)
for k, v in self.coredata.options.items():
for k, v in self.coredata.optstore.items():
if k in dir_option_names:
dir_options[k] = v
elif k in test_option_names:
@ -280,17 +282,17 @@ class Conf:
host_core_options = self.split_options_per_subproject({k: v for k, v in core_options.items() if k.machine is MachineChoice.HOST})
build_core_options = self.split_options_per_subproject({k: v for k, v in core_options.items() if k.machine is MachineChoice.BUILD})
host_compiler_options = self.split_options_per_subproject({k: v for k, v in self.coredata.options.items() if k.is_compiler() and k.machine is MachineChoice.HOST})
build_compiler_options = self.split_options_per_subproject({k: v for k, v in self.coredata.options.items() if k.is_compiler() and k.machine is MachineChoice.BUILD})
project_options = self.split_options_per_subproject({k: v for k, v in self.coredata.options.items() if k.is_project()})
host_compiler_options = self.split_options_per_subproject({k: v for k, v in self.coredata.optstore.items() if k.is_compiler() and k.machine is MachineChoice.HOST})
build_compiler_options = self.split_options_per_subproject({k: v for k, v in self.coredata.optstore.items() if k.is_compiler() and k.machine is MachineChoice.BUILD})
project_options = self.split_options_per_subproject({k: v for k, v in self.coredata.optstore.items() if k.is_project()})
show_build_options = self.default_values_only or self.build.environment.is_cross_build()
self.add_section('Main project options')
self.print_options('Core options', host_core_options[''])
if show_build_options:
self.print_options('', build_core_options[''])
self.print_options('Backend options', {k: v for k, v in self.coredata.options.items() if k.is_backend()})
self.print_options('Base options', {k: v for k, v in self.coredata.options.items() if k.is_base()})
self.print_options('Backend options', {k: v for k, v in self.coredata.optstore.items() if k.is_backend()})
self.print_options('Base options', {k: v for k, v in self.coredata.optstore.items() if k.is_base()})
self.print_options('Compiler options', host_compiler_options.get('', {}))
if show_build_options:
self.print_options('', build_compiler_options.get('', {}))

View File

@ -30,6 +30,8 @@ from .mparser import FunctionNode, ArrayNode, ArgumentNode, StringNode
if T.TYPE_CHECKING:
import argparse
from typing import Any
from .options import UserOption
from .interpreter import Interpreter
from .mparser import BaseNode
@ -291,7 +293,7 @@ def list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[s
dir_options: 'cdata.MutableKeyedOptionDictType' = {}
test_options: 'cdata.MutableKeyedOptionDictType' = {}
core_options: 'cdata.MutableKeyedOptionDictType' = {}
for k, v in coredata.options.items():
for k, v in coredata.optstore.items():
if k in dir_option_names:
dir_options[k] = v
elif k in test_option_names:
@ -302,7 +304,7 @@ def list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[s
for s in subprojects:
core_options[k.evolve(subproject=s)] = v
def add_keys(opts: 'cdata.KeyedOptionDictType', section: str) -> None:
def add_keys(opts: 'T.Union[dict[OptionKey, UserOption[Any]], cdata.KeyedOptionDictType]', section: str) -> None:
for key, opt in sorted(opts.items()):
optdict = {'name': str(key), 'value': opt.value, 'section': section,
'machine': key.machine.get_lower_case_name() if coredata.is_per_machine_option(key) else 'any'}
@ -326,14 +328,14 @@ def list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[s
optlist.append(optdict)
add_keys(core_options, 'core')
add_keys({k: v for k, v in coredata.options.items() if k.is_backend()}, 'backend')
add_keys({k: v for k, v in coredata.options.items() if k.is_base()}, 'base')
add_keys({k: v for k, v in coredata.optstore.items() if k.is_backend()}, 'backend')
add_keys({k: v for k, v in coredata.optstore.items() if k.is_base()}, 'base')
add_keys(
{k: v for k, v in sorted(coredata.options.items(), key=lambda i: i[0].machine) if k.is_compiler()},
{k: v for k, v in sorted(coredata.optstore.items(), key=lambda i: i[0].machine) if k.is_compiler()},
'compiler',
)
add_keys(dir_options, 'directory')
add_keys({k: v for k, v in coredata.options.items() if k.is_project()}, 'user')
add_keys({k: v for k, v in coredata.optstore.items() if k.is_project()}, 'user')
add_keys(test_options, 'test')
return optlist

View File

@ -906,7 +906,7 @@ class GnomeModule(ExtensionModule):
if state.project_args.get(lang):
cflags += state.project_args[lang]
if mesonlib.OptionKey('b_sanitize') in compiler.base_options:
sanitize = state.environment.coredata.options[mesonlib.OptionKey('b_sanitize')].value
sanitize = state.environment.coredata.optstore.get_value('b_sanitize')
cflags += compiler.sanitizer_compile_args(sanitize)
sanitize = sanitize.split(',')
# These must be first in ldflags

View File

@ -207,7 +207,7 @@ class PythonInstallation(_ExternalProgramHolder['PythonExternalProgram']):
new_link_args = mesonlib.extract_as_list(kwargs, 'link_args')
is_debug = self.interpreter.environment.coredata.options[OptionKey('debug')].value
is_debug = self.interpreter.environment.coredata.optstore.get_value('debug')
if is_debug:
new_link_args.append(python_windows_debug_link_exception)
else:

View File

@ -231,7 +231,7 @@ class RustModule(ExtensionModule):
# bindgen always uses clang, so it's safe to hardcode -I here
clang_args.extend([f'-I{x}' for x in i.to_string_list(
state.environment.get_source_dir(), state.environment.get_build_dir())])
if are_asserts_disabled(state.environment.coredata.options):
if are_asserts_disabled(state.environment.coredata.optstore):
clang_args.append('-DNDEBUG')
for de in kwargs['dependencies']:

View File

@ -273,9 +273,9 @@ class MesonApp:
# collect warnings about unsupported build configurations; must be done after full arg processing
# by Interpreter() init, but this is most visible at the end
if env.coredata.options[mesonlib.OptionKey('backend')].value == 'xcode':
if env.coredata.optstore.get_value('backend') == 'xcode':
mlog.warning('xcode backend is currently unmaintained, patches welcome')
if env.coredata.options[mesonlib.OptionKey('layout')].value == 'flat':
if env.coredata.optstore.get_value('layout') == 'flat':
mlog.warning('-Dlayout=flat is unsupported and probably broken. It was a failed experiment at '
'making Windows build artifacts runnable while uninstalled, due to PATH considerations, '
'but was untested by CI and anyways breaks reasonable use of conflicting targets in different subdirs. '

View File

@ -25,6 +25,7 @@ from .mesonlib import (
from . import mlog
import typing as T
from typing import ItemsView
DEFAULT_YIELDING = False
@ -473,8 +474,65 @@ BUILTIN_DIR_NOPREFIX_OPTIONS: T.Dict[OptionKey, T.Dict[str, str]] = {
OptionKey('purelibdir', module='python'): {},
}
class OptionStore:
def __init__(self):
# This class will hold all options for a given build directory
self.dummy = None
self.d: T.Dict['OptionKey', 'UserOption[T.Any]'] = {}
def __len__(self):
return len(self.d)
def ensure_key(self, key: T.Union[OptionKey, str]) -> OptionKey:
if isinstance(key, str):
return OptionKey(key)
return key
def get_value_object(self, key: T.Union[OptionKey, str]) -> 'UserOption[T.Any]':
return self.d[self.ensure_key(key)]
def get_value(self, key: T.Union[OptionKey, str]) -> 'T.Any':
return self.get_value_object(key).value
def add_system_option(self, key: T.Union[OptionKey, str], valobj: 'UserOption[T.Any]'):
key = self.ensure_key(key)
self.d[key] = valobj
def add_project_option(self, key: T.Union[OptionKey, str], valobj: 'UserOption[T.Any]'):
key = self.ensure_key(key)
self.d[key] = valobj
def set_value(self, key: T.Union[OptionKey, str], new_value: 'T.Any') -> bool:
key = self.ensure_key(key)
return self.d[key].set_value(new_value)
# FIXME, this should be removed.or renamed to "change_type_of_existing_object" or something like that
def set_value_object(self, key: T.Union[OptionKey, str], new_object: 'UserOption[T.Any]') -> bool:
key = self.ensure_key(key)
self.d[key] = new_object
def remove(self, key):
del self.d[key]
def __contains__(self, key):
key = self.ensure_key(key)
return key in self.d
def __repr__(self):
return repr(self.d)
def keys(self):
return self.d.keys()
def values(self):
return self.d.values()
def items(self) -> ItemsView['OptionKey', 'UserOption[T.Any]']:
return self.d.items()
def update(self, *args, **kwargs):
return self.d.update(*args, **kwargs)
def setdefault(self, k, o):
return self.d.setdefault(k, o)
def get(self, *args, **kwargs) -> UserOption:
return self.d.get(*args, **kwargs)

View File

@ -470,11 +470,11 @@ class Rewriter:
cdata = self.interpreter.coredata
options = {
**{str(k): v for k, v in cdata.options.items()},
**{str(k): v for k, v in cdata.options.items()},
**{str(k): v for k, v in cdata.options.items()},
**{str(k): v for k, v in cdata.options.items()},
**{str(k): v for k, v in cdata.options.items()},
**{str(k): v for k, v in cdata.optstore.items()},
**{str(k): v for k, v in cdata.optstore.items()},
**{str(k): v for k, v in cdata.optstore.items()},
**{str(k): v for k, v in cdata.optstore.items()},
**{str(k): v for k, v in cdata.optstore.items()},
}
for key, val in sorted(cmd['options'].items()):

View File

@ -151,7 +151,7 @@ def get_fake_env(sdir='', bdir=None, prefix='', opts=None):
if opts is None:
opts = get_fake_options(prefix)
env = Environment(sdir, bdir, opts)
env.coredata.options[OptionKey('args', lang='c')] = FakeCompilerOptions()
env.coredata.optstore.set_value_object(OptionKey('args', lang='c'), FakeCompilerOptions())
env.machines.host.cpu_family = 'x86_64' # Used on macOS inside find_library
# Invalidate cache when using a different Environment object.
clear_meson_configure_class_caches()

View File

@ -2621,35 +2621,35 @@ class AllPlatformTests(BasePlatformTests):
out = self.init(testdir, extra_args=['--profile-self', '--fatal-meson-warnings'])
self.assertNotIn('[default: true]', out)
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('default_library')].value, 'static')
self.assertEqual(obj.options[OptionKey('warning_level')].value, '1')
self.assertEqual(obj.options[OptionKey('set_sub_opt')].value, True)
self.assertEqual(obj.options[OptionKey('subp_opt', 'subp')].value, 'default3')
self.assertEqual(obj.optstore.get_value('default_library'), 'static')
self.assertEqual(obj.optstore.get_value('warning_level'), '1')
self.assertEqual(obj.optstore.get_value('set_sub_opt'), True)
self.assertEqual(obj.optstore.get_value(OptionKey('subp_opt', 'subp')), 'default3')
self.wipe()
# warning_level is special, it's --warnlevel instead of --warning-level
# for historical reasons
self.init(testdir, extra_args=['--warnlevel=2', '--fatal-meson-warnings'])
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('warning_level')].value, '2')
self.assertEqual(obj.optstore.get_value('warning_level'), '2')
self.setconf('--warnlevel=3')
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('warning_level')].value, '3')
self.assertEqual(obj.optstore.get_value('warning_level'), '3')
self.setconf('--warnlevel=everything')
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('warning_level')].value, 'everything')
self.assertEqual(obj.optstore.get_value('warning_level'), 'everything')
self.wipe()
# But when using -D syntax, it should be 'warning_level'
self.init(testdir, extra_args=['-Dwarning_level=2', '--fatal-meson-warnings'])
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('warning_level')].value, '2')
self.assertEqual(obj.optstore.get_value('warning_level'), '2')
self.setconf('-Dwarning_level=3')
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('warning_level')].value, '3')
self.assertEqual(obj.optstore.get_value('warning_level'), '3')
self.setconf('-Dwarning_level=everything')
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('warning_level')].value, 'everything')
self.assertEqual(obj.optstore.get_value('warning_level'), 'everything')
self.wipe()
# Mixing --option and -Doption is forbidden
@ -2673,15 +2673,15 @@ class AllPlatformTests(BasePlatformTests):
# --default-library should override default value from project()
self.init(testdir, extra_args=['--default-library=both', '--fatal-meson-warnings'])
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('default_library')].value, 'both')
self.assertEqual(obj.optstore.get_value('default_library'), 'both')
self.setconf('--default-library=shared')
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('default_library')].value, 'shared')
self.assertEqual(obj.optstore.get_value('default_library'), 'shared')
if self.backend is Backend.ninja:
# reconfigure target works only with ninja backend
self.build('reconfigure')
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('default_library')].value, 'shared')
self.assertEqual(obj.optstore.get_value('default_library'), 'shared')
self.wipe()
# Should fail on unknown options
@ -2718,22 +2718,22 @@ class AllPlatformTests(BasePlatformTests):
# Test we can set subproject option
self.init(testdir, extra_args=['-Dsubp:subp_opt=foo', '--fatal-meson-warnings'])
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('subp_opt', 'subp')].value, 'foo')
self.assertEqual(obj.optstore.get_value(OptionKey('subp_opt', 'subp')), 'foo')
self.wipe()
# c_args value should be parsed with split_args
self.init(testdir, extra_args=['-Dc_args=-Dfoo -Dbar "-Dthird=one two"', '--fatal-meson-warnings'])
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('args', lang='c')].value, ['-Dfoo', '-Dbar', '-Dthird=one two'])
self.assertEqual(obj.optstore.get_value(OptionKey('args', lang='c')), ['-Dfoo', '-Dbar', '-Dthird=one two'])
self.setconf('-Dc_args="foo bar" one two')
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('args', lang='c')].value, ['foo bar', 'one', 'two'])
self.assertEqual(obj.optstore.get_value(OptionKey('args', lang='c')), ['foo bar', 'one', 'two'])
self.wipe()
self.init(testdir, extra_args=['-Dset_percent_opt=myoption%', '--fatal-meson-warnings'])
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('set_percent_opt')].value, 'myoption%')
self.assertEqual(obj.optstore.get_value('set_percent_opt'), 'myoption%')
self.wipe()
# Setting a 2nd time the same option should override the first value
@ -2744,19 +2744,19 @@ class AllPlatformTests(BasePlatformTests):
'-Dc_args=-Dfoo', '-Dc_args=-Dbar',
'-Db_lundef=false', '--fatal-meson-warnings'])
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('bindir')].value, 'bar')
self.assertEqual(obj.options[OptionKey('buildtype')].value, 'release')
self.assertEqual(obj.options[OptionKey('b_sanitize')].value, 'thread')
self.assertEqual(obj.options[OptionKey('args', lang='c')].value, ['-Dbar'])
self.assertEqual(obj.optstore.get_value('bindir'), 'bar')
self.assertEqual(obj.optstore.get_value('buildtype'), 'release')
self.assertEqual(obj.optstore.get_value('b_sanitize'), 'thread')
self.assertEqual(obj.optstore.get_value(OptionKey('args', lang='c')), ['-Dbar'])
self.setconf(['--bindir=bar', '--bindir=foo',
'-Dbuildtype=release', '-Dbuildtype=plain',
'-Db_sanitize=thread', '-Db_sanitize=address',
'-Dc_args=-Dbar', '-Dc_args=-Dfoo'])
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('bindir')].value, 'foo')
self.assertEqual(obj.options[OptionKey('buildtype')].value, 'plain')
self.assertEqual(obj.options[OptionKey('b_sanitize')].value, 'address')
self.assertEqual(obj.options[OptionKey('args', lang='c')].value, ['-Dfoo'])
self.assertEqual(obj.optstore.get_value('bindir'), 'foo')
self.assertEqual(obj.optstore.get_value('buildtype'), 'plain')
self.assertEqual(obj.optstore.get_value('b_sanitize'), 'address')
self.assertEqual(obj.optstore.get_value(OptionKey('args', lang='c')), ['-Dfoo'])
self.wipe()
except KeyError:
# Ignore KeyError, it happens on CI for compilers that does not
@ -2770,25 +2770,25 @@ class AllPlatformTests(BasePlatformTests):
# Verify default values when passing no args
self.init(testdir)
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('warning_level')].value, '0')
self.assertEqual(obj.optstore.get_value('warning_level'), '0')
self.wipe()
# verify we can override w/ --warnlevel
self.init(testdir, extra_args=['--warnlevel=1'])
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('warning_level')].value, '1')
self.assertEqual(obj.optstore.get_value('warning_level'), '1')
self.setconf('--warnlevel=0')
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('warning_level')].value, '0')
self.assertEqual(obj.optstore.get_value('warning_level'), '0')
self.wipe()
# verify we can override w/ -Dwarning_level
self.init(testdir, extra_args=['-Dwarning_level=1'])
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('warning_level')].value, '1')
self.assertEqual(obj.optstore.get_value('warning_level'), '1')
self.setconf('-Dwarning_level=0')
obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.options[OptionKey('warning_level')].value, '0')
self.assertEqual(obj.optstore.get_value('warning_level'), '0')
self.wipe()
def test_feature_check_usage_subprojects(self):

View File

@ -163,9 +163,9 @@ class DataTests(unittest.TestCase):
else:
raise RuntimeError(f'Invalid debug value {debug!r} in row:\n{m.group()}')
env.coredata.set_option(OptionKey('buildtype'), buildtype)
self.assertEqual(env.coredata.options[OptionKey('buildtype')].value, buildtype)
self.assertEqual(env.coredata.options[OptionKey('optimization')].value, opt)
self.assertEqual(env.coredata.options[OptionKey('debug')].value, debug)
self.assertEqual(env.coredata.optstore.get_value('buildtype'), buildtype)
self.assertEqual(env.coredata.optstore.get_value('optimization'), opt)
self.assertEqual(env.coredata.optstore.get_value('debug'), debug)
def test_cpu_families_documented(self):
with open("docs/markdown/Reference-tables.md", encoding='utf-8') as f:

View File

@ -625,7 +625,7 @@ class InternalTests(unittest.TestCase):
env = get_fake_env()
compiler = detect_c_compiler(env, MachineChoice.HOST)
env.coredata.compilers.host = {'c': compiler}
env.coredata.options[OptionKey('link_args', lang='c')] = FakeCompilerOptions()
env.coredata.optstore.set_value_object(OptionKey('link_args', lang='c'), FakeCompilerOptions())
p1 = Path(tmpdir) / '1'
p2 = Path(tmpdir) / '2'
p1.mkdir()

View File

@ -1124,7 +1124,7 @@ class LinuxlikeTests(BasePlatformTests):
# option, adding the meson-uninstalled directory to it.
PkgConfigInterface.setup_env({}, env, MachineChoice.HOST, uninstalled=True)
pkg_config_path = env.coredata.options[OptionKey('pkg_config_path')].value
pkg_config_path = env.coredata.optstore.get_value('pkg_config_path')
self.assertEqual(pkg_config_path, [pkg_dir])
@skipIfNoPkgconfig