interpreter: replace ConfigurationDataObject with ConfigurationDataHolder

This is much cleaner, and more in line with the way we handle
interpreter objects in modern meson practice
pull/9850/head
Dylan Baker 3 years ago committed by Eli Schwartz
parent 23af9e4c1a
commit 5074e2d3b5
  1. 4
      mesonbuild/interpreter/__init__.py
  2. 29
      mesonbuild/interpreter/interpreter.py
  3. 50
      mesonbuild/interpreter/interpreterobjects.py
  4. 8
      mesonbuild/modules/cmake.py
  5. 8
      mesonbuild/modules/sourceset.py
  6. 6
      mesonbuild/modules/unstable_simd.py

@ -28,7 +28,7 @@ __all__ = [
'CustomTargetIndexHolder', 'CustomTargetIndexHolder',
'MachineHolder', 'MachineHolder',
'Test', 'Test',
'ConfigurationDataObject', 'ConfigurationDataHolder',
'SubprojectHolder', 'SubprojectHolder',
'DependencyHolder', 'DependencyHolder',
'GeneratedListHolder', 'GeneratedListHolder',
@ -46,7 +46,7 @@ from .interpreter import Interpreter, permitted_dependency_kwargs
from .compiler import CompilerHolder from .compiler import CompilerHolder
from .interpreterobjects import (ExecutableHolder, BuildTargetHolder, CustomTargetHolder, from .interpreterobjects import (ExecutableHolder, BuildTargetHolder, CustomTargetHolder,
CustomTargetIndexHolder, MachineHolder, Test, CustomTargetIndexHolder, MachineHolder, Test,
ConfigurationDataObject, SubprojectHolder, DependencyHolder, ConfigurationDataHolder, SubprojectHolder, DependencyHolder,
GeneratedListHolder, ExternalProgramHolder, GeneratedListHolder, ExternalProgramHolder,
extract_required_kwarg) extract_required_kwarg)

@ -43,7 +43,6 @@ from .mesonmain import MesonMain
from .dependencyfallbacks import DependencyFallbacksHolder from .dependencyfallbacks import DependencyFallbacksHolder
from .interpreterobjects import ( from .interpreterobjects import (
SubprojectHolder, SubprojectHolder,
ConfigurationDataObject,
Test, Test,
RunProcess, RunProcess,
extract_required_kwarg, extract_required_kwarg,
@ -433,6 +432,7 @@ class Interpreter(InterpreterBase, HoldableObject):
dependencies.ExternalLibrary: OBJ.ExternalLibraryHolder, dependencies.ExternalLibrary: OBJ.ExternalLibraryHolder,
coredata.UserFeatureOption: OBJ.FeatureOptionHolder, coredata.UserFeatureOption: OBJ.FeatureOptionHolder,
envconfig.MachineInfo: OBJ.MachineHolder, envconfig.MachineInfo: OBJ.MachineHolder,
build.ConfigurationData: OBJ.ConfigurationDataHolder,
}) })
''' '''
@ -488,7 +488,7 @@ class Interpreter(InterpreterBase, HoldableObject):
elif isinstance(v, Test): elif isinstance(v, Test):
self.build.tests.append(v) self.build.tests.append(v)
elif isinstance(v, (int, str, bool, Disabler, ObjectHolder, build.GeneratedList, elif isinstance(v, (int, str, bool, Disabler, ObjectHolder, build.GeneratedList,
ExternalProgram)): ExternalProgram, build.ConfigurationData)):
pass pass
else: else:
raise InterpreterException(f'Module returned a value of unknown type {v!r}.') raise InterpreterException(f'Module returned a value of unknown type {v!r}.')
@ -1020,13 +1020,16 @@ external dependencies (including libraries) must go to "dependencies".''')
@typed_pos_args('configuration_data', optargs=[dict]) @typed_pos_args('configuration_data', optargs=[dict])
@noKwargs @noKwargs
def func_configuration_data(self, node: mparser.BaseNode, args: T.Optional[dict], kwargs: 'TYPE_kwargs') -> ConfigurationDataObject: def func_configuration_data(self, node: mparser.BaseNode, args: T.Tuple[T.Optional[T.Dict[str, T.Any]]],
kwargs: 'TYPE_kwargs') -> build.ConfigurationData:
initial_values = args[0] initial_values = args[0]
if initial_values is not None: if initial_values is not None:
FeatureNew.single_use('configuration_data dictionary', '0.49.0', self.subproject) FeatureNew.single_use('configuration_data dictionary', '0.49.0', self.subproject)
else: for k, v in initial_values.items():
initial_values = {} if not isinstance(v, (str, int ,bool)):
return ConfigurationDataObject(self.subproject, initial_values) raise InvalidArguments(
f'"configuration_data": initial value dictionary key "{k!r}"" must be "str | int | bool", not "{v!r}"')
return build.ConfigurationData(initial_values)
def set_backend(self): def set_backend(self):
# The backend is already set when parsing subprojects # The backend is already set when parsing subprojects
@ -2235,8 +2238,12 @@ external dependencies (including libraries) must go to "dependencies".''')
conf = kwargs['configuration'] conf = kwargs['configuration']
if isinstance(conf, dict): if isinstance(conf, dict):
FeatureNew.single_use('configure_file.configuration dictionary', '0.49.0', self.subproject) FeatureNew.single_use('configure_file.configuration dictionary', '0.49.0', self.subproject)
conf = ConfigurationDataObject(self.subproject, conf) for k, v in conf.items():
elif not isinstance(conf, ConfigurationDataObject): if not isinstance(v, (str, int ,bool)):
raise InvalidArguments(
f'"configuration_data": initial value dictionary key "{k!r}"" must be "str | int | bool", not "{v!r}"')
conf = build.ConfigurationData(conf)
elif not isinstance(conf, build.ConfigurationData):
raise InterpreterException('Argument "configuration" is not of type configuration_data') raise InterpreterException('Argument "configuration" is not of type configuration_data')
mlog.log('Configuring', mlog.bold(output), 'using configuration') mlog.log('Configuring', mlog.bold(output), 'using configuration')
if len(inputs) > 1: if len(inputs) > 1:
@ -2245,7 +2252,7 @@ external dependencies (including libraries) must go to "dependencies".''')
os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True) os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True)
file_encoding = kwargs.setdefault('encoding', 'utf-8') file_encoding = kwargs.setdefault('encoding', 'utf-8')
missing_variables, confdata_useless = \ missing_variables, confdata_useless = \
mesonlib.do_conf_file(inputs_abs[0], ofile_abs, conf.conf_data, mesonlib.do_conf_file(inputs_abs[0], ofile_abs, conf,
fmt, file_encoding) fmt, file_encoding)
if missing_variables: if missing_variables:
var_list = ", ".join(map(repr, sorted(missing_variables))) var_list = ", ".join(map(repr, sorted(missing_variables)))
@ -2261,8 +2268,8 @@ external dependencies (including libraries) must go to "dependencies".''')
'copy a file to the build dir, use the \'copy:\' keyword ' 'copy a file to the build dir, use the \'copy:\' keyword '
'argument added in 0.47.0', location=node) 'argument added in 0.47.0', location=node)
else: else:
mesonlib.dump_conf_header(ofile_abs, conf.conf_data, output_format) mesonlib.dump_conf_header(ofile_abs, conf, output_format)
conf.mark_used() conf.used = True
elif 'command' in kwargs: elif 'command' in kwargs:
if len(inputs) > 1: if len(inputs) > 1:
FeatureNew.single_use('multiple inputs in configure_file()', '0.52.0', self.subproject) FeatureNew.single_use('multiple inputs in configure_file()', '0.52.0', self.subproject)

