Rename OptionOverrideProxy to OptionsView and move to coredata

Coredata is where all option handling is done so it makes sense there.
It is a view on a list of options for a given subproject and with
optional overrides. This change prepare for using that view in a more
generic way in the future.
pull/11822/merge
Xavier Claessens 1 year ago committed by Xavier Claessens
parent 3fc16f05b5
commit d5f17bc9ff
  1. 6
      mesonbuild/build.py
  2. 4
      mesonbuild/compilers/cuda.py
  3. 46
      mesonbuild/coredata.py
  4. 50
      mesonbuild/utils/universal.py

@ -34,7 +34,7 @@ from .mesonlib import (
File, MesonException, MachineChoice, PerMachine, OrderedSet, listify,
extract_as_list, typeslistify, stringlistify, classify_unity_sources,
get_filenames_templates_dict, substitute_values, has_path_sep,
OptionKey, PerMachineDefaultable, OptionOverrideProxy,
OptionKey, PerMachineDefaultable,
MesonBugException, EnvironmentVariables, pickle_load,
)
from .compilers import (
@ -535,7 +535,7 @@ class Target(HoldableObject, metaclass=abc.ABCMeta):
for k, v in overrides.items()}
else:
ovr = {}
self.options = OptionOverrideProxy(ovr, self.environment.coredata.options, self.subproject)
self.options = coredata.OptionsView(self.environment.coredata.options, self.subproject, ovr)
# XXX: this should happen in the interpreter
if has_path_sep(self.name):
# Fix failing test 53 when this becomes an error.
@ -655,7 +655,7 @@ class Target(HoldableObject, metaclass=abc.ABCMeta):
else:
self.options.overrides[k] = v
def get_options(self) -> OptionOverrideProxy:
def get_options(self) -> coredata.OptionsView:
return self.options
def get_option(self, key: 'OptionKey') -> T.Union[str, int, bool, 'WrapMode']:

