summaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/cargo/interpreter.py2
-rw-r--r--mesonbuild/compilers/c.py39
-rw-r--r--mesonbuild/compilers/compilers.py78
-rw-r--r--mesonbuild/compilers/cpp.py173
-rw-r--r--mesonbuild/compilers/cuda.py23
-rw-r--r--mesonbuild/compilers/cython.py27
-rw-r--r--mesonbuild/compilers/fortran.py18
-rw-r--r--mesonbuild/compilers/mixins/emscripten.py15
-rw-r--r--mesonbuild/compilers/objc.py17
-rw-r--r--mesonbuild/compilers/objcpp.py23
-rw-r--r--mesonbuild/compilers/rust.py15
-rw-r--r--mesonbuild/coredata.py91
-rw-r--r--mesonbuild/optinterpreter.py26
13 files changed, 301 insertions, 246 deletions
diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py
index f1ed23953..e1b092897 100644
--- a/mesonbuild/cargo/interpreter.py
+++ b/mesonbuild/cargo/interpreter.py
@@ -716,7 +716,7 @@ def interpret(subp_name: str, subdir: str, env: Environment) -> T.Tuple[mparser.
for feature in cargo.features:
key = OptionKey(_option_name(feature), subproject=subp_name)
enabled = feature == 'default'
- options[key] = coredata.UserBooleanOption(f'Cargo {feature} feature', enabled)
+ options[key] = coredata.UserBooleanOption(key.name, f'Cargo {feature} feature', enabled)
ast = _create_project(cargo, build)
ast += [build.assign(build.function('import', [build.string('rust')]), 'rust')]
diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py
index 048649a32..7e2146111 100644
--- a/mesonbuild/compilers/c.py
+++ b/mesonbuild/compilers/c.py
@@ -152,12 +152,13 @@ class ClangCCompiler(_ClangCStds, ClangCompiler, CCompiler):
def get_options(self) -> 'MutableKeyedOptionDictType':
opts = super().get_options()
if self.info.is_windows() or self.info.is_cygwin():
- opts.update({
- OptionKey('winlibs', machine=self.for_machine, lang=self.language): coredata.UserArrayOption(
- 'Standard Win libraries to link against',
- gnu_winlibs,
- ),
- })
+ self.update_options(
+ opts,
+ self.create_option(coredata.UserArrayOption,
+ OptionKey('winlibs', machine=self.for_machine, lang=self.language),
+ 'Standard Win libraries to link against',
+ gnu_winlibs),
+ )
return opts
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
@@ -290,12 +291,13 @@ class GnuCCompiler(GnuCompiler, CCompiler):
assert isinstance(std_opt, coredata.UserStdOption), 'for mypy'
std_opt.set_versions(stds, gnu=True)
if self.info.is_windows() or self.info.is_cygwin():
- opts.update({
- key.evolve('winlibs'): coredata.UserArrayOption(
- 'Standard Win libraries to link against',
- gnu_winlibs,
- ),
- })
+ self.update_options(
+ opts,
+ self.create_option(coredata.UserArrayOption,
+ key.evolve('winlibs'),
+ 'Standard Win libraries to link against',
+ gnu_winlibs),
+ )
return opts
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
@@ -425,15 +427,16 @@ class VisualStudioLikeCCompilerMixin(CompilerMixinBase):
"""Shared methods that apply to MSVC-like C compilers."""
- def get_options(self) -> 'MutableKeyedOptionDictType':
- opts = super().get_options()
- opts.update({
- OptionKey('winlibs', machine=self.for_machine, lang=self.language): coredata.UserArrayOption(
+ def get_options(self) -> MutableKeyedOptionDictType:
+ return self.update_options(
+ super().get_options(),
+ self.create_option(
+ coredata.UserArrayOption,
+ OptionKey('winlibs', machine=self.for_machine, lang=self.language),
'Windows libs to link against.',
msvc_winlibs,
),
- })
- return opts
+ )
def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
# need a TypeDict to make this work
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 9e99706c0..5854c9e60 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -9,6 +9,7 @@ import contextlib, os.path, re
import enum
import itertools
import typing as T
+from dataclasses import dataclass
from functools import lru_cache
from .. import coredata
@@ -34,6 +35,7 @@ if T.TYPE_CHECKING:
CompilerType = T.TypeVar('CompilerType', bound='Compiler')
_T = T.TypeVar('_T')
+ UserOptionType = T.TypeVar('UserOptionType', bound=coredata.UserOption)
"""This file contains the data files of all compilers Meson knows
about. To support a new compiler, add its information below.
@@ -206,36 +208,46 @@ clike_debug_args: T.Dict[bool, T.List[str]] = {
MSCRT_VALS = ['none', 'md', 'mdd', 'mt', 'mtd']
-base_options: 'KeyedOptionDictType' = {
- OptionKey('b_pch'): coredata.UserBooleanOption('Use precompiled headers', True),
- OptionKey('b_lto'): coredata.UserBooleanOption('Use link time optimization', False),
- OptionKey('b_lto_threads'): coredata.UserIntegerOption('Use multiple threads for Link Time Optimization', (None, None, 0)),
- OptionKey('b_lto_mode'): coredata.UserComboOption('Select between different LTO modes.',
- ['default', 'thin'],
- 'default'),
- OptionKey('b_thinlto_cache'): coredata.UserBooleanOption('Use LLVM ThinLTO caching for faster incremental builds', False),
- OptionKey('b_thinlto_cache_dir'): coredata.UserStringOption('Directory to store ThinLTO cache objects', ''),
- OptionKey('b_sanitize'): coredata.UserComboOption('Code sanitizer to use',
- ['none', 'address', 'thread', 'undefined', 'memory', 'leak', 'address,undefined'],
- 'none'),
- OptionKey('b_lundef'): coredata.UserBooleanOption('Use -Wl,--no-undefined when linking', True),
- OptionKey('b_asneeded'): coredata.UserBooleanOption('Use -Wl,--as-needed when linking', True),
- OptionKey('b_pgo'): coredata.UserComboOption('Use profile guided optimization',
- ['off', 'generate', 'use'],
- 'off'),
- OptionKey('b_coverage'): coredata.UserBooleanOption('Enable coverage tracking.', False),
- OptionKey('b_colorout'): coredata.UserComboOption('Use colored output',
- ['auto', 'always', 'never'],
- 'always'),
- OptionKey('b_ndebug'): coredata.UserComboOption('Disable asserts', ['true', 'false', 'if-release'], 'false'),
- OptionKey('b_staticpic'): coredata.UserBooleanOption('Build static libraries as position independent', True),
- OptionKey('b_pie'): coredata.UserBooleanOption('Build executables as position independent', False),
- OptionKey('b_bitcode'): coredata.UserBooleanOption('Generate and embed bitcode (only macOS/iOS/tvOS)', False),
- OptionKey('b_vscrt'): coredata.UserComboOption('VS run-time library type to use.',
- MSCRT_VALS + ['from_buildtype', 'static_from_buildtype'],
- 'from_buildtype'),
+@dataclass
+class BaseOption(T.Generic[coredata._T, coredata._U]):
+ opt_type: T.Type[coredata._U]
+ description: str
+ default: T.Any = None
+ choices: T.Any = None
+
+ def init_option(self, name: OptionKey) -> coredata._U:
+ keywords = {'value': self.default}
+ if self.choices:
+ keywords['choices'] = self.choices
+ return self.opt_type(name.name, self.description, **keywords)
+
+BASE_OPTIONS: T.Mapping[OptionKey, BaseOption] = {
+ OptionKey('b_pch'): BaseOption(coredata.UserBooleanOption, 'Use precompiled headers', True),
+ OptionKey('b_lto'): BaseOption(coredata.UserBooleanOption, 'Use link time optimization', False),
+ OptionKey('b_lto_threads'): BaseOption(coredata.UserIntegerOption, 'Use multiple threads for Link Time Optimization', (None, None, 0)),
+ OptionKey('b_lto_mode'): BaseOption(coredata.UserComboOption, 'Select between different LTO modes.', 'default',
+ choices=['default', 'thin']),
+ OptionKey('b_thinlto_cache'): BaseOption(coredata.UserBooleanOption, 'Use LLVM ThinLTO caching for faster incremental builds', False),
+ OptionKey('b_thinlto_cache_dir'): BaseOption(coredata.UserStringOption, 'Directory to store ThinLTO cache objects', ''),
+ OptionKey('b_sanitize'): BaseOption(coredata.UserComboOption, 'Code sanitizer to use', 'none',
+ choices=['none', 'address', 'thread', 'undefined', 'memory', 'leak', 'address,undefined']),
+ OptionKey('b_lundef'): BaseOption(coredata.UserBooleanOption, 'Use -Wl,--no-undefined when linking', True),
+ OptionKey('b_asneeded'): BaseOption(coredata.UserBooleanOption, 'Use -Wl,--as-needed when linking', True),
+ OptionKey('b_pgo'): BaseOption(coredata.UserComboOption, 'Use profile guided optimization', 'off',
+ choices=['off', 'generate', 'use']),
+ OptionKey('b_coverage'): BaseOption(coredata.UserBooleanOption, 'Enable coverage tracking.', False),
+ OptionKey('b_colorout'): BaseOption(coredata.UserComboOption, 'Use colored output', 'always',
+ choices=['auto', 'always', 'never']),
+ OptionKey('b_ndebug'): BaseOption(coredata.UserComboOption, 'Disable asserts', 'false', choices=['true', 'false', 'if-release']),
+ OptionKey('b_staticpic'): BaseOption(coredata.UserBooleanOption, 'Build static libraries as position independent', True),
+ OptionKey('b_pie'): BaseOption(coredata.UserBooleanOption, 'Build executables as position independent', False),
+ OptionKey('b_bitcode'): BaseOption(coredata.UserBooleanOption, 'Generate and embed bitcode (only macOS/iOS/tvOS)', False),
+ OptionKey('b_vscrt'): BaseOption(coredata.UserComboOption, 'VS run-time library type to use.', 'from_buildtype',
+ choices=MSCRT_VALS + ['from_buildtype', 'static_from_buildtype']),
}
+base_options: KeyedOptionDictType = {key: base_opt.init_option(key) for key, base_opt in BASE_OPTIONS.items()}
+
def option_enabled(boptions: T.Set[OptionKey], options: 'KeyedOptionDictType',
option: OptionKey) -> bool:
try:
@@ -577,6 +589,14 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta):
"""
return []
+ def create_option(self, option_type: T.Type[UserOptionType], option_key: OptionKey, *args: T.Any, **kwargs: T.Any) -> T.Tuple[OptionKey, UserOptionType]:
+ return option_key, option_type(f'{self.language}_{option_key.name}', *args, **kwargs)
+
+ @staticmethod
+ def update_options(options: MutableKeyedOptionDictType, *args: T.Tuple[OptionKey, UserOptionType]) -> MutableKeyedOptionDictType:
+ options.update(args)
+ return options
+
def get_options(self) -> 'MutableKeyedOptionDictType':
return {}
@@ -1346,10 +1366,12 @@ def get_global_options(lang: str,
link_options = env.options.get(largkey, [])
cargs = coredata.UserArrayOption(
+ f'{lang}_{argkey.name}',
description + ' compiler',
comp_options, split_args=True, allow_dups=True)
largs = coredata.UserArrayOption(
+ f'{lang}_{largkey.name}',
description + ' linker',
link_options, split_args=True, allow_dups=True)
diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py
index 5e412e7a5..540dedb18 100644
--- a/mesonbuild/compilers/cpp.py
+++ b/mesonbuild/compilers/cpp.py
@@ -237,18 +237,22 @@ class ClangCPPCompiler(_StdCPPLibMixin, ClangCompiler, CPPCompiler):
def get_options(self) -> 'MutableKeyedOptionDictType':
opts = CPPCompiler.get_options(self)
key = OptionKey('key', machine=self.for_machine, lang=self.language)
- opts.update({
- key.evolve('debugstl'): coredata.UserBooleanOption(
- 'STL debug mode',
- False,
- ),
- key.evolve('eh'): coredata.UserComboOption(
- 'C++ exception handling type.',
- ['none', 'default', 'a', 's', 'sc'],
- 'default',
- ),
- key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True),
- })
+ self.update_options(
+ opts,
+ self.create_option(coredata.UserComboOption,
+ key.evolve('eh'),
+ 'C++ exception handling type.',
+ ['none', 'default', 'a', 's', 'sc'],
+ 'default'),
+ self.create_option(coredata.UserBooleanOption,
+ key.evolve('rtti'),
+ 'Enable RTTI',
+ True),
+ self.create_option(coredata.UserBooleanOption,
+ key.evolve('debugstl'),
+ 'STL debug mode',
+ False),
+ )
cppstd_choices = [
'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z', 'c++2a', 'c++20',
]
@@ -260,12 +264,13 @@ class ClangCPPCompiler(_StdCPPLibMixin, ClangCompiler, CPPCompiler):
assert isinstance(std_opt, coredata.UserStdOption), 'for mypy'
std_opt.set_versions(cppstd_choices, gnu=True)
if self.info.is_windows() or self.info.is_cygwin():
- opts.update({
- key.evolve('winlibs'): coredata.UserArrayOption(
- 'Standard Win libraries to link against',
- gnu_winlibs,
- ),
- })
+ self.update_options(
+ opts,
+ self.create_option(coredata.UserArrayOption,
+ key.evolve('winlibs'),
+ 'Standard Win libraries to link against',
+ gnu_winlibs),
+ )
return opts
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
@@ -378,13 +383,14 @@ class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler):
def get_options(self) -> 'MutableKeyedOptionDictType':
opts = CPPCompiler.get_options(self)
key = OptionKey('std', machine=self.for_machine, lang=self.language)
- opts.update({
- key.evolve('eh'): coredata.UserComboOption(
- 'C++ exception handling type.',
- ['none', 'default', 'a', 's', 'sc'],
- 'default',
- ),
- })
+ self.update_options(
+ opts,
+ self.create_option(coredata.UserComboOption,
+ key.evolve('eh'),
+ 'C++ exception handling type.',
+ ['none', 'default', 'a', 's', 'sc'],
+ 'default'),
+ )
std_opt = opts[key]
assert isinstance(std_opt, coredata.UserStdOption), 'for mypy'
std_opt.set_versions(['c++98', 'c++03', 'c++11', 'c++14', 'c++17'], gnu=True)
@@ -426,18 +432,22 @@ class GnuCPPCompiler(_StdCPPLibMixin, GnuCompiler, CPPCompiler):
def get_options(self) -> 'MutableKeyedOptionDictType':
key = OptionKey('std', machine=self.for_machine, lang=self.language)
opts = CPPCompiler.get_options(self)
- opts.update({
- key.evolve('eh'): coredata.UserComboOption(
- 'C++ exception handling type.',
- ['none', 'default', 'a', 's', 'sc'],
- 'default',
- ),
- key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True),
- key.evolve('debugstl'): coredata.UserBooleanOption(
- 'STL debug mode',
- False,
- )
- })
+ self.update_options(
+ opts,
+ self.create_option(coredata.UserComboOption,
+ key.evolve('eh'),
+ 'C++ exception handling type.',
+ ['none', 'default', 'a', 's', 'sc'],
+ 'default'),
+ self.create_option(coredata.UserBooleanOption,
+ key.evolve('rtti'),
+ 'Enable RTTI',
+ True),
+ self.create_option(coredata.UserBooleanOption,
+ key.evolve('debugstl'),
+ 'STL debug mode',
+ False),
+ )
cppstd_choices = [
'c++98', 'c++03', 'c++11', 'c++14', 'c++17', 'c++1z',
'c++2a', 'c++20',
@@ -450,12 +460,13 @@ class GnuCPPCompiler(_StdCPPLibMixin, GnuCompiler, CPPCompiler):
assert isinstance(std_opt, coredata.UserStdOption), 'for mypy'
std_opt.set_versions(cppstd_choices, gnu=True)
if self.info.is_windows() or self.info.is_cygwin():
- opts.update({
- key.evolve('winlibs'): coredata.UserArrayOption(
- 'Standard Win libraries to link against',
- gnu_winlibs,
- ),
- })
+ self.update_options(
+ opts,
+ self.create_option(coredata.UserArrayOption,
+ key.evolve('winlibs'),
+ 'Standard Win libraries to link against',
+ gnu_winlibs),
+ )
return opts
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
@@ -550,17 +561,18 @@ class ElbrusCPPCompiler(ElbrusCompiler, CPPCompiler):
cpp_stds += ['c++20']
key = OptionKey('std', machine=self.for_machine, lang=self.language)
- opts.update({
- key.evolve('eh'): coredata.UserComboOption(
- 'C++ exception handling type.',
- ['none', 'default', 'a', 's', 'sc'],
- 'default',
- ),
- key.evolve('debugstl'): coredata.UserBooleanOption(
- 'STL debug mode',
- False,
- ),
- })
+ self.update_options(
+ opts,
+ self.create_option(coredata.UserComboOption,
+ key.evolve('eh'),
+ 'C++ exception handling type.',
+ ['none', 'default', 'a', 's', 'sc'],
+ 'default'),
+ self.create_option(coredata.UserBooleanOption,
+ key.evolve('debugstl'),
+ 'STL debug mode',
+ False),
+ )
std_opt = opts[key]
assert isinstance(std_opt, coredata.UserStdOption), 'for mypy'
std_opt.set_versions(cpp_stds, gnu=True)
@@ -628,15 +640,22 @@ class IntelCPPCompiler(IntelGnuLikeCompiler, CPPCompiler):
g_stds += ['gnu++2a']
key = OptionKey('std', machine=self.for_machine, lang=self.language)
- opts.update({
- key.evolve('eh'): coredata.UserComboOption(
- 'C++ exception handling type.',
- ['none', 'default', 'a', 's', 'sc'],
- 'default',
- ),
- key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True),
- key.evolve('debugstl'): coredata.UserBooleanOption('STL debug mode', False),
- })
+ self.update_options(
+ opts,
+ self.create_option(coredata.UserComboOption,
+ key.evolve('eh'),
+ 'C++ exception handling type.',
+ ['none', 'default', 'a', 's', 'sc'],
+ 'default'),
+ self.create_option(coredata.UserBooleanOption,
+ key.evolve('rtti'),
+ 'Enable RTTI',
+ True),
+ self.create_option(coredata.UserBooleanOption,
+ key.evolve('debugstl'),
+ 'STL debug mode',
+ False),
+ )
std_opt = opts[key]
assert isinstance(std_opt, coredata.UserStdOption), 'for mypy'
std_opt.set_versions(c_stds + g_stds)
@@ -694,18 +713,22 @@ class VisualStudioLikeCPPCompilerMixin(CompilerMixinBase):
def _get_options_impl(self, opts: 'MutableKeyedOptionDictType', cpp_stds: T.List[str]) -> 'MutableKeyedOptionDictType':
key = OptionKey('std', machine=self.for_machine, lang=self.language)
- opts.update({
- key.evolve('eh'): coredata.UserComboOption(
- 'C++ exception handling type.',
- ['none', 'default', 'a', 's', 'sc'],
- 'default',
- ),
- key.evolve('rtti'): coredata.UserBooleanOption('Enable RTTI', True),
- key.evolve('winlibs'): coredata.UserArrayOption(
- 'Windows libs to link against.',
- msvc_winlibs,
- ),
- })
+ self.update_options(
+ opts,
+ self.create_option(coredata.UserComboOption,
+ key.evolve('eh'),
+ 'C++ exception handling type.',
+ ['none', 'default', 'a', 's', 'sc'],
+ 'default'),
+ self.create_option(coredata.UserBooleanOption,
+ key.evolve('rtti'),
+ 'Enable RTTI',
+ True),
+ self.create_option(coredata.UserArrayOption,
+ key.evolve('winlibs'),
+ 'Windows libs to link against.',
+ msvc_winlibs),
+ )
std_opt = opts[key]
assert isinstance(std_opt, coredata.UserStdOption), 'for mypy'
std_opt.set_versions(cpp_stds)
diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py
index 391107f84..ab4810798 100644
--- a/mesonbuild/compilers/cuda.py
+++ b/mesonbuild/compilers/cuda.py
@@ -630,10 +630,6 @@ class CudaCompiler(Compiler):
_CPP20_VERSION = '>=12.0'
def get_options(self) -> 'MutableKeyedOptionDictType':
- opts = super().get_options()
- std_key = OptionKey('std', machine=self.for_machine, lang=self.language)
- ccbindir_key = OptionKey('ccbindir', machine=self.for_machine, lang=self.language)
-
cpp_stds = ['none', 'c++03', 'c++11']
if version_compare(self.version, self._CPP14_VERSION):
cpp_stds += ['c++14']
@@ -642,13 +638,18 @@ class CudaCompiler(Compiler):
if version_compare(self.version, self._CPP20_VERSION):
cpp_stds += ['c++20']
- opts.update({
- std_key: coredata.UserComboOption('C++ language standard to use with CUDA',
- cpp_stds, 'none'),
- ccbindir_key: coredata.UserStringOption('CUDA non-default toolchain directory to use (-ccbin)',
- ''),
- })
- return opts
+ return self.update_options(
+ super().get_options(),
+ self.create_option(coredata.UserComboOption,
+ OptionKey('std', machine=self.for_machine, lang=self.language),
+ 'C++ language standard to use with CUDA',
+ cpp_stds,
+ 'none'),
+ self.create_option(coredata.UserStringOption,
+ OptionKey('ccbindir', machine=self.for_machine, lang=self.language),
+ 'CUDA non-default toolchain directory to use (-ccbin)',
+ ''),
+ )
def _to_host_compiler_options(self, options: 'KeyedOptionDictType') -> 'KeyedOptionDictType':
"""
diff --git a/mesonbuild/compilers/cython.py b/mesonbuild/compilers/cython.py
index a58b3a814..30cec81e3 100644
--- a/mesonbuild/compilers/cython.py
+++ b/mesonbuild/compilers/cython.py
@@ -67,20 +67,19 @@ class CythonCompiler(Compiler):
return new
def get_options(self) -> 'MutableKeyedOptionDictType':
- opts = super().get_options()
- opts.update({
- OptionKey('version', machine=self.for_machine, lang=self.language): coredata.UserComboOption(
- 'Python version to target',
- ['2', '3'],
- '3',
- ),
- OptionKey('language', machine=self.for_machine, lang=self.language): coredata.UserComboOption(
- 'Output C or C++ files',
- ['c', 'cpp'],
- 'c',
- )
- })
- return opts
+ return self.update_options(
+ super().get_options(),
+ self.create_option(coredata.UserComboOption,
+ OptionKey('version', machine=self.for_machine, lang=self.language),
+ 'Python version to target',
+ ['2', '3'],
+ '3'),
+ self.create_option(coredata.UserComboOption,
+ OptionKey('language', machine=self.for_machine, lang=self.language),
+ 'Output C or C++ files',
+ ['c', 'cpp'],
+ 'c'),
+ )
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args: T.List[str] = []
diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py
index 3a7365046..2cdff36de 100644
--- a/mesonbuild/compilers/fortran.py
+++ b/mesonbuild/compilers/fortran.py
@@ -112,16 +112,14 @@ class FortranCompiler(CLikeCompiler, Compiler):
return self._has_multi_link_arguments(args, env, 'stop; end program')
def get_options(self) -> 'MutableKeyedOptionDictType':
- opts = super().get_options()
- key = OptionKey('std', machine=self.for_machine, lang=self.language)
- opts.update({
- key: coredata.UserComboOption(
- 'Fortran language standard to use',
- ['none'],
- 'none',
- ),
- })
- return opts
+ return self.update_options(
+ super().get_options(),
+ self.create_option(coredata.UserComboOption,
+ OptionKey('std', machine=self.for_machine, lang=self.language),
+ 'Fortran language standard to use',
+ ['none'],
+ 'none'),
+ )
class GnuFortranCompiler(GnuCompiler, FortranCompiler):
diff --git a/mesonbuild/compilers/mixins/emscripten.py b/mesonbuild/compilers/mixins/emscripten.py
index d10c49987..bb8a52054 100644
--- a/mesonbuild/compilers/mixins/emscripten.py
+++ b/mesonbuild/compilers/mixins/emscripten.py
@@ -55,17 +55,16 @@ class EmscriptenMixin(Compiler):
args.append(f'-sPTHREAD_POOL_SIZE={count}')
return args
- def get_options(self) -> 'coredata.MutableKeyedOptionDictType':
- opts = super().get_options()
- key = OptionKey('thread_count', machine=self.for_machine, lang=self.language)
- opts.update({
- key: coredata.UserIntegerOption(
+ def get_options(self) -> coredata.MutableKeyedOptionDictType:
+ return self.update_options(
+ super().get_options(),
+ self.create_option(
+ coredata.UserIntegerOption,
+ OptionKey('thread_count', machine=self.for_machine, lang=self.language),
'Number of threads to use in web assembly, set to 0 to disable',
(0, None, 4), # Default was picked at random
),
- })
-
- return opts
+ )
@classmethod
def native_args_to_unix(cls, args: T.List[str]) -> T.List[str]:
diff --git a/mesonbuild/compilers/objc.py b/mesonbuild/compilers/objc.py
index f805bd6be..7c19c1b7d 100644
--- a/mesonbuild/compilers/objc.py
+++ b/mesonbuild/compilers/objc.py
@@ -78,15 +78,14 @@ class ClangObjCCompiler(ClangCompiler, ObjCCompiler):
'everything': ['-Weverything']}
def get_options(self) -> 'coredata.MutableKeyedOptionDictType':
- opts = super().get_options()
- opts.update({
- OptionKey('std', machine=self.for_machine, lang='c'): coredata.UserComboOption(
- 'C language standard to use',
- ['none', 'c89', 'c99', 'c11', 'c17', 'gnu89', 'gnu99', 'gnu11', 'gnu17'],
- 'none',
- )
- })
- return opts
+ return self.update_options(
+ super().get_options(),
+ self.create_option(coredata.UserComboOption,
+ OptionKey('std', machine=self.for_machine, lang='c'),
+ 'C language standard to use',
+ ['none', 'c89', 'c99', 'c11', 'c17', 'gnu89', 'gnu99', 'gnu11', 'gnu17'],
+ 'none'),
+ )
def get_option_compile_args(self, options: 'coredata.KeyedOptionDictType') -> T.List[str]:
args = []
diff --git a/mesonbuild/compilers/objcpp.py b/mesonbuild/compilers/objcpp.py
index baf4fb5ca..46eaa5049 100644
--- a/mesonbuild/compilers/objcpp.py
+++ b/mesonbuild/compilers/objcpp.py
@@ -77,18 +77,17 @@ class ClangObjCPPCompiler(ClangCompiler, ObjCPPCompiler):
'3': default_warn_args + ['-Wextra', '-Wpedantic'],
'everything': ['-Weverything']}
- def get_options(self) -> 'coredata.MutableKeyedOptionDictType':
- opts = super().get_options()
- opts.update({
- OptionKey('std', machine=self.for_machine, lang='cpp'): coredata.UserComboOption(
- 'C++ language standard to use',
- ['none', 'c++98', 'c++11', 'c++14', 'c++17', 'c++20', 'c++2b',
- 'gnu++98', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++20',
- 'gnu++2b'],
- 'none',
- )
- })
- return opts
+ def get_options(self) -> coredata.MutableKeyedOptionDictType:
+ return self.update_options(
+ super().get_options(),
+ self.create_option(coredata.UserComboOption,
+ OptionKey('std', machine=self.for_machine, lang='cpp'),
+ 'C++ language standard to use',
+ ['none', 'c++98', 'c++11', 'c++14', 'c++17', 'c++20', 'c++2b',
+ 'gnu++98', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++20',
+ 'gnu++2b'],
+ 'none'),
+ )
def get_option_compile_args(self, options: 'coredata.KeyedOptionDictType') -> T.List[str]:
args = []
diff --git a/mesonbuild/compilers/rust.py b/mesonbuild/compilers/rust.py
index 65f4ac1b1..05e8b2b27 100644
--- a/mesonbuild/compilers/rust.py
+++ b/mesonbuild/compilers/rust.py
@@ -156,15 +156,12 @@ 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) -> 'MutableKeyedOptionDictType':
- key = OptionKey('std', machine=self.for_machine, lang=self.language)
- return {
- key: coredata.UserComboOption(
- 'Rust edition to use',
- ['none', '2015', '2018', '2021'],
- 'none',
- ),
- }
+ def get_options(self) -> MutableKeyedOptionDictType:
+ return dict((self.create_option(coredata.UserComboOption,
+ OptionKey('std', machine=self.for_machine, lang=self.language),
+ 'Rust edition to use',
+ ['none', '2015', '2018', '2021'],
+ 'none'),))
def get_dependency_compile_args(self, dep: 'Dependency') -> T.List[str]:
# Rust doesn't have dependency compile arguments so simply return
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 112310745..df575981a 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -109,10 +109,11 @@ class MesonVersionMismatchException(MesonException):
class UserOption(T.Generic[_T], HoldableObject):
- def __init__(self, description: str, choices: T.Optional[T.Union[str, T.List[_T]]],
+ def __init__(self, name: str, description: str, choices: T.Optional[T.Union[str, T.List[_T]]],
yielding: bool,
deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
super().__init__()
+ self.name = name
self.choices = choices
self.description = description
if not isinstance(yielding, bool):
@@ -140,20 +141,20 @@ class UserOption(T.Generic[_T], HoldableObject):
return self.value != oldvalue
class UserStringOption(UserOption[str]):
- def __init__(self, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING,
+ def __init__(self, name: str, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING,
deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
- super().__init__(description, None, yielding, deprecated)
+ super().__init__(name, description, None, yielding, deprecated)
self.set_value(value)
def validate_value(self, value: T.Any) -> str:
if not isinstance(value, str):
- raise MesonException('Value "%s" for string option is not a string.' % str(value))
+ raise MesonException(f'The value of option "{self.name}" is "{value}", which is not a string.')
return value
class UserBooleanOption(UserOption[bool]):
- def __init__(self, description: str, value: bool, yielding: bool = DEFAULT_YIELDING,
+ def __init__(self, name: str, description: str, value: bool, yielding: bool = DEFAULT_YIELDING,
deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
- super().__init__(description, [True, False], yielding, deprecated)
+ super().__init__(name, description, [True, False], yielding, deprecated)
self.set_value(value)
def __bool__(self) -> bool:
@@ -163,15 +164,15 @@ class UserBooleanOption(UserOption[bool]):
if isinstance(value, bool):
return value
if not isinstance(value, str):
- raise MesonException(f'Value {value} cannot be converted to a boolean')
+ raise MesonException(f'Option "{self.name}" value {value} cannot be converted to a boolean')
if value.lower() == 'true':
return True
if value.lower() == 'false':
return False
- raise MesonException('Value %s is not boolean (true or false).' % value)
+ raise MesonException(f'Option "{self.name}" value {value} is not boolean (true or false).')
class UserIntegerOption(UserOption[int]):
- def __init__(self, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING,
+ def __init__(self, name: str, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING,
deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
min_value, max_value, default_value = value
self.min_value = min_value
@@ -182,25 +183,25 @@ class UserIntegerOption(UserOption[int]):
if max_value is not None:
c.append('<=' + str(max_value))
choices = ', '.join(c)
- super().__init__(description, choices, yielding, deprecated)
+ super().__init__(name, description, choices, yielding, deprecated)
self.set_value(default_value)
def validate_value(self, value: T.Any) -> int:
if isinstance(value, str):
value = self.toint(value)
if not isinstance(value, int):
- raise MesonException('New value for integer option is not an integer.')
+ raise MesonException(f'Value {value!r} for option "{self.name}" is not an integer.')
if self.min_value is not None and value < self.min_value:
- raise MesonException('New value %d is less than minimum value %d.' % (value, self.min_value))
+ raise MesonException(f'Value {value} for option "{self.name}" is less than minimum value {self.min_value}.')
if self.max_value is not None and value > self.max_value:
- raise MesonException('New value %d is more than maximum value %d.' % (value, self.max_value))
+ raise MesonException(f'Value {value} for option "{self.name}" is more than maximum value {self.max_value}.')
return value
def toint(self, valuestring: str) -> int:
try:
return int(valuestring)
except ValueError:
- raise MesonException('Value string "%s" is not convertible to an integer.' % valuestring)
+ raise MesonException(f'Value string "{valuestring}" for option "{self.name}" is not convertible to an integer.')
class OctalInt(int):
# NinjaBackend.get_user_option_args uses str() to converts it to a command line option
@@ -210,9 +211,9 @@ class OctalInt(int):
return oct(int(self))
class UserUmaskOption(UserIntegerOption, UserOption[T.Union[str, OctalInt]]):
- def __init__(self, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING,
+ def __init__(self, name: str, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING,
deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
- super().__init__(description, (0, 0o777, value), yielding, deprecated)
+ super().__init__(name, description, (0, 0o777, value), yielding, deprecated)
self.choices = ['preserve', '0000-0777']
def printable_value(self) -> str:
@@ -229,18 +230,18 @@ class UserUmaskOption(UserIntegerOption, UserOption[T.Union[str, OctalInt]]):
try:
return int(valuestring, 8)
except ValueError as e:
- raise MesonException(f'Invalid mode: {e}')
+ raise MesonException(f'Invalid mode for option "{self.name}" {e}')
class UserComboOption(UserOption[str]):
- def __init__(self, description: str, choices: T.List[str], value: T.Any,
+ def __init__(self, name: str, description: str, choices: T.List[str], value: T.Any,
yielding: bool = DEFAULT_YIELDING,
deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
- super().__init__(description, choices, yielding, deprecated)
+ super().__init__(name, description, choices, yielding, deprecated)
if not isinstance(self.choices, list):
- raise MesonException('Combo choices must be an array.')
+ raise MesonException(f'Combo choices for option "{self.name}" must be an array.')
for i in self.choices:
if not isinstance(i, str):
- raise MesonException('Combo choice elements must be strings.')
+ raise MesonException(f'Combo choice elements for option "{self.name}" must be strings.')
self.set_value(value)
def validate_value(self, value: T.Any) -> str:
@@ -252,24 +253,27 @@ class UserComboOption(UserOption[str]):
else:
_type = 'string'
optionsstring = ', '.join([f'"{item}"' for item in self.choices])
- raise MesonException('Value "{}" (of type "{}") for combo option "{}" is not one of the choices.'
+ raise MesonException('Value "{}" (of type "{}") for option "{}" is not one of the choices.'
' Possible choices are (as string): {}.'.format(
- value, _type, self.description, optionsstring))
+ value, _type, self.name, optionsstring))
return value
class UserArrayOption(UserOption[T.List[str]]):
- def __init__(self, description: str, value: T.Union[str, T.List[str]],
+ def __init__(self, name: str, description: str, value: T.Union[str, T.List[str]],
split_args: bool = False,
allow_dups: bool = False, yielding: bool = DEFAULT_YIELDING,
choices: T.Optional[T.List[str]] = None,
deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
- super().__init__(description, choices if choices is not None else [], yielding, deprecated)
+ super().__init__(name, description, choices if choices is not None else [], yielding, deprecated)
self.split_args = split_args
self.allow_dups = allow_dups
self.set_value(value)
def listify(self, value: T.Any) -> T.List[T.Any]:
- return listify_array_value(value, self.split_args)
+ try:
+ return listify_array_value(value, self.split_args)
+ except MesonException as e:
+ raise MesonException(f'error in option "{self.name}": {e!s}')
def validate_value(self, value: T.Union[str, T.List[str]]) -> T.List[str]:
newvalue = self.listify(value)
@@ -280,12 +284,17 @@ class UserArrayOption(UserOption[T.List[str]]):
mlog.deprecation(msg)
for i in newvalue:
if not isinstance(i, str):
- raise MesonException(f'String array element "{newvalue!s}" is not a string.')
+ raise MesonException(f'String array element "{newvalue!s}" for option "{self.name}" is not a string.')
if self.choices:
bad = [x for x in newvalue if x not in self.choices]
if bad:
- raise MesonException('Options "{}" are not in allowed choices: "{}"'.format(
- ', '.join(bad), ', '.join(self.choices)))
+ raise MesonException('Value{} "{}" for option "{}" {} not in allowed choices: "{}"'.format(
+ '' if len(bad) == 1 else 's',
+ ', '.join(bad),
+ self.name,
+ 'is' if len(bad) == 1 else 'are',
+ ', '.join(self.choices))
+ )
return newvalue
def extend_value(self, value: T.Union[str, T.List[str]]) -> None:
@@ -297,9 +306,9 @@ class UserArrayOption(UserOption[T.List[str]]):
class UserFeatureOption(UserComboOption):
static_choices = ['enabled', 'disabled', 'auto']
- def __init__(self, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING,
+ def __init__(self, name: str, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING,
deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
- super().__init__(description, self.static_choices, value, yielding, deprecated)
+ super().__init__(name, description, self.static_choices, value, yielding, deprecated)
self.name: T.Optional[str] = None # TODO: Refactor options to all store their name
def is_enabled(self) -> bool:
@@ -330,7 +339,8 @@ class UserStdOption(UserComboOption):
self.all_stds = ['none'] + all_stds
# Map a deprecated std to its replacement. e.g. gnu11 -> c11.
self.deprecated_stds: T.Dict[str, str] = {}
- super().__init__(f'{lang} language standard to use', ['none'], 'none')
+ opt_name = 'cpp_std' if lang == 'c++' else f'{lang}_std'
+ super().__init__(opt_name, f'{lang} language standard to use', ['none'], 'none')
def set_versions(self, versions: T.List[str], gnu: bool = False, gnu_deprecated: bool = False) -> None:
assert all(std in self.all_stds for std in versions)
@@ -343,10 +353,13 @@ class UserStdOption(UserComboOption):
self.choices += gnu_stds_map.keys()
def validate_value(self, value: T.Union[str, T.List[str]]) -> str:
- candidates = listify_array_value(value)
- unknown = [std for std in candidates if std not in self.all_stds]
+ try:
+ candidates = listify_array_value(value)
+ except MesonException as e:
+ raise MesonException(f'error in option "{self.name}": {e!s}')
+ unknown = ','.join(std for std in candidates if std not in self.all_stds)
if unknown:
- raise MesonException(f'Unknown {self.lang.upper()} std {unknown}. Possible values are {self.all_stds}.')
+ raise MesonException(f'Unknown option "{self.name}" value {unknown}. Possible values are {self.all_stds}.')
# Check first if any of the candidates are not deprecated
for std in candidates:
if std in self.choices:
@@ -360,10 +373,10 @@ class UserStdOption(UserComboOption):
f'However, the deprecated {std} std currently falls back to {newstd}.\n' +
'This will be an error in the future.\n' +
'If the project supports both GNU and MSVC compilers, a value such as\n' +
- '"c_std=gnu11,c11" specifies that GNU is prefered but it can safely fallback to plain c11.')
+ '"c_std=gnu11,c11" specifies that GNU is preferred but it can safely fallback to plain c11.')
return newstd
raise MesonException(f'None of values {candidates} are supported by the {self.lang.upper()} compiler. ' +
- f'Possible values are {self.choices}')
+ f'Possible values for option "{self.name}" are {self.choices}')
@dataclass
class OptionsView(abc.Mapping):
@@ -720,11 +733,13 @@ class CoreData:
def init_backend_options(self, backend_name: str) -> None:
if backend_name == 'ninja':
self.options[OptionKey('backend_max_links')] = UserIntegerOption(
+ 'backend_max_links',
'Maximum number of linker processes to run or 0 for no '
'limit',
(0, None, 0))
elif backend_name.startswith('vs'):
self.options[OptionKey('backend_startup_project')] = UserStringOption(
+ 'backend_startup_project',
'Default project to execute in Visual Studio',
'')
@@ -1294,7 +1309,7 @@ class BuiltinOption(T.Generic[_T, _U]):
keywords = {'yielding': self.yielding, 'value': value}
if self.choices:
keywords['choices'] = self.choices
- o = self.opt_type(self.description, **keywords)
+ o = self.opt_type(name.name, self.description, **keywords)
o.readonly = self.readonly
return o
diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py
index e9c201eec..9da355a51 100644
--- a/mesonbuild/optinterpreter.py
+++ b/mesonbuild/optinterpreter.py
@@ -196,7 +196,7 @@ class OptionInterpreter:
n_kwargs = {k: v for k, v in kwargs.items()
if k not in {'type', 'description', 'deprecated', 'yield'}}
- opt = parser(description, (kwargs['yield'], kwargs['deprecated']), n_kwargs)
+ opt = parser(opt_name, description, (kwargs['yield'], kwargs['deprecated']), n_kwargs)
if key in self.options:
mlog.deprecation(f'Option {opt_name} already exists.')
self.options[key] = opt
@@ -205,8 +205,8 @@ class OptionInterpreter:
'string option',
KwargInfo('value', str, default=''),
)
- def string_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: StringArgs) -> coredata.UserOption:
- return coredata.UserStringOption(description, kwargs['value'], *args)
+ def string_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: StringArgs) -> coredata.UserOption:
+ return coredata.UserStringOption(name, description, kwargs['value'], *args)
@typed_kwargs(
'boolean option',
@@ -218,20 +218,20 @@ class OptionInterpreter:
deprecated_values={str: ('1.1.0', 'use a boolean, not a string')},
),
)
- def boolean_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: BooleanArgs) -> coredata.UserOption:
- return coredata.UserBooleanOption(description, kwargs['value'], *args)
+ def boolean_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: BooleanArgs) -> coredata.UserOption:
+ return coredata.UserBooleanOption(name, description, kwargs['value'], *args)
@typed_kwargs(
'combo option',
KwargInfo('value', (str, NoneType)),
KwargInfo('choices', ContainerTypeInfo(list, str, allow_empty=False), required=True),
)
- def combo_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: ComboArgs) -> coredata.UserOption:
+ def combo_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: ComboArgs) -> coredata.UserOption:
choices = kwargs['choices']
value = kwargs['value']
if value is None:
value = kwargs['choices'][0]
- return coredata.UserComboOption(description, choices, value, *args)
+ return coredata.UserComboOption(name, description, choices, value, *args)
@typed_kwargs(
'integer option',
@@ -245,17 +245,17 @@ class OptionInterpreter:
KwargInfo('min', (int, NoneType)),
KwargInfo('max', (int, NoneType)),
)
- def integer_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: IntegerArgs) -> coredata.UserOption:
+ def integer_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: IntegerArgs) -> coredata.UserOption:
value = kwargs['value']
inttuple = (kwargs['min'], kwargs['max'], value)
- return coredata.UserIntegerOption(description, inttuple, *args)
+ return coredata.UserIntegerOption(name, description, inttuple, *args)
@typed_kwargs(
'string array option',
KwargInfo('value', (ContainerTypeInfo(list, str), str, NoneType)),
KwargInfo('choices', ContainerTypeInfo(list, str), default=[]),
)
- def string_array_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: StringArrayArgs) -> coredata.UserOption:
+ def string_array_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: StringArrayArgs) -> coredata.UserOption:
choices = kwargs['choices']
value = kwargs['value'] if kwargs['value'] is not None else choices
if isinstance(value, str):
@@ -263,7 +263,7 @@ class OptionInterpreter:
FeatureDeprecated('String value for array option', '1.3.0').use(self.subproject)
else:
raise mesonlib.MesonException('Value does not define an array: ' + value)
- return coredata.UserArrayOption(description, value,
+ return coredata.UserArrayOption(name, description, value,
choices=choices,
yielding=args[0],
deprecated=args[1])
@@ -272,5 +272,5 @@ class OptionInterpreter:
'feature option',
KwargInfo('value', str, default='auto', validator=in_set_validator({'auto', 'enabled', 'disabled'})),
)
- def feature_parser(self, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: FeatureArgs) -> coredata.UserOption:
- return coredata.UserFeatureOption(description, kwargs['value'], *args)
+ def feature_parser(self, name: str, description: str, args: T.Tuple[bool, _DEPRECATED_ARGS], kwargs: FeatureArgs) -> coredata.UserOption:
+ return coredata.UserFeatureOption(name, description, kwargs['value'], *args)