Remove language (AKA compiler) type from OptionKey.

pull/12487/head
Jussi Pakkanen 5 months ago
parent de8e3d65e0
commit 61c742fae9
  1. 4
      mesonbuild/backend/ninjabackend.py
  2. 6
      mesonbuild/backend/vs2010backend.py
  3. 14
      mesonbuild/build.py
  4. 2
      mesonbuild/cmake/interpreter.py
  5. 2
      mesonbuild/compilers/c.py
  6. 8
      mesonbuild/compilers/compilers.py
  7. 16
      mesonbuild/compilers/cpp.py
  8. 2
      mesonbuild/compilers/cuda.py
  9. 2
      mesonbuild/compilers/mixins/elbrus.py
  10. 4
      mesonbuild/compilers/mixins/emscripten.py
  11. 4
      mesonbuild/compilers/objc.py
  12. 4
      mesonbuild/compilers/objcpp.py
  13. 14
      mesonbuild/coredata.py
  14. 9
      mesonbuild/environment.py
  15. 5
      mesonbuild/modules/__init__.py
  16. 4
      mesonbuild/modules/rust.py
  17. 52
      mesonbuild/options.py
  18. 2
      run_tests.py
  19. 8
      unittests/allplatformstests.py
  20. 6
      unittests/internaltests.py
  21. 2
      unittests/linuxliketests.py

@ -1091,7 +1091,7 @@ class NinjaBackend(backends.Backend):
cpp = target.compilers['cpp'] cpp = target.compilers['cpp']
if cpp.get_id() != 'msvc': if cpp.get_id() != 'msvc':
return False return False
cppversion = target.get_option(OptionKey('std', machine=target.for_machine, lang='cpp')) cppversion = target.get_option(OptionKey('cpp_std', machine=target.for_machine))
if cppversion not in ('latest', 'c++latest', 'vc++latest'): if cppversion not in ('latest', 'c++latest', 'vc++latest'):
return False return False
if not mesonlib.current_vs_supports_modules(): if not mesonlib.current_vs_supports_modules():
@ -1783,7 +1783,7 @@ class NinjaBackend(backends.Backend):
args += self.build.get_project_args(cython, target.subproject, target.for_machine) args += self.build.get_project_args(cython, target.subproject, target.for_machine)
args += target.get_extra_args('cython') args += target.get_extra_args('cython')
ext = target.get_option(OptionKey('language', machine=target.for_machine, lang='cython')) ext = target.get_option(OptionKey('cython_language', machine=target.for_machine))
pyx_sources = [] # Keep track of sources we're adding to build pyx_sources = [] # Keep track of sources we're adding to build

@ -1011,8 +1011,8 @@ class Vs2010Backend(backends.Backend):
file_args[l] += args file_args[l] += args
# Compile args added from the env or cross file: CFLAGS/CXXFLAGS, etc. We want these # 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. # to override all the defaults, but not the per-target compile args.
for l in file_args.keys(): for lang in file_args.keys():
file_args[l] += target.get_option(OptionKey('args', machine=target.for_machine, lang=l)) file_args[lang] += target.get_option(OptionKey(f'{lang}_args', machine=target.for_machine))
for args in file_args.values(): for args in file_args.values():
# This is where Visual Studio will insert target_args, target_defines, # This is where Visual Studio will insert target_args, target_defines,
# etc, which are added later from external deps (see below). # etc, which are added later from external deps (see below).
@ -1340,7 +1340,7 @@ class Vs2010Backend(backends.Backend):
# Exception handling has to be set in the xml in addition to the "AdditionalOptions" because otherwise # 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 # cl will give warning D9025: overriding '/Ehs' with cpp_eh value
if 'cpp' in target.compilers: if 'cpp' in target.compilers:
eh = target.get_option(OptionKey('eh', machine=target.for_machine, lang='cpp')) eh = target.get_option(OptionKey('cpp_eh', machine=target.for_machine))
if eh == 'a': if eh == 'a':
ET.SubElement(clconf, 'ExceptionHandling').text = 'Async' ET.SubElement(clconf, 'ExceptionHandling').text = 'Async'
elif eh == 's': elif eh == 's':