@ -21,7 +21,7 @@ import typing as T
from .. import coredata
from .. import mlog
from ..mesonlib import (
EnvironmentException, Popen_safe, OptionOverrideProxy,
EnvironmentException, Popen_safe,
is_windows, LibType, OptionKey, version_compare,
)
from .compilers import (Compiler, cuda_buildtype_args, cuda_optimization_args,
@ -650,7 +650,7 @@ class CudaCompiler(Compiler):
host_options = {key: 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)
overrides = {std_key: 'none'}
return OptionOverrideProxy(overrides, host_options)
return coredata.OptionsView(host_options, overrides=overrides)
def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
args = self.get_ccbin_args(options)

@ -19,7 +19,9 @@ import pickle, os, uuid
import sys
from itertools import chain
from pathlib import PurePath
from collections import OrderedDict
from collections import OrderedDict, abc
from dataclasses import dataclass
from .mesonlib import (
HoldableObject,
MesonException, EnvironmentException, MachineChoice, PerMachine,
@ -42,12 +44,12 @@ if T.TYPE_CHECKING:
from .compilers.compilers import Compiler, CompileResult, RunResult, CompileCheckMode
from .dependencies.detect import TV_DepID
from .environment import Environment
from .mesonlib import OptionOverrideProxy, FileOrString
from .mesonlib import FileOrString
from .cmake.traceparser import CMakeCacheEntry
OptionDictType = T.Union[T.Dict[str, 'UserOption[T.Any]'], OptionOverrideProxy]
OptionDictType = T.Union[T.Dict[str, 'UserOption[T.Any]'], 'OptionsView']
MutableKeyedOptionDictType = T.Dict['OptionKey', 'UserOption[T.Any]']
KeyedOptionDictType = T.Union[MutableKeyedOptionDictType, OptionOverrideProxy]
KeyedOptionDictType = T.Union[MutableKeyedOptionDictType, 'OptionsView']
CompilerCheckCacheKey = T.Tuple[T.Tuple[str, ...], str, FileOrString, T.Tuple[str, ...], CompileCheckMode]
# code, args
RunCheckCacheKey = T.Tuple[str, T.Tuple[str, ...]]
@ -375,6 +377,42 @@ class UserStdOption(UserComboOption):
raise MesonException(f'None of values {candidates} are supported by the {self.lang.upper()} compiler. ' +
f'Possible values are {self.choices}')
@dataclass
class OptionsView(abc.Mapping):
'''A view on an options dictionary for a given subproject and with overrides.
'''
# TODO: the typing here could be made more explicit using a TypeDict from
# python 3.8 or typing_extensions
options: KeyedOptionDictType
subproject: T.Optional[str] = None
overrides: T.Optional[T.Mapping[OptionKey, T.Union[str, int, bool, T.List[str]]]] = None
def __getitem__(self, key: OptionKey) -> UserOption:
# FIXME: This is fundamentally the same algorithm than interpreter.get_option_internal().
# We should try to share the code somehow.
key = key.evolve(subproject=self.subproject)
if not key.is_project():
opt = self.options.get(key)
if opt is None or opt.yielding:
opt = self.options[key.as_root()]
else:
opt = self.options[key]
if opt.yielding:
opt = self.options.get(key.as_root(), opt)
if self.overrides:
override_value = self.overrides.get(key.as_root())
if override_value is not None:
opt = copy.copy(opt)
opt.set_value(override_value)
return opt
def __iter__(self) -> T.Iterator[OptionKey]:
return iter(self.options)
def __len__(self) -> int:
return len(self.options)
class DependencyCacheType(enum.Enum):
OTHER = 0

@ -29,7 +29,6 @@ from itertools import tee
from tempfile import TemporaryDirectory, NamedTemporaryFile
import typing as T
import textwrap
import copy
import pickle
import errno
import json
@ -42,7 +41,7 @@ if T.TYPE_CHECKING:
from .._typing import ImmutableListProtocol
from ..build import ConfigurationData
from ..coredata import KeyedOptionDictType, UserOption, StrOrBytesPath
from ..coredata import StrOrBytesPath
from ..environment import Environment
from ..compilers.compilers import Compiler
from ..interpreterbase.baseobjects import SubProject
@ -79,7 +78,6 @@ __all__ = [
'GitException',
'OptionKey',
'dump_conf_header',
'OptionOverrideProxy',
'OptionType',
'OrderedSet',
'PerMachine',
@ -2124,52 +2122,6 @@ def generate_list(func: T.Callable[..., T.Generator[_T, None, None]]) -> T.Calla
return wrapper
class OptionOverrideProxy(collections.abc.Mapping):
'''Mimic an option list but transparently override selected option
values.
'''
# TODO: the typing here could be made more explicit using a TypeDict from
# python 3.8 or typing_extensions
def __init__(self, overrides: T.Dict['OptionKey', T.Any], options: 'KeyedOptionDictType',
subproject: T.Optional[str] = None):
self.overrides = overrides
self.options = options
self.subproject = subproject
def __getitem__(self, key: 'OptionKey') -> 'UserOption':
# FIXME: This is fundamentally the same algorithm than interpreter.get_option_internal().
# We should try to share the code somehow.
key = key.evolve(subproject=self.subproject)
if not key.is_project():
opt = self.options.get(key)
if opt is None or opt.yielding:
opt = self.options[key.as_root()]
else:
opt = self.options[key]
if opt.yielding:
opt = self.options.get(key.as_root(), opt)
override_value = self.overrides.get(key.as_root())
if override_value is not None:
opt = copy.copy(opt)
opt.set_value(override_value)
return opt
def __iter__(self) -> T.Iterator['OptionKey']:
return iter(self.options)
def __len__(self) -> int:
return len(self.options)
def __eq__(self, other: object) -> bool:
if not isinstance(other, OptionOverrideProxy):
return NotImplemented
t1 = (self.overrides, self.subproject, self.options)
t2 = (other.overrides, other.subproject, other.options)
return t1 == t2
class OptionType(enum.IntEnum):
"""Enum used to specify what kind of argument a thing is."""

Loading…
Cancel
Save