diff options
-rw-r--r-- | mesonbuild/build.py | 6 | ||||
-rw-r--r-- | mesonbuild/compilers/cuda.py | 4 | ||||
-rw-r--r-- | mesonbuild/coredata.py | 46 | ||||
-rw-r--r-- | mesonbuild/utils/universal.py | 50 |
4 files changed, 48 insertions, 58 deletions
diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 8fed785..edec75d 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.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']: diff --git a/mesonbuild/compilers/cuda.py b/mesonbuild/compilers/cuda.py index 8ed7fa4..09a7d6a 100644 --- a/mesonbuild/compilers/cuda.py +++ b/mesonbuild/compilers/cuda.py @@ -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) diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 4b0f9af..f151c7b 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -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 diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py index d44ec03..7f0f385 100644 --- a/mesonbuild/utils/universal.py +++ b/mesonbuild/utils/universal.py @@ -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.""" |