@ -652,10 +652,20 @@ class Target(HoldableObject, metaclass=abc.ABCMeta):
self.set_option_overrides(self.parse_overrides(kwargs)) self.set_option_overrides(self.parse_overrides(kwargs))
def is_compiler_option_hack(self, key):
# FIXME this method must be deleted when OptionsView goes away.
# At that point the build target only stores the original string.
# The decision on how to use those pieces of data is done elsewhere.
from .compilers import all_languages
if '_' not in key.name:
return False
prefix = key.name.split('_')[0]
return prefix in all_languages
def set_option_overrides(self, option_overrides: T.Dict[OptionKey, str]) -> None: def set_option_overrides(self, option_overrides: T.Dict[OptionKey, str]) -> None:
self.options.overrides = {} self.options.overrides = {}
for k, v in option_overrides.items(): for k, v in option_overrides.items():
if k.lang: if self.is_compiler_option_hack(k):
self.options.overrides[k.evolve(machine=self.for_machine)] = v self.options.overrides[k.evolve(machine=self.for_machine)] = v
else: else:
self.options.overrides[k] = v self.options.overrides[k] = v
@ -1002,7 +1012,7 @@ class BuildTarget(Target):
if 'vala' in self.compilers and 'c' not in self.compilers: if 'vala' in self.compilers and 'c' not in self.compilers:
self.compilers['c'] = self.all_compilers['c'] self.compilers['c'] = self.all_compilers['c']
if 'cython' in self.compilers: if 'cython' in self.compilers:
key = OptionKey('language', machine=self.for_machine, lang='cython') key = OptionKey('cython_language', machine=self.for_machine)
value = self.get_option(key) value = self.get_option(key)
try: try:

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

@ -310,7 +310,7 @@ class GnuCCompiler(GnuCompiler, CCompiler):
self.update_options( self.update_options(
opts, opts,
self.create_option(options.UserArrayOption, self.create_option(options.UserArrayOption,
key.evolve('winlibs'), key.evolve('c_winlibs'),
'Standard Win libraries to link against', 'Standard Win libraries to link against',
gnu_winlibs), gnu_winlibs),
) )

