aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2020-12-04 16:09:10 -0800
committerDylan Baker <dylan@pnwbakers.com>2021-01-04 12:20:40 -0800
commit71db6b04a31707674ad776be1cf22f667056d56b (patch)
treeb62c0721557766ddc2034e740960d00a37cd9991
parentf9b19e73a5b87a2f3c8506cf19cfd5bbc468e938 (diff)
downloadmeson-71db6b04a31707674ad776be1cf22f667056d56b.zip
meson-71db6b04a31707674ad776be1cf22f667056d56b.tar.gz
meson-71db6b04a31707674ad776be1cf22f667056d56b.tar.bz2
use OptionKey for builtin and base options
I would have prefered to do these seperatately, but they are combined in some cases, so it was much easier to convert them together. this eliminates the builtins_per_machine dict, as it's duplicated with the OptionKey's machine parameter.
-rw-r--r--mesonbuild/backend/backends.py29
-rw-r--r--mesonbuild/backend/ninjabackend.py39
-rw-r--r--mesonbuild/backend/vs2010backend.py8
-rw-r--r--mesonbuild/build.py35
-rw-r--r--mesonbuild/cmake/executor.py4
-rw-r--r--mesonbuild/cmake/interpreter.py2
-rw-r--r--mesonbuild/compilers/compilers.py106
-rw-r--r--mesonbuild/compilers/cpp.py2
-rw-r--r--mesonbuild/compilers/d.py12
-rw-r--r--mesonbuild/compilers/mixins/arm.py7
-rw-r--r--mesonbuild/compilers/mixins/clang.py7
-rw-r--r--mesonbuild/compilers/mixins/clike.py7
-rw-r--r--mesonbuild/compilers/mixins/elbrus.py6
-rw-r--r--mesonbuild/compilers/mixins/emscripten.py2
-rw-r--r--mesonbuild/compilers/mixins/gnu.py14
-rw-r--r--mesonbuild/compilers/mixins/intel.py5
-rw-r--r--mesonbuild/compilers/mixins/pgi.py3
-rw-r--r--mesonbuild/compilers/mixins/visualstudio.py2
-rw-r--r--mesonbuild/compilers/rust.py4
-rw-r--r--mesonbuild/compilers/vala.py4
-rw-r--r--mesonbuild/coredata.py244
-rw-r--r--mesonbuild/dependencies/base.py11
-rw-r--r--mesonbuild/dependencies/boost.py4
-rw-r--r--mesonbuild/dependencies/ui.py4
-rw-r--r--mesonbuild/interpreter.py43
-rw-r--r--mesonbuild/mconf.py60
-rw-r--r--mesonbuild/mesonlib.py78
-rw-r--r--mesonbuild/mintro.py38
-rw-r--r--mesonbuild/modules/gnome.py14
-rw-r--r--mesonbuild/msetup.py2
-rw-r--r--mesonbuild/rewriter.py6
-rwxr-xr-xrun_unittests.py73
32 files changed, 444 insertions, 431 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 4c35253..b6d084f 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -32,7 +32,7 @@ from .. import mlog
from ..compilers import languages_using_ldflags
from ..mesonlib import (
File, MachineChoice, MesonException, OrderedSet, OptionOverrideProxy,
- classify_unity_sources, unholder
+ classify_unity_sources, unholder, OptionKey
)
if T.TYPE_CHECKING:
@@ -211,21 +211,21 @@ class Backend:
def get_target_filename_abs(self, target):
return os.path.join(self.environment.get_build_dir(), self.get_target_filename(target))
- def get_base_options_for_target(self, target):
+ def get_base_options_for_target(self, target: build.BuildTarget) -> OptionOverrideProxy:
return OptionOverrideProxy(target.option_overrides_base,
self.environment.coredata.builtins,
- self.environment.coredata.base_options)
+ {k: v for k, v in self.environment.coredata.base_options.items()})
def get_compiler_options_for_target(self, target: build.BuildTarget) -> OptionOverrideProxy:
comp_reg = self.environment.coredata.compiler_options
comp_override = target.option_overrides_compiler
return OptionOverrideProxy(comp_override, comp_reg)
- def get_option_for_target(self, option_name, target):
+ def get_option_for_target(self, option_name: 'OptionKey', target: build.BuildTarget):
if option_name in target.option_overrides_base:
override = target.option_overrides_base[option_name]
return self.environment.coredata.validate_option_value(option_name, override)
- return self.environment.coredata.get_builtin_option(option_name, target.subproject)
+ return self.environment.coredata.get_builtin_option(str(option_name), target.subproject)
def get_target_filename_for_linking(self, target):
# On some platforms (msvc for instance), the file that is used for
@@ -299,7 +299,7 @@ class Backend:
abs_files = []
result = []
compsrcs = classify_unity_sources(target.compilers.values(), unity_src)
- unity_size = self.get_option_for_target('unity_size', target)
+ unity_size = self.get_option_for_target(OptionKey('unity_size'), target)
def init_language_file(suffix, unity_file_number):
unity_src = self.get_unity_source_file(target, suffix, unity_file_number)
@@ -620,7 +620,8 @@ class Backend:
if self.is_unity(extobj.target):
compsrcs = classify_unity_sources(extobj.target.compilers.values(), sources)
sources = []
- unity_size = self.get_option_for_target('unity_size', extobj.target)
+ unity_size = self.get_option_for_target(OptionKey('unity_size'), extobj.target)
+
for comp, srcs in compsrcs.items():
for i in range(len(srcs) // unity_size + 1):
osrc = self.get_unity_source_file(extobj.target,
@@ -689,20 +690,20 @@ class Backend:
if no_warn_args:
commands += compiler.get_no_warn_args()
else:
- commands += compiler.get_warn_args(self.get_option_for_target('warning_level', target))
+ commands += compiler.get_warn_args(self.get_option_for_target(OptionKey('warning_level'), target))
# Add -Werror if werror=true is set in the build options set on the
# command-line or default_options inside project(). This only sets the
# action to be done for warnings if/when they are emitted, so it's ok
# to set it after get_no_warn_args() or get_warn_args().
- if self.get_option_for_target('werror', target):
+ if self.get_option_for_target(OptionKey('werror'), target):
commands += compiler.get_werror_args()
# Add compile args for c_* or cpp_* build options set on the
# command-line or default_options inside project().
commands += compiler.get_option_compile_args(copt_proxy)
# Add buildtype args: optimization level, debugging, etc.
- commands += compiler.get_buildtype_args(self.get_option_for_target('buildtype', target))
- commands += compiler.get_optimization_args(self.get_option_for_target('optimization', target))
- commands += compiler.get_debug_args(self.get_option_for_target('debug', target))
+ commands += compiler.get_buildtype_args(self.get_option_for_target(OptionKey('buildtype'), target))
+ commands += compiler.get_optimization_args(self.get_option_for_target(OptionKey('optimization'), target))
+ commands += compiler.get_debug_args(self.get_option_for_target(OptionKey('debug'), target))
# MSVC debug builds have /ZI argument by default and /Zi is added with debug flag
# /ZI needs to be removed in that case to avoid cl's warning to that effect (D9025 : overriding '/ZI' with '/Zi')
if ('/ZI' in commands) and ('/Zi' in commands):
@@ -1021,7 +1022,7 @@ class Backend:
return libs
def is_unity(self, target):
- optval = self.get_option_for_target('unity', target)
+ optval = self.get_option_for_target(OptionKey('unity'), target)
if optval == 'on' or (optval == 'subprojects' and target.subproject != ''):
return True
return False
@@ -1227,7 +1228,7 @@ class Backend:
#
# TODO: Create GNUStrip/AppleStrip/etc. hierarchy for more
# fine-grained stripping of static archives.
- should_strip = not isinstance(t, build.StaticLibrary) and self.get_option_for_target('strip', t)
+ should_strip = not isinstance(t, build.StaticLibrary) and self.get_option_for_target(OptionKey('strip'), t)
# Install primary build output (library/executable/jar, etc)
# Done separately because of strip/aliases/rpath
if outdirs[0] is not False:
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index a4cdefd..4bc76ab 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -537,8 +537,9 @@ int dummy;
self.add_build_comment(NinjaComment('Install rules'))
self.generate_install()
self.generate_dist()
- if 'b_coverage' in self.environment.coredata.base_options and \
- self.environment.coredata.base_options['b_coverage'].value:
+ key = OptionKey('b_coverage')
+ if (key in self.environment.coredata.base_options and
+ self.environment.coredata.base_options[key].value):
self.add_build_comment(NinjaComment('Coverage rules'))
self.generate_coverage_rules()
self.add_build_comment(NinjaComment('Suffix'))
@@ -814,7 +815,7 @@ int dummy;
source2object[s] = o
obj_list.append(o)
- use_pch = self.environment.coredata.base_options.get('b_pch', False)
+ use_pch = self.environment.coredata.base_options.get(OptionKey('b_pch'))
if use_pch and target.has_pch():
pch_objects = self.generate_pch(target, header_deps=header_deps)
else:
@@ -1297,8 +1298,8 @@ int dummy;
args.append(a)
return args, deps
- def generate_cs_target(self, target):
- buildtype = self.get_option_for_target('buildtype', target)
+ def generate_cs_target(self, target: build.BuildTarget):
+ buildtype = self.get_option_for_target(OptionKey('buildtype'), target)
fname = target.get_filename()
outname_rel = os.path.join(self.get_target_dir(target), fname)
src_list = target.get_sources()
@@ -1307,8 +1308,8 @@ int dummy;
deps = []
commands = compiler.compiler_args(target.extra_args.get('cs', []))
commands += compiler.get_buildtype_args(buildtype)
- commands += compiler.get_optimization_args(self.get_option_for_target('optimization', target))
- commands += compiler.get_debug_args(self.get_option_for_target('debug', target))
+ commands += compiler.get_optimization_args(self.get_option_for_target(OptionKey('optimization'), target))
+ commands += compiler.get_debug_args(self.get_option_for_target(OptionKey('debug'), target))
if isinstance(target, build.Executable):
commands.append('-target:exe')
elif isinstance(target, build.SharedLibrary):
@@ -1349,7 +1350,7 @@ int dummy;
def determine_single_java_compile_args(self, target, compiler):
args = []
- args += compiler.get_buildtype_args(self.get_option_for_target('buildtype', target))
+ args += compiler.get_buildtype_args(self.get_option_for_target(OptionKey('buildtype'), target))
args += self.build.get_global_args(compiler, target.for_machine)
args += self.build.get_project_args(compiler, target.subproject, target.for_machine)
args += target.get_java_args()
@@ -1512,7 +1513,7 @@ int dummy;
valac_outputs.append(vala_c_file)
args = self.generate_basic_compiler_args(target, valac)
- args += valac.get_colorout_args(self.environment.coredata.base_options.get('b_colorout').value)
+ args += valac.get_colorout_args(self.environment.coredata.base_options.get(OptionKey('b_colorout')).value)
# Tell Valac to output everything in our private directory. Sadly this
# means it will also preserve the directory components of Vala sources
# found inside the build tree (generated sources).
@@ -1619,9 +1620,9 @@ int dummy;
opt_proxy = self.get_compiler_options_for_target(target)
args += ['--crate-name', target.name]
- args += rustc.get_buildtype_args(self.get_option_for_target('buildtype', target))
- args += rustc.get_debug_args(self.get_option_for_target('debug', target))
- args += rustc.get_optimization_args(self.get_option_for_target('optimization', target))
+ args += rustc.get_buildtype_args(self.get_option_for_target(OptionKey('buildtype'), target))
+ args += rustc.get_debug_args(self.get_option_for_target(OptionKey('debug'), target))
+ args += rustc.get_optimization_args(self.get_option_for_target(OptionKey('optimization'), target))
args += rustc.get_option_compile_args(opt_proxy)
args += self.build.get_global_args(rustc, target.for_machine)
args += self.build.get_project_args(rustc, target.subproject, target.for_machine)
@@ -1772,8 +1773,8 @@ int dummy;
raise InvalidArguments('Swift target {} contains a non-swift source file.'.format(target.get_basename()))
os.makedirs(self.get_target_private_dir_abs(target), exist_ok=True)
compile_args = swiftc.get_compile_only_args()
- compile_args += swiftc.get_optimization_args(self.get_option_for_target('optimization', target))
- compile_args += swiftc.get_debug_args(self.get_option_for_target('debug', target))
+ compile_args += swiftc.get_optimization_args(self.get_option_for_target(OptionKey('optimization'), target))
+ compile_args += swiftc.get_debug_args(self.get_option_for_target(OptionKey('debug'), target))
compile_args += swiftc.get_module_args(module_name)
compile_args += self.build.get_project_args(swiftc, target.subproject, target.for_machine)
compile_args += self.build.get_global_args(swiftc, target.for_machine)
@@ -2498,7 +2499,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
commands += self.get_compile_debugfile_args(compiler, target, rel_obj)
# PCH handling
- if self.environment.coredata.base_options.get('b_pch', False):
+ if self.environment.coredata.base_options.get(OptionKey('b_pch')):
commands += self.get_pch_include_args(compiler, target)
pchlist = target.get_pch(compiler.language)
else:
@@ -2869,9 +2870,9 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
# Add things like /NOLOGO; usually can't be overridden
commands += linker.get_linker_always_args()
# Add buildtype linker args: optimization level, etc.
- commands += linker.get_buildtype_linker_args(self.get_option_for_target('buildtype', target))
+ commands += linker.get_buildtype_linker_args(self.get_option_for_target(OptionKey('buildtype'), target))
# Add /DEBUG and the pdb filename when using MSVC
- if self.get_option_for_target('debug', target):
+ if self.get_option_for_target(OptionKey('debug'), target):
commands += self.get_link_debugfile_args(linker, target, outname)
debugfile = self.get_link_debugfile_name(linker, target, outname)
if debugfile is not None:
@@ -3155,8 +3156,8 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
if ctlist:
elem.add_dep(self.generate_custom_target_clean(ctlist))
- if 'b_coverage' in self.environment.coredata.base_options and \
- self.environment.coredata.base_options['b_coverage'].value:
+ if OptionKey('b_coverage') in self.environment.coredata.base_options and \
+ self.environment.coredata.base_options[OptionKey('b_coverage')].value:
self.generate_gcov_clean()
elem.add_dep('clean-gcda')
elem.add_dep('clean-gcno')
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index 8af83e6..ed84828 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -785,7 +785,7 @@ class Vs2010Backend(backends.Backend):
build_args += compiler.get_optimization_args(self.optimization)
build_args += compiler.get_debug_args(self.debug)
buildtype_link_args = compiler.get_buildtype_linker_args(self.buildtype)
- vscrt_type = self.environment.coredata.base_options['b_vscrt']
+ vscrt_type = self.environment.coredata.base_options[OptionKey('b_vscrt')]
project_name = target.name
target_name = target.name
root = ET.Element('Project', {'DefaultTargets': "Build",
@@ -1048,9 +1048,9 @@ class Vs2010Backend(backends.Backend):
ET.SubElement(clconf, 'PreprocessorDefinitions').text = ';'.join(target_defines)
ET.SubElement(clconf, 'FunctionLevelLinking').text = 'true'
# Warning level
- warning_level = self.get_option_for_target('warning_level', target)
+ warning_level = self.get_option_for_target(OptionKey('warning_level'), target)
ET.SubElement(clconf, 'WarningLevel').text = 'Level' + str(1 + int(warning_level))
- if self.get_option_for_target('werror', target):
+ if self.get_option_for_target(OptionKey('werror'), target):
ET.SubElement(clconf, 'TreatWarningAsError').text = 'true'
# Optimization flags
o_flags = split_o_flags_args(build_args)
@@ -1075,7 +1075,7 @@ class Vs2010Backend(backends.Backend):
ET.SubElement(clconf, 'FavorSizeOrSpeed').text = 'Speed'
# Note: SuppressStartupBanner is /NOLOGO and is 'true' by default
pch_sources = {}
- if self.environment.coredata.base_options.get('b_pch', False):
+ if self.environment.coredata.base_options.get(OptionKey('b_pch')):
for lang in ['c', 'cpp']:
pch = target.get_pch(lang)
if not pch:
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index d61ca73..2916976 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -404,7 +404,7 @@ class EnvironmentVariables:
return env
class Target:
- def __init__(self, name, subdir, subproject, build_by_default, for_machine: MachineChoice):
+ def __init__(self, name, subdir, subproject, build_by_default: bool, for_machine: MachineChoice):
if has_path_sep(name):
# Fix failing test 53 when this becomes an error.
mlog.warning('''Target "{}" has a path separator in its name.
@@ -417,7 +417,7 @@ a hard error in the future.'''.format(name))
self.for_machine = for_machine
self.install = False
self.build_always_stale = False
- self.option_overrides_base: 'OptionDictType' = {}
+ self.option_overrides_base: T.Dict[OptionKey, str] = {}
self.option_overrides_compiler: 'KeyedOptionDictType' = {}
self.extra_files = [] # type: T.List[File]
if not hasattr(self, 'typename'):
@@ -499,7 +499,7 @@ a hard error in the future.'''.format(name))
return self.construct_id_from_path(
self.subdir, self.name, self.type_suffix())
- def process_kwargs_base(self, kwargs):
+ def process_kwargs_base(self, kwargs: T.Dict[str, T.Any]) -> None:
if 'build_by_default' in kwargs:
self.build_by_default = kwargs['build_by_default']
if not isinstance(self.build_by_default, bool):
@@ -512,23 +512,22 @@ a hard error in the future.'''.format(name))
option_overrides = self.parse_overrides(kwargs)
for k, v in option_overrides.items():
- if '_' in k:
- key = OptionKey.from_string(k)
- if key.lang:
- self.option_overrides_compiler[key.evolve(machine=self.for_machine)] = v
- continue
+ if k.lang:
+ self.option_overrides_compiler[k.evolve(machine=self.for_machine)] = v
+ continue
self.option_overrides_base[k] = v
- def parse_overrides(self, kwargs) -> dict:
- result = {}
+ @staticmethod
+ def parse_overrides(kwargs: T.Dict[str, T.Any]) -> T.Dict[OptionKey, str]:
+ result: T.Dict[OptionKey, str] = {}
overrides = stringlistify(kwargs.get('override_options', []))
for o in overrides:
if '=' not in o:
raise InvalidArguments('Overrides must be of form "key=value"')
k, v = o.split('=', 1)
- k = k.strip()
+ key = OptionKey.from_string(k.strip())
v = v.strip()
- result[k] = v
+ result[key] = v
return result
def is_linkable_target(self) -> bool:
@@ -1066,17 +1065,18 @@ This will become a hard error in a future Meson release.''')
raise InvalidArguments('Invalid value for win_subsystem: {}.'.format(value))
return value
- def _extract_pic_pie(self, kwargs, arg, environment, option):
+ def _extract_pic_pie(self, kwargs, arg: str, environment, option: str):
# Check if we have -fPIC, -fpic, -fPIE, or -fpie in cflags
all_flags = self.extra_args['c'] + self.extra_args['cpp']
if '-f' + arg.lower() in all_flags or '-f' + arg.upper() in all_flags:
mlog.warning("Use the '{}' kwarg instead of passing '{}' manually to {!r}".format(arg, '-f' + arg, self.name))
return True
+ k = OptionKey(option)
if arg in kwargs:
val = kwargs[arg]
- elif option in environment.coredata.base_options:
- val = environment.coredata.base_options[option].value
+ elif k in environment.coredata.base_options:
+ val = environment.coredata.base_options[k].value
else:
val = False
@@ -1597,8 +1597,9 @@ class Executable(BuildTarget):
def __init__(self, name: str, subdir: str, subproject: str, for_machine: MachineChoice,
sources: T.List[File], objects, environment: environment.Environment, kwargs):
self.typename = 'executable'
- if 'pie' not in kwargs and 'b_pie' in environment.coredata.base_options:
- kwargs['pie'] = environment.coredata.base_options['b_pie'].value
+ key = OptionKey('b_pie')
+ if 'pie' not in kwargs and key in environment.coredata.base_options:
+ kwargs['pie'] = environment.coredata.base_options[key].value
super().__init__(name, subdir, subproject, for_machine, sources, objects, environment, kwargs)
# Unless overridden, executables have no suffix or prefix. Except on
# Windows and with C#/Mono executables where the suffix is 'exe'
diff --git a/mesonbuild/cmake/executor.py b/mesonbuild/cmake/executor.py
index 19971e3..21dfd356 100644
--- a/mesonbuild/cmake/executor.py
+++ b/mesonbuild/cmake/executor.py
@@ -23,7 +23,7 @@ import re
import os
from .. import mlog
-from ..mesonlib import PerMachine, Popen_safe, version_compare, MachineChoice, is_windows
+from ..mesonlib import PerMachine, Popen_safe, version_compare, MachineChoice, is_windows, OptionKey
from ..envconfig import get_env_var
if T.TYPE_CHECKING:
@@ -62,7 +62,7 @@ class CMakeExecutor:
self.cmakebin = None
return
- self.prefix_paths = self.environment.coredata.builtins_per_machine[self.for_machine]['cmake_prefix_path'].value
+ self.prefix_paths = self.environment.coredata.builtins[OptionKey('cmake_prefix_path', machine=self.for_machine)].value
env_pref_path_raw = get_env_var(
self.for_machine,
self.environment.is_cross_build(),
diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py
index 5931fd1..5d2dd7f 100644
--- a/mesonbuild/cmake/interpreter.py
+++ b/mesonbuild/cmake/interpreter.py
@@ -578,7 +578,7 @@ class ConverterTarget:
@lru_cache(maxsize=None)
def _all_lang_stds(self, lang: str) -> T.List[str]:
try:
- res = self.env.coredata.compiler_options[OptionKey('std', machine=MachineChoice.BUILD, lang=lang)].choices # type: ignore
+ res = self.env.coredata.compiler_options[OptionKey('std', machine=MachineChoice.BUILD, lang=lang)].choices
except KeyError:
return []
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 40bb9e6..234ce06 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -265,36 +265,32 @@ cuda_debug_args = {False: [],
clike_debug_args = {False: [],
True: ['-g']} # type: T.Dict[bool, T.List[str]]
-base_options = {'b_pch': coredata.UserBooleanOption('Use precompiled headers', True),
- 'b_lto': coredata.UserBooleanOption('Use link time optimization', False),
- 'b_sanitize': coredata.UserComboOption('Code sanitizer to use',
- ['none', 'address', 'thread', 'undefined', 'memory', 'address,undefined'],
- 'none'),
- 'b_lundef': coredata.UserBooleanOption('Use -Wl,--no-undefined when linking', True),
- 'b_asneeded': coredata.UserBooleanOption('Use -Wl,--as-needed when linking', True),
- 'b_pgo': coredata.UserComboOption('Use profile guided optimization',
- ['off', 'generate', 'use'],
- 'off'),
- 'b_coverage': coredata.UserBooleanOption('Enable coverage tracking.',
- False),
- 'b_colorout': coredata.UserComboOption('Use colored output',
- ['auto', 'always', 'never'],
- 'always'),
- 'b_ndebug': coredata.UserComboOption('Disable asserts',
- ['true', 'false', 'if-release'], 'false'),
- 'b_staticpic': coredata.UserBooleanOption('Build static libraries as position independent',
- True),
- 'b_pie': coredata.UserBooleanOption('Build executables as position independent',
- False),
- 'b_bitcode': coredata.UserBooleanOption('Generate and embed bitcode (only macOS/iOS/tvOS)',
- False),
- 'b_vscrt': coredata.UserComboOption('VS run-time library type to use.',
- ['none', 'md', 'mdd', 'mt', 'mtd', 'from_buildtype', 'static_from_buildtype'],
- 'from_buildtype'),
- } # type: OptionDictType
-
-def option_enabled(boptions: T.List[str], options: 'OptionDictType',
- option: str) -> bool:
+base_options: 'KeyedOptionDictType' = {
+ OptionKey('b_pch'): coredata.UserBooleanOption('Use precompiled headers', True),
+ OptionKey('b_lto'): coredata.UserBooleanOption('Use link time optimization', False),
+ OptionKey('b_sanitize'): coredata.UserComboOption('Code sanitizer to use',
+ ['none', 'address', 'thread', 'undefined', 'memory', 'address,undefined'],
+ 'none'),
+ OptionKey('b_lundef'): coredata.UserBooleanOption('Use -Wl,--no-undefined when linking', True),
+ OptionKey('b_asneeded'): coredata.UserBooleanOption('Use -Wl,--as-needed when linking', True),
+ OptionKey('b_pgo'): coredata.UserComboOption('Use profile guided optimization',
+ ['off', 'generate', 'use'],
+ 'off'),
+ OptionKey('b_coverage'): coredata.UserBooleanOption('Enable coverage tracking.', False),
+ OptionKey('b_colorout'): coredata.UserComboOption('Use colored output',
+ ['auto', 'always', 'never'],
+ 'always'),
+ OptionKey('b_ndebug'): coredata.UserComboOption('Disable asserts', ['true', 'false', 'if-release'], 'false'),
+ OptionKey('b_staticpic'): coredata.UserBooleanOption('Build static libraries as position independent', True),
+ OptionKey('b_pie'): coredata.UserBooleanOption('Build executables as position independent', False),
+ OptionKey('b_bitcode'): coredata.UserBooleanOption('Generate and embed bitcode (only macOS/iOS/tvOS)', False),
+ OptionKey('b_vscrt'): coredata.UserComboOption('VS run-time library type to use.',
+ ['none', 'md', 'mdd', 'mt', 'mtd', 'from_buildtype', 'static_from_buildtype'],
+ 'from_buildtype'),
+}
+
+def option_enabled(boptions: T.Set[OptionKey], options: 'KeyedOptionDictType',
+ option: OptionKey) -> bool:
try:
if option not in boptions:
return False
@@ -304,23 +300,23 @@ def option_enabled(boptions: T.List[str], options: 'OptionDictType',
except KeyError:
return False
-def get_base_compile_args(options: 'OptionDictType', compiler: 'Compiler') -> T.List[str]:
+def get_base_compile_args(options: 'KeyedOptionDictType', compiler: 'Compiler') -> T.List[str]:
args = [] # type T.List[str]
try:
- if options['b_lto'].value:
+ if options[OptionKey('b_lto')].value:
args.extend(compiler.get_lto_compile_args())
except KeyError:
pass
try:
- args += compiler.get_colorout_args(options['b_colorout'].value)
+ args += compiler.get_colorout_args(options[OptionKey('b_colorout')].value)
except KeyError:
pass
try:
- args += compiler.sanitizer_compile_args(options['b_sanitize'].value)
+ args += compiler.sanitizer_compile_args(options[OptionKey('b_sanitize')].value)
except KeyError:
pass
try:
- pgo_val = options['b_pgo'].value
+ pgo_val = options[OptionKey('b_pgo')].value
if pgo_val == 'generate':
args.extend(compiler.get_profile_generate_args())
elif pgo_val == 'use':
@@ -328,23 +324,23 @@ def get_base_compile_args(options: 'OptionDictType', compiler: 'Compiler') -> T.
except KeyError:
pass
try:
- if options['b_coverage'].value:
+ if options[OptionKey('b_coverage')].value:
args += compiler.get_coverage_args()
except KeyError:
pass
try:
- if (options['b_ndebug'].value == 'true' or
- (options['b_ndebug'].value == 'if-release' and
- options['buildtype'].value in {'release', 'plain'})):
+ if (options[OptionKey('b_ndebug')].value == 'true' or
+ (options[OptionKey('b_ndebug')].value == 'if-release' and
+ options[OptionKey('buildtype')].value in {'release', 'plain'})):
args += compiler.get_disable_assert_args()
except KeyError:
pass
# This does not need a try...except
- if option_enabled(compiler.base_options, options, 'b_bitcode'):
+ if option_enabled(compiler.base_options, options, OptionKey('b_bitcode')):
args.append('-fembed-bitcode')
try:
- crt_val = options['b_vscrt'].value
- buildtype = options['buildtype'].value
+ crt_val = options[OptionKey('b_vscrt')].value
+ buildtype = options[OptionKey('buildtype')].value
try:
args += compiler.get_crt_compile_args(crt_val, buildtype)
except AttributeError:
@@ -353,20 +349,20 @@ def get_base_compile_args(options: 'OptionDictType', compiler: 'Compiler') -> T.
pass
return args
-def get_base_link_args(options: 'OptionDictType', linker: 'Compiler',
+def get_base_link_args(options: 'KeyedOptionDictType', linker: 'Compiler',
is_shared_module: bool) -> T.List[str]:
args = [] # type: T.List[str]
try:
- if options['b_lto'].value:
+ if options[OptionKey('b_lto')].value:
args.extend(linker.get_lto_link_args())
except KeyError:
pass
try:
- args += linker.sanitizer_link_args(options['b_sanitize'].value)
+ args += linker.sanitizer_link_args(options[OptionKey('b_sanitize')].value)
except KeyError:
pass
try:
- pgo_val = options['b_pgo'].value
+ pgo_val = options[OptionKey('b_pgo')].value
if pgo_val == 'generate':
args.extend(linker.get_profile_generate_args())
elif pgo_val == 'use':
@@ -374,13 +370,13 @@ def get_base_link_args(options: 'OptionDictType', linker: 'Compiler',
except KeyError:
pass
try:
- if options['b_coverage'].value:
+ if options[OptionKey('b_coverage')].value:
args += linker.get_coverage_link_args()
except KeyError:
pass
- as_needed = option_enabled(linker.base_options, options, 'b_asneeded')
- bitcode = option_enabled(linker.base_options, options, 'b_bitcode')
+ as_needed = option_enabled(linker.base_options, options, OptionKey('b_asneeded'))
+ bitcode = option_enabled(linker.base_options, options, OptionKey('b_bitcode'))
# Shared modules cannot be built with bitcode_bundle because
# -bitcode_bundle is incompatible with -undefined and -bundle
if bitcode and not is_shared_module:
@@ -394,14 +390,14 @@ def get_base_link_args(options: 'OptionDictType', linker: 'Compiler',
if not bitcode:
args.extend(linker.headerpad_args())
if (not is_shared_module and
- option_enabled(linker.base_options, options, 'b_lundef')):
+ option_enabled(linker.base_options, options, OptionKey('b_lundef'))):
args.extend(linker.no_undefined_link_args())
else:
args.extend(linker.get_allow_undefined_link_args())
try:
- crt_val = options['b_vscrt'].value
- buildtype = options['buildtype'].value
+ crt_val = options[OptionKey('b_vscrt')].value
+ buildtype = options[OptionKey('buildtype')].value
try:
args += linker.get_crt_link_args(crt_val, buildtype)
except AttributeError:
@@ -477,7 +473,7 @@ class Compiler(metaclass=abc.ABCMeta):
self.version = version
self.full_version = full_version
self.for_machine = for_machine
- self.base_options = [] # type: T.List[str]
+ self.base_options: T.Set[OptionKey] = set()
self.linker = linker
self.info = info
self.is_cross = is_cross
@@ -1248,14 +1244,14 @@ def get_global_options(lang: str,
description = 'Extra arguments passed to the {}'.format(lang)
argkey = OptionKey('args', lang=lang, machine=for_machine)
largkey = argkey.evolve('link_args')
- opts = {
+ opts: 'KeyedOptionDictType' = {
argkey: coredata.UserArrayOption(
description + ' compiler',
[], split_args=True, user_input=True, allow_dups=True),
largkey: coredata.UserArrayOption(
description + ' linker',
[], split_args=True, user_input=True, allow_dups=True),
- } # type: OptionDictType
+ }
# Get from env vars.
compile_args, link_args = get_args_from_envvars(
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index b94beb6..2e94e48 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -664,7 +664,7 @@ class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixi
CPPCompiler.__init__(self, exelist, version, for_machine, is_cross,
info, exe_wrapper, linker=linker, full_version=full_version)
MSVCCompiler.__init__(self, target)
- self.base_options = ['b_pch', 'b_vscrt', 'b_ndebug'] # FIXME add lto, pgo and the like
+ self.base_options = {OptionKey(o) for o in ['b_pch', 'b_vscrt', 'b_ndebug']} # FIXME add lto, pgo and the like
self.id = 'msvc'
def get_options(self) -> 'KeyedOptionDictType':
diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py
index ca6de38..eac2aa7 100644
--- a/mesonbuild/compilers/d.py
+++ b/mesonbuild/compilers/d.py
@@ -18,7 +18,7 @@ import subprocess
import typing as T
from ..mesonlib import (
- EnvironmentException, MachineChoice, version_compare,
+ EnvironmentException, MachineChoice, version_compare, OptionKey,
)
from ..arglist import CompilerArgs
@@ -653,8 +653,10 @@ class GnuDCompiler(GnuCompiler, DCompiler):
'1': default_warn_args,
'2': default_warn_args + ['-Wextra'],
'3': default_warn_args + ['-Wextra', '-Wpedantic']}
- self.base_options = ['b_colorout', 'b_sanitize', 'b_staticpic',
- 'b_vscrt', 'b_coverage', 'b_pgo', 'b_ndebug']
+ self.base_options = {
+ OptionKey(o) for o in [
+ 'b_colorout', 'b_sanitize', 'b_staticpic', 'b_vscrt',
+ 'b_coverage', 'b_pgo', 'b_ndebug']}
self._has_color_support = version_compare(self.version, '>=4.9')
# dependencies were implemented before, but broken - support was fixed in GCC 7.1+
@@ -724,7 +726,7 @@ class LLVMDCompiler(DmdLikeCompilerMixin, DCompiler):
full_version=full_version, is_cross=is_cross)
DmdLikeCompilerMixin.__init__(self, dmd_frontend_version=find_ldc_dmd_frontend_version(version_output))
self.id = 'llvm'
- self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']
+ self.base_options = {OptionKey(o) for o in ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']}
def get_colorout_args(self, colortype: str) -> T.List[str]:
if colortype == 'always':
@@ -782,7 +784,7 @@ class DmdDCompiler(DmdLikeCompilerMixin, DCompiler):
full_version=full_version, is_cross=is_cross)
DmdLikeCompilerMixin.__init__(self, version)
self.id = 'dmd'
- self.base_options = ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']
+ self.base_options = {OptionKey(o) for o in ['b_coverage', 'b_colorout', 'b_vscrt', 'b_ndebug']}
def get_colorout_args(self, colortype: str) -> T.List[str]:
if colortype == 'always':
diff --git a/mesonbuild/compilers/mixins/arm.py b/mesonbuild/compilers/mixins/arm.py
index ee7d337..beb5fd5 100644
--- a/mesonbuild/compilers/mixins/arm.py
+++ b/mesonbuild/compilers/mixins/arm.py
@@ -19,6 +19,7 @@ import typing as T
from ... import mesonlib
from ...linkers import ArmClangDynamicLinker
+from ...mesonlib import OptionKey
from ..compilers import clike_debug_args
from .clang import clang_color_args
@@ -145,8 +146,10 @@ class ArmclangCompiler(Compiler):
if not mesonlib.version_compare(self.version, '==' + self.linker.version):
raise mesonlib.EnvironmentException('armlink version does not match with compiler version')
self.id = 'armclang'
- self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
- 'b_ndebug', 'b_staticpic', 'b_colorout']
+ self.base_options = {
+ OptionKey(o) for o in
+ ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
+ 'b_ndebug', 'b_staticpic', 'b_colorout']}
# Assembly
self.can_compile_suffixes.add('s')
diff --git a/mesonbuild/compilers/mixins/clang.py b/mesonbuild/compilers/mixins/clang.py
index 2e50577..fcb2225 100644
--- a/mesonbuild/compilers/mixins/clang.py
+++ b/mesonbuild/compilers/mixins/clang.py
@@ -20,6 +20,7 @@ import typing as T
from ... import mesonlib
from ...linkers import AppleDynamicLinker
+from ...mesonlib import OptionKey
from ..compilers import CompileCheckMode
from .gnu import GnuLikeCompiler
@@ -48,11 +49,11 @@ class ClangCompiler(GnuLikeCompiler):
super().__init__()
self.id = 'clang'
self.defines = defines or {}
- self.base_options.append('b_colorout')
+ self.base_options.add(OptionKey('b_colorout'))
# TODO: this really should be part of the linker base_options, but
# linkers don't have base_options.
if isinstance(self.linker, AppleDynamicLinker):
- self.base_options.append('b_bitcode')
+ self.base_options.add(OptionKey('b_bitcode'))
# All Clang backends can also do LLVM IR
self.can_compile_suffixes.add('ll')
@@ -108,7 +109,7 @@ class ClangCompiler(GnuLikeCompiler):
else:
# Shouldn't work, but it'll be checked explicitly in the OpenMP dependency.
return []
-
+
@classmethod
def use_linker_args(cls, linker: str) -> T.List[str]:
# Clang additionally can use a linker specified as a path, which GCC
diff --git a/mesonbuild/compilers/mixins/clike.py b/mesonbuild/compilers/mixins/clike.py
index dca09ea..0f30f55 100644
--- a/mesonbuild/compilers/mixins/clike.py
+++ b/mesonbuild/compilers/mixins/clike.py
@@ -35,6 +35,7 @@ from ... import mesonlib
from ... import mlog
from ...linkers import GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker
from ...mesonlib import LibType
+from ...coredata import OptionKey
from .. import compilers
from ..compilers import CompileCheckMode
from .visualstudio import VisualStudioLikeCompiler
@@ -393,14 +394,16 @@ 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.base_options['b_vscrt'].value
- buildtype = env.coredata.builtins['buildtype'].value
+ crt_val = env.coredata.base_options[OptionKey('b_vscrt')].value
+ buildtype = env.coredata.builtins[OptionKey('buildtype')].value
cargs += self.get_crt_compile_args(crt_val, buildtype)
except (KeyError, AttributeError):
pass
# Add CFLAGS/CXXFLAGS/OBJCFLAGS/OBJCXXFLAGS and CPPFLAGS from the env
sys_args = env.coredata.get_external_args(self.for_machine, self.language)
+ if isinstance(sys_args, str):
+ sys_args = [sys_args]
# Apparently it is a thing to inject linker flags both
# via CFLAGS _and_ LDFLAGS, even though the former are
# also used during linking. These flags can break
diff --git a/mesonbuild/compilers/mixins/elbrus.py b/mesonbuild/compilers/mixins/elbrus.py
index 2ea3599..16f6210 100644
--- a/mesonbuild/compilers/mixins/elbrus.py
+++ b/mesonbuild/compilers/mixins/elbrus.py
@@ -21,7 +21,7 @@ import re
from .gnu import GnuLikeCompiler
from .gnu import gnu_optimization_args
-from ...mesonlib import Popen_safe
+from ...mesonlib import Popen_safe, OptionKey
if T.TYPE_CHECKING:
from ...environment import Environment
@@ -34,9 +34,7 @@ class ElbrusCompiler(GnuLikeCompiler):
def __init__(self) -> None:
super().__init__()
self.id = 'lcc'
- self.base_options = ['b_pgo', 'b_coverage',
- 'b_ndebug', 'b_staticpic',
- 'b_lundef', 'b_asneeded']
+ self.base_options = {OptionKey(o) for o in ['b_pgo', 'b_coverage', 'b_ndebug', 'b_staticpic', 'b_lundef', 'b_asneeded']}
# FIXME: use _build_wrapper to call this so that linker flags from the env
# get applied
diff --git a/mesonbuild/compilers/mixins/emscripten.py b/mesonbuild/compilers/mixins/emscripten.py
index b480de3..537ae92 100644
--- a/mesonbuild/compilers/mixins/emscripten.py
+++ b/mesonbuild/compilers/mixins/emscripten.py
@@ -51,7 +51,7 @@ class EmscriptenMixin(Compiler):
def thread_link_flags(self, env: 'Environment') -> T.List[str]:
args = ['-s', 'USE_PTHREADS=1']
- count: int = env.coredata.compiler_options[OptionKey('thread_count', lang=self.language, machine=self.for_machine)].value # type: ignore
+ count: int = env.coredata.compiler_options[OptionKey('thread_count', lang=self.language, machine=self.for_machine)].value
if count:
args.extend(['-s', 'PTHREAD_POOL_SIZE={}'.format(count)])
return args
diff --git a/mesonbuild/compilers/mixins/gnu.py b/mesonbuild/compilers/mixins/gnu.py
index 3d43162..95bcd7c 100644
--- a/mesonbuild/compilers/mixins/gnu.py
+++ b/mesonbuild/compilers/mixins/gnu.py
@@ -24,6 +24,7 @@ import typing as T
from ... import mesonlib
from ... import mlog
+from ...mesonlib import OptionKey
if T.TYPE_CHECKING:
from ...environment import Environment
@@ -146,14 +147,15 @@ class GnuLikeCompiler(Compiler, metaclass=abc.ABCMeta):
LINKER_PREFIX = '-Wl,'
def __init__(self) -> None:
- self.base_options = ['b_pch', 'b_lto', 'b_pgo', 'b_coverage',
- 'b_ndebug', 'b_staticpic', 'b_pie']
+ self.base_options = {
+ OptionKey(o) for o in ['b_pch', 'b_lto', 'b_pgo', 'b_coverage',
+ 'b_ndebug', 'b_staticpic', 'b_pie']}
if not (self.info.is_windows() or self.info.is_cygwin() or self.info.is_openbsd()):
- self.base_options.append('b_lundef')
+ self.base_options.add(OptionKey('b_lundef'))
if not self.info.is_windows() or self.info.is_cygwin():
- self.base_options.append('b_asneeded')
+ self.base_options.add(OptionKey('b_asneeded'))
if not self.info.is_hurd():
- self.base_options.append('b_sanitize')
+ self.base_options.add(OptionKey('b_sanitize'))
# All GCC-like backends can do assembly
self.can_compile_suffixes.add('s')
@@ -328,7 +330,7 @@ class GnuCompiler(GnuLikeCompiler):
super().__init__()
self.id = 'gcc'
self.defines = defines or {}
- self.base_options.append('b_colorout')
+ self.base_options.add(OptionKey('b_colorout'))
def get_colorout_args(self, colortype: str) -> T.List[str]:
if mesonlib.version_compare(self.version, '>=4.9.0'):
diff --git a/mesonbuild/compilers/mixins/intel.py b/mesonbuild/compilers/mixins/intel.py
index 442e8c7..5bca254 100644
--- a/mesonbuild/compilers/mixins/intel.py
+++ b/mesonbuild/compilers/mixins/intel.py
@@ -79,8 +79,9 @@ class IntelGnuLikeCompiler(GnuLikeCompiler):
# It does have IPO, which serves much the same purpose as LOT, but
# there is an unfortunate rule for using IPO (you can't control the
# name of the output file) which break assumptions meson makes
- self.base_options = ['b_pch', 'b_lundef', 'b_asneeded', 'b_pgo',
- 'b_coverage', 'b_ndebug', 'b_staticpic', 'b_pie']
+ self.base_options = {mesonlib.OptionKey(o) for o in [
+ 'b_pch', 'b_lundef', 'b_asneeded', 'b_pgo', 'b_coverage',
+ 'b_ndebug', 'b_staticpic', 'b_pie']}
self.id = 'intel'
self.lang_header = 'none'
diff --git a/mesonbuild/compilers/mixins/pgi.py b/mesonbuild/compilers/mixins/pgi.py
index 61dee8d..8461574 100644
--- a/mesonbuild/compilers/mixins/pgi.py
+++ b/mesonbuild/compilers/mixins/pgi.py
@@ -19,6 +19,7 @@ import os
from pathlib import Path
from ..compilers import clike_debug_args, clike_optimization_args
+from ...mesonlib import OptionKey
if T.TYPE_CHECKING:
from ...environment import Environment
@@ -43,7 +44,7 @@ pgi_buildtype_args = {
class PGICompiler(Compiler):
def __init__(self) -> None:
- self.base_options = ['b_pch']
+ self.base_options = {OptionKey('b_pch')}
self.id = 'pgi'
default_warn_args = ['-Minform=inform']
diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py
index c38d59a..92f4fcd 100644
--- a/mesonbuild/compilers/mixins/visualstudio.py
+++ b/mesonbuild/compilers/mixins/visualstudio.py
@@ -129,7 +129,7 @@ class VisualStudioLikeCompiler(Compiler, metaclass=abc.ABCMeta):
INVOKES_LINKER = False
def __init__(self, target: str):
- self.base_options = ['b_pch', 'b_ndebug', 'b_vscrt'] # FIXME add lto, pgo and the like
+ self.base_options = {mesonlib.OptionKey(o) for o in ['b_pch', 'b_ndebug', 'b_vscrt']} # FIXME add lto, pgo and the like
self.target = target
self.is_64 = ('x64' in target) or ('x86_64' in target)
# do some canonicalization of target machine
diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py
index 8a1acc7..fd58819 100644
--- a/mesonbuild/compilers/rust.py
+++ b/mesonbuild/compilers/rust.py
@@ -55,9 +55,9 @@ class RustCompiler(Compiler):
linker=linker)
self.exe_wrapper = exe_wrapper
self.id = 'rustc'
- self.base_options.append('b_colorout')
+ self.base_options.add(OptionKey('b_colorout'))
if 'link' in self.linker.id:
- self.base_options.append('b_vscrt')
+ self.base_options.add(OptionKey('b_vscrt'))
def needs_static_linker(self) -> bool:
return False
diff --git a/mesonbuild/compilers/vala.py b/mesonbuild/compilers/vala.py
index 14971d4..80e91f6 100644
--- a/mesonbuild/compilers/vala.py
+++ b/mesonbuild/compilers/vala.py
@@ -16,7 +16,7 @@ import os.path
import typing as T
from .. import mlog
-from ..mesonlib import EnvironmentException, MachineChoice, version_compare
+from ..mesonlib import EnvironmentException, MachineChoice, version_compare, OptionKey
from .compilers import Compiler, LibType
@@ -33,7 +33,7 @@ class ValaCompiler(Compiler):
super().__init__(exelist, version, for_machine, info, is_cross=is_cross)
self.version = version
self.id = 'valac'
- self.base_options = ['b_colorout']
+ self.base_options = {OptionKey('b_colorout')}
def needs_static_linker(self) -> bool:
return False # Because compiles into C.
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index f09c398..6d6583f 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -21,7 +21,7 @@ from collections import OrderedDict, defaultdict
from .mesonlib import (
MesonException, EnvironmentException, MachineChoice, PerMachine,
default_libdir, default_libexecdir, default_prefix, split_args,
- OptionKey,
+ OptionKey, OptionType,
)
from .wrap import WrapMode
import ast
@@ -301,16 +301,17 @@ class DependencyCache:
successfully lookup by providing a simple get/put interface.
"""
- def __init__(self, builtins_per_machine: PerMachine[T.Dict[str, UserOption[T.Any]]], for_machine: MachineChoice):
+ def __init__(self, builtins: 'KeyedOptionDictType', for_machine: MachineChoice):
self.__cache = OrderedDict() # type: T.MutableMapping[CacheKeyType, DependencySubCache]
- self.__builtins_per_machine = builtins_per_machine
- self.__for_machine = for_machine
+ self.__builtins = builtins
+ self.__pkg_conf_key = OptionKey('pkg_config_path', machine=for_machine)
+ self.__cmake_key = OptionKey('cmake_prefix_path', machine=for_machine)
def __calculate_subkey(self, type_: DependencyCacheType) -> T.Tuple[T.Any, ...]:
if type_ is DependencyCacheType.PKG_CONFIG:
- return tuple(self.__builtins_per_machine[self.__for_machine]['pkg_config_path'].value)
+ return tuple(self.__builtins[self.__pkg_conf_key].value)
elif type_ is DependencyCacheType.CMAKE:
- return tuple(self.__builtins_per_machine[self.__for_machine]['cmake_prefix_path'].value)
+ return tuple(self.__builtins[self.__cmake_key].value)
assert type_ is DependencyCacheType.OTHER, 'Someone forgot to update subkey calculations for a new type'
return tuple()
@@ -384,17 +385,16 @@ class CoreData:
self.meson_command = meson_command
self.target_guids = {}
self.version = version
- self.builtins = {} # type: OptionDictType
- self.builtins_per_machine: PerMachine['OptionDictType'] = PerMachine({}, {})
+ self.builtins: 'KeyedOptionDictType' = {}
self.backend_options: 'KeyedOptionDictType' = {}
self.user_options: 'KeyedOptionDictType' = {}
self.compiler_options: 'KeyedOptionDictType' = {}
- self.base_options = {} # type: OptionDictType
+ self.base_options: 'KeyedOptionDictType' = {}
self.cross_files = self.__load_config_files(options, scratch_dir, 'cross')
self.compilers = PerMachine(OrderedDict(), OrderedDict()) # type: PerMachine[T.Dict[str, Compiler]]
- build_cache = DependencyCache(self.builtins_per_machine, MachineChoice.BUILD)
- host_cache = DependencyCache(self.builtins_per_machine, MachineChoice.BUILD)
+ build_cache = DependencyCache(self.builtins, MachineChoice.BUILD)
+ host_cache = DependencyCache(self.builtins, MachineChoice.BUILD)
self.deps = PerMachine(build_cache, host_cache) # type: PerMachine[DependencyCache]
self.compiler_check_cache = OrderedDict() # type: T.Dict[CompilerCheckCacheKey, compiler.CompileResult]
@@ -466,7 +466,7 @@ class CoreData:
# getting the "system default" is always wrong on multiarch
# platforms as it gets a value like lib/x86_64-linux-gnu.
if self.cross_files:
- BUILTIN_OPTIONS['libdir'].default = 'lib'
+ BUILTIN_OPTIONS[OptionKey('libdir')].default = 'lib'
def sanitize_prefix(self, prefix):
prefix = os.path.expanduser(prefix)
@@ -486,7 +486,7 @@ class CoreData:
prefix = prefix[:-1]
return prefix
- def sanitize_dir_option_value(self, prefix: str, option: str, value: T.Any) -> T.Any:
+ def sanitize_dir_option_value(self, prefix: str, option: OptionKey, value: T.Any) -> T.Any:
'''
If the option is an installation directory option and the value is an
absolute path, check that it resides within prefix and return the value
@@ -501,13 +501,13 @@ class CoreData:
value = PurePath(value)
except TypeError:
return value
- if option.endswith('dir') and value.is_absolute() and \
- option not in builtin_dir_noprefix_options:
+ if option.name.endswith('dir') and value.is_absolute() and \
+ option not in BULITIN_DIR_NOPREFIX_OPTIONS:
# Value must be a subdir of the prefix
# commonpath will always return a path in the native format, so we
# must use pathlib.PurePath to do the same conversion before
# comparing.
- msg = ('The value of the {!r} option is \'{!s}\' which must be a '
+ msg = ('The value of the \'{!s}\' option is \'{!s}\' which must be a '
'subdir of the prefix {!r}.\nNote that if you pass a '
'relative path, it is assumed to be a subdir of prefix.')
# os.path.commonpath doesn't understand case-insensitive filesystems,
@@ -520,25 +520,25 @@ class CoreData:
raise MesonException(msg.format(option, value, prefix))
return value.as_posix()
- def init_builtins(self, subproject: str):
+ def init_builtins(self, subproject: str) -> None:
# Create builtin options with default values
for key, opt in BUILTIN_OPTIONS.items():
- self.add_builtin_option(self.builtins, key, opt, subproject)
+ self.add_builtin_option(self.builtins, key.evolve(subproject=subproject), opt)
for for_machine in iter(MachineChoice):
for key, opt in BUILTIN_OPTIONS_PER_MACHINE.items():
- self.add_builtin_option(self.builtins_per_machine[for_machine], key, opt, subproject)
+ self.add_builtin_option(self.builtins, key.evolve(subproject=subproject, machine=for_machine), opt)
- def add_builtin_option(self, opts_map, key, opt, subproject):
- if subproject:
+ @staticmethod
+ def add_builtin_option(opts_map: 'KeyedOptionDictType', key: OptionKey,
+ opt: 'BuiltinOption') -> None:
+ if key.subproject:
if opt.yielding:
# This option is global and not per-subproject
return
- optname = subproject + ':' + key
- value = opts_map[key].value
+ value = opts_map[key.as_root()].value
else:
- optname = key
value = None
- opts_map[optname] = opt.init_option(key, value, default_prefix())
+ opts_map[key] = opt.init_option(key, value, default_prefix())
def init_backend_options(self, backend_name: str) -> None:
if backend_name == 'ninja':
@@ -552,45 +552,43 @@ class CoreData:
'')
def get_builtin_option(self, optname: str, subproject: str = '') -> T.Union[str, int, bool]:
- raw_optname = optname
- if subproject:
- optname = subproject + ':' + optname
+ key = OptionKey.from_string(optname).evolve(subproject=subproject)
for opts in self._get_all_builtin_options():
- v = opts.get(optname)
+ v = opts.get(str(key))
if v is None or v.yielding:
- v = opts.get(raw_optname)
+ v = opts.get(str(key.as_root()))
if v is None:
continue
- if raw_optname == 'wrap_mode':
+ if key.name == 'wrap_mode':
return WrapMode.from_string(v.value)
return v.value
- raise RuntimeError('Tried to get unknown builtin option %s.' % raw_optname)
+ raise RuntimeError(f'Tried to get unknown builtin option {key.name}.')
- def _try_set_builtin_option(self, optname, value):
+ def _try_set_builtin_option(self, key: OptionKey, value) -> bool:
for opts in self._get_all_builtin_options():
- opt = opts.get(optname)
+ opt = opts.get(str(key))
if opt is None:
continue
- if optname == 'prefix':
+ if key.name == 'prefix':
value = self.sanitize_prefix(value)
else:
- prefix = self.builtins['prefix'].value
- value = self.sanitize_dir_option_value(prefix, optname, value)
+ prefix = self.builtins[OptionKey('prefix')].value
+ value = self.sanitize_dir_option_value(prefix, key, value)
break
else:
return False
opt.set_value(value)
# Make sure that buildtype matches other settings.
- if optname == 'buildtype':
+ if key.name == 'buildtype':
self.set_others_from_buildtype(value)
else:
self.set_buildtype_from_others()
return True
- def set_builtin_option(self, optname, value):
+ def set_builtin_option(self, optname: OptionKey, value) -> None:
res = self._try_set_builtin_option(optname, value)
if not res:
- raise RuntimeError('Tried to set unknown builtin option %s.' % optname)
+ raise RuntimeError(f'Tried to set unknown builtin option {str(optname)}')
def set_others_from_buildtype(self, value):
if value == 'plain':
@@ -611,12 +609,12 @@ class CoreData:
else:
assert(value == 'custom')
return
- self.builtins['optimization'].set_value(opt)
- self.builtins['debug'].set_value(debug)
+ self.builtins[OptionKey('optimization')].set_value(opt)
+ self.builtins[OptionKey('debug')].set_value(debug)
def set_buildtype_from_others(self):
- opt = self.builtins['optimization'].value
- debug = self.builtins['debug'].value
+ opt = self.builtins[OptionKey('optimization')].value
+ debug = self.builtins[OptionKey('debug')].value
if opt == '0' and not debug:
mode = 'plain'
elif opt == '0' and debug:
@@ -629,7 +627,7 @@ class CoreData:
mode = 'minsize'
else:
mode = 'custom'
- self.builtins['buildtype'].set_value(mode)
+ self.builtins[OptionKey('buildtype')].set_value(mode)
@classmethod
def get_prefixed_options_per_machine(
@@ -666,19 +664,18 @@ class CoreData:
yield {str(k): v for k, v in self.backend_options.items()}
yield {str(k): v for k, v in self.user_options.items()}
yield {str(k): v for k, v in self.compiler_options.items()}
- yield self.base_options
+ yield {str(k): v for k, v in self.base_options.items()}
def _get_all_builtin_options(self) -> T.Iterable[T.Dict[str, UserOption]]:
- yield dict(self.get_prefixed_options_per_machine(self.builtins_per_machine))
- yield self.builtins
+ yield {str(k): v for k, v in self.builtins.items()}
def get_all_options(self) -> T.Iterable[T.Dict[str, UserOption]]:
yield from self._get_all_nonbuiltin_options()
yield from self._get_all_builtin_options()
- def validate_option_value(self, option_name, override_value):
+ def validate_option_value(self, option_name: OptionKey, override_value):
for opts in self.get_all_options():
- opt = opts.get(option_name)
+ opt = opts.get(str(option_name))
if opt is not None:
try:
return opt.validate_value(override_value)
@@ -718,10 +715,11 @@ class CoreData:
return False
return len(self.cross_files) > 0
- def copy_build_options_from_regular_ones(self):
+ def copy_build_options_from_regular_ones(self) -> None:
assert not self.is_cross_build()
- for k, o in self.builtins_per_machine.host.items():
- self.builtins_per_machine.build[k].set_value(o.value)
+ for k in BUILTIN_OPTIONS_PER_MACHINE:
+ o = self.builtins[k]
+ self.builtins[k.as_build()].set_value(o.value)
for bk, bv in self.compiler_options.items():
if bk.machine is MachineChoice.BUILD:
hk = bk.as_host()
@@ -738,8 +736,8 @@ class CoreData:
pfk = OptionKey('prefix')
if pfk in options:
prefix = self.sanitize_prefix(options[pfk])
- self.builtins['prefix'].set_value(prefix)
- for key in builtin_dir_noprefix_options:
+ self.builtins[OptionKey('prefix')].set_value(prefix)
+ for key in BULITIN_DIR_NOPREFIX_OPTIONS:
if key not in options:
self.builtins[key].set_value(BUILTIN_OPTIONS[key].prefixed_default(key, prefix))
@@ -747,7 +745,7 @@ class CoreData:
for k, v in options.items():
if k == pfk:
continue
- if self._try_set_builtin_option(str(k), v):
+ if self._try_set_builtin_option(k, v):
continue
for opts in self._get_all_nonbuiltin_options():
tgt = opts.get(str(k))
@@ -783,15 +781,13 @@ class CoreData:
# to know which backend we'll use).
options: T.MutableMapping[OptionKey, T.Any] = OrderedDict()
- from . import optinterpreter
for k, v in chain(default_options.items(), env.options.items()):
# Subproject: skip options for other subprojects
if k.subproject and k.subproject != subproject:
continue
# Skip base, compiler, and backend options, they are handled when
# adding languages and setting backend.
- if (k.name not in self.builtins and k.name not in self.builtins_per_machine[k.machine] and
- optinterpreter.is_invalid_name(str(k), log=False)):
+ if k.type in {OptionType.COMPILER, OptionType.BACKEND, OptionType.BASE}:
continue
options[k] = v
@@ -818,20 +814,19 @@ class CoreData:
self.compilers[comp.for_machine][lang] = comp
self.add_compiler_options(comp.get_options(), lang, comp.for_machine, env)
- enabled_opts = []
- for optname in comp.base_options:
- if optname in self.base_options:
+ enabled_opts: T.List[OptionKey] = []
+ for key in comp.base_options:
+ if key in self.base_options:
continue
- oobj = compilers.base_options[optname]
- key = OptionKey(optname, machine=comp.for_machine)
+ oobj = compilers.base_options[key]
if key in env.options:
oobj.set_value(env.options[key])
- enabled_opts.append(optname)
- self.base_options[optname] = oobj
+ enabled_opts.append(key)
+ self.base_options[key] = oobj
self.emit_base_options_warnings(enabled_opts)
- def emit_base_options_warnings(self, enabled_opts: list):
- if 'b_bitcode' in enabled_opts:
+ def emit_base_options_warnings(self, enabled_opts: T.List[OptionKey]) -> None:
+ if OptionKey('b_bitcode') in enabled_opts:
mlog.warning('Base option \'b_bitcode\' is enabled, which is incompatible with many linker options. Incompatible options such as \'b_asneeded\' have been disabled.', fatal=False)
mlog.warning('Please see https://mesonbuild.com/Builtin-options.html#Notes_about_Apple_Bitcode_support for more details.', fatal=False)
@@ -1007,10 +1002,10 @@ def save(obj: CoreData, build_dir: str) -> str:
def register_builtin_arguments(parser: argparse.ArgumentParser) -> None:
for n, b in BUILTIN_OPTIONS.items():
- b.add_to_argparse(n, parser, '', '')
+ b.add_to_argparse(str(n), parser, '')
for n, b in BUILTIN_OPTIONS_PER_MACHINE.items():
- b.add_to_argparse(n, parser, '', ' (just for host machine)')
- b.add_to_argparse(n, parser, 'build.', ' (just for build machine)')
+ b.add_to_argparse(str(n), parser, ' (just for host machine)')
+ b.add_to_argparse(str(n.as_build()), parser, ' (just for build machine)')
parser.add_argument('-D', action='append', dest='projectoptions', default=[], metavar="option",
help='Set the value of an option, can be used several times to set multiple options.')
@@ -1031,14 +1026,14 @@ def parse_cmd_line_options(args: argparse.Namespace) -> None:
args.cmd_line_options = create_options_dict(args.projectoptions)
# Merge builtin options set with --option into the dict.
- for name in chain(
+ for key in chain(
BUILTIN_OPTIONS.keys(),
- ('build.' + k for k in BUILTIN_OPTIONS_PER_MACHINE.keys()),
+ (k.as_build() for k in BUILTIN_OPTIONS_PER_MACHINE.keys()),
BUILTIN_OPTIONS_PER_MACHINE.keys(),
):
+ name = str(key)
value = getattr(args, name, None)
if value is not None:
- key = OptionKey.from_string(name)
if key in args.cmd_line_options:
cmdline_name = BuiltinOption.argparse_name_to_arg(name)
raise MesonException(
@@ -1064,7 +1059,7 @@ class BuiltinOption(T.Generic[_T, _U]):
self.choices = choices
self.yielding = yielding
- def init_option(self, name: str, value: T.Optional[T.Any], prefix: str) -> _U:
+ def init_option(self, name: 'OptionKey', value: T.Optional[T.Any], prefix: str) -> _U:
"""Create an instance of opt_type and return it."""
if value is None:
value = self.prefixed_default(name, prefix)
@@ -1095,16 +1090,16 @@ class BuiltinOption(T.Generic[_T, _U]):
else:
return '--' + name.replace('_', '-')
- def prefixed_default(self, name: str, prefix: str = '') -> T.Any:
+ def prefixed_default(self, name: 'OptionKey', prefix: str = '') -> T.Any:
if self.opt_type in [UserComboOption, UserIntegerOption]:
return self.default
try:
- return builtin_dir_noprefix_options[name][prefix]
+ return BULITIN_DIR_NOPREFIX_OPTIONS[name][prefix]
except KeyError:
pass
return self.default
- def add_to_argparse(self, name: str, parser: argparse.ArgumentParser, prefix: str, help_suffix: str) -> None:
+ def add_to_argparse(self, name: str, parser: argparse.ArgumentParser, help_suffix: str) -> None:
kwargs = OrderedDict()
c = self._argparse_choices()
@@ -1117,64 +1112,65 @@ class BuiltinOption(T.Generic[_T, _U]):
if c and not b:
kwargs['choices'] = c
kwargs['default'] = argparse.SUPPRESS
- kwargs['dest'] = prefix + name
+ kwargs['dest'] = name
- cmdline_name = self.argparse_name_to_arg(prefix + name)
+ cmdline_name = self.argparse_name_to_arg(name)
parser.add_argument(cmdline_name, help=h + help_suffix, **kwargs)
# Update `docs/markdown/Builtin-options.md` after changing the options below
-BUILTIN_DIR_OPTIONS = OrderedDict([
- ('prefix', BuiltinOption(UserStringOption, 'Installation prefix', default_prefix())),
- ('bindir', BuiltinOption(UserStringOption, 'Executable directory', 'bin')),
- ('datadir', BuiltinOption(UserStringOption, 'Data file directory', 'share')),
- ('includedir', BuiltinOption(UserStringOption, 'Header file directory', 'include')),
- ('infodir', BuiltinOption(UserStringOption, 'Info page directory', 'share/info')),
- ('libdir', BuiltinOption(UserStringOption, 'Library directory', default_libdir())),
- ('libexecdir', BuiltinOption(UserStringOption, 'Library executable directory', default_libexecdir())),
- ('localedir', BuiltinOption(UserStringOption, 'Locale data directory', 'share/locale')),
- ('localstatedir', BuiltinOption(UserStringOption, 'Localstate data directory', 'var')),
- ('mandir', BuiltinOption(UserStringOption, 'Manual page directory', 'share/man')),
- ('sbindir', BuiltinOption(UserStringOption, 'System executable directory', 'sbin')),
- ('sharedstatedir', BuiltinOption(UserStringOption, 'Architecture-independent data directory', 'com')),
- ('sysconfdir', BuiltinOption(UserStringOption, 'Sysconf data directory', 'etc')),
-]) # type: OptionDictType
-
-BUILTIN_CORE_OPTIONS = OrderedDict([
- ('auto_features', BuiltinOption(UserFeatureOption, "Override value of all 'auto' features", 'auto')),
- ('backend', BuiltinOption(UserComboOption, 'Backend to use', 'ninja', choices=backendlist)),
- ('buildtype', BuiltinOption(UserComboOption, 'Build type to use', 'debug',
- choices=['plain', 'debug', 'debugoptimized', 'release', 'minsize', 'custom'])),
- ('debug', BuiltinOption(UserBooleanOption, 'Debug', True)),
- ('default_library', BuiltinOption(UserComboOption, 'Default library type', 'shared', choices=['shared', 'static', 'both'],
- yielding=False)),
- ('errorlogs', BuiltinOption(UserBooleanOption, "Whether to print the logs from failing tests", True)),
- ('install_umask', BuiltinOption(UserUmaskOption, 'Default umask to apply on permissions of installed files', '022')),
- ('layout', BuiltinOption(UserComboOption, 'Build directory layout', 'mirror', choices=['mirror', 'flat'])),
- ('optimization', BuiltinOption(UserComboOption, 'Optimization level', '0', choices=['0', 'g', '1', '2', '3', 's'])),
- ('stdsplit', BuiltinOption(UserBooleanOption, 'Split stdout and stderr in test logs', True)),
- ('strip', BuiltinOption(UserBooleanOption, 'Strip targets on install', False)),
- ('unity', BuiltinOption(UserComboOption, 'Unity build', 'off', choices=['on', 'off', 'subprojects'])),
- ('unity_size', BuiltinOption(UserIntegerOption, 'Unity block size', (2, None, 4))),
- ('warning_level', BuiltinOption(UserComboOption, 'Compiler warning level to use', '1', choices=['0', '1', '2', '3'], yielding=False)),
- ('werror', BuiltinOption(UserBooleanOption, 'Treat warnings as errors', False, yielding=False)),
- ('wrap_mode', BuiltinOption(UserComboOption, 'Wrap mode', 'default', choices=['default', 'nofallback', 'nodownload', 'forcefallback'])),
- ('force_fallback_for', BuiltinOption(UserArrayOption, 'Force fallback for those subprojects', [])),
-]) # type: OptionDictType
+# Also update mesonlib._BUILTIN_NAMES. See the comment there for why this is required.
+BUILTIN_DIR_OPTIONS: 'KeyedOptionDictType' = OrderedDict([
+ (OptionKey('prefix'), BuiltinOption(UserStringOption, 'Installation prefix', default_prefix())),
+ (OptionKey('bindir'), BuiltinOption(UserStringOption, 'Executable directory', 'bin')),
+ (OptionKey('datadir'), BuiltinOption(UserStringOption, 'Data file directory', 'share')),
+ (OptionKey('includedir'), BuiltinOption(UserStringOption, 'Header file directory', 'include')),
+ (OptionKey('infodir'), BuiltinOption(UserStringOption, 'Info page directory', 'share/info')),
+ (OptionKey('libdir'), BuiltinOption(UserStringOption, 'Library directory', default_libdir())),
+ (OptionKey('libexecdir'), BuiltinOption(UserStringOption, 'Library executable directory', default_libexecdir())),
+ (OptionKey('localedir'), BuiltinOption(UserStringOption, 'Locale data directory', 'share/locale')),
+ (OptionKey('localstatedir'), BuiltinOption(UserStringOption, 'Localstate data directory', 'var')),
+ (OptionKey('mandir'), BuiltinOption(UserStringOption, 'Manual page directory', 'share/man')),
+ (OptionKey('sbindir'), BuiltinOption(UserStringOption, 'System executable directory', 'sbin')),
+ (OptionKey('sharedstatedir'), BuiltinOption(UserStringOption, 'Architecture-independent data directory', 'com')),
+ (OptionKey('sysconfdir'), BuiltinOption(UserStringOption, 'Sysconf data directory', 'etc')),
+])
+
+BUILTIN_CORE_OPTIONS: 'KeyedOptionDictType' = OrderedDict([
+ (OptionKey('auto_features'), BuiltinOption(UserFeatureOption, "Override value of all 'auto' features", 'auto')),
+ (OptionKey('backend'), BuiltinOption(UserComboOption, 'Backend to use', 'ninja', choices=backendlist)),
+ (OptionKey('buildtype'), BuiltinOption(UserComboOption, 'Build type to use', 'debug',
+ choices=['plain', 'debug', 'debugoptimized', 'release', 'minsize', 'custom'])),
+ (OptionKey('debug'), BuiltinOption(UserBooleanOption, 'Debug', True)),
+ (OptionKey('default_library'), BuiltinOption(UserComboOption, 'Default library type', 'shared', choices=['shared', 'static', 'both'],
+ yielding=False)),
+ (OptionKey('errorlogs'), BuiltinOption(UserBooleanOption, "Whether to print the logs from failing tests", True)),
+ (OptionKey('install_umask'), BuiltinOption(UserUmaskOption, 'Default umask to apply on permissions of installed files', '022')),
+ (OptionKey('layout'), BuiltinOption(UserComboOption, 'Build directory layout', 'mirror', choices=['mirror', 'flat'])),
+ (OptionKey('optimization'), BuiltinOption(UserComboOption, 'Optimization level', '0', choices=['0', 'g', '1', '2', '3', 's'])),
+ (OptionKey('stdsplit'), BuiltinOption(UserBooleanOption, 'Split stdout and stderr in test logs', True)),
+ (OptionKey('strip'), BuiltinOption(UserBooleanOption, 'Strip targets on install', False)),
+ (OptionKey('unity'), BuiltinOption(UserComboOption, 'Unity build', 'off', choices=['on', 'off', 'subprojects'])),
+ (OptionKey('unity_size'), BuiltinOption(UserIntegerOption, 'Unity block size', (2, None, 4))),
+ (OptionKey('warning_level'), BuiltinOption(UserComboOption, 'Compiler warning level to use', '1', choices=['0', '1', '2', '3'], 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'])),
+ (OptionKey('force_fallback_for'), BuiltinOption(UserArrayOption, 'Force fallback for those subprojects', [])),
+])
BUILTIN_OPTIONS = OrderedDict(chain(BUILTIN_DIR_OPTIONS.items(), BUILTIN_CORE_OPTIONS.items()))
-BUILTIN_OPTIONS_PER_MACHINE = OrderedDict([
- ('pkg_config_path', BuiltinOption(UserArrayOption, 'List of additional paths for pkg-config to search', [])),
- ('cmake_prefix_path', BuiltinOption(UserArrayOption, 'List of additional prefixes for cmake to search', [])),
+BUILTIN_OPTIONS_PER_MACHINE: 'KeyedOptionDictType' = OrderedDict([
+ (OptionKey('pkg_config_path'), BuiltinOption(UserArrayOption, 'List of additional paths for pkg-config to search', [])),
+ (OptionKey('cmake_prefix_path'), BuiltinOption(UserArrayOption, 'List of additional prefixes for cmake to search', [])),
])
# Special prefix-dependent defaults for installation directories that reside in
# a path outside of the prefix in FHS and common usage.
-builtin_dir_noprefix_options = {
- 'sysconfdir': {'/usr': '/etc'},
- 'localstatedir': {'/usr': '/var', '/usr/local': '/var/local'},
- 'sharedstatedir': {'/usr': '/var/lib', '/usr/local': '/var/local/lib'},
+BULITIN_DIR_NOPREFIX_OPTIONS: T.Dict[OptionKey, T.Dict[str, str]] = {
+ OptionKey('sysconfdir'): {'/usr': '/etc'},
+ OptionKey('localstatedir'): {'/usr': '/var', '/usr/local': '/var/local'},
+ OptionKey('sharedstatedir'): {'/usr': '/var/lib', '/usr/local': '/var/local/lib'},
}
FORBIDDEN_TARGET_NAMES = {'clean': None,
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index 6f568d3..7b8045d 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -37,7 +37,7 @@ from ..environment import Environment, MachineInfo
from ..cmake import CMakeExecutor, CMakeTraceParser, CMakeException, CMakeToolchain, CMakeExecScope, check_cmake_args
from ..mesonlib import MachineChoice, MesonException, OrderedSet, PerMachine
from ..mesonlib import Popen_safe, version_compare_many, version_compare, listify, stringlistify, extract_as_list, split_args
-from ..mesonlib import Version, LibType
+from ..mesonlib import Version, LibType, OptionKey
from ..mesondata import mesondata
if T.TYPE_CHECKING:
@@ -656,8 +656,9 @@ class PkgConfigDependency(ExternalDependency):
return rc, out, err
@staticmethod
- def setup_env(env, environment, for_machine, extra_path=None):
- extra_paths = environment.coredata.builtins_per_machine[for_machine]['pkg_config_path'].value
+ def setup_env(env: T.MutableMapping[str, str], environment: 'Environment', for_machine: MachineChoice,
+ extra_path: T.Optional[str] = None) -> None:
+ extra_paths: T.List[str] = environment.coredata.builtins[OptionKey('pkg_config_path', machine=for_machine)].value
if extra_path:
extra_paths.append(extra_path)
sysroot = environment.properties[for_machine].get_sys_root()
@@ -1484,9 +1485,9 @@ class CMakeDependency(ExternalDependency):
cfgs = [x for x in tgt.properties['IMPORTED_CONFIGURATIONS'] if x]
cfg = cfgs[0]
- if 'b_vscrt' in self.env.coredata.base_options:
+ if OptionKey('b_vscrt') in self.env.coredata.base_options:
is_debug = self.env.coredata.get_builtin_option('buildtype') == 'debug'
- if self.env.coredata.base_options['b_vscrt'].value in ('mdd', 'mtd'):
+ if self.env.coredata.base_options[OptionKey('b_vscrt')].value in {'mdd', 'mtd'}:
is_debug = True
else:
is_debug = self.env.coredata.get_builtin_option('debug')
diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py
index 370fa72..e2e4789 100644
--- a/mesonbuild/dependencies/boost.py
+++ b/mesonbuild/dependencies/boost.py
@@ -616,8 +616,8 @@ class BoostDependency(ExternalDependency):
# MSVC is very picky with the library tags
vscrt = ''
try:
- crt_val = self.env.coredata.base_options['b_vscrt'].value
- buildtype = self.env.coredata.builtins['buildtype'].value
+ crt_val = self.env.coredata.base_options[mesonlib.OptionKey('b_vscrt')].value
+ buildtype = self.env.coredata.builtins[mesonlib.OptionKey('buildtype')].value
vscrt = self.clib_compiler.get_crt_compile_args(crt_val, buildtype)[0]
except (KeyError, IndexError, AttributeError):
pass
diff --git a/mesonbuild/dependencies/ui.py b/mesonbuild/dependencies/ui.py
index baf8e94..942f69a 100644
--- a/mesonbuild/dependencies/ui.py
+++ b/mesonbuild/dependencies/ui.py
@@ -383,8 +383,8 @@ class QtBaseDependency(ExternalDependency):
# Use the buildtype by default, but look at the b_vscrt option if the
# compiler supports it.
is_debug = self.env.coredata.get_builtin_option('buildtype') == 'debug'
- if 'b_vscrt' in self.env.coredata.base_options:
- if self.env.coredata.base_options['b_vscrt'].value in ('mdd', 'mtd'):
+ if mesonlib.OptionKey('b_vscrt') in self.env.coredata.base_options:
+ if self.env.coredata.base_options[mesonlib.OptionKey('b_vscrt')].value in {'mdd', 'mtd'}:
is_debug = True
modules_lib_suffix = self._get_modules_lib_suffix(is_debug)
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index b4336eb..1329ecf 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -11,7 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import pdb
from . import mparser
from . import environment
from . import coredata
@@ -22,7 +21,7 @@ from . import optinterpreter
from . import compilers
from .wrap import wrap, WrapMode
from . import mesonlib
-from .mesonlib import FileMode, MachineChoice, Popen_safe, listify, extract_as_list, has_path_sep, unholder
+from .mesonlib import FileMode, MachineChoice, OptionKey, Popen_safe, listify, extract_as_list, has_path_sep, unholder
from .dependencies import ExternalProgram
from .dependencies import InternalDependency, Dependency, NotFoundDependency, DependencyException
from .depfile import DepFile
@@ -83,7 +82,7 @@ class FeatureOptionHolder(InterpreterObject, ObjectHolder):
InterpreterObject.__init__(self)
ObjectHolder.__init__(self, option)
if option.is_auto():
- self.held_object = env.coredata.builtins['auto_features']
+ self.held_object = env.coredata.builtins[OptionKey('auto_features')]
self.name = name
self.methods.update({'enabled': self.enabled_method,
'disabled': self.disabled_method,
@@ -3010,7 +3009,7 @@ external dependencies (including libraries) must go to "dependencies".''')
def _do_subproject_cmake(self, subp_name, subdir, subdir_abs, default_options, kwargs):
with mlog.nested():
new_build = self.build.copy()
- prefix = self.coredata.builtins['prefix'].value
+ prefix = self.coredata.builtins[OptionKey('prefix')].value
from .modules.cmake import CMakeSubprojectOptions
options = kwargs.get('options', CMakeSubprojectOptions())
@@ -3052,23 +3051,10 @@ external dependencies (including libraries) must go to "dependencies".''')
return result
def get_option_internal(self, optname: str):
- raw_optname = optname
- if self.is_subproject():
- optname = self.subproject + ':' + optname
-
-
- for opts in [
- self.coredata.base_options, compilers.base_options, self.coredata.builtins,
- dict(self.coredata.get_prefixed_options_per_machine(self.coredata.builtins_per_machine)),
- ]:
- v = opts.get(optname)
- if v is None or v.yielding:
- v = opts.get(raw_optname)
- if v is not None:
- return v
+ # TODO: this optname may be a compiler option
+ key = OptionKey.from_string(optname).evolve(subproject=self.subproject)
- key = mesonlib.OptionKey.from_string(optname)
- for opts in [self.coredata.compiler_options]:
+ for opts in [self.coredata.builtins, self.coredata.base_options, compilers.base_options, self.coredata.compiler_options]:
v = opts.get(key)
if v is None or v.yielding:
v = opts.get(key.as_root())
@@ -3090,7 +3076,7 @@ external dependencies (including libraries) must go to "dependencies".''')
mlog.warning('Option {0!r} of type {1!r} in subproject {2!r} cannot yield '
'to parent option of type {3!r}, ignoring parent value. '
'Use -D{2}:{0}=value to set the value for this option manually'
- '.'.format(raw_optname, opt_type, self.subproject, popt_type),
+ '.'.format(optname, opt_type, self.subproject, popt_type),
location=self.current_node)
return opt
except KeyError:
@@ -4786,15 +4772,15 @@ different subdirectory.
break
def check_clang_asan_lundef(self) -> None:
- if 'b_lundef' not in self.coredata.base_options:
+ if OptionKey('b_lundef') not in self.coredata.base_options:
return
- if 'b_sanitize' not in self.coredata.base_options:
+ if OptionKey('b_sanitize') not in self.coredata.base_options:
return
- if (self.coredata.base_options['b_lundef'].value and
- self.coredata.base_options['b_sanitize'].value != 'none'):
+ if (self.coredata.base_options[OptionKey('b_lundef')].value and
+ self.coredata.base_options[OptionKey('b_sanitize')].value != 'none'):
mlog.warning('''Trying to use {} sanitizer on Clang with b_lundef.
This will probably not work.
-Try setting b_lundef to false instead.'''.format(self.coredata.base_options['b_sanitize'].value),
+Try setting b_lundef to false instead.'''.format(self.coredata.base_options[OptionKey('b_sanitize')].value),
location=self.current_node)
def evaluate_subproject_info(self, path_from_source_root, subproject_dir):
@@ -4889,10 +4875,11 @@ Try setting b_lundef to false instead.'''.format(self.coredata.base_options['b_s
# Check if user forces non-PIC static library.
pic = True
+ key = OptionKey('b_staticpic')
if 'pic' in kwargs:
pic = kwargs['pic']
- elif 'b_staticpic' in self.environment.coredata.base_options:
- pic = self.environment.coredata.base_options['b_staticpic'].value
+ elif key in self.environment.coredata.base_options:
+ pic = self.environment.coredata.base_options[key].value
if pic:
# Exclude sources from args and kwargs to avoid building them twice
diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py
index 70d6806..d6584d5 100644
--- a/mesonbuild/mconf.py
+++ b/mesonbuild/mconf.py
@@ -17,12 +17,11 @@ from . import coredata, environment, mesonlib, build, mintro, mlog
from .ast import AstIDGenerator
import typing as T
-from .mesonlib import MachineChoice
+from .mesonlib import MachineChoice, OptionKey
if T.TYPE_CHECKING:
import argparse
from .coredata import UserOption
- from .mesonlib import OptionKey
def add_arguments(parser: 'argparse.ArgumentParser') -> None:
coredata.register_builtin_arguments(parser)
@@ -30,7 +29,6 @@ def add_arguments(parser: 'argparse.ArgumentParser') -> None:
parser.add_argument('--clearcache', action='store_true', default=False,
help='Clear cached state (e.g. found dependencies)')
-
def make_lower_case(val: T.Any) -> T.Union[str, T.List[T.Any]]: # T.Any because of recursion...
if isinstance(val, bool):
return str(val).lower()
@@ -39,12 +37,6 @@ def make_lower_case(val: T.Any) -> T.Union[str, T.List[T.Any]]: # T.Any because
else:
return str(val)
-def insert_build_prefix(k: str) -> str:
- idx = k.find(':')
- if idx < 0:
- return 'build.' + k
- return k[:idx + 1] + 'build.' + k[idx + 1:]
-
class ConfException(mesonlib.MesonException):
pass
@@ -62,8 +54,8 @@ class Conf:
self.choices_col = []
self.descr_col = []
self.has_choices = False
- self.all_subprojects = set()
- self.yielding_options = set()
+ self.all_subprojects: T.Set[str] = set()
+ self.yielding_options: T.Set[OptionKey] = set()
if os.path.isdir(os.path.join(self.build_dir, 'meson-private')):
self.build = build.load(self.build_dir)
@@ -111,20 +103,8 @@ class Conf:
else:
print('{0:{width[0]}} {1:{width[1]}} {3}'.format(*line, width=col_widths))
- def split_options_per_subproject(self, options: T.Dict[str, 'UserOption']) -> T.Dict[str, T.Dict[str, 'UserOption']]:
- result = {}
- for k, o in options.items():
- subproject = ''
- if ':' in k:
- subproject, optname = k.split(':')
- if o.yielding and optname in options:
- self.yielding_options.add(k)
- self.all_subprojects.add(subproject)
- result.setdefault(subproject, {})[k] = o
- return result
-
- def split_options_per_subproject2(self, options: 'coredata.KeyedOptionDictType') -> T.Dict[str, T.Dict[str, 'UserOption']]:
- result = {}
+ def split_options_per_subproject(self, options: 'coredata.KeyedOptionDictType') -> T.Dict[str, T.Dict[str, 'UserOption']]:
+ result: T.Dict[str, T.Dict[str, 'UserOption']] = {}
for k, o in options.items():
subproject = k.subproject
if k.subproject:
@@ -135,8 +115,8 @@ class Conf:
result.setdefault(subproject, {})[str(k)] = o
return result
- def _add_line(self, name, value, choices, descr):
- self.name_col.append(' ' * self.print_margin + name)
+ def _add_line(self, name: OptionKey, value, choices, descr) -> None:
+ self.name_col.append(' ' * self.print_margin + str(name))
self.value_col.append(value)
self.choices_col.append(choices)
self.descr_col.append(descr)
@@ -185,7 +165,7 @@ class Conf:
self._add_line(section + ':', '', '', '')
self.print_margin = 2
- def print_options(self, title: str, options: 'coredata.OptionDictType') -> None:
+ def print_options(self, title: str, options: 'coredata.KeyedOptionDictType') -> None:
if not options:
return
if title:
@@ -210,28 +190,28 @@ class Conf:
if not self.default_values_only:
print(' Build dir ', self.build_dir)
- dir_option_names = list(coredata.BUILTIN_DIR_OPTIONS)
- test_option_names = ['errorlogs',
- 'stdsplit']
- core_option_names = [k for k in self.coredata.builtins if k not in dir_option_names + test_option_names]
+ dir_option_names = set(coredata.BUILTIN_DIR_OPTIONS)
+ test_option_names = {OptionKey('errorlogs'),
+ OptionKey('stdsplit')}
+ core_option_names = [k for k in self.coredata.builtins if k not in dir_option_names | test_option_names]
dir_options = {k: o for k, o in self.coredata.builtins.items() if k in dir_option_names}
test_options = {k: o for k, o in self.coredata.builtins.items() if k in test_option_names}
core_options = {k: o for k, o in self.coredata.builtins.items() if k in core_option_names}
- core_options = self.split_options_per_subproject(core_options)
- host_compiler_options = self.split_options_per_subproject2({k: v for k, v in self.coredata.compiler_options.items() if k.machine is MachineChoice.HOST})
- build_compiler_options = self.split_options_per_subproject2({k: v for k, v in self.coredata.compiler_options.items() if k.machine is MachineChoice.BUILD})
- project_options = self.split_options_per_subproject2(self.coredata.user_options)
+ host_core_options = self.split_options_per_subproject({k: v for k, v in self.coredata.builtins.items() if k.machine is MachineChoice.HOST})
+ build_core_options = self.split_options_per_subproject({k: v for k, v in self.coredata.builtins.items() if k.machine is MachineChoice.BUILD})
+ host_compiler_options = self.split_options_per_subproject({k: v for k, v in self.coredata.compiler_options.items() if k.machine is MachineChoice.HOST})
+ build_compiler_options = self.split_options_per_subproject({k: v for k, v in self.coredata.compiler_options.items() if k.machine is MachineChoice.BUILD})
+ project_options = self.split_options_per_subproject(self.coredata.user_options)
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', core_options[''])
- self.print_options('', self.coredata.builtins_per_machine.host)
+ self.print_options('Core options', host_core_options[''])
if show_build_options:
- self.print_options('', {insert_build_prefix(k): o for k, o in self.coredata.builtins_per_machine.build.items()})
+ self.print_options('', build_core_options[''])
self.print_options('Backend options', {str(k): v for k, v in self.coredata.backend_options.items()})
- self.print_options('Base options', self.coredata.base_options)
+ self.print_options('Base options', {str(k): v for k, v in self.coredata.base_options.items()})
self.print_options('Compiler options', host_compiler_options.get('', {}))
if show_build_options:
self.print_options('', build_compiler_options.get('', {}))
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index 8252f79..07cc3a1 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -32,7 +32,7 @@ from mesonbuild import mlog
if T.TYPE_CHECKING:
from .build import ConfigurationData
- from .coredata import OptionDictType, UserOption
+ from .coredata import KeyedOptionDictType, UserOption
from .compilers.compilers import CompilerType
from .interpreterbase import ObjectHolder
@@ -1743,6 +1743,10 @@ class OptionProxy(T.Generic[_T]):
self.value = value
self.choices = choices
+ def set_value(self, v: _T) -> None:
+ # XXX: should this be an error
+ self.value = v
+
class OptionOverrideProxy(collections.abc.MutableMapping):
@@ -1753,13 +1757,13 @@ class OptionOverrideProxy(collections.abc.MutableMapping):
# TODO: the typing here could be made more explicit using a TypeDict from
# python 3.8 or typing_extensions
- def __init__(self, overrides: T.Dict[str, T.Any], *options: 'OptionDictType'):
+ def __init__(self, overrides: T.Dict['OptionKey', T.Any], *options: 'KeyedOptionDictType'):
self.overrides = overrides.copy()
- self.options = {} # type: T.Dict[str, UserOption]
+ self.options: T.Dict['OptionKey', UserOption] = {}
for o in options:
self.options.update(o)
- def __getitem__(self, key: str) -> T.Union['UserOption', OptionProxy]:
+ def __getitem__(self, key: 'OptionKey') -> T.Union['UserOption', OptionProxy]:
if key in self.options:
opt = self.options[key]
if key in self.overrides:
@@ -1767,13 +1771,13 @@ class OptionOverrideProxy(collections.abc.MutableMapping):
return opt
raise KeyError('Option not found', key)
- def __setitem__(self, key: str, value: T.Union['UserOption', OptionProxy]) -> None:
+ def __setitem__(self, key: 'OptionKey', value: T.Union['UserOption', OptionProxy]) -> None:
self.overrides[key] = value.value
- def __delitem__(self, key: str) -> None:
+ def __delitem__(self, key: 'OptionKey') -> None:
del self.overrides[key]
- def __iter__(self) -> T.Iterator[str]:
+ def __iter__(self) -> T.Iterator['OptionKey']:
return iter(self.options)
def __len__(self) -> int:
@@ -1793,20 +1797,54 @@ class OptionType(enum.Enum):
PROJECT = 3
BACKEND = 4
+# This is copied from coredata. There is no way to share this, because this
+# is used in the OptionKey constructor, and the coredata lists are
+# OptionKeys...
+_BUILTIN_NAMES = {
+ 'prefix',
+ 'bindir',
+ 'datadir',
+ 'includedir',
+ 'infodir',
+ 'libdir',
+ 'libexecdir',
+ 'localedir',
+ 'localstatedir',
+ 'mandir',
+ 'sbindir',
+ 'sharedstatedir',
+ 'sysconfdir',
+ 'auto_features',
+ 'backend',
+ 'buildtype',
+ 'debug',
+ 'default_library',
+ 'errorlogs',
+ 'install_umask',
+ 'layout',
+ 'optimization',
+ 'stdsplit',
+ 'strip',
+ 'unity',
+ 'unity_size',
+ 'warning_level',
+ 'werror',
+ 'wrap_mode',
+ 'force_fallback_for',
+ 'pkg_config_path',
+ 'cmake_prefix_path',
+}
+
def _classify_argument(key: 'OptionKey') -> OptionType:
"""Classify arguments into groups so we know which dict to assign them to."""
- from .compilers import base_options
- from .coredata import BUILTIN_OPTIONS, BUILTIN_OPTIONS_PER_MACHINE, builtin_dir_noprefix_options
- all_builtins = set(BUILTIN_OPTIONS) | set(BUILTIN_OPTIONS_PER_MACHINE) | set(builtin_dir_noprefix_options)
-
- if key.name in base_options:
+ if key.name.startswith('b_'):
assert key.machine is MachineChoice.HOST, str(key)
return OptionType.BASE
elif key.lang is not None:
return OptionType.COMPILER
- elif key.name in all_builtins:
+ elif key.name in _BUILTIN_NAMES:
return OptionType.BUILTIN
elif key.name.startswith('backend_'):
assert key.machine is MachineChoice.HOST, str(key)
@@ -1868,9 +1906,10 @@ class OptionKey:
This is very clever. __init__ is not a constructor, it's an
initializer, therefore it's safe to call more than once. We create a
state in the custom __getstate__ method, which is valid to pass
- unsplatted to the initializer.
+ splatted to the initializer.
"""
- self.__init__(**state)
+ # Mypy doesn't like this, because it's so clever.
+ self.__init__(**state) # type: ignore
def __hash__(self) -> int:
return self._hash
@@ -1884,6 +1923,15 @@ class OptionKey:
self.lang == other.lang)
return NotImplemented
+ def __lt__(self, other: object) -> bool:
+ if isinstance(other, OptionKey):
+ return (
+ self.name < other.name and
+ self.subproject < other.subproject and
+ self.machine < other.machine and
+ self.lang < other.lang)
+ return NotImplemented
+
def __str__(self) -> str:
out = self.name
if self.lang:
diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py
index 7b2560f..b1d2831 100644
--- a/mesonbuild/mintro.py
+++ b/mesonbuild/mintro.py
@@ -33,7 +33,7 @@ import typing as T
import os
import argparse
-from .mesonlib import MachineChoice
+from .mesonlib import MachineChoice, OptionKey
def get_meson_info_file(info_dir: str) -> str:
return os.path.join(info_dir, 'meson-info.json')
@@ -213,24 +213,16 @@ def list_buildoptions_from_source(intr: IntrospectionInterpreter) -> T.List[T.Di
def list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[str]] = None) -> T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]:
optlist = [] # type: T.List[T.Dict[str, T.Union[str, bool, int, T.List[str]]]]
- dir_option_names = list(cdata.BUILTIN_DIR_OPTIONS)
- test_option_names = ['errorlogs',
- 'stdsplit']
- core_option_names = [k for k in coredata.builtins if k not in dir_option_names + test_option_names]
-
- dir_options = {k: o for k, o in coredata.builtins.items() if k in dir_option_names}
- test_options = {k: o for k, o in coredata.builtins.items() if k in test_option_names}
- core_options = {k: o for k, o in coredata.builtins.items() if k in core_option_names}
-
- if subprojects:
- # Add per subproject built-in options
- sub_core_options = {}
- for sub in subprojects:
- for k, o in core_options.items():
- if o.yielding:
- continue
- sub_core_options[sub + ':' + k] = o
- core_options.update(sub_core_options)
+ dir_option_names = set(cdata.BUILTIN_DIR_OPTIONS)
+ test_option_names = {OptionKey('errorlogs'),
+ OptionKey('stdsplit')}
+ core_option_names = {k for k in coredata.builtins if k not in dir_option_names | test_option_names}
+
+ dir_options = {str(k): o for k, o in coredata.builtins.items() if k in dir_option_names}
+ test_options = {str(k): o for k, o in coredata.builtins.items() if k in test_option_names}
+ core_options = {str(k): o for k, o in coredata.builtins.items() if k in core_option_names}
+ for s in subprojects or []:
+ core_options.update({str(k.evolve(subproject=s)): v for k, v in coredata.builtins.items() if not v.yielding})
def add_keys(options: 'cdata.OptionDictType', section: str, machine: str = 'any') -> None:
for key, opt in sorted(options.items()):
@@ -253,14 +245,8 @@ def list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[s
optlist.append(optdict)
add_keys(core_options, 'core')
- add_keys(coredata.builtins_per_machine.host, 'core', machine='host')
- add_keys(
- {'build.' + k: o for k, o in coredata.builtins_per_machine.build.items()},
- 'core',
- machine='build',
- )
add_keys({str(k): v for k, v in coredata.backend_options.items()}, 'backend')
- add_keys(coredata.base_options, 'base')
+ add_keys({str(k): v for k, v in coredata.base_options.items()}, 'base')
add_keys(
{str(k): v for k, v in coredata.compiler_options.items() if k.machine is MachineChoice.HOST},
'compiler',
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index 547aff1..565fd82 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -19,6 +19,7 @@ import os
import copy
import subprocess
import functools
+import typing as T
from .. import build
from .. import mlog
@@ -35,6 +36,9 @@ from ..mesonlib import (
from ..dependencies import Dependency, PkgConfigDependency, InternalDependency, ExternalProgram
from ..interpreterbase import noKwargs, permittedKwargs, FeatureNew, FeatureNewKwargs, FeatureDeprecatedKwargs
+if T.TYPE_CHECKING:
+ from ..compilers import Compiler
+
# gresource compilation is broken due to the way
# the resource compiler and Ninja clash about it
#
@@ -574,8 +578,8 @@ class GnomeModule(ExtensionModule):
return ret
- def _get_girtargets_langs_compilers(self, girtargets):
- ret = []
+ def _get_girtargets_langs_compilers(self, girtargets: T.List[GirTarget]) -> T.List[T.Tuple[str, 'Compiler']]:
+ ret: T.List[T.Tuple[str, 'Compiler']] = []
for girtarget in girtargets:
for lang, compiler in girtarget.compilers.items():
# XXX: Can you use g-i with any other language?
@@ -598,7 +602,7 @@ class GnomeModule(ExtensionModule):
ret += girtarget.get_include_dirs()
return ret
- def _get_langs_compilers_flags(self, state, langs_compilers):
+ def _get_langs_compilers_flags(self, state, langs_compilers: T.List[T.Tuple[str, 'Compiler']]):
cflags = []
internal_ldflags = []
external_ldflags = []
@@ -608,8 +612,8 @@ class GnomeModule(ExtensionModule):
cflags += state.global_args[lang]
if state.project_args.get(lang):
cflags += state.project_args[lang]
- if 'b_sanitize' in compiler.base_options:
- sanitize = state.environment.coredata.base_options['b_sanitize'].value
+ if mesonlib.OptionKey('b_sanitize') in compiler.base_options:
+ sanitize = state.environment.coredata.base_options[mesonlib.OptionKey('b_sanitize')].value
cflags += compiler.sanitizer_compile_args(sanitize)
sanitize = sanitize.split(',')
# These must be first in ldflags
diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py
index d336a13..55c9e09 100644
--- a/mesonbuild/msetup.py
+++ b/mesonbuild/msetup.py
@@ -177,7 +177,7 @@ class MesonApp:
mlog.initialize(env.get_log_dir(), self.options.fatal_warnings)
if self.options.profile:
mlog.set_timestamp_start(time.monotonic())
- if env.coredata.builtins['backend'].value == 'xcode':
+ if env.coredata.builtins[mesonlib.OptionKey('backend')].value == 'xcode':
mlog.warning('xcode backend is currently unmaintained, patches welcome')
with mesonlib.BuildDirLock(self.build_dir):
self._generate(env)
diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py
index 776a39a..fbbdcc1 100644
--- a/mesonbuild/rewriter.py
+++ b/mesonbuild/rewriter.py
@@ -464,11 +464,9 @@ class Rewriter:
cdata = self.interpreter.coredata
options = {
- **cdata.builtins,
- **cdata.builtins_per_machine.host,
- **{'build.' + k: o for k, o in cdata.builtins_per_machine.build.items()},
+ **{str(k): v for k, v in cdata.builtins.items()},
**{str(k): v for k, v in cdata.backend_options.items()},
- **cdata.base_options,
+ **{str(k): v for k, v in cdata.base_options.items()},
**{str(k): v for k, v in cdata.compiler_options.items()},
**{str(k): v for k, v in cdata.user_options.items()},
}
diff --git a/run_unittests.py b/run_unittests.py
index 744556e..cba46c5 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -263,7 +263,8 @@ def skip_if_not_base_option(feature):
def wrapped(*args, **kwargs):
env = get_fake_env()
cc = env.detect_c_compiler(MachineChoice.HOST)
- if feature not in cc.base_options:
+ key = OptionKey(feature)
+ if key not in cc.base_options:
raise unittest.SkipTest(
'{} not available with {}'.format(feature, cc.id))
return f(*args, **kwargs)
@@ -1390,8 +1391,8 @@ class DataTests(unittest.TestCase):
found_entries |= options
self.assertEqual(found_entries, set([
- *mesonbuild.coredata.BUILTIN_OPTIONS.keys(),
- *mesonbuild.coredata.BUILTIN_OPTIONS_PER_MACHINE.keys()
+ *[str(k) for k in mesonbuild.coredata.BUILTIN_OPTIONS],
+ *[str(k) for k in mesonbuild.coredata.BUILTIN_OPTIONS_PER_MACHINE],
]))
# Check that `buildtype` table inside `Core options` matches how
@@ -1412,10 +1413,10 @@ class DataTests(unittest.TestCase):
debug = False
else:
raise RuntimeError('Invalid debug value {!r} in row:\n{}'.format(debug, m.group()))
- env.coredata.set_builtin_option('buildtype', buildtype)
- self.assertEqual(env.coredata.builtins['buildtype'].value, buildtype)
- self.assertEqual(env.coredata.builtins['optimization'].value, opt)
- self.assertEqual(env.coredata.builtins['debug'].value, debug)
+ env.coredata.set_builtin_option(OptionKey('buildtype'), buildtype)
+ self.assertEqual(env.coredata.builtins[OptionKey('buildtype')].value, buildtype)
+ self.assertEqual(env.coredata.builtins[OptionKey('optimization')].value, opt)
+ self.assertEqual(env.coredata.builtins[OptionKey('debug')].value, debug)
def test_cpu_families_documented(self):
with open("docs/markdown/Reference-tables.md", encoding='utf-8') as f:
@@ -1903,11 +1904,14 @@ class AllPlatformTests(BasePlatformTests):
https://github.com/mesonbuild/meson/issues/1349
'''
testdir = os.path.join(self.common_test_dir, '88 default options')
- self.init(testdir, default_args=False)
+ self.init(testdir, default_args=False, inprocess=True)
opts = self.introspect('--buildoptions')
for opt in opts:
if opt['name'] == 'prefix':
prefix = opt['value']
+ break
+ else:
+ raise self.fail('Did not find option "prefix"')
self.assertEqual(prefix, '/absoluteprefix')
def test_do_conf_file_preserve_newlines(self):
@@ -3679,35 +3683,34 @@ class AllPlatformTests(BasePlatformTests):
def test_command_line(self):
testdir = os.path.join(self.unit_test_dir, '34 command line')
- K = OptionKey
# Verify default values when passing no args that affect the
# configuration, and as a bonus, test that --profile-self works.
self.init(testdir, extra_args=['--profile-self', '--fatal-meson-warnings'])
obj = mesonbuild.coredata.load(self.builddir)
- self.assertEqual(obj.builtins['default_library'].value, 'static')
- self.assertEqual(obj.builtins['warning_level'].value, '1')
- self.assertEqual(obj.user_options[K('set_sub_opt')].value, True)
- self.assertEqual(obj.user_options[K('subp_opt', 'subp')].value, 'default3')
+ self.assertEqual(obj.builtins[OptionKey('default_library')].value, 'static')
+ self.assertEqual(obj.builtins[OptionKey('warning_level')].value, '1')
+ self.assertEqual(obj.user_options[OptionKey('set_sub_opt')].value, True)
+ self.assertEqual(obj.user_options[OptionKey('subp_opt', 'subp')].value, '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.builtins['warning_level'].value, '2')
+ self.assertEqual(obj.builtins[OptionKey('warning_level')].value, '2')
self.setconf('--warnlevel=3')
obj = mesonbuild.coredata.load(self.builddir)
- self.assertEqual(obj.builtins['warning_level'].value, '3')
+ self.assertEqual(obj.builtins[OptionKey('warning_level')].value, '3')
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.builtins['warning_level'].value, '2')
+ self.assertEqual(obj.builtins[OptionKey('warning_level')].value, '2')
self.setconf('-Dwarning_level=3')
obj = mesonbuild.coredata.load(self.builddir)
- self.assertEqual(obj.builtins['warning_level'].value, '3')
+ self.assertEqual(obj.builtins[OptionKey('warning_level')].value, '3')
self.wipe()
# Mixing --option and -Doption is forbidden
@@ -3731,15 +3734,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.builtins['default_library'].value, 'both')
+ self.assertEqual(obj.builtins[OptionKey('default_library')].value, 'both')
self.setconf('--default-library=shared')
obj = mesonbuild.coredata.load(self.builddir)
- self.assertEqual(obj.builtins['default_library'].value, 'shared')
+ self.assertEqual(obj.builtins[OptionKey('default_library')].value, '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.builtins['default_library'].value, 'shared')
+ self.assertEqual(obj.builtins[OptionKey('default_library')].value, 'shared')
self.wipe()
# Should warn on unknown options
@@ -3774,7 +3777,7 @@ 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.user_options[K('subp_opt', 'subp')].value, 'foo')
+ self.assertEqual(obj.user_options[OptionKey('subp_opt', 'subp')].value, 'foo')
self.wipe()
# c_args value should be parsed with split_args
@@ -3789,7 +3792,7 @@ class AllPlatformTests(BasePlatformTests):
self.init(testdir, extra_args=['-Dset_percent_opt=myoption%', '--fatal-meson-warnings'])
obj = mesonbuild.coredata.load(self.builddir)
- self.assertEqual(obj.user_options[K('set_percent_opt')].value, 'myoption%')
+ self.assertEqual(obj.user_options[OptionKey('set_percent_opt')].value, 'myoption%')
self.wipe()
# Setting a 2nd time the same option should override the first value
@@ -3800,18 +3803,18 @@ class AllPlatformTests(BasePlatformTests):
'-Dc_args=-Dfoo', '-Dc_args=-Dbar',
'-Db_lundef=false', '--fatal-meson-warnings'])
obj = mesonbuild.coredata.load(self.builddir)
- self.assertEqual(obj.builtins['bindir'].value, 'bar')
- self.assertEqual(obj.builtins['buildtype'].value, 'release')
- self.assertEqual(obj.base_options['b_sanitize'].value, 'thread')
+ self.assertEqual(obj.builtins[OptionKey('bindir')].value, 'bar')
+ self.assertEqual(obj.builtins[OptionKey('buildtype')].value, 'release')
+ self.assertEqual(obj.base_options[OptionKey('b_sanitize')].value, 'thread')
self.assertEqual(obj.compiler_options[OptionKey('args', lang='c')].value, ['-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.builtins['bindir'].value, 'foo')
- self.assertEqual(obj.builtins['buildtype'].value, 'plain')
- self.assertEqual(obj.base_options['b_sanitize'].value, 'address')
+ self.assertEqual(obj.builtins[OptionKey('bindir')].value, 'foo')
+ self.assertEqual(obj.builtins[OptionKey('buildtype')].value, 'plain')
+ self.assertEqual(obj.base_options[OptionKey('b_sanitize')].value, 'address')
self.assertEqual(obj.compiler_options[OptionKey('args', lang='c')].value, ['-Dfoo'])
self.wipe()
except KeyError:
@@ -3826,25 +3829,25 @@ class AllPlatformTests(BasePlatformTests):
# Verify default values when passing no args
self.init(testdir)
obj = mesonbuild.coredata.load(self.builddir)
- self.assertEqual(obj.builtins['warning_level'].value, '0')
+ self.assertEqual(obj.builtins[OptionKey('warning_level')].value, '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.builtins['warning_level'].value, '1')
+ self.assertEqual(obj.builtins[OptionKey('warning_level')].value, '1')
self.setconf('--warnlevel=0')
obj = mesonbuild.coredata.load(self.builddir)
- self.assertEqual(obj.builtins['warning_level'].value, '0')
+ self.assertEqual(obj.builtins[OptionKey('warning_level')].value, '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.builtins['warning_level'].value, '1')
+ self.assertEqual(obj.builtins[OptionKey('warning_level')].value, '1')
self.setconf('-Dwarning_level=0')
obj = mesonbuild.coredata.load(self.builddir)
- self.assertEqual(obj.builtins['warning_level'].value, '0')
+ self.assertEqual(obj.builtins[OptionKey('warning_level')].value, '0')
self.wipe()
def test_feature_check_usage_subprojects(self):
@@ -5771,7 +5774,7 @@ class WindowsTests(BasePlatformTests):
# Verify that the `b_vscrt` option is available
env = get_fake_env()
cc = env.detect_c_compiler(MachineChoice.HOST)
- if 'b_vscrt' not in cc.base_options:
+ if OptionKey('b_vscrt') not in cc.base_options:
raise unittest.SkipTest('Compiler does not support setting the VS CRT')
# Verify that qmake is for Qt5
if not shutil.which('qmake-qt5'):
@@ -5797,7 +5800,7 @@ class WindowsTests(BasePlatformTests):
# Verify that the `b_vscrt` option is available
env = get_fake_env()
cc = env.detect_c_compiler(MachineChoice.HOST)
- if 'b_vscrt' not in cc.base_options:
+ if OptionKey('b_vscrt') not in cc.base_options:
raise unittest.SkipTest('Compiler does not support setting the VS CRT')
def sanitycheck_vscrt(vscrt):