aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/backend/backends.py15
-rw-r--r--mesonbuild/backend/ninjabackend.py13
-rw-r--r--mesonbuild/backend/vs2010backend.py10
-rw-r--r--mesonbuild/build.py12
-rw-r--r--mesonbuild/cmake/interpreter.py7
-rw-r--r--mesonbuild/compilers/c.py141
-rw-r--r--mesonbuild/compilers/compilers.py26
-rw-r--r--mesonbuild/compilers/cpp.py202
-rw-r--r--mesonbuild/compilers/cuda.py17
-rw-r--r--mesonbuild/compilers/fortran.py40
-rw-r--r--mesonbuild/compilers/mixins/emscripten.py7
-rw-r--r--mesonbuild/compilers/mixins/islinker.py6
-rw-r--r--mesonbuild/compilers/objc.py2
-rw-r--r--mesonbuild/compilers/objcpp.py2
-rw-r--r--mesonbuild/compilers/rust.py13
-rw-r--r--mesonbuild/compilers/swift.py2
-rw-r--r--mesonbuild/compilers/vala.py4
-rw-r--r--mesonbuild/coredata.py63
-rw-r--r--mesonbuild/environment.py20
-rw-r--r--mesonbuild/interpreter.py16
-rw-r--r--mesonbuild/linkers.py12
-rw-r--r--mesonbuild/mconf.py11
-rw-r--r--mesonbuild/mintro.py7
-rw-r--r--mesonbuild/rewriter.py3
-rwxr-xr-xrun_tests.py4
-rwxr-xr-xrun_unittests.py44
26 files changed, 382 insertions, 317 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index b9f175a..4c35253 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -36,6 +36,8 @@ from ..mesonlib import (
)
if T.TYPE_CHECKING:
+ from ..arglist import CompilerArgs
+ from ..compilers import Compiler
from ..interpreter import Interpreter, Test
@@ -214,13 +216,10 @@ class Backend:
self.environment.coredata.builtins,
self.environment.coredata.base_options)
- def get_compiler_options_for_target(self, target):
- comp_reg = self.environment.coredata.compiler_options[target.for_machine]
+ 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 {
- lang: OptionOverrideProxy(comp_override[lang], comp_reg[lang])
- for lang in set(comp_reg.keys()) | set(comp_override.keys())
- }
+ return OptionOverrideProxy(comp_override, comp_reg)
def get_option_for_target(self, option_name, target):
if option_name in target.option_overrides_base:
@@ -672,13 +671,13 @@ class Backend:
return extra_args
- def generate_basic_compiler_args(self, target, compiler, no_warn_args=False):
+ def generate_basic_compiler_args(self, target: build.BuildTarget, compiler: 'Compiler', no_warn_args: bool = False) -> 'CompilerArgs':
# Create an empty commands list, and start adding arguments from
# various sources in the order in which they must override each other
# starting from hard-coded defaults followed by build options and so on.
commands = compiler.compiler_args()
- copt_proxy = self.get_compiler_options_for_target(target)[compiler.language]
+ copt_proxy = self.get_compiler_options_for_target(target)
# First, the trivial ones that are impossible to override.
#
# Add -nostdinc/-nostdinc++ if needed; can't be overridden
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 836cd5b..39e0645 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -49,6 +49,9 @@ from ..build import InvalidArguments
from ..interpreter import Interpreter
from ..coredata import OptionKey
+if T.TYPE_CHECKING:
+ from ..linkers import StaticLinker
+
FORTRAN_INCLUDE_PAT = r"^\s*#?include\s*['\"](\w+\.\w+)['\"]"
FORTRAN_MODULE_PAT = r"^\s*\bmodule\b\s+(\w+)\s*(?:!+.*)*$"
FORTRAN_SUBMOD_PAT = r"^\s*\bsubmodule\b\s*\((\w+:?\w+)\)\s*(\w+)"
@@ -891,7 +894,7 @@ int dummy;
cpp = target.compilers['cpp']
if cpp.get_id() != 'msvc':
return False
- if self.environment.coredata.compiler_options[target.for_machine]['cpp']['std'] != 'c++latest':
+ if self.environment.coredata.compiler_options[OptionKey('std', machine=target.for_machine, lang='cpp')] != 'latest':
return False
if not mesonlib.current_vs_supports_modules():
return False
@@ -1614,7 +1617,7 @@ int dummy;
for a in rustc.linker.get_always_args():
args += ['-C', 'link-arg={}'.format(a)]
- opt_proxy = self.get_compiler_options_for_target(target)[rustc.language]
+ 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))
@@ -2832,7 +2835,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
self.add_build(elem)
return [prelink_name]
- def generate_link(self, target, outname, obj_list, linker, extra_args=None, stdlib_args=None):
+ def generate_link(self, target: build.BuildTarget, outname, obj_list, linker: T.Union['Compiler', 'StaticLinker'], extra_args=None, stdlib_args=None):
extra_args = extra_args if extra_args is not None else []
stdlib_args = stdlib_args if stdlib_args is not None else []
implicit_outs = []
@@ -2929,14 +2932,14 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
# to be after all internal and external libraries so that unresolved
# symbols from those can be found here. This is needed when the
# *_winlibs that we want to link to are static mingw64 libraries.
- if hasattr(linker, 'get_language'):
+ if isinstance(linker, Compiler):
# The static linker doesn't know what language it is building, so we
# don't know what option. Fortunately, it doesn't care to see the
# language-specific options either.
#
# We shouldn't check whether we are making a static library, because
# in the LTO case we do use a real compiler here.
- commands += linker.get_option_link_args(self.environment.coredata.compiler_options[target.for_machine][linker.get_language()])
+ commands += linker.get_option_link_args(self.environment.coredata.compiler_options)
dep_targets = []
dep_targets.extend(self.guess_external_link_dependencies(linker, target, commands, internal))
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index 59a5ed4..f893e8f 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -879,7 +879,7 @@ class Vs2010Backend(backends.Backend):
# Exception handling has to be set in the xml in addition to the "AdditionalOptions" because otherwise
# cl will give warning D9025: overriding '/Ehs' with cpp_eh value
if 'cpp' in target.compilers:
- eh = self.environment.coredata.compiler_options[target.for_machine]['cpp']['eh']
+ eh = self.environment.coredata.compiler_options[OptionKey('eh', machine=target.for_machine, lang='cpp')]
if eh.value == 'a':
ET.SubElement(clconf, 'ExceptionHandling').text = 'Async'
elif eh.value == 's':
@@ -927,7 +927,7 @@ class Vs2010Backend(backends.Backend):
file_args[l] += compilers.get_base_compile_args(
self.get_base_options_for_target(target), comp)
file_args[l] += comp.get_option_compile_args(
- self.environment.coredata.compiler_options[target.for_machine][comp.language])
+ self.environment.coredata.compiler_options)
# Add compile args added using add_project_arguments()
for l, args in self.build.projects_args[target.for_machine].get(target.subproject, {}).items():
@@ -941,10 +941,8 @@ class Vs2010Backend(backends.Backend):
# Compile args added from the env or cross file: CFLAGS/CXXFLAGS, etc. We want these
# to override all the defaults, but not the per-target compile args.
for l in file_args.keys():
- opts = self.environment.coredata.compiler_options[target.for_machine][l]
- k = 'args'
- if k in opts:
- file_args[l] += opts[k].value
+ opts = self.environment.coredata.compiler_options[OptionKey('args', machine=target.for_machine, lang=l)]
+ file_args[l] += opts.value
for args in file_args.values():
# This is where Visual Studio will insert target_args, target_defines,
# etc, which are added later from external deps (see below).
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 091bfc8..3b7e10d 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -36,8 +36,10 @@ from .compilers import (
)
from .linkers import StaticLinker
from .interpreterbase import FeatureNew
+from .coredata import OptionKey
if T.TYPE_CHECKING:
+ from .coredata import KeyedOptionDictType, OptionDictType
from .interpreter import Test
from .mesonlib import FileMode, FileOrString
@@ -415,8 +417,8 @@ 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 = {}
- self.option_overrides_compiler = defaultdict(dict)
+ self.option_overrides_base: 'OptionDictType' = {}
+ self.option_overrides_compiler: 'KeyedOptionDictType' = {}
self.extra_files = [] # type: T.List[File]
if not hasattr(self, 'typename'):
raise RuntimeError('Target type is not set for target class "{}". This is a bug'.format(type(self).__name__))
@@ -511,9 +513,9 @@ a hard error in the future.'''.format(name))
for k, v in option_overrides.items():
if '_' in k:
- lang, k2 = k.split('_', 1)
- if lang in all_languages:
- self.option_overrides_compiler[lang][k2] = v
+ key = OptionKey.from_string(k)
+ if key.lang:
+ self.option_overrides_compiler[key.evolve(machine=self.for_machine)] = v
continue
self.option_overrides_base[k] = v
diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py
index d4f7fba..6125f15 100644
--- a/mesonbuild/cmake/interpreter.py
+++ b/mesonbuild/cmake/interpreter.py
@@ -31,6 +31,7 @@ from pathlib import Path
import typing as T
import re
from os import environ
+from ..coredata import OptionKey
from ..mparser import (
Token,
@@ -577,10 +578,10 @@ class ConverterTarget:
@lru_cache(maxsize=None)
def _all_lang_stds(self, lang: str) -> T.List[str]:
- lang_opts = self.env.coredata.compiler_options.build.get(lang, None)
- if not lang_opts or 'std' not in lang_opts:
+ try:
+ res = self.env.coredata.compiler_options[OptionKey('std', machine=MachineChoice.BUILD, lang=lang)].choices # type: ignore
+ except KeyError:
return []
- res = lang_opts['std'].choices
# TODO: Get rid of this once we have propper typing for options
assert isinstance(res, list)
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 7340896..fe5f465 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -37,9 +37,10 @@ from .compilers import (
msvc_winlibs,
Compiler,
)
+from ..coredata import OptionKey
if T.TYPE_CHECKING:
- from ..coredata import OptionDictType
+ from ..coredata import KeyedOptionDictType
from ..dependencies import Dependency, ExternalProgram
from ..envconfig import MachineInfo
from ..environment import Environment
@@ -95,10 +96,10 @@ class CCompiler(CLikeCompiler, Compiler):
return self.compiles(t.format(**fargs), env, extra_args=extra_args,
dependencies=dependencies)
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = super().get_options()
opts.update({
- 'std': coredata.UserComboOption(
+ OptionKey('std', machine=self.for_machine, lang=self.language): coredata.UserComboOption(
'C langauge standard to use',
['none'],
'none',
@@ -119,7 +120,7 @@ class _ClangCStds(CompilerMixinBase):
_C18_VERSION = '>=8.0.0'
_C2X_VERSION = '>=9.0.0'
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = super().get_options()
c_stds = ['c89', 'c99', 'c11']
g_stds = ['gnu89', 'gnu99', 'gnu11']
@@ -134,7 +135,7 @@ class _ClangCStds(CompilerMixinBase):
if version_compare(self.version, self._C2X_VERSION):
c_stds += ['c2x']
g_stds += ['gnu2x']
- opts['std'].choices = ['none'] + c_stds + g_stds
+ opts[OptionKey('std', machine=self.for_machine, lang=self.language)].choices = ['none'] + c_stds + g_stds
return opts
@@ -153,28 +154,28 @@ class ClangCCompiler(_ClangCStds, ClangCompiler, CCompiler):
'2': default_warn_args + ['-Wextra'],
'3': default_warn_args + ['-Wextra', '-Wpedantic']}
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = super().get_options()
if self.info.is_windows() or self.info.is_cygwin():
opts.update({
- 'winlibs': coredata.UserArrayOption(
+ OptionKey('winlibs', machine=self.for_machine, lang=self.language): coredata.UserArrayOption(
'Standard Win libraries to link against',
gnu_winlibs,
),
})
return opts
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ std = options[OptionKey('std', machine=self.for_machine, lang=self.language)]
if std.value != 'none':
args.append('-std=' + std.value)
return args
- def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
if self.info.is_windows() or self.info.is_cygwin():
# without a typedict mypy can't understand this.
- libs = options['winlibs'].value.copy()
+ libs = options[OptionKey('winlibs', machine=self.for_machine, lang=self.language)].value.copy()
assert isinstance(libs, list)
for l in libs:
assert isinstance(l, str)
@@ -223,19 +224,20 @@ class ArmclangCCompiler(ArmclangCompiler, CCompiler):
'2': default_warn_args + ['-Wextra'],
'3': default_warn_args + ['-Wextra', '-Wpedantic']}
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = CCompiler.get_options(self)
- opts['std'].choices = ['none', 'c90', 'c99', 'c11', 'gnu90', 'gnu99', 'gnu11']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ opts[key].choices = ['none', 'c90', 'c99', 'c11', 'gnu90', 'gnu99', 'gnu11']
return opts
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ std = options[OptionKey('std', machine=self.for_machine, lang=self.language)]
if std.value != 'none':
args.append('-std=' + std.value)
return args
- def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return []
@@ -257,7 +259,7 @@ class GnuCCompiler(GnuCompiler, CCompiler):
'2': default_warn_args + ['-Wextra'],
'3': default_warn_args + ['-Wextra', '-Wpedantic']}
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = CCompiler.get_options(self)
c_stds = ['c89', 'c99', 'c11']
g_stds = ['gnu89', 'gnu99', 'gnu11']
@@ -267,27 +269,28 @@ class GnuCCompiler(GnuCompiler, CCompiler):
if version_compare(self.version, self._C2X_VERSION):
c_stds += ['c2x']
g_stds += ['gnu2x']
- opts['std'].choices = ['none'] + c_stds + g_stds
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ opts[key].choices = ['none'] + c_stds + g_stds
if self.info.is_windows() or self.info.is_cygwin():
opts.update({
- 'winlibs': coredata.UserArrayOption(
+ key.evolve('winlibs'): coredata.UserArrayOption(
'Standard Win libraries to link against',
gnu_winlibs,
),
})
return opts
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ std = options[OptionKey('std', lang=self.language, machine=self.for_machine)]
if std.value != 'none':
args.append('-std=' + std.value)
return args
- def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
if self.info.is_windows() or self.info.is_cygwin():
# without a typeddict mypy can't figure this out
- libs = options['winlibs'].value.copy()
+ libs: T.List[str] = options[OptionKey('winlibs', lang=self.language, machine=self.for_machine)].value.copy()
assert isinstance(libs, list)
for l in libs:
assert isinstance(l, str)
@@ -331,9 +334,9 @@ class ElbrusCCompiler(GnuCCompiler, ElbrusCompiler):
ElbrusCompiler.__init__(self)
# It does support some various ISO standards and c/gnu 90, 9x, 1x in addition to those which GNU CC supports.
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = CCompiler.get_options(self)
- opts['std'].choices = [
+ opts[OptionKey('std', machine=self.for_machine, lang=self.language)].choices = [
'none', 'c89', 'c90', 'c9x', 'c99', 'c1x', 'c11',
'gnu89', 'gnu90', 'gnu9x', 'gnu99', 'gnu1x', 'gnu11',
'iso9899:2011', 'iso9899:1990', 'iso9899:199409', 'iso9899:1999',
@@ -368,18 +371,18 @@ class IntelCCompiler(IntelGnuLikeCompiler, CCompiler):
'2': default_warn_args + ['-Wextra'],
'3': default_warn_args + ['-Wextra']}
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = CCompiler.get_options(self)
c_stds = ['c89', 'c99']
g_stds = ['gnu89', 'gnu99']
if version_compare(self.version, '>=16.0.0'):
c_stds += ['c11']
- opts['std'].choices = ['none'] + c_stds + g_stds
+ opts[OptionKey('std', machine=self.for_machine, lang=self.language)].choices = ['none'] + c_stds + g_stds
return opts
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ std = options[OptionKey('std', machine=self.for_machine, lang=self.language)]
if std.value != 'none':
args.append('-std=' + std.value)
return args
@@ -389,19 +392,20 @@ class VisualStudioLikeCCompilerMixin(CompilerMixinBase):
"""Shared methods that apply to MSVC-like C compilers."""
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = super().get_options()
opts.update({
- 'winlibs': coredata.UserArrayOption(
+ OptionKey('winlibs', machine=self.for_machine, lang=self.language): coredata.UserArrayOption(
'Windows libs to link against.',
msvc_winlibs,
),
})
return opts
- def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
# need a TypeDict to make this work
- libs = options['winlibs'].value.copy()
+ key = OptionKey('winlibs', machine=self.for_machine, lang=self.language)
+ libs = options[key].value.copy()
assert isinstance(libs, list)
for l in libs:
assert isinstance(l, str)
@@ -423,7 +427,7 @@ class VisualStudioCCompiler(MSVCCompiler, VisualStudioLikeCCompilerMixin, CCompi
full_version=full_version)
MSVCCompiler.__init__(self, target)
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = super().get_options()
c_stds = ['c89', 'c99']
# Need to have these to be compatible with projects
@@ -436,12 +440,13 @@ class VisualStudioCCompiler(MSVCCompiler, VisualStudioLikeCCompilerMixin, CCompi
if version_compare(self.version, self._C17_VERSION):
c_stds += ['c17', 'c18']
g_stds += ['gnu17', 'gnu18']
- opts['std'].choices = ['none'] + c_stds + g_stds
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ opts[key].choices = ['none'] + c_stds + g_stds
return opts
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ std = options[OptionKey('std', machine=self.for_machine, lang=self.language)]
if std.value.startswith('gnu'):
mlog.log_once(
'cl.exe does not actually support gnu standards, and meson '
@@ -466,8 +471,9 @@ class ClangClCCompiler(_ClangCStds, ClangClCompiler, VisualStudioLikeCCompilerMi
full_version=full_version)
ClangClCompiler.__init__(self, target)
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
- std = options['std'].value
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ std = options[key].value
if std != "none":
return ['/clang:-std={}'.format(std)]
return []
@@ -487,14 +493,16 @@ class IntelClCCompiler(IntelVisualStudioLikeCompiler, VisualStudioLikeCCompilerM
full_version=full_version)
IntelVisualStudioLikeCompiler.__init__(self, target)
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = super().get_options()
- opts['std'].choices = ['none', 'c89', 'c99', 'c11']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ opts[key].choices = ['none', 'c89', 'c99', 'c11']
return opts
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ std = options[key]
if std.value == 'c89':
mlog.log_once("ICL doesn't explicitly implement c89, setting the standard to 'none', which is close.")
elif std.value != 'none':
@@ -513,14 +521,16 @@ class ArmCCompiler(ArmCompiler, CCompiler):
full_version=full_version)
ArmCompiler.__init__(self)
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = CCompiler.get_options(self)
- opts['std'].choices = ['none', 'c89', 'c99', 'c11']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ opts[key].choices = ['none', 'c89', 'c99', 'c11']
return opts
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ std = options[key]
if std.value != 'none':
args.append('--' + std.value)
return args
@@ -540,17 +550,19 @@ class CcrxCCompiler(CcrxCompiler, CCompiler):
def get_always_args(self) -> T.List[str]:
return ['-nologo']
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = CCompiler.get_options(self)
- opts['std'].choices = ['none', 'c89', 'c99']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ opts[key].choices = ['none', 'c89', 'c99']
return opts
def get_no_stdinc_args(self) -> T.List[str]:
return []
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ std = options[key]
if std.value == 'c89':
args.append('-lang=c')
elif std.value == 'c99':
@@ -585,17 +597,19 @@ class Xc16CCompiler(Xc16Compiler, CCompiler):
info, exe_wrapper, linker=linker, full_version=full_version)
Xc16Compiler.__init__(self)
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = CCompiler.get_options(self)
- opts['std'].choices = ['none', 'c89', 'c99', 'gnu89', 'gnu99']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ opts[key].choices = ['none', 'c89', 'c99', 'gnu89', 'gnu99']
return opts
def get_no_stdinc_args(self) -> T.List[str]:
return []
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['c_std']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ std = options[key]
if std.value != 'none':
args.append('-ansi')
args.append('-std=' + std.value)
@@ -628,12 +642,13 @@ class CompCertCCompiler(CompCertCompiler, CCompiler):
info, exe_wrapper, linker=linker, full_version=full_version)
CompCertCompiler.__init__(self)
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = CCompiler.get_options(self)
- opts['std'].choices = ['none', 'c89', 'c99']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ opts[key].choices = ['none', 'c89', 'c99']
return opts
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return []
def get_no_optimization_args(self) -> T.List[str]:
@@ -664,17 +679,19 @@ class C2000CCompiler(C2000Compiler, CCompiler):
def get_always_args(self) -> T.List[str]:
return []
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = CCompiler.get_options(self)
- opts['std'].choices = ['none', 'c89', 'c99', 'c11']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ opts[key].choices = ['none', 'c89', 'c99', 'c11']
return opts
def get_no_stdinc_args(self) -> T.List[str]:
return []
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['c_std']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ std = options[key]
if std.value != 'none':
args.append('--' + std.value)
return args
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 0bd2b4c..acf3823 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -32,10 +32,11 @@ from ..envconfig import (
)
from ..arglist import CompilerArgs
+from ..coredata import OptionKey
if T.TYPE_CHECKING:
from ..build import BuildTarget
- from ..coredata import OptionDictType
+ from ..coredata import OptionDictType, KeyedOptionDictType
from ..envconfig import MachineInfo
from ..environment import Environment
from ..linkers import DynamicLinker # noqa: F401
@@ -596,13 +597,13 @@ class Compiler(metaclass=abc.ABCMeta):
is_cross: bool) -> T.List[str]:
return self.linker.get_args_from_envvars(for_machine, is_cross)
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
return {}
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return []
- def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return self.linker.get_option_args(options)
def check_header(self, hname: str, prefix: str, env: 'Environment', *,
@@ -826,7 +827,7 @@ class Compiler(metaclass=abc.ABCMeta):
def get_std_shared_lib_link_args(self) -> T.List[str]:
return self.linker.get_std_shared_lib_args()
- def get_std_shared_module_link_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_std_shared_module_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return self.linker.get_std_shared_module_args(options)
def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
@@ -1243,14 +1244,16 @@ def get_args_from_envvars(lang: str,
def get_global_options(lang: str,
comp: T.Type[Compiler],
for_machine: MachineChoice,
- is_cross: bool) -> 'OptionDictType':
+ is_cross: bool) -> 'KeyedOptionDictType':
"""Retreive options that apply to all compilers for a given language."""
description = 'Extra arguments passed to the {}'.format(lang)
+ argkey = OptionKey('args', lang=lang, machine=for_machine)
+ largkey = argkey.evolve('link_args')
opts = {
- 'args': coredata.UserArrayOption(
+ argkey: coredata.UserArrayOption(
description + ' compiler',
[], split_args=True, user_input=True, allow_dups=True),
- 'link_args': coredata.UserArrayOption(
+ largkey: coredata.UserArrayOption(
description + ' linker',
[], split_args=True, user_input=True, allow_dups=True),
} # type: OptionDictType
@@ -1262,10 +1265,7 @@ def get_global_options(lang: str,
is_cross,
comp.INVOKES_LINKER)
- for k, o in opts.items():
- if k == 'args':
- o.set_value(compile_args)
- elif k == 'link_args':
- o.set_value(link_args)
+ opts[argkey].set_value(compile_args)
+ opts[largkey].set_value(link_args)
return opts
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index 7577a54..578e362 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -41,8 +41,10 @@ from .mixins.elbrus import ElbrusCompiler
from .mixins.pgi import PGICompiler
from .mixins.emscripten import EmscriptenMixin
+from ..coredata import OptionKey
+
if T.TYPE_CHECKING:
- from ..coredata import OptionDictType
+ from ..coredata import KeyedOptionDictType
from ..dependencies import Dependency, ExternalProgram
from ..envconfig import MachineInfo
from ..environment import Environment
@@ -169,10 +171,11 @@ class CPPCompiler(CLikeCompiler, Compiler):
raise MesonException('C++ Compiler does not support -std={}'.format(cpp_std))
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = super().get_options()
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
opts.update({
- 'std': coredata.UserComboOption(
+ key: coredata.UserComboOption(
'C++ language standard to use',
['none'],
'none',
@@ -196,47 +199,50 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler):
'2': default_warn_args + ['-Wextra'],
'3': default_warn_args + ['-Wextra', '-Wpedantic']}
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = CPPCompiler.get_options(self)
+ key = OptionKey('key', machine=self.for_machine, lang=self.language)
opts.update({
- 'eh': coredata.UserComboOption(
+ key.evolve('eh'): coredata.UserComboOption(
'C++ exception handling type.',
['none', 'default', 'a', 's', 'sc'],
'default',
),
- 'rtti': coredata.UserBooleanOption('Enable RTTI', True),
+ key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True),
})
- opts['std'].choices = [
+ opts[key.evolve('std')].choices = [
'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z',
'c++2a', 'c++20', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++1z',
'gnu++2a', 'gnu++20',
]
if self.info.is_windows() or self.info.is_cygwin():
opts.update({
- 'winlibs': coredata.UserArrayOption(
+ key.evolve('winlibs'): coredata.UserArrayOption(
'Standard Win libraries to link against',
gnu_winlibs,
),
})
return opts
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ std = options[key]
if std.value != 'none':
args.append(self._find_best_cpp_std(std.value))
- non_msvc_eh_options(options['eh'].value, args)
+ non_msvc_eh_options(options[key.evolve('eh')].value, args)
- if not options['rtti'].value:
+ if not options[key.evolve('rtti')].value:
args.append('-fno-rtti')
return args
- def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
if self.info.is_windows() or self.info.is_cygwin():
# without a typedict mypy can't understand this.
- libs = options['winlibs'].value.copy()
+ key = OptionKey('winlibs', machine=self.for_machine, lang=self.language)
+ libs = options[key].value.copy()
assert isinstance(libs, list)
for l in libs:
assert isinstance(l, str)
@@ -265,9 +271,10 @@ class EmscriptenCPPCompiler(EmscriptenMixin, LinkerEnvVarsMixin, ClangCPPCompile
defines=defines, full_version=full_version)
self.id = 'emscripten'
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ std = options[key]
if std.value != 'none':
args.append(self._find_best_cpp_std(std.value))
return args
@@ -287,32 +294,34 @@ class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler):
'2': default_warn_args + ['-Wextra'],
'3': default_warn_args + ['-Wextra', '-Wpedantic']}
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = CPPCompiler.get_options(self)
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
opts.update({
- 'eh': coredata.UserComboOption(
+ key.evolve('eh'): coredata.UserComboOption(
'C++ exception handling type.',
['none', 'default', 'a', 's', 'sc'],
'default',
),
})
- opts['std'].choices = [
+ opts[key].choices = [
'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'gnu++98',
'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17',
]
return opts
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ std = options[key]
if std.value != 'none':
args.append('-std=' + std.value)
- non_msvc_eh_options(options['eh'].value, args)
+ non_msvc_eh_options(options[key.evolve('eh')].value, args)
return args
- def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return []
@@ -331,53 +340,56 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler):
'2': default_warn_args + ['-Wextra'],
'3': default_warn_args + ['-Wextra', '-Wpedantic']}
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
opts = CPPCompiler.get_options(self)
opts.update({
- 'eh': coredata.UserComboOption(
+ key.evolve('eh'): coredata.UserComboOption(
'C++ exception handling type.',
['none', 'default', 'a', 's', 'sc'],
'default',
),
- 'rtti': coredata.UserBooleanOption('Enable RTTI', True),
- 'debugstl': coredata.UserBooleanOption(
+ key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True),
+ key.evolve('debugstl'): coredata.UserBooleanOption(
'STL debug mode',
False,
)
})
- opts['std'].choices = [
+ opts[key].choices = [
'none', 'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z',
'c++2a', 'c++20', 'gnu++03', 'gnu++11', 'gnu++14', 'gnu++17',
'gnu++1z', 'gnu++2a', 'gnu++20',
]
if self.info.is_windows() or self.info.is_cygwin():
opts.update({
- 'winlibs': coredata.UserArrayOption(
+ key.evolve('winlibs'): coredata.UserArrayOption(
'Standard Win libraries to link against',
gnu_winlibs,
),
})
return opts
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ std = options[key]
if std.value != 'none':
args.append(self._find_best_cpp_std(std.value))
- non_msvc_eh_options(options['eh'].value, args)
+ non_msvc_eh_options(options[key.evolve('eh')].value, args)
- if not options['rtti'].value:
+ if not options[key.evolve('rtti')].value:
args.append('-fno-rtti')
- if options['debugstl'].value:
+ if options[key.evolve('debugstl')].value:
args.append('-D_GLIBCXX_DEBUG=1')
return args
- def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
if self.info.is_windows() or self.info.is_cygwin():
# without a typedict mypy can't understand this.
- libs = options['winlibs'].value.copy()
+ key = OptionKey('winlibs', machine=self.for_machine, lang=self.language)
+ libs = options[key].value.copy()
assert isinstance(libs, list)
for l in libs:
assert isinstance(l, str)
@@ -424,7 +436,7 @@ class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler):
full_version=full_version, defines=defines)
ElbrusCompiler.__init__(self)
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = CPPCompiler.get_options(self)
cpp_stds = [
@@ -438,18 +450,19 @@ class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler):
if version_compare(self.version, '>=1.25.00'):
cpp_stds += [ 'c++2a', 'gnu++2a' ]
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
opts.update({
- 'eh': coredata.UserComboOption(
+ key.evolve('eh'): coredata.UserComboOption(
'C++ exception handling type.',
['none', 'default', 'a', 's', 'sc'],
'default',
),
- 'debugstl': coredata.UserBooleanOption(
+ key.evolve('debugstl'): coredata.UserBooleanOption(
'STL debug mode',
False,
),
})
- opts['std'].choices = cpp_stds
+ opts[key].choices = cpp_stds
return opts
# Elbrus C++ compiler does not have lchmod, but there is only linker warning, not compiler error.
@@ -465,15 +478,16 @@ class ElbrusCPPCompiler(GnuCPPCompiler, ElbrusCompiler):
dependencies=dependencies)
# Elbrus C++ compiler does not support RTTI, so don't check for it.
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ std = options[key]
if std.value != 'none':
args.append(self._find_best_cpp_std(std.value))
- non_msvc_eh_options(options['eh'].value, args)
+ non_msvc_eh_options(options[key.evolve('eh')].value, args)
- if options['debugstl'].value:
+ if options[key.evolve('debugstl')].value:
args.append('-D_GLIBCXX_DEBUG=1')
return args
@@ -494,7 +508,7 @@ class IntelCPPCompiler(IntelGnuLikeCompiler, CPPCompiler):
'2': default_warn_args + ['-Wextra'],
'3': default_warn_args + ['-Wextra']}
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = CPPCompiler.get_options(self)
# Every Unix compiler under the sun seems to accept -std=c++03,
# with the exception of ICC. Instead of preventing the user from
@@ -511,36 +525,40 @@ class IntelCPPCompiler(IntelGnuLikeCompiler, CPPCompiler):
if version_compare(self.version, '>=19.1.0'):
c_stds += ['c++2a']
g_stds += ['gnu++2a']
+
+
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
opts.update({
- 'eh': coredata.UserComboOption(
+ key.evolve('eh'): coredata.UserComboOption(
'C++ exception handling type.',
['none', 'default', 'a', 's', 'sc'],
'default',
),
- 'rtti': coredata.UserBooleanOption('Enable RTTI', True),
- 'debugstl': coredata.UserBooleanOption('STL debug mode', False),
+ key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True),
+ key.evolve('debugstl'): coredata.UserBooleanOption('STL debug mode', False),
})
- opts['std'].choices = ['none'] + c_stds + g_stds
+ opts[key].choices = ['none'] + c_stds + g_stds
return opts
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ std = options[key]
if std.value != 'none':
remap_cpp03 = {
'c++03': 'c++98',
'gnu++03': 'gnu++98'
}
args.append('-std=' + remap_cpp03.get(std.value, std.value))
- if options['eh'].value == 'none':
+ if options[key.evolve('eh')].value == 'none':
args.append('-fno-exceptions')
- if not options['rtti'].value:
+ if not options[key.evolve('rtti')].value:
args.append('-fno-rtti')
- if options['debugstl'].value:
+ if options[key.evolve('debugstl')].value:
args.append('-D_GLIBCXX_DEBUG=1')
return args
- def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return []
@@ -560,30 +578,33 @@ class VisualStudioLikeCPPCompilerMixin(CompilerMixinBase):
'c++latest': (False, "latest"),
}
- def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
# need a typeddict for this
- return T.cast(T.List[str], options['winlibs'].value[:])
+ key = OptionKey('winlibs', machine=self.for_machine, lang=self.language)
+ return T.cast(T.List[str], options[key].value[:])
- def _get_options_impl(self, opts: 'OptionDictType', cpp_stds: T.List[str]) -> 'OptionDictType':
+ def _get_options_impl(self, opts: 'KeyedOptionDictType', cpp_stds: T.List[str]) -> 'KeyedOptionDictType':
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
opts.update({
- 'eh': coredata.UserComboOption(
+ key.evolve('eh'): coredata.UserComboOption(
'C++ exception handling type.',
['none', 'default', 'a', 's', 'sc'],
'default',
),
- 'rtti': coredata.UserBooleanOption('Enable RTTI', True),
- 'winlibs': coredata.UserArrayOption(
+ key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True),
+ key.evolve('winlibs'): coredata.UserArrayOption(
'Windows libs to link against.',
msvc_winlibs,
),
})
- opts['std'].choices = cpp_stds
+ opts[key.evolve('std')].choices = cpp_stds
return opts
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
- eh = options['eh']
+ eh = options[key.evolve('eh')]
if eh.value == 'default':
args.append('/EHsc')
elif eh.value == 'none':
@@ -591,10 +612,10 @@ class VisualStudioLikeCPPCompilerMixin(CompilerMixinBase):
else:
args.append('/EH' + eh.value)
- if not options['rtti'].value:
+ if not options[key.evolve('rtti')].value:
args.append('/GR-')
- permissive, ver = self.VC_VERSION_MAP[options['std'].value]
+ permissive, ver = self.VC_VERSION_MAP[options[key].value]
if ver is not None:
args.append('/std:c++{}'.format(ver))
@@ -616,22 +637,23 @@ class CPP11AsCPP14Mixin(CompilerMixinBase):
This is a limitation of Clang and MSVC that ICL doesn't share.
"""
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
# Note: there is no explicit flag for supporting C++11; we attempt to do the best we can
# which means setting the C++ standard version to C++14, in compilers that support it
# (i.e., after VS2015U3)
# if one is using anything before that point, one cannot set the standard.
- if options['std'].value in {'vc++11', 'c++11'}:
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ if options[key].value in {'vc++11', 'c++11'}:
mlog.warning(self.id, 'does not support C++11;',
'attempting best effort; setting the standard to C++14', once=True)
# Don't mutate anything we're going to change, we need to use
# deepcopy since we're messing with members, and we can't simply
# copy the members because the option proxy doesn't support it.
options = copy.deepcopy(options)
- if options['std'].value == 'vc++11':
- options['std'].value = 'vc++14'
+ if options[key].value == 'vc++11':
+ options[key].value = 'vc++14'
else:
- options['std'].value = 'c++14'
+ options[key].value = 'c++14'
return super().get_option_compile_args(options)
@@ -647,7 +669,7 @@ class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixi
self.base_options = ['b_pch', 'b_vscrt', 'b_ndebug'] # FIXME add lto, pgo and the like
self.id = 'msvc'
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
cpp_stds = ['none', 'c++11', 'vc++11']
# Visual Studio 2015 and later
if version_compare(self.version, '>=19'):
@@ -657,11 +679,12 @@ class VisualStudioCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixi
cpp_stds.extend(['vc++14', 'c++17', 'vc++17'])
return self._get_options_impl(super().get_options(), cpp_stds)
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
- if options['std'].value != 'none' and version_compare(self.version, '<19.00.24210'):
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ if options[key].value != 'none' and version_compare(self.version, '<19.00.24210'):
mlog.warning('This version of MSVC does not support cpp_std arguments')
options = copy.copy(options)
- options['std'].value = 'none'
+ options[key].value = 'none'
args = super().get_option_compile_args(options)
@@ -684,7 +707,7 @@ class ClangClCPPCompiler(CPP11AsCPP14Mixin, VisualStudioLikeCPPCompilerMixin, Cl
ClangClCompiler.__init__(self, target)
self.id = 'clang-cl'
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
cpp_stds = ['none', 'c++11', 'vc++11', 'c++14', 'vc++14', 'c++17', 'vc++17', 'c++latest']
return self._get_options_impl(super().get_options(), cpp_stds)
@@ -700,7 +723,7 @@ class IntelClCPPCompiler(VisualStudioLikeCPPCompilerMixin, IntelVisualStudioLike
info, exe_wrapper, linker=linker, full_version=full_version)
IntelVisualStudioLikeCompiler.__init__(self, target)
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
# This has only been tested with version 19.0,
cpp_stds = ['none', 'c++11', 'vc++11', 'c++14', 'vc++14', 'c++17', 'vc++17', 'c++latest']
return self._get_options_impl(super().get_options(), cpp_stds)
@@ -719,21 +742,23 @@ class ArmCPPCompiler(ArmCompiler, CPPCompiler):
info, exe_wrapper, linker=linker, full_version=full_version)
ArmCompiler.__init__(self)
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = CPPCompiler.get_options(self)
- opts['std'].choices = ['none', 'c++03', 'c++11']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ opts[key].choices = ['none', 'c++03', 'c++11']
return opts
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ std = options[key]
if std.value == 'c++11':
args.append('--cpp11')
elif std.value == 'c++03':
args.append('--cpp')
return args
- def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return []
def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]:
@@ -753,7 +778,7 @@ class CcrxCPPCompiler(CcrxCompiler, CPPCompiler):
def get_always_args(self) -> T.List[str]:
return ['-nologo', '-lang=cpp']
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return []
def get_compile_only_args(self) -> T.List[str]:
@@ -762,7 +787,7 @@ class CcrxCPPCompiler(CcrxCompiler, CPPCompiler):
def get_output_args(self, target: str) -> T.List[str]:
return ['-output=obj=%s' % target]
- def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return []
def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]:
@@ -777,15 +802,16 @@ class C2000CPPCompiler(C2000Compiler, CPPCompiler):
info, exe_wrapper, linker=linker, full_version=full_version)
C2000Compiler.__init__(self)
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = CPPCompiler.get_options(self)
- opts['std'].choices = ['none', 'c++03']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ opts[key].choices = ['none', 'c++03']
return opts
def get_always_args(self) -> T.List[str]:
return ['-nologo', '-lang=cpp']
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return []
def get_compile_only_args(self) -> T.List[str]:
@@ -794,7 +820,7 @@ class C2000CPPCompiler(C2000Compiler, CPPCompiler):
def get_output_args(self, target: str) -> T.List[str]:
return ['-output=obj=%s' % target]
- def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return []
def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]:
diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py
index 89fcf40..da1e002 100644
--- a/mesonbuild/compilers/cuda.py
+++ b/mesonbuild/compilers/cuda.py
@@ -17,6 +17,7 @@ import os.path
import typing as T
from .. import coredata
+from ..coredata import OptionKey
from .. import mlog
from ..mesonlib import EnvironmentException, MachineChoice, Popen_safe, OptionOverrideProxy, is_windows, LibType
from .compilers import (Compiler, cuda_buildtype_args, cuda_optimization_args,
@@ -24,7 +25,7 @@ from .compilers import (Compiler, cuda_buildtype_args, cuda_optimization_args,
if T.TYPE_CHECKING:
from ..build import BuildTarget
- from ..coredata import OptionDictType
+ from ..coredata import KeyedOptionDictType
from ..dependencies import Dependency, ExternalProgram
from ..environment import Environment # noqa: F401
from ..envconfig import MachineInfo
@@ -195,24 +196,26 @@ class CudaCompiler(Compiler):
}}'''
return self.compiles(t.format_map(fargs), env, extra_args=extra_args, dependencies=dependencies)
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = super().get_options()
- opts.update({'std': coredata.UserComboOption('C++ language standard to use with cuda',
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ opts.update({key: coredata.UserComboOption('C++ language standard to use with cuda',
['none', 'c++03', 'c++11', 'c++14'],
'none')})
return opts
- def _to_host_compiler_options(self, options: 'OptionDictType') -> 'OptionDictType':
+ def _to_host_compiler_options(self, options: 'KeyedOptionDictType') -> 'KeyedOptionDictType':
overrides = {name: opt.value for name, opt in options.items()}
return OptionOverrideProxy(overrides, self.host_compiler.get_options())
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
# On Windows, the version of the C++ standard used by nvcc is dictated by
# the combination of CUDA version and MSVC version; the --std= is thus ignored
# and attempting to use it will result in a warning: https://stackoverflow.com/a/51272091/741027
if not is_windows():
- std = options['std']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ std = options[key]
if std.value != 'none':
args.append('--std=' + std.value)
@@ -229,7 +232,7 @@ class CudaCompiler(Compiler):
cooked.append(arg)
return cls._to_host_flags(cooked, _Phase.LINKER)
- def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return self._cook_link_args(self.host_compiler.get_option_link_args(self._to_host_compiler_options(options)))
def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str,
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index e17be17..edd7911 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -17,6 +17,7 @@ import typing as T
import subprocess, os
from .. import coredata
+from ..coredata import OptionKey
from .compilers import (
clike_debug_args,
Compiler,
@@ -35,7 +36,7 @@ from mesonbuild.mesonlib import (
)
if T.TYPE_CHECKING:
- from ..coredata import OptionDictType
+ from ..coredata import KeyedOptionDictType
from ..dependencies import Dependency, ExternalProgram
from ..envconfig import MachineInfo
from ..environment import Environment
@@ -71,7 +72,7 @@ class FortranCompiler(CLikeCompiler, Compiler):
source_name.write_text('print *, "Fortran compilation is working."; end')
- extra_flags = []
+ extra_flags: T.List[str] = []
extra_flags += environment.coredata.get_external_args(self.for_machine, self.language)
extra_flags += environment.coredata.get_external_link_args(self.for_machine, self.language)
extra_flags += self.get_always_args()
@@ -150,10 +151,11 @@ class FortranCompiler(CLikeCompiler, Compiler):
def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
return self._has_multi_link_arguments(args, env, 'stop; end program')
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = super().get_options()
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
opts.update({
- 'std': coredata.UserComboOption(
+ key: coredata.UserComboOption(
'Fortran language standard to use',
['none'],
'none',
@@ -179,19 +181,21 @@ class GnuFortranCompiler(GnuCompiler, FortranCompiler):
'2': default_warn_args + ['-Wextra'],
'3': default_warn_args + ['-Wextra', '-Wpedantic', '-fimplicit-none']}
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = FortranCompiler.get_options(self)
fortran_stds = ['legacy', 'f95', 'f2003']
if version_compare(self.version, '>=4.4.0'):
fortran_stds += ['f2008']
if version_compare(self.version, '>=8.0.0'):
fortran_stds += ['f2018']
- opts['std'].choices = ['none'] + fortran_stds
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ opts[key].choices = ['none'] + fortran_stds
return opts
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ std = options[key]
if std.value != 'none':
args.append('-std=' + std.value)
return args
@@ -313,14 +317,16 @@ class IntelFortranCompiler(IntelGnuLikeCompiler, FortranCompiler):
'2': default_warn_args + ['-warn', 'unused'],
'3': ['-warn', 'all']}
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = FortranCompiler.get_options(self)
- opts['std'].choices = ['none', 'legacy', 'f95', 'f2003', 'f2008', 'f2018']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ opts[key].choices = ['none', 'legacy', 'f95', 'f2003', 'f2008', 'f2018']
return opts
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ std = options[key]
stds = {'legacy': 'none', 'f95': 'f95', 'f2003': 'f03', 'f2008': 'f08', 'f2018': 'f18'}
if std.value != 'none':
args.append('-stand=' + stds[std.value])
@@ -363,14 +369,16 @@ class IntelClFortranCompiler(IntelVisualStudioLikeCompiler, FortranCompiler):
'2': default_warn_args + ['/warn:unused'],
'3': ['/warn:all']}
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
opts = FortranCompiler.get_options(self)
- opts['std'].choices = ['none', 'legacy', 'f95', 'f2003', 'f2008', 'f2018']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ opts[key].choices = ['none', 'legacy', 'f95', 'f2003', 'f2008', 'f2018']
return opts
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ std = options[key]
stds = {'legacy': 'none', 'f95': 'f95', 'f2003': 'f03', 'f2008': 'f08', 'f2018': 'f18'}
if std.value != 'none':
args.append('/stand:' + stds[std.value])
diff --git a/mesonbuild/compilers/mixins/emscripten.py b/mesonbuild/compilers/mixins/emscripten.py
index cd18b35..aacea15 100644
--- a/mesonbuild/compilers/mixins/emscripten.py
+++ b/mesonbuild/compilers/mixins/emscripten.py
@@ -50,15 +50,16 @@ class EmscriptenMixin(Compiler):
def thread_link_flags(self, env: 'Environment') -> T.List[str]:
args = ['-s', 'USE_PTHREADS=1']
- count = env.coredata.compiler_options[self.for_machine][self.language]['thread_count'].value # type: int
+ count: int = env.coredata.compiler_options[coredata.OptionKey('thread_count', lang=self.language, machine=self.for_machine)].value # type: ignore
if count:
args.extend(['-s', 'PTHREAD_POOL_SIZE={}'.format(count)])
return args
- def get_options(self) -> 'coredata.OptionDictType':
+ def get_options(self) -> 'coredata.KeyedOptionDictType':
opts = super().get_options()
+ key = coredata.OptionKey('thread_count', machine=self.for_machine, lang=self.language)
opts.update({
- 'thread_count': coredata.UserIntegerOption(
+ key: coredata.UserIntegerOption(
'Number of threads to use in web assembly, set to 0 to disable',
(0, None, 4), # Default was picked at random
),
diff --git a/mesonbuild/compilers/mixins/islinker.py b/mesonbuild/compilers/mixins/islinker.py
index 2445eec..3fe3382 100644
--- a/mesonbuild/compilers/mixins/islinker.py
+++ b/mesonbuild/compilers/mixins/islinker.py
@@ -25,7 +25,7 @@ import typing as T
from ... import mesonlib
if T.TYPE_CHECKING:
- from ...coredata import OptionDictType
+ from ...coredata import KeyedOptionDictType
from ...environment import Environment
from ...compilers.compilers import Compiler
else:
@@ -66,7 +66,7 @@ class BasicLinkerIsCompilerMixin(Compiler):
def get_linker_lib_prefix(self) -> str:
return ''
- def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return []
def has_multi_link_args(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
@@ -78,7 +78,7 @@ class BasicLinkerIsCompilerMixin(Compiler):
def get_std_shared_lib_link_args(self) -> T.List[str]:
return []
- def get_std_shared_module_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_std_shared_module_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return self.get_std_shared_lib_link_args()
def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
diff --git a/mesonbuild/compilers/objc.py b/mesonbuild/compilers/objc.py
index 1b280eb..e47bf2f 100644
--- a/mesonbuild/compilers/objc.py
+++ b/mesonbuild/compilers/objc.py
@@ -51,7 +51,7 @@ class ObjCCompiler(CLikeCompiler, Compiler):
# TODO try to use sanity_check_impl instead of duplicated code
source_name = os.path.join(work_dir, 'sanitycheckobjc.m')
binary_name = os.path.join(work_dir, 'sanitycheckobjc')
- extra_flags = []
+ extra_flags: T.List[str] = []
extra_flags += environment.coredata.get_external_args(self.for_machine, self.language)
if self.is_cross:
extra_flags += self.get_compile_only_args()
diff --git a/mesonbuild/compilers/objcpp.py b/mesonbuild/compilers/objcpp.py
index 16ba77e..c0f93d7 100644
--- a/mesonbuild/compilers/objcpp.py
+++ b/mesonbuild/compilers/objcpp.py
@@ -50,7 +50,7 @@ class ObjCPPCompiler(CLikeCompiler, Compiler):
# TODO try to use sanity_check_impl instead of duplicated code
source_name = os.path.join(work_dir, 'sanitycheckobjcpp.mm')
binary_name = os.path.join(work_dir, 'sanitycheckobjcpp')
- extra_flags = []
+ extra_flags: T.List[str] = []
extra_flags += environment.coredata.get_external_args(self.for_machine, self.language)
if self.is_cross:
extra_flags += self.get_compile_only_args()
diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py
index 312b3b6..cf1af0a 100644
--- a/mesonbuild/compilers/rust.py
+++ b/mesonbuild/compilers/rust.py
@@ -17,11 +17,12 @@ import textwrap
import typing as T
from .. import coredata
+from ..coredata import OptionKey
from ..mesonlib import EnvironmentException, MachineChoice, MesonException, Popen_safe
from .compilers import Compiler, rust_buildtype_args, clike_debug_args
if T.TYPE_CHECKING:
- from ..coredata import OptionDictType
+ from ..coredata import KeyedOptionDictType
from ..dependencies import ExternalProgram
from ..envconfig import MachineInfo
from ..environment import Environment # noqa: F401
@@ -133,18 +134,20 @@ class RustCompiler(Compiler):
# C compiler for dynamic linking, as such we invoke the C compiler's
# use_linker_args method instead.
- def get_options(self) -> 'OptionDictType':
+ def get_options(self) -> 'KeyedOptionDictType':
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
return {
- 'std': coredata.UserComboOption(
+ key: coredata.UserComboOption(
'Rust Eddition to use',
['none', '2015', '2018'],
'none',
),
}
- def get_option_compile_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = []
- std = options['std']
+ key = OptionKey('std', machine=self.for_machine, lang=self.language)
+ std = options[key]
if std.value != 'none':
args.append('--edition=' + std.value)
return args
diff --git a/mesonbuild/compilers/swift.py b/mesonbuild/compilers/swift.py
index 8682e54..7b18591 100644
--- a/mesonbuild/compilers/swift.py
+++ b/mesonbuild/compilers/swift.py
@@ -101,7 +101,7 @@ class SwiftCompiler(Compiler):
src = 'swifttest.swift'
source_name = os.path.join(work_dir, src)
output_name = os.path.join(work_dir, 'swifttest')
- extra_flags = []
+ extra_flags: T.List[str] = []
extra_flags += environment.coredata.get_external_args(self.for_machine, self.language)
if self.is_cross:
extra_flags += self.get_compile_only_args()
diff --git a/mesonbuild/compilers/vala.py b/mesonbuild/compilers/vala.py
index af800c2..14971d4 100644
--- a/mesonbuild/compilers/vala.py
+++ b/mesonbuild/compilers/vala.py
@@ -92,7 +92,7 @@ class ValaCompiler(Compiler):
def sanity_check(self, work_dir: str, environment: 'Environment') -> None:
code = 'class MesonSanityCheck : Object { }'
- extra_flags = []
+ extra_flags: T.List[str] = []
extra_flags += environment.coredata.get_external_args(self.for_machine, self.language)
if self.is_cross:
extra_flags += self.get_compile_only_args()
@@ -116,7 +116,7 @@ class ValaCompiler(Compiler):
# no extra dirs are specified.
if not extra_dirs:
code = 'class MesonFindLibrary : Object { }'
- args = []
+ args: T.List[str] = []
args += env.coredata.get_external_args(self.for_machine, self.language)
vapi_args = ['--pkg', libname]
args += vapi_args
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index eae986d..97f5fff 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -67,16 +67,17 @@ def classify_argument(key: 'OptionKey') -> OptionType:
all_builtins = set(BUILTIN_OPTIONS) | set(BUILTIN_OPTIONS_PER_MACHINE) | set(builtin_dir_noprefix_options)
if key.name in base_options:
- assert key.machine is MachineChoice.HOST
+ 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:
return OptionType.BUILTIN
elif key.name.startswith('backend_'):
+ assert key.machine is MachineChoice.HOST, str(key)
return OptionType.BACKEND
else:
- assert key.machine is MachineChoice.HOST
+ assert key.machine is MachineChoice.HOST, str(key)
return OptionType.PROJECT
@@ -168,23 +169,24 @@ class OptionKey:
This takes strings like `mysubproject:build.myoption` and Creates an
OptionKey out of them.
"""
- from .compilers import all_languages
- if any(raw.startswith(f'{l}_') for l in all_languages):
- lang, raw2 = raw.split('_', 1)
- else:
- lang, raw2 = None, raw
try:
- subproject, raw3 = raw2.split(':')
+ subproject, raw2 = raw.split(':')
except ValueError:
- subproject, raw3 = '', raw2
+ subproject, raw2 = '', raw
- if raw3.startswith('build.'):
- opt = raw3.lstrip('build.')
+ if raw2.startswith('build.'):
+ raw3 = raw2.lstrip('build.')
for_machine = MachineChoice.BUILD
else:
- opt = raw3
+ raw3 = raw2
for_machine = MachineChoice.HOST
+
+ from .compilers import all_languages
+ if any(raw3.startswith(f'{l}_') for l in all_languages):
+ lang, opt = raw3.split('_', 1)
+ else:
+ lang, opt = None, raw3
assert ':' not in opt
assert 'build.' not in opt
@@ -580,10 +582,7 @@ class CoreData:
self.builtins_per_machine: PerMachine['OptionDictType'] = PerMachine({}, {})
self.backend_options: 'KeyedOptionDictType' = {}
self.user_options: 'KeyedOptionDictType' = {}
- self.compiler_options = PerMachine(
- defaultdict(dict),
- defaultdict(dict),
- ) # type: PerMachine[T.defaultdict[str, OptionDictType]]
+ self.compiler_options: 'KeyedOptionDictType' = {}
self.base_options = {} # type: OptionDictType
self.cross_files = self.__load_config_files(options, scratch_dir, 'cross')
self.compilers = PerMachine(OrderedDict(), OrderedDict()) # type: PerMachine[T.Dict[str, Compiler]]
@@ -860,7 +859,7 @@ class CoreData:
def _get_all_nonbuiltin_options(self) -> T.Iterable[T.Dict[str, UserOption]]:
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 dict(self.flatten_lang_iterator(self.get_prefixed_options_per_machine(self.compiler_options)))
+ yield {str(k): v for k, v in self.compiler_options.items()}
yield self.base_options
def _get_all_builtin_options(self) -> T.Iterable[T.Dict[str, UserOption]]:
@@ -882,11 +881,11 @@ class CoreData:
.with_traceback(sys.exc_info()[2])
raise MesonException('Tried to validate unknown option %s.' % option_name)
- def get_external_args(self, for_machine: MachineChoice, lang):
- return self.compiler_options[for_machine][lang]['args'].value
+ def get_external_args(self, for_machine: MachineChoice, lang: str) -> T.Union[str, T.List[str]]:
+ return self.compiler_options[OptionKey('args', machine=for_machine, lang=lang)].value
- def get_external_link_args(self, for_machine: MachineChoice, lang):
- return self.compiler_options[for_machine][lang]['link_args'].value
+ def get_external_link_args(self, for_machine: MachineChoice, lang: str) -> T.Union[str, T.List[str]]:
+ return self.compiler_options[OptionKey('link_args', machine=for_machine, lang=lang)].value
def merge_user_options(self, options: T.Dict[str, UserOption[T.Any]]) -> None:
for name, value in options.items():
@@ -914,14 +913,17 @@ class CoreData:
return len(self.cross_files) > 0
def copy_build_options_from_regular_ones(self):
- assert(not self.is_cross_build())
+ 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 lang, host_opts in self.compiler_options.host.items():
- build_opts = self.compiler_options.build[lang]
- for k, o in host_opts.items():
- if k in build_opts:
- build_opts[k].set_value(o.value)
+ for bk, bv in self.compiler_options.items():
+ if bk.machine is MachineChoice.BUILD:
+ hk = bk.as_host()
+ try:
+ hv = self.compiler_options[hk]
+ bv.set_value(hv.value)
+ except KeyError:
+ continue
def set_options(self, options: T.Dict[OptionKey, T.Any], subproject: str = '', warn_unknown: bool = True) -> None:
if not self.is_cross_build():
@@ -989,14 +991,13 @@ class CoreData:
self.set_options(options, subproject=subproject)
- def add_compiler_options(self, options: 'OptionDictType', lang: str, for_machine: MachineChoice,
+ def add_compiler_options(self, options: 'KeyedOptionDictType', lang: str, for_machine: MachineChoice,
env: 'Environment') -> None:
for k, o in options.items():
- key = OptionKey(k, lang=lang, machine=for_machine)
- value = env.options.get(key)
+ value = env.options.get(k)
if value is not None:
o.set_value(value)
- self.compiler_options[for_machine][lang].setdefault(k, o)
+ self.compiler_options.setdefault(k, o)
def add_lang_args(self, lang: str, comp: T.Type['Compiler'],
for_machine: MachineChoice, env: 'Environment') -> None:
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index d2a118f..3120279 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -629,7 +629,9 @@ class Environment:
machines.target = MachineInfo.from_literal(config['target_machine'])
# Keep only per machine options from the native file. The cross
# file takes precedence over all other options.
- self.keep_per_machine_options()
+ for key, value in list(self.options.items()):
+ if self.coredata.is_per_machine_option(key):
+ self.options[key.as_build()] = value
self.load_machine_file_options(config, properties.host, MachineChoice.HOST)
else:
# IF we aren't cross compiling, but we hav ea native file, the
@@ -736,15 +738,15 @@ class Environment:
subproject, section = section.split(':')
else:
subproject = ''
- if section in ['project options', 'built-in options']:
+ if section == 'built-in options':
for k, v in values.items():
key = coredata.OptionKey.from_string(k).evolve(subproject=subproject, machine=machine)
self.options[key] = v
-
- def keep_per_machine_options(self) -> None:
- for key, value in self.options.items():
- if self.coredata.is_per_machine_option(key):
- self.options[key.as_build()] = value
+ elif section == 'project options':
+ for k, v in values.items():
+ # Project options are always for the machine machine
+ key = coredata.OptionKey.from_string(k).evolve(subproject=subproject)
+ self.options[key] = v
def set_default_options_from_env(self) -> None:
for for_machine in MachineChoice:
@@ -936,7 +938,7 @@ class Environment:
elif isinstance(comp_class.LINKER_PREFIX, list):
check_args = comp_class.LINKER_PREFIX + ['/logo'] + comp_class.LINKER_PREFIX + ['--version']
- check_args += self.coredata.compiler_options[for_machine][comp_class.language]['args'].value
+ check_args += self.coredata.compiler_options[coredata.OptionKey('args', lang=comp_class.language, machine=for_machine)].value
override = [] # type: T.List[str]
value = self.lookup_binary_entry(for_machine, comp_class.language + '_ld')
@@ -1002,7 +1004,7 @@ class Environment:
"""
self.coredata.add_lang_args(comp_class.language, comp_class, for_machine, self)
extra_args = extra_args or []
- extra_args += self.coredata.compiler_options[for_machine][comp_class.language]['args'].value
+ extra_args += self.coredata.compiler_options[coredata.OptionKey('args', lang=comp_class.language, machine=for_machine)].value
if isinstance(comp_class.LINKER_PREFIX, str):
check_args = [comp_class.LINKER_PREFIX + '--version'] + extra_args
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index e6936e4..6aba3e7 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -52,6 +52,7 @@ import typing as T
import importlib
if T.TYPE_CHECKING:
+ from .compilers import Compiler
from .envconfig import MachineInfo
from .environment import Environment
from .modules import ExtensionModule
@@ -1058,7 +1059,7 @@ find_library_permitted_kwargs = set([
find_library_permitted_kwargs |= set(['header_' + k for k in header_permitted_kwargs])
class CompilerHolder(InterpreterObject):
- def __init__(self, compiler, env, subproject):
+ def __init__(self, compiler: 'Compiler', env: 'Environment', subproject: str):
InterpreterObject.__init__(self)
self.compiler = compiler
self.environment = env
@@ -1143,7 +1144,7 @@ class CompilerHolder(InterpreterObject):
args += self.compiler.get_include_args(idir, False)
if not nobuiltins:
for_machine = Interpreter.machine_from_native_kwarg(kwargs)
- opts = self.environment.coredata.compiler_options[for_machine][self.compiler.language]
+ opts = self.environment.coredata.compiler_options
args += self.compiler.get_option_compile_args(opts)
if mode == 'link':
args += self.compiler.get_option_link_args(opts)
@@ -3059,8 +3060,6 @@ external dependencies (including libraries) must go to "dependencies".''')
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)),
- dict(self.coredata.flatten_lang_iterator(
- self.coredata.get_prefixed_options_per_machine(self.coredata.compiler_options))),
]:
v = opts.get(optname)
if v is None or v.yielding:
@@ -3068,8 +3067,15 @@ external dependencies (including libraries) must go to "dependencies".''')
if v is not None:
return v
+ key = coredata.OptionKey.from_string(optname)
+ for opts in [self.coredata.compiler_options]:
+ v = opts.get(key)
+ if v is None or v.yielding:
+ v = opts.get(key.as_root())
+ if v is not None:
+ return v
+
try:
- key = coredata.OptionKey.from_string(optname)
opt = self.coredata.user_options[key]
if opt.yielding and key.subproject and key.as_root() in self.coredata.user_options:
popt = self.coredata.user_options[key.as_root()]
diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py
index 0f05fef..141c8fd 100644
--- a/mesonbuild/linkers.py
+++ b/mesonbuild/linkers.py
@@ -21,7 +21,7 @@ from .arglist import CompilerArgs
from .envconfig import get_env_var
if T.TYPE_CHECKING:
- from .coredata import OptionDictType
+ from .coredata import KeyedOptionDictType
from .envconfig import MachineChoice
from .environment import Environment
@@ -40,7 +40,7 @@ class StaticLinker:
"""
return mesonlib.is_windows()
- def get_base_link_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_base_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
"""Like compilers.get_base_link_args, but for the static linker."""
return []
@@ -70,7 +70,7 @@ class StaticLinker:
def openmp_flags(self) -> T.List[str]:
return []
- def get_option_link_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return []
@classmethod
@@ -378,7 +378,7 @@ class DynamicLinker(LinkerEnvVarsMixin, metaclass=abc.ABCMeta):
# XXX: is use_ldflags a compiler or a linker attribute?
- def get_option_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_option_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return []
def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
@@ -401,7 +401,7 @@ class DynamicLinker(LinkerEnvVarsMixin, metaclass=abc.ABCMeta):
def get_std_shared_lib_args(self) -> T.List[str]:
return []
- def get_std_shared_module_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_std_shared_module_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return self.get_std_shared_lib_args()
def get_pie_args(self) -> T.List[str]:
@@ -693,7 +693,7 @@ class AppleDynamicLinker(PosixDynamicLinkerMixin, DynamicLinker):
def get_allow_undefined_args(self) -> T.List[str]:
return self._apply_prefix('-undefined,dynamic_lookup')
- def get_std_shared_module_args(self, options: 'OptionDictType') -> T.List[str]:
+ def get_std_shared_module_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
return ['-bundle'] + self._apply_prefix('-undefined,dynamic_lookup')
def get_pie_args(self) -> T.List[str]:
diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py
index 20e6d26..c14d701 100644
--- a/mesonbuild/mconf.py
+++ b/mesonbuild/mconf.py
@@ -17,6 +17,8 @@ from . import coredata, environment, mesonlib, build, mintro, mlog
from .ast import AstIDGenerator
import typing as T
+from .mesonlib import MachineChoice
+
if T.TYPE_CHECKING:
import argparse
from .coredata import OptionKey, UserOption
@@ -217,13 +219,8 @@ class Conf:
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_subproject(
- dict(self.coredata.flatten_lang_iterator(
- self.coredata.compiler_options.host.items())))
- build_compiler_options = self.split_options_per_subproject(
- dict(self.coredata.flatten_lang_iterator(
- (insert_build_prefix(k), o)
- for k, o in self.coredata.compiler_options.build.items())))
+ 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)
show_build_options = self.default_values_only or self.build.environment.is_cross_build()
diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py
index e252e82..7b2560f 100644
--- a/mesonbuild/mintro.py
+++ b/mesonbuild/mintro.py
@@ -33,6 +33,8 @@ import typing as T
import os
import argparse
+from .mesonlib import MachineChoice
+
def get_meson_info_file(info_dir: str) -> str:
return os.path.join(info_dir, 'meson-info.json')
@@ -260,13 +262,12 @@ def list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[s
add_keys({str(k): v for k, v in coredata.backend_options.items()}, 'backend')
add_keys(coredata.base_options, 'base')
add_keys(
- dict(coredata.flatten_lang_iterator(coredata.compiler_options.host.items())),
+ {str(k): v for k, v in coredata.compiler_options.items() if k.machine is MachineChoice.HOST},
'compiler',
machine='host',
)
- tmp_dict = dict(coredata.flatten_lang_iterator(coredata.compiler_options.build.items())) # type: T.Dict[str, cdata.UserOption]
add_keys(
- {'build.' + k: o for k, o in tmp_dict.items()},
+ {str(k): v for k, v in coredata.compiler_options.items() if k.machine is MachineChoice.BUILD},
'compiler',
machine='build',
)
diff --git a/mesonbuild/rewriter.py b/mesonbuild/rewriter.py
index dcc5040..776a39a 100644
--- a/mesonbuild/rewriter.py
+++ b/mesonbuild/rewriter.py
@@ -469,8 +469,7 @@ class Rewriter:
**{'build.' + k: o for k, o in cdata.builtins_per_machine.build.items()},
**{str(k): v for k, v in cdata.backend_options.items()},
**cdata.base_options,
- **(dict(cdata.flatten_lang_iterator(cdata.compiler_options.host.items()))),
- **{'build.' + k: o for k, o in cdata.flatten_lang_iterator(cdata.compiler_options.build.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_tests.py b/run_tests.py
index 0f02636..15e643a 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -34,7 +34,7 @@ from mesonbuild import mesonmain
from mesonbuild import mtest
from mesonbuild import mlog
from mesonbuild.environment import Environment, detect_ninja
-from mesonbuild.coredata import backendlist, version as meson_version
+from mesonbuild.coredata import backendlist, version as meson_version, OptionKey
NINJA_1_9_OR_NEWER = False
NINJA_CMD = None
@@ -127,7 +127,7 @@ def get_fake_env(sdir='', bdir=None, prefix='', opts=None):
if opts is None:
opts = get_fake_options(prefix)
env = Environment(sdir, bdir, opts)
- env.coredata.compiler_options.host['c']['args'] = FakeCompilerOptions()
+ env.coredata.compiler_options[OptionKey('args', lang='c')] = FakeCompilerOptions()
env.machines.host.cpu_family = 'x86_64' # Used on macOS inside find_library
return env
diff --git a/run_unittests.py b/run_unittests.py
index 1a7a0c4..0236909 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -30,8 +30,6 @@ import functools
import io
import operator
import threading
-import urllib.error
-import urllib.request
import zipfile
import hashlib
from itertools import chain
@@ -66,6 +64,7 @@ from mesonbuild.dependencies import PkgConfigDependency, ExternalProgram
import mesonbuild.dependencies.base
from mesonbuild.build import Target, ConfigurationData
import mesonbuild.modules.pkgconfig
+from mesonbuild.coredata import OptionKey
from mesonbuild.mtest import TAPParser, TestResult
@@ -874,7 +873,7 @@ class InternalTests(unittest.TestCase):
env = get_fake_env()
compiler = env.detect_c_compiler(MachineChoice.HOST)
env.coredata.compilers.host = {'c': compiler}
- env.coredata.compiler_options.host['c']['link_args'] = FakeCompilerOptions()
+ env.coredata.compiler_options[OptionKey('link_args', lang='c')] = FakeCompilerOptions()
p1 = Path(tmpdir) / '1'
p2 = Path(tmpdir) / '2'
p1.mkdir()
@@ -1336,10 +1335,10 @@ class DataTests(unittest.TestCase):
cc = env.detect_c_compiler(MachineChoice.HOST)
cpp = env.detect_cpp_compiler(MachineChoice.HOST)
for comp in (cc, cpp):
- for opt in comp.get_options().keys():
- self.assertIn(opt, md)
+ for opt in comp.get_options():
+ self.assertIn(str(opt), md)
for opt in comp.base_options:
- self.assertIn(opt, md)
+ self.assertIn(str(opt), md)
self.assertNotIn('b_unknown', md)
@staticmethod
@@ -3681,7 +3680,7 @@ class AllPlatformTests(BasePlatformTests):
def test_command_line(self):
testdir = os.path.join(self.unit_test_dir, '34 command line')
- K = mesonbuild.coredata.OptionKey
+ K = OptionKey
# Verify default values when passing no args that affect the
# configuration, and as a bonus, test that --profile-self works.
@@ -3782,11 +3781,11 @@ class AllPlatformTests(BasePlatformTests):
# c_args value should be parsed with split_args
self.init(testdir, extra_args=['-Dc_args=-Dfoo -Dbar "-Dthird=one two"', '--fatal-meson-warnings'])
obj = mesonbuild.coredata.load(self.builddir)
- self.assertEqual(obj.compiler_options.host['c']['args'].value, ['-Dfoo', '-Dbar', '-Dthird=one two'])
+ self.assertEqual(obj.compiler_options[OptionKey('args', lang='c')].value, ['-Dfoo', '-Dbar', '-Dthird=one two'])
self.setconf('-Dc_args="foo bar" one two')
obj = mesonbuild.coredata.load(self.builddir)
- self.assertEqual(obj.compiler_options.host['c']['args'].value, ['foo bar', 'one', 'two'])
+ self.assertEqual(obj.compiler_options[OptionKey('args', lang='c')].value, ['foo bar', 'one', 'two'])
self.wipe()
self.init(testdir, extra_args=['-Dset_percent_opt=myoption%', '--fatal-meson-warnings'])
@@ -3805,7 +3804,7 @@ class AllPlatformTests(BasePlatformTests):
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.compiler_options.host['c']['args'].value, ['-Dbar'])
+ 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',
@@ -3814,7 +3813,7 @@ class AllPlatformTests(BasePlatformTests):
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.compiler_options.host['c']['args'].value, ['-Dfoo'])
+ self.assertEqual(obj.compiler_options[OptionKey('args', lang='c')].value, ['-Dfoo'])
self.wipe()
except KeyError:
# Ignore KeyError, it happens on CI for compilers that does not
@@ -6300,7 +6299,7 @@ class LinuxlikeTests(BasePlatformTests):
Oargs = [arg for arg in cmd if arg.startswith('-O')]
self.assertEqual(Oargs, [Oflag, '-O0'])
- def _test_stds_impl(self, testdir, compiler: 'Compiler', p: str) -> None:
+ def _test_stds_impl(self, testdir: str, compiler: 'Compiler') -> None:
has_cpp17 = (compiler.get_id() not in {'clang', 'gcc'} or
compiler.get_id() == 'clang' and _clang_at_least(compiler, '>=5.0.0', '>=9.1') or
compiler.get_id() == 'gcc' and version_compare(compiler.version, '>=5.0.0'))
@@ -6316,8 +6315,8 @@ class LinuxlikeTests(BasePlatformTests):
# Check that all the listed -std=xxx options for this compiler work just fine when used
# https://en.wikipedia.org/wiki/Xcode#Latest_versions
# https://www.gnu.org/software/gcc/projects/cxx-status.html
- for v in compiler.get_options()['std'].choices:
- lang_std = p + '_std'
+ key = OptionKey('std', lang=compiler.language)
+ for v in compiler.get_options()[key].choices:
# we do it like this to handle gnu++17,c++17 and gnu17,c17 cleanly
# thus, C++ first
if '++17' in v and not has_cpp17:
@@ -6331,8 +6330,7 @@ class LinuxlikeTests(BasePlatformTests):
continue
elif '18' in v and not has_c18:
continue
- std_opt = '{}={}'.format(lang_std, v)
- self.init(testdir, extra_args=['-D' + std_opt])
+ self.init(testdir, extra_args=[f'-D{key!s}={v}'])
cmd = self.get_compdb()[0]['command']
# c++03 and gnu++03 are not understood by ICC, don't try to look for them
skiplist = frozenset([
@@ -6344,15 +6342,15 @@ class LinuxlikeTests(BasePlatformTests):
try:
self.build()
except Exception:
- print('{} was {!r}'.format(lang_std, v))
+ print(f'{key!s} was {v!r}')
raise
self.wipe()
# Check that an invalid std option in CFLAGS/CPPFLAGS fails
# Needed because by default ICC ignores invalid options
cmd_std = '-std=FAIL'
- if p == 'c':
+ if compiler.language == 'c':
env_flag_name = 'CFLAGS'
- elif p == 'cpp':
+ elif compiler.language == 'cpp':
env_flag_name = 'CXXFLAGS'
else:
raise NotImplementedError('Language {} not defined.'.format(p))
@@ -6373,7 +6371,7 @@ class LinuxlikeTests(BasePlatformTests):
testdir = os.path.join(self.common_test_dir, '1 trivial')
env = get_fake_env(testdir, self.builddir, self.prefix)
cc = env.detect_c_compiler(MachineChoice.HOST)
- self._test_stds_impl(testdir, cc, 'c')
+ self._test_stds_impl(testdir, cc)
def test_compiler_cpp_stds(self):
'''
@@ -6383,7 +6381,7 @@ class LinuxlikeTests(BasePlatformTests):
testdir = os.path.join(self.common_test_dir, '2 cpp')
env = get_fake_env(testdir, self.builddir, self.prefix)
cpp = env.detect_cpp_compiler(MachineChoice.HOST)
- self._test_stds_impl(testdir, cpp, 'cpp')
+ self._test_stds_impl(testdir, cpp)
def test_unity_subproj(self):
testdir = os.path.join(self.common_test_dir, '43 subproject')
@@ -6905,7 +6903,7 @@ class LinuxlikeTests(BasePlatformTests):
self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'librelativepath.pc')))
env = get_fake_env(testdir, self.builddir, self.prefix)
- env.coredata.set_options({mesonbuild.coredata.OptionKey('pkg_config_path'): pkg_dir}, subproject='')
+ env.coredata.set_options({OptionKey('pkg_config_path'): pkg_dir}, subproject='')
kwargs = {'required': True, 'silent': True}
relative_path_dep = PkgConfigDependency('librelativepath', env, kwargs)
self.assertTrue(relative_path_dep.found())
@@ -9318,7 +9316,7 @@ class SubprojectsCommandTests(BasePlatformTests):
out = self._subprojects_cmd(['foreach', '--types', 'git'] + dummy_cmd)
self.assertEqual(ran_in(out), ['subprojects/sub_git'])
-def _clang_at_least(compiler, minver: str, apple_minver: T.Optional[str]) -> bool:
+def _clang_at_least(compiler: 'Compiler', minver: str, apple_minver: T.Optional[str]) -> bool:
"""
check that Clang compiler is at least a specified version, whether AppleClang or regular Clang