@ -1355,7 +1355,7 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta):
raise EnvironmentException(f'{self.get_id()} does not support preprocessor') raise EnvironmentException(f'{self.get_id()} does not support preprocessor')
def form_compileropt_key(self, basename: str) -> OptionKey: def form_compileropt_key(self, basename: str) -> OptionKey:
return OptionKey(basename, machine=self.for_machine, lang=self.language) return OptionKey(f'{self.language}_{basename}', machine=self.for_machine)
def get_global_options(lang: str, def get_global_options(lang: str,
comp: T.Type[Compiler], comp: T.Type[Compiler],
@ -1363,9 +1363,9 @@ def get_global_options(lang: str,
env: 'Environment') -> 'dict[OptionKey, options.UserOption[Any]]': env: 'Environment') -> 'dict[OptionKey, options.UserOption[Any]]':
"""Retrieve options that apply to all compilers for a given language.""" """Retrieve options that apply to all compilers for a given language."""
description = f'Extra arguments passed to the {lang}' description = f'Extra arguments passed to the {lang}'
argkey = OptionKey('args', lang=lang, machine=for_machine) argkey = OptionKey(f'{lang}_args', machine=for_machine)
largkey = argkey.evolve('link_args') largkey = argkey.evolve(f'{lang}_link_args')
envkey = argkey.evolve('env_args') envkey = argkey.evolve(f'{lang}_env_args')
comp_key = argkey if argkey in env.options else envkey comp_key = argkey if argkey in env.options else envkey

@ -475,7 +475,7 @@ class GnuCPPCompiler(_StdCPPLibMixin, GnuCompiler, CPPCompiler):
self.update_options( self.update_options(
opts, opts,
self.create_option(options.UserArrayOption, self.create_option(options.UserArrayOption,
key.evolve('winlibs'), key.evolve('cpp_winlibs'),
'Standard Win libraries to link against', 'Standard Win libraries to link against',
gnu_winlibs), gnu_winlibs),
) )
@ -483,17 +483,21 @@ class GnuCPPCompiler(_StdCPPLibMixin, GnuCompiler, CPPCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args: T.List[str] = [] args: T.List[str] = []
key = self.form_compileropt_key('std') stdkey = self.form_compileropt_key('std')
std = options.get_value(key) ehkey = self.form_compileropt_key('eh')
rttikey = self.form_compileropt_key('rtti')
debugstlkey = self.form_compileropt_key('debugstl')
std = options.get_value(stdkey)
if std != 'none': if std != 'none':
args.append(self._find_best_cpp_std(std)) args.append(self._find_best_cpp_std(std))
non_msvc_eh_options(options.get_value(key.evolve('eh')), args) non_msvc_eh_options(options.get_value(ehkey), args)
if not options.get_value(key.evolve('rtti')): if not options.get_value(rttikey):
args.append('-fno-rtti') args.append('-fno-rtti')
if options.get_value(key.evolve('debugstl')): if options.get_value(debugstlkey):
args.append('-D_GLIBCXX_DEBUG=1') args.append('-D_GLIBCXX_DEBUG=1')
return args return args

@ -664,7 +664,7 @@ class CudaCompiler(Compiler):
# We must strip the -std option from the host compiler option set, as NVCC has # We must strip the -std option from the host compiler option set, as NVCC has
# its own -std flag that may not agree with the host compiler's. # its own -std flag that may not agree with the host compiler's.
host_options = {key: master_options.get(key, opt) for key, opt in self.host_compiler.get_options().items()} host_options = {key: master_options.get(key, opt) for key, opt in self.host_compiler.get_options().items()}
std_key = OptionKey('std', machine=self.for_machine, lang=self.host_compiler.language) std_key = OptionKey(f'{self.host_compiler.language}_std', machine=self.for_machine)
overrides = {std_key: 'none'} overrides = {std_key: 'none'}
# To shut up mypy. # To shut up mypy.
return coredata.OptionsView(host_options, overrides=overrides) return coredata.OptionsView(host_options, overrides=overrides)

@ -85,7 +85,7 @@ class ElbrusCompiler(GnuLikeCompiler):
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]: def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args: T.List[str] = [] args: T.List[str] = []
std = options.get_value(OptionKey('std', lang=self.language, machine=self.for_machine)) std = options.get_value(OptionKey(f'{self.language}_std', machine=self.for_machine))
if std != 'none': if std != 'none':
args.append('-std=' + std) args.append('-std=' + std)
return args return args

@ -51,7 +51,7 @@ class EmscriptenMixin(Compiler):
def thread_link_flags(self, env: 'Environment') -> T.List[str]: def thread_link_flags(self, env: 'Environment') -> T.List[str]:
args = ['-pthread'] args = ['-pthread']
count: int = env.coredata.optstore.get_value(OptionKey('thread_count', lang=self.language, machine=self.for_machine)) count: int = env.coredata.optstore.get_value(OptionKey(f'{self.language}_thread_count', machine=self.for_machine))
if count: if count:
args.append(f'-sPTHREAD_POOL_SIZE={count}') args.append(f'-sPTHREAD_POOL_SIZE={count}')
return args return args
@ -61,7 +61,7 @@ class EmscriptenMixin(Compiler):
super().get_options(), super().get_options(),
self.create_option( self.create_option(
options.UserIntegerOption, options.UserIntegerOption,
OptionKey('thread_count', machine=self.for_machine, lang=self.language), OptionKey(f'{self.language}_thread_count', machine=self.for_machine),
'Number of threads to use in web assembly, set to 0 to disable', 'Number of threads to use in web assembly, set to 0 to disable',
(0, None, 4), # Default was picked at random (0, None, 4), # Default was picked at random
), ),

@ -82,7 +82,7 @@ class ClangObjCCompiler(ClangCompiler, ObjCCompiler):
return self.update_options( return self.update_options(
super().get_options(), super().get_options(),
self.create_option(options.UserComboOption, self.create_option(options.UserComboOption,
OptionKey('std', machine=self.for_machine, lang='c'), OptionKey('c_std', machine=self.for_machine),
'C language standard to use', 'C language standard to use',
['none', 'c89', 'c99', 'c11', 'c17', 'gnu89', 'gnu99', 'gnu11', 'gnu17'], ['none', 'c89', 'c99', 'c11', 'c17', 'gnu89', 'gnu99', 'gnu11', 'gnu17'],
'none'), 'none'),
@ -90,7 +90,7 @@ class ClangObjCCompiler(ClangCompiler, ObjCCompiler):
def get_option_compile_args(self, options: 'coredata.KeyedOptionDictType') -> T.List[str]: def get_option_compile_args(self, options: 'coredata.KeyedOptionDictType') -> T.List[str]:
args = [] args = []
std = options.get_value(OptionKey('std', machine=self.for_machine, lang='c')) std = options.get_value(OptionKey('c_std', machine=self.for_machine))
if std != 'none': if std != 'none':
args.append('-std=' + std) args.append('-std=' + std)
return args return args

@ -82,7 +82,7 @@ class ClangObjCPPCompiler(ClangCompiler, ObjCPPCompiler):
return self.update_options( return self.update_options(
super().get_options(), super().get_options(),
self.create_option(options.UserComboOption, self.create_option(options.UserComboOption,
OptionKey('std', machine=self.for_machine, lang='cpp'), OptionKey('cpp_std', machine=self.for_machine),
'C++ language standard to use', 'C++ language standard to use',
['none', 'c++98', 'c++11', 'c++14', 'c++17', 'c++20', 'c++2b', ['none', 'c++98', 'c++11', 'c++14', 'c++17', 'c++20', 'c++2b',
'gnu++98', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++20', 'gnu++98', 'gnu++11', 'gnu++14', 'gnu++17', 'gnu++20',
@ -92,7 +92,7 @@ class ClangObjCPPCompiler(ClangCompiler, ObjCPPCompiler):
def get_option_compile_args(self, options: 'coredata.KeyedOptionDictType') -> T.List[str]: def get_option_compile_args(self, options: 'coredata.KeyedOptionDictType') -> T.List[str]:
args = [] args = []
std = options.get_value(OptionKey('std', machine=self.for_machine, lang='cpp')) std = options.get_value(OptionKey('cpp_std', machine=self.for_machine))
if std != 'none': if std != 'none':
args.append('-std=' + std) args.append('-std=' + std)
return args return args

@ -568,20 +568,19 @@ class CoreData:
return dirty return dirty
@staticmethod def is_per_machine_option(self, optname: OptionKey) -> bool:
def is_per_machine_option(optname: OptionKey) -> bool:
if optname.as_host() in options.BUILTIN_OPTIONS_PER_MACHINE: if optname.as_host() in options.BUILTIN_OPTIONS_PER_MACHINE:
return True return True
return optname.lang is not None return self.optstore.is_compiler_option(optname)
def get_external_args(self, for_machine: MachineChoice, lang: str) -> T.List[str]: def get_external_args(self, for_machine: MachineChoice, lang: str) -> T.List[str]:
# mypy cannot analyze type of OptionKey # mypy cannot analyze type of OptionKey
key = OptionKey('args', machine=for_machine, lang=lang) key = OptionKey(f'{lang}_args', machine=for_machine)
return T.cast('T.List[str]', self.optstore.get_value(key)) return T.cast('T.List[str]', self.optstore.get_value(key))
def get_external_link_args(self, for_machine: MachineChoice, lang: str) -> T.List[str]: def get_external_link_args(self, for_machine: MachineChoice, lang: str) -> T.List[str]:
# mypy cannot analyze type of OptionKey # mypy cannot analyze type of OptionKey
key = OptionKey('link_args', machine=for_machine, lang=lang) key = OptionKey(f'{lang}_link_args', machine=for_machine)
return T.cast('T.List[str]', self.optstore.get_value(key)) return T.cast('T.List[str]', self.optstore.get_value(key))
def update_project_options(self, project_options: 'MutableKeyedOptionDictType', subproject: SubProject) -> None: def update_project_options(self, project_options: 'MutableKeyedOptionDictType', subproject: SubProject) -> None:
@ -732,7 +731,8 @@ class CoreData:
# These options are all new at this point, because the compiler is # These options are all new at this point, because the compiler is
# responsible for adding its own options, thus calling # responsible for adding its own options, thus calling
# `self.optstore.update()`` is perfectly safe. # `self.optstore.update()`` is perfectly safe.
self.optstore.update(compilers.get_global_options(lang, comp, for_machine, env)) for gopt_key, gopt_valobj in compilers.get_global_options(lang, comp, for_machine, env).items():
self.optstore.add_compiler_option(lang, gopt_key, gopt_valobj)
def process_compiler_options(self, lang: str, comp: Compiler, env: Environment, subproject: str) -> None: def process_compiler_options(self, lang: str, comp: Compiler, env: Environment, subproject: str) -> None:
from . import compilers from . import compilers
@ -924,7 +924,7 @@ class OptionsView(abc.Mapping):
# to hold overrides. # to hold overrides.
if isinstance(self.original_options, options.OptionStore): if isinstance(self.original_options, options.OptionStore):
if key2 not in self.original_options: if key2 not in self.original_options:
raise KeyError raise KeyError(f'{key} {key2}')
opt = self.original_options.get_value_object(key2) opt = self.original_options.get_value_object(key2)
else: else:
opt = self.original_options[key2] opt = self.original_options[key2]

@ -743,14 +743,12 @@ class Environment:
# if it changes on future invocations. # if it changes on future invocations.
if self.first_invocation: if self.first_invocation:
if keyname == 'ldflags': if keyname == 'ldflags':
key = OptionKey('link_args', machine=for_machine, lang='c') # needs a language to initialize properly
for lang in compilers.compilers.LANGUAGES_USING_LDFLAGS: for lang in compilers.compilers.LANGUAGES_USING_LDFLAGS:
key = key.evolve(lang=lang) key = OptionKey(name=f'{lang}_link_args', machine=for_machine)
env_opts[key].extend(p_list) env_opts[key].extend(p_list)
elif keyname == 'cppflags': elif keyname == 'cppflags':
key = OptionKey('env_args', machine=for_machine, lang='c')
for lang in compilers.compilers.LANGUAGES_USING_CPPFLAGS: for lang in compilers.compilers.LANGUAGES_USING_CPPFLAGS:
key = key.evolve(lang=lang) key = OptionKey(f'{lang}_env_args', machine=for_machine)
env_opts[key].extend(p_list) env_opts[key].extend(p_list)
else: else:
key = OptionKey.from_string(keyname).evolve(machine=for_machine) key = OptionKey.from_string(keyname).evolve(machine=for_machine)
@ -770,7 +768,8 @@ class Environment:
# We still use the original key as the base here, as # We still use the original key as the base here, as
# we want to inherit the machine and the compiler # we want to inherit the machine and the compiler
# language # language
key = key.evolve('env_args') lang = key.name.split('_', 1)[0]
key = key.evolve(f'{lang}_env_args')
env_opts[key].extend(p_list) env_opts[key].extend(p_list)
# Only store options that are not already in self.options, # Only store options that are not already in self.options,

@ -133,15 +133,14 @@ class ModuleState:
def get_option(self, name: str, subproject: str = '', def get_option(self, name: str, subproject: str = '',
machine: MachineChoice = MachineChoice.HOST, machine: MachineChoice = MachineChoice.HOST,
lang: T.Optional[str] = None,
module: T.Optional[str] = None) -> T.Union[T.List[str], str, int, bool]: module: T.Optional[str] = None) -> T.Union[T.List[str], str, int, bool]:
return self.environment.coredata.get_option(OptionKey(name, subproject, machine, lang, module)) return self.environment.coredata.get_option(OptionKey(name, subproject, machine, module))
def is_user_defined_option(self, name: str, subproject: str = '', def is_user_defined_option(self, name: str, subproject: str = '',
machine: MachineChoice = MachineChoice.HOST, machine: MachineChoice = MachineChoice.HOST,
lang: T.Optional[str] = None, lang: T.Optional[str] = None,
module: T.Optional[str] = None) -> bool: module: T.Optional[str] = None) -> bool:
key = OptionKey(name, subproject, machine, lang, module) key = OptionKey(name, subproject, machine, module)
return key in self._interpreter.user_defined_options.cmd_line_options return key in self._interpreter.user_defined_options.cmd_line_options
def process_include_dirs(self, dirs: T.Iterable[T.Union[str, IncludeDirs]]) -> T.Iterable[IncludeDirs]: def process_include_dirs(self, dirs: T.Iterable[T.Union[str, IncludeDirs]]) -> T.Iterable[IncludeDirs]:

@ -269,7 +269,7 @@ class RustModule(ExtensionModule):
raise InterpreterException(f'Unknown file type extension for: {name}') raise InterpreterException(f'Unknown file type extension for: {name}')
# We only want include directories and defines, other things may not be valid # We only want include directories and defines, other things may not be valid
cargs = state.get_option('args', state.subproject, lang=language) cargs = state.get_option(f'{language}_args', state.subproject)
assert isinstance(cargs, list), 'for mypy' assert isinstance(cargs, list), 'for mypy'
for a in itertools.chain(state.global_args.get(language, []), state.project_args.get(language, []), cargs): for a in itertools.chain(state.global_args.get(language, []), state.project_args.get(language, []), cargs):
if a.startswith(('-I', '/I', '-D', '/D', '-U', '/U')): if a.startswith(('-I', '/I', '-D', '/D', '-U', '/U')):
@ -280,7 +280,7 @@ class RustModule(ExtensionModule):
# Add the C++ standard to the clang arguments. Attempt to translate VS # Add the C++ standard to the clang arguments. Attempt to translate VS
# extension versions into the nearest standard version # extension versions into the nearest standard version
std = state.get_option('std', lang=language) std = state.get_option(f'{language}_std')
assert isinstance(std, str), 'for mypy' assert isinstance(std, str), 'for mypy'
if std.startswith('vc++'): if std.startswith('vc++'):
if std.endswith('latest'): if std.endswith('latest'):

@ -90,18 +90,16 @@ class OptionKey:
internally easier to reason about and produce. internally easier to reason about and produce.
""" """
__slots__ = ['name', 'subproject', 'machine', 'lang', '_hash', 'module'] __slots__ = ['name', 'subproject', 'machine', '_hash', 'module']
name: str name: str
subproject: str subproject: str
machine: MachineChoice machine: MachineChoice
lang: T.Optional[str]
_hash: int _hash: int
module: T.Optional[str] module: T.Optional[str]
def __init__(self, name: str, subproject: str = '', def __init__(self, name: str, subproject: str = '',
machine: MachineChoice = MachineChoice.HOST, machine: MachineChoice = MachineChoice.HOST,
lang: T.Optional[str] = None,
module: T.Optional[str] = None): module: T.Optional[str] = None):
# the _type option to the constructor is kinda private. We want to be # the _type option to the constructor is kinda private. We want to be
# able tos ave the state and avoid the lookup function when # able tos ave the state and avoid the lookup function when
@ -110,9 +108,8 @@ class OptionKey:
object.__setattr__(self, 'name', name) object.__setattr__(self, 'name', name)
object.__setattr__(self, 'subproject', subproject) object.__setattr__(self, 'subproject', subproject)
object.__setattr__(self, 'machine', machine) object.__setattr__(self, 'machine', machine)
object.__setattr__(self, 'lang', lang)
object.__setattr__(self, 'module', module) object.__setattr__(self, 'module', module)
object.__setattr__(self, '_hash', hash((name, subproject, machine, lang, module))) object.__setattr__(self, '_hash', hash((name, subproject, machine, module)))
def __setattr__(self, key: str, value: T.Any) -> None: def __setattr__(self, key: str, value: T.Any) -> None:
raise AttributeError('OptionKey instances do not support mutation.') raise AttributeError('OptionKey instances do not support mutation.')
@ -122,7 +119,6 @@ class OptionKey:
'name': self.name, 'name': self.name,
'subproject': self.subproject, 'subproject': self.subproject,
'machine': self.machine, 'machine': self.machine,
'lang': self.lang,
'module': self.module, 'module': self.module,
} }
@ -141,7 +137,7 @@ class OptionKey:
return self._hash return self._hash
def _to_tuple(self) -> T.Tuple[str, str, str, MachineChoice, str]: def _to_tuple(self) -> T.Tuple[str, str, str, MachineChoice, str]:
return (self.subproject, self.lang or '', self.module or '', self.machine, self.name) return (self.subproject, self.module or '', self.machine, self.name)
def __eq__(self, other: object) -> bool: def __eq__(self, other: object) -> bool:
if isinstance(other, OptionKey): if isinstance(other, OptionKey):
@ -155,8 +151,6 @@ class OptionKey:
def __str__(self) -> str: def __str__(self) -> str:
out = self.name out = self.name
if self.lang:
out = f'{self.lang}_{out}'
if self.machine is MachineChoice.BUILD: if self.machine is MachineChoice.BUILD:
out = f'build.{out}' out = f'build.{out}'
if self.module: if self.module:
@ -166,7 +160,7 @@ class OptionKey:
return out return out
def __repr__(self) -> str: def __repr__(self) -> str:
return f'OptionKey({self.name!r}, {self.subproject!r}, {self.machine!r}, {self.lang!r}, {self.module!r})' return f'OptionKey({self.name!r}, {self.subproject!r}, {self.machine!r}, {self.module!r})'
@classmethod @classmethod
def from_string(cls, raw: str) -> 'OptionKey': def from_string(cls, raw: str) -> 'OptionKey':
@ -191,18 +185,14 @@ class OptionKey:
except ValueError: except ValueError:
raw3 = raw2 raw3 = raw2
from .compilers import all_languages opt = raw3
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 ':' not in opt
assert '.' not in opt assert '.' not in opt
return cls(opt, subproject, for_machine, lang, module) return cls(opt, subproject, for_machine, module)
def evolve(self, name: T.Optional[str] = None, subproject: T.Optional[str] = None, def evolve(self, name: T.Optional[str] = None, subproject: T.Optional[str] = None,
machine: T.Optional[MachineChoice] = None, lang: T.Optional[str] = '', machine: T.Optional[MachineChoice] = None,
module: T.Optional[str] = '') -> 'OptionKey': module: T.Optional[str] = '') -> 'OptionKey':
"""Create a new copy of this key, but with altered members. """Create a new copy of this key, but with altered members.
@ -218,7 +208,6 @@ class OptionKey:
name if name is not None else self.name, name if name is not None else self.name,
subproject if subproject is not None else self.subproject, subproject if subproject is not None else self.subproject,
machine if machine is not None else self.machine, machine if machine is not None else self.machine,
lang if lang != '' else self.lang,
module if module != '' else self.module module if module != '' else self.module
) )
@ -681,6 +670,10 @@ class OptionStore:
def __init__(self): def __init__(self):
self.d: T.Dict['OptionKey', 'UserOption[T.Any]'] = {} self.d: T.Dict['OptionKey', 'UserOption[T.Any]'] = {}
self.project_options = set() self.project_options = set()
self.all_languages = set()
from .compilers import all_languages
for lang in all_languages:
self.all_languages.add(lang)
def __len__(self): def __len__(self):
return len(self.d) return len(self.d)
@ -698,8 +691,15 @@ class OptionStore:
def add_system_option(self, key: T.Union[OptionKey, str], valobj: 'UserOption[T.Any]'): def add_system_option(self, key: T.Union[OptionKey, str], valobj: 'UserOption[T.Any]'):
key = self.ensure_key(key) key = self.ensure_key(key)
assert isinstance(valobj, UserOption)
self.d[key] = valobj self.d[key] = valobj
def add_compiler_option(self, language: str, key: T.Union[OptionKey, str], valobj: 'UserOption[T.Any]'):
key = self.ensure_key(key)
if not key.name.startswith(language + '_'):
raise MesonException(f'Internal error: all compiler option names must start with language prefix. ({key.name} vs {language}_)')
self.add_system_option(key, valobj)
def add_project_option(self, key: T.Union[OptionKey, str], valobj: 'UserOption[T.Any]'): def add_project_option(self, key: T.Union[OptionKey, str], valobj: 'UserOption[T.Any]'):
key = self.ensure_key(key) key = self.ensure_key(key)
self.d[key] = valobj self.d[key] = valobj
@ -733,6 +733,7 @@ class OptionStore:
def items(self) -> ItemsView['OptionKey', 'UserOption[T.Any]']: def items(self) -> ItemsView['OptionKey', 'UserOption[T.Any]']:
return self.d.items() return self.d.items()
# FIXME: this method must be deleted and users moved to use "add_xxx_option"s instead.
def update(self, *args, **kwargs): def update(self, *args, **kwargs):
return self.d.update(*args, **kwargs) return self.d.update(*args, **kwargs)
@ -749,9 +750,6 @@ class OptionStore:
def is_reserved_name(self, key: OptionKey) -> bool: def is_reserved_name(self, key: OptionKey) -> bool:
if key.name in _BUILTIN_NAMES: if key.name in _BUILTIN_NAMES:
return True return True
# FIXME, this hack is needed until the lang field is removed from OptionKey.
if key.lang is not None:
return True
if '_' not in key.name: if '_' not in key.name:
return False return False
prefix = key.name.split('_')[0] prefix = key.name.split('_')[0]
@ -760,8 +758,7 @@ class OptionStore:
# values. It is not, thank you very much. # values. It is not, thank you very much.
if prefix in ('b', 'backend'): # pylint: disable=R6201 if prefix in ('b', 'backend'): # pylint: disable=R6201
return True return True
from .compilers import all_languages if prefix in self.all_languages:
if prefix in all_languages:
return True return True
return False return False
@ -779,4 +776,11 @@ class OptionStore:
def is_compiler_option(self, key: OptionKey) -> bool: def is_compiler_option(self, key: OptionKey) -> bool:
"""Convenience method to check if this is a compiler option.""" """Convenience method to check if this is a compiler option."""
return key.lang is not None
# FIXME, duplicate of is_reserved_name above. Should maybe store a cache instead.
if '_' not in key.name:
return False
prefix = key.name.split('_')[0]
if prefix in self.all_languages:
return True
return False

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

@ -2725,11 +2725,11 @@ class AllPlatformTests(BasePlatformTests):
# c_args value should be parsed with split_args # c_args value should be parsed with split_args
self.init(testdir, extra_args=['-Dc_args=-Dfoo -Dbar "-Dthird=one two"', '--fatal-meson-warnings']) self.init(testdir, extra_args=['-Dc_args=-Dfoo -Dbar "-Dthird=one two"', '--fatal-meson-warnings'])
obj = mesonbuild.coredata.load(self.builddir) obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.optstore.get_value(OptionKey('args', lang='c')), ['-Dfoo', '-Dbar', '-Dthird=one two']) self.assertEqual(obj.optstore.get_value(OptionKey('c_args')), ['-Dfoo', '-Dbar', '-Dthird=one two'])
self.setconf('-Dc_args="foo bar" one two') self.setconf('-Dc_args="foo bar" one two')
obj = mesonbuild.coredata.load(self.builddir) obj = mesonbuild.coredata.load(self.builddir)
self.assertEqual(obj.optstore.get_value(OptionKey('args', lang='c')), ['foo bar', 'one', 'two']) self.assertEqual(obj.optstore.get_value(OptionKey('c_args')), ['foo bar', 'one', 'two'])
self.wipe() self.wipe()
self.init(testdir, extra_args=['-Dset_percent_opt=myoption%', '--fatal-meson-warnings']) self.init(testdir, extra_args=['-Dset_percent_opt=myoption%', '--fatal-meson-warnings'])
@ -2748,7 +2748,7 @@ class AllPlatformTests(BasePlatformTests):
self.assertEqual(obj.optstore.get_value('bindir'), 'bar') self.assertEqual(obj.optstore.get_value('bindir'), 'bar')
self.assertEqual(obj.optstore.get_value('buildtype'), 'release') self.assertEqual(obj.optstore.get_value('buildtype'), 'release')
self.assertEqual(obj.optstore.get_value('b_sanitize'), 'thread') self.assertEqual(obj.optstore.get_value('b_sanitize'), 'thread')
self.assertEqual(obj.optstore.get_value(OptionKey('args', lang='c')), ['-Dbar']) self.assertEqual(obj.optstore.get_value(OptionKey('c_args')), ['-Dbar'])
self.setconf(['--bindir=bar', '--bindir=foo', self.setconf(['--bindir=bar', '--bindir=foo',
'-Dbuildtype=release', '-Dbuildtype=plain', '-Dbuildtype=release', '-Dbuildtype=plain',
'-Db_sanitize=thread', '-Db_sanitize=address', '-Db_sanitize=thread', '-Db_sanitize=address',
@ -2757,7 +2757,7 @@ class AllPlatformTests(BasePlatformTests):
self.assertEqual(obj.optstore.get_value('bindir'), 'foo') self.assertEqual(obj.optstore.get_value('bindir'), 'foo')
self.assertEqual(obj.optstore.get_value('buildtype'), 'plain') self.assertEqual(obj.optstore.get_value('buildtype'), 'plain')
self.assertEqual(obj.optstore.get_value('b_sanitize'), 'address') self.assertEqual(obj.optstore.get_value('b_sanitize'), 'address')
self.assertEqual(obj.optstore.get_value(OptionKey('args', lang='c')), ['-Dfoo']) self.assertEqual(obj.optstore.get_value(OptionKey('c_args')), ['-Dfoo'])
self.wipe() self.wipe()
except KeyError: except KeyError:
# Ignore KeyError, it happens on CI for compilers that does not # Ignore KeyError, it happens on CI for compilers that does not

@ -626,7 +626,7 @@ class InternalTests(unittest.TestCase):
env = get_fake_env() env = get_fake_env()
compiler = detect_c_compiler(env, MachineChoice.HOST) compiler = detect_c_compiler(env, MachineChoice.HOST)
env.coredata.compilers.host = {'c': compiler} env.coredata.compilers.host = {'c': compiler}
env.coredata.optstore.set_value_object(OptionKey('link_args', lang='c'), FakeCompilerOptions()) env.coredata.optstore.set_value_object(OptionKey('c_link_args'), FakeCompilerOptions())
p1 = Path(tmpdir) / '1' p1 = Path(tmpdir) / '1'
p2 = Path(tmpdir) / '2' p2 = Path(tmpdir) / '2'
p1.mkdir() p1.mkdir()
@ -1704,8 +1704,8 @@ class InternalTests(unittest.TestCase):
def test_option_key_from_string(self) -> None: def test_option_key_from_string(self) -> None:
cases = [ cases = [
('c_args', OptionKey('args', lang='c')), ('c_args', OptionKey('c_args')),
('build.cpp_args', OptionKey('args', machine=MachineChoice.BUILD, lang='cpp')), ('build.cpp_args', OptionKey('cpp_args', machine=MachineChoice.BUILD)),
('prefix', OptionKey('prefix')), ('prefix', OptionKey('prefix')),
('made_up', OptionKey('made_up')), ('made_up', OptionKey('made_up')),

@ -486,7 +486,7 @@ class LinuxlikeTests(BasePlatformTests):
# Check that all the listed -std=xxx options for this compiler work just fine when used # 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://en.wikipedia.org/wiki/Xcode#Latest_versions
# https://www.gnu.org/software/gcc/projects/cxx-status.html # https://www.gnu.org/software/gcc/projects/cxx-status.html
key = OptionKey('std', lang=compiler.language) key = OptionKey(f'{compiler.language}_std')
for v in compiler.get_options()[key].choices: for v in compiler.get_options()[key].choices:
# we do it like this to handle gnu++17,c++17 and gnu17,c17 cleanly # we do it like this to handle gnu++17,c++17 and gnu17,c17 cleanly
# thus, C++ first # thus, C++ first

Loading…
Cancel
Save