use OptionKey for compiler_options

pull/8080/head
Dylan Baker 4 years ago
parent bdca05e2e6
commit fe973d9fc4
  1. 15
      mesonbuild/backend/backends.py
  2. 13
      mesonbuild/backend/ninjabackend.py
  3. 10
      mesonbuild/backend/vs2010backend.py
  4. 12
      mesonbuild/build.py
  5. 7
      mesonbuild/cmake/interpreter.py
  6. 141
      mesonbuild/compilers/c.py
  7. 26
      mesonbuild/compilers/compilers.py
  8. 202
      mesonbuild/compilers/cpp.py
  9. 17
      mesonbuild/compilers/cuda.py
  10. 40
      mesonbuild/compilers/fortran.py
  11. 7
      mesonbuild/compilers/mixins/emscripten.py
  12. 6
      mesonbuild/compilers/mixins/islinker.py
  13. 2
      mesonbuild/compilers/objc.py
  14. 2
      mesonbuild/compilers/objcpp.py
  15. 13
      mesonbuild/compilers/rust.py
  16. 2
      mesonbuild/compilers/swift.py
  17. 4
      mesonbuild/compilers/vala.py
  18. 63
      mesonbuild/coredata.py
  19. 20
      mesonbuild/environment.py
  20. 16
      mesonbuild/interpreter.py
  21. 12
      mesonbuild/linkers.py
  22. 11
      mesonbuild/mconf.py
  23. 7
      mesonbuild/mintro.py
  24. 3
      mesonbuild/rewriter.py
  25. 4
      run_tests.py
  26. 44
      run_unittests.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

@ -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))

@ -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).

@ -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

@ -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)

@ -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

@ -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

@ -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]:

@ -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,

@ -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])

@ -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
),

@ -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]:

@ -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()

@ -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()

@ -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

@ -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()

@ -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

@ -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:

@ -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

@ -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()]

@ -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]:

@ -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()

@ -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',
)

@ -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()},
}

@ -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

@ -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

Loading…
Cancel
Save