@ -279,11 +279,10 @@ class EnvironmentVariablesHolder(ObjectHolder[build.EnvironmentVariables], Mutab
_CONF_DATA_SET_KWS: KwargInfo[T.Optional[str]] = KwargInfo('description', (str, NoneType)) _CONF_DATA_SET_KWS: KwargInfo[T.Optional[str]] = KwargInfo('description', (str, NoneType))
class ConfigurationDataObject(MutableInterpreterObject, MesonInterpreterObject): class ConfigurationDataHolder(ObjectHolder[build.ConfigurationData], MutableInterpreterObject):
def __init__(self, subproject: str, initial_values: T.Optional[T.Dict[str, T.Union[str, int, bool]]] = None) -> None:
self.used = False # These objects become immutable after use in configure_file. def __init__(self, obj: build.ConfigurationData, interpreter: 'Interpreter'):
super().__init__(subproject=subproject) super().__init__(obj, interpreter)
self.conf_data = build.ConfigurationData()
self.methods.update({'set': self.set_method, self.methods.update({'set': self.set_method,
'set10': self.set10_method, 'set10': self.set10_method,
'set_quoted': self.set_quoted_method, 'set_quoted': self.set_quoted_method,
@ -293,43 +292,40 @@ class ConfigurationDataObject(MutableInterpreterObject, MesonInterpreterObject):
'get_unquoted': self.get_unquoted_method, 'get_unquoted': self.get_unquoted_method,
'merge_from': self.merge_from_method, 'merge_from': self.merge_from_method,
}) })
if initial_values:
for k, v in initial_values.items():
self.conf_data.values[k] = (v, None)
def is_used(self) -> bool: def __deepcopy__(self, memo: T.Dict) -> 'ConfigurationDataHolder':
return self.used return ConfigurationDataHolder(copy.deepcopy(self.held_object), self.interpreter)
def mark_used(self) -> None: def is_used(self) -> bool:
self.used = True return self.held_object.used
def __check_used(self) -> None: def __check_used(self) -> None:
if self.used: if self.is_used():
raise InterpreterException("Can not set values on configuration object that has been used.") raise InterpreterException("Can not set values on configuration object that has been used.")
@typed_pos_args('configuration_data.set', str, (str, int, bool)) @typed_pos_args('configuration_data.set', str, (str, int, bool))
@typed_kwargs('configuration_data.set', _CONF_DATA_SET_KWS) @typed_kwargs('configuration_data.set', _CONF_DATA_SET_KWS)
def set_method(self, args: T.Tuple[str, T.Union[str, int, bool]], kwargs: 'kwargs.ConfigurationDataSet') -> None: def set_method(self, args: T.Tuple[str, T.Union[str, int, bool]], kwargs: 'kwargs.ConfigurationDataSet') -> None:
self.__check_used() self.__check_used()
self.conf_data.values[args[0]] = (args[1], kwargs['description']) self.held_object.values[args[0]] = (args[1], kwargs['description'])
@typed_pos_args('configuration_data.set_quoted', str, str) @typed_pos_args('configuration_data.set_quoted', str, str)
@typed_kwargs('configuration_data.set_quoted', _CONF_DATA_SET_KWS) @typed_kwargs('configuration_data.set_quoted', _CONF_DATA_SET_KWS)
def set_quoted_method(self, args: T.Tuple[str, str], kwargs: 'kwargs.ConfigurationDataSet') -> None: def set_quoted_method(self, args: T.Tuple[str, str], kwargs: 'kwargs.ConfigurationDataSet') -> None:
self.__check_used() self.__check_used()
escaped_val = '\\"'.join(args[1].split('"')) escaped_val = '\\"'.join(args[1].split('"'))
self.conf_data.values[args[0]] = (f'"{escaped_val}"', kwargs['description']) self.held_object.values[args[0]] = (f'"{escaped_val}"', kwargs['description'])
@typed_pos_args('configuration_data.set10', str, (int, bool)) @typed_pos_args('configuration_data.set10', str, (int, bool))
@typed_kwargs('configuration_data.set10', _CONF_DATA_SET_KWS) @typed_kwargs('configuration_data.set10', _CONF_DATA_SET_KWS)
def set10_method(self, args: T.Tuple[str, T.Union[int, bool]], kwargs: 'kwargs.ConfigurationDataSet') -> None: def set10_method(self, args: T.Tuple[str, T.Union[int, bool]], kwargs: 'kwargs.ConfigurationDataSet') -> None:
self.__check_used() self.__check_used()
self.conf_data.values[args[0]] = (int(args[1]), kwargs['description']) self.held_object.values[args[0]] = (int(args[1]), kwargs['description'])
@typed_pos_args('configuration_data.has', (str, int, bool)) @typed_pos_args('configuration_data.has', (str, int, bool))
@noKwargs @noKwargs
def has_method(self, args: T.Tuple[T.Union[str, int, bool]], kwargs: TYPE_kwargs) -> bool: def has_method(self, args: T.Tuple[T.Union[str, int, bool]], kwargs: TYPE_kwargs) -> bool:
return args[0] in self.conf_data.values return args[0] in self.held_object.values
@FeatureNew('configuration_data.get()', '0.38.0') @FeatureNew('configuration_data.get()', '0.38.0')
@noArgsFlattening @noArgsFlattening
@ -338,8 +334,8 @@ class ConfigurationDataObject(MutableInterpreterObject, MesonInterpreterObject):
def get_method(self, args: T.Tuple[str, T.Optional[T.Union[str, int, bool]]], def get_method(self, args: T.Tuple[str, T.Optional[T.Union[str, int, bool]]],
kwargs: TYPE_kwargs) -> T.Union[str, int, bool]: kwargs: TYPE_kwargs) -> T.Union[str, int, bool]:
name = args[0] name = args[0]
if name in self.conf_data: if name in self.held_object:
return self.conf_data.get(name)[0] return self.held_object.get(name)[0]
elif args[1] is not None: elif args[1] is not None:
return args[1] return args[1]
raise InterpreterException(f'Entry {name} not in configuration data.') raise InterpreterException(f'Entry {name} not in configuration data.')
@ -350,8 +346,8 @@ class ConfigurationDataObject(MutableInterpreterObject, MesonInterpreterObject):
def get_unquoted_method(self, args: T.Tuple[str, T.Optional[T.Union[str, int, bool]]], def get_unquoted_method(self, args: T.Tuple[str, T.Optional[T.Union[str, int, bool]]],
kwargs: TYPE_kwargs) -> T.Union[str, int, bool]: kwargs: TYPE_kwargs) -> T.Union[str, int, bool]:
name = args[0] name = args[0]
if name in self.conf_data: if name in self.held_object:
val = self.conf_data.get(name)[0] val = self.held_object.get(name)[0]
elif args[1] is not None: elif args[1] is not None:
val = args[1] val = args[1]
else: else:
@ -361,7 +357,7 @@ class ConfigurationDataObject(MutableInterpreterObject, MesonInterpreterObject):
return val return val
def get(self, name: str) -> T.Tuple[T.Union[str, int, bool], T.Optional[str]]: def get(self, name: str) -> T.Tuple[T.Union[str, int, bool], T.Optional[str]]:
return self.conf_data.values[name] return self.held_object.values[name]
@FeatureNew('configuration_data.keys()', '0.57.0') @FeatureNew('configuration_data.keys()', '0.57.0')
@noPosargs @noPosargs
@ -369,15 +365,13 @@ class ConfigurationDataObject(MutableInterpreterObject, MesonInterpreterObject):
return sorted(self.keys()) return sorted(self.keys())
def keys(self) -> T.List[str]: def keys(self) -> T.List[str]:
return list(self.conf_data.values.keys()) return list(self.held_object.values.keys())
@typed_pos_args('configuration_data.merge_from', object) # yay for recursive type validation! @typed_pos_args('configuration_data.merge_from', build.ConfigurationData)
@noKwargs @noKwargs
def merge_from_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> None: def merge_from_method(self, args: T.Tuple[build.ConfigurationData], kwargs: TYPE_kwargs) -> None:
from_object = args[0] from_object = args[0]
if not isinstance(from_object, ConfigurationDataObject): self.held_object.values.update(from_object.values)
raise InterpreterException('Merge_from argument must be a configuration data object.')
self.conf_data.values.update(from_object.conf_data.values)
_PARTIAL_DEP_KWARGS = [ _PARTIAL_DEP_KWARGS = [

@ -20,7 +20,7 @@ from . import ExtensionModule, ModuleReturnValue, ModuleObject
from .. import build, mesonlib, mlog, dependencies from .. import build, mesonlib, mlog, dependencies
from ..cmake import SingleTargetOptions, TargetOptions, cmake_defines_to_args from ..cmake import SingleTargetOptions, TargetOptions, cmake_defines_to_args
from ..interpreter import ConfigurationDataObject, SubprojectHolder from ..interpreter import SubprojectHolder
from ..interpreterbase import ( from ..interpreterbase import (
FeatureNew, FeatureNew,
FeatureNewKwargs, FeatureNewKwargs,
@ -358,7 +358,7 @@ class CmakeModule(ExtensionModule):
if 'configuration' not in kwargs: if 'configuration' not in kwargs:
raise mesonlib.MesonException('"configuration" not specified.') raise mesonlib.MesonException('"configuration" not specified.')
conf = kwargs['configuration'] conf = kwargs['configuration']
if not isinstance(conf, ConfigurationDataObject): if not isinstance(conf, build.ConfigurationData):
raise mesonlib.MesonException('Argument "configuration" is not of type configuration_data') raise mesonlib.MesonException('Argument "configuration" is not of type configuration_data')
prefix = state.environment.coredata.get_option(mesonlib.OptionKey('prefix')) prefix = state.environment.coredata.get_option(mesonlib.OptionKey('prefix'))
@ -372,8 +372,8 @@ class CmakeModule(ExtensionModule):
extra = PACKAGE_INIT_EXT.replace('@absInstallDir@', abs_install_dir) extra = PACKAGE_INIT_EXT.replace('@absInstallDir@', abs_install_dir)
extra = extra.replace('@installPrefix@', prefix) extra = extra.replace('@installPrefix@', prefix)
self.create_package_file(ifile_abs, ofile_abs, PACKAGE_RELATIVE_PATH, extra, conf.conf_data) self.create_package_file(ifile_abs, ofile_abs, PACKAGE_RELATIVE_PATH, extra, conf)
conf.mark_used() conf.used = True
conffile = os.path.normpath(inputfile.relative_name()) conffile = os.path.normpath(inputfile.relative_name())
if conffile not in self.interpreter.build_def_files: if conffile not in self.interpreter.build_def_files:

@ -154,8 +154,12 @@ class SourceSet(MutableModuleObject):
def _get_from_config_data(key): def _get_from_config_data(key):
nonlocal config_cache nonlocal config_cache
if key not in config_cache: if key not in config_cache:
args = [key] if strict else [key, False] if key in config_data:
config_cache[key] = config_data.get_method(args, {}) config_cache[key] = config_data.get(key)[0]
elif strict:
raise InvalidArguments(f'sourceset.apply: key "{key}" not in passed configuration, and strict set.')
else:
config_cache[key] = False
return config_cache[key] return config_cache[key]
files = self.collect(_get_from_config_data, False) files = self.collect(_get_from_config_data, False)

@ -13,6 +13,7 @@
# limitations under the License. # limitations under the License.
from .. import mesonlib, compilers, mlog from .. import mesonlib, compilers, mlog
from .. import build
from . import ExtensionModule from . import ExtensionModule
@ -57,8 +58,7 @@ class SimdModule(ExtensionModule):
compiler = kwargs['compiler'] compiler = kwargs['compiler']
if not isinstance(compiler, compilers.compilers.Compiler): if not isinstance(compiler, compilers.compilers.Compiler):
raise mesonlib.MesonException('Compiler argument must be a compiler object.') raise mesonlib.MesonException('Compiler argument must be a compiler object.')
cdata = self.interpreter.func_configuration_data(None, [], {}) conf = build.ConfigurationData()
conf = cdata.conf_data
for iset in self.isets: for iset in self.isets:
if iset not in kwargs: if iset not in kwargs:
continue continue
@ -82,7 +82,7 @@ class SimdModule(ExtensionModule):
all_lang_args = old_lang_args + args all_lang_args = old_lang_args + args
lib_kwargs[langarg_key] = all_lang_args lib_kwargs[langarg_key] = all_lang_args
result.append(self.interpreter.func_static_lib(None, [libname], lib_kwargs)) result.append(self.interpreter.func_static_lib(None, [libname], lib_kwargs))
return [result, cdata] return [result, conf]
def initialize(*args, **kwargs): def initialize(*args, **kwargs):
return SimdModule(*args, **kwargs) return SimdModule(*args, **kwargs)

Loading…
Cancel
Save