diff options
author | Xavier Claessens <xavier.claessens@collabora.com> | 2021-03-03 12:48:30 -0500 |
---|---|---|
committer | Xavier Claessens <xclaesse@gmail.com> | 2021-05-28 15:17:10 -0400 |
commit | 3340284805b96a4b9b62405f626020276341944c (patch) | |
tree | 83ff4cbaed7db7d89360eedbfa63930c2e0c68a6 | |
parent | 723c5227a471aff3a1a5a3bc481984c99bf592aa (diff) | |
download | meson-3340284805b96a4b9b62405f626020276341944c.zip meson-3340284805b96a4b9b62405f626020276341944c.tar.gz meson-3340284805b96a4b9b62405f626020276341944c.tar.bz2 |
modules: Stop using InterpreterObject
Custom objects returned by modules must be subclass of ModuleObject and
have the state argument in its methods.
Add MutableModuleObject base class for objects that needs to be deep
copied on assignation.
-rw-r--r-- | mesonbuild/interpreter/interpreter.py | 10 | ||||
-rw-r--r-- | mesonbuild/interpreter/interpreterobjects.py | 7 | ||||
-rw-r--r-- | mesonbuild/modules/__init__.py | 16 | ||||
-rw-r--r-- | mesonbuild/modules/cmake.py | 56 | ||||
-rw-r--r-- | mesonbuild/modules/sourceset.py | 46 | ||||
-rw-r--r-- | mesonbuild/modules/unstable_cuda.py | 4 | ||||
-rw-r--r-- | mesonbuild/modules/unstable_external_project.py | 10 |
7 files changed, 79 insertions, 70 deletions
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 70fd556..ecaeb7a 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -31,7 +31,7 @@ from ..interpreterbase import InterpreterException, InvalidArguments, InvalidCod from ..interpreterbase import InterpreterObject, Disabler, disablerIfNotFound from ..interpreterbase import FeatureNew, FeatureDeprecated, FeatureNewKwargs, FeatureDeprecatedKwargs from ..interpreterbase import ObjectHolder, RangeHolder -from ..modules import ModuleObject +from ..modules import ModuleObject, MutableModuleObject from ..cmake import CMakeInterpreter from ..backend.backends import Backend, ExecutableSerialisation @@ -46,7 +46,7 @@ from .interpreterobjects import (SubprojectHolder, MachineHolder, EnvironmentVar SharedModuleHolder, HeadersHolder, BothLibrariesHolder, BuildTargetHolder, DataHolder, JarHolder, Test, RunProcess, ManHolder, GeneratorHolder, InstallDirHolder, extract_required_kwarg, - extract_search_dirs) + extract_search_dirs, MutableModuleObjectHolder) from pathlib import Path import os @@ -363,7 +363,7 @@ class Interpreter(InterpreterBase): if isinstance(item, build.CustomTarget): return CustomTargetHolder(item, self) - elif isinstance(item, (int, str, bool, Disabler, InterpreterObject)) or item is None: + elif isinstance(item, (int, str, bool, Disabler, InterpreterObject, mesonlib.File)) or item is None: return item elif isinstance(item, build.Executable): return ExecutableHolder(item, self) @@ -379,6 +379,8 @@ class Interpreter(InterpreterBase): return DependencyHolder(item, self.subproject) elif isinstance(item, ExternalProgram): return ExternalProgramHolder(item, self.subproject) + elif isinstance(item, MutableModuleObject): + return MutableModuleObjectHolder(item, self) elif isinstance(item, ModuleObject): return ModuleObjectHolder(item, self) elif isinstance(item, (InterpreterObject, ObjectHolder)): @@ -825,7 +827,7 @@ external dependencies (including libraries) must go to "dependencies".''') prefix = self.coredata.options[OptionKey('prefix')].value from ..modules.cmake import CMakeSubprojectOptions - options = kwargs.get('options', CMakeSubprojectOptions()) + options = unholder(kwargs.get('options', CMakeSubprojectOptions())) if not isinstance(options, CMakeSubprojectOptions): raise InterpreterException('"options" kwarg must be CMakeSubprojectOptions' ' object (created by cmake.subproject_options())') diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index 1c64f5b..3f76e4e 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -2,6 +2,7 @@ import os import shlex import subprocess import re +import copy from pathlib import Path, PurePath @@ -810,6 +811,12 @@ class ModuleObjectHolder(InterpreterObject, ObjectHolder['ModuleObject']): ret = ret.return_value return self.interpreter.holderify(ret) +class MutableModuleObjectHolder(ModuleObjectHolder, MutableInterpreterObject): + def __deepcopy__(self, memo): + # Deepcopy only held object, not interpreter + modobj = copy.deepcopy(self.held_object, memo) + return MutableModuleObjectHolder(modobj, self.interpreter) + _Target = T.TypeVar('_Target', bound=build.Target) diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index f73a50b..7a83122 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -86,16 +86,20 @@ class ModuleState: class ModuleObject: """Base class for all objects returned by modules """ - def __init__(self, interpreter: T.Optional['Interpreter'] = None) -> None: + def __init__(self) -> None: self.methods = {} # type: T.Dict[str, T.Callable[[T.List[TYPE_nvar], TYPE_nkwargs], TYPE_var]] - # FIXME: Port all modules to stop using self.interpreter and use API on - # ModuleState instead. - self.interpreter = interpreter -# FIXME: Port all modules to use ModuleObject directly. -class ExtensionModule(ModuleObject): +class MutableModuleObject(ModuleObject): pass +# FIXME: Port all modules to stop using self.interpreter and use API on +# ModuleState instead. Modules should stop using this class and instead use +# ModuleObject base class. +class ExtensionModule(ModuleObject): + def __init__(self, interpreter: 'Interpreter') -> None: + super().__init__() + self.interpreter = interpreter + def is_module_library(fname): ''' Check if the file is a library-like file generated by a module-specific diff --git a/mesonbuild/modules/cmake.py b/mesonbuild/modules/cmake.py index bef7a00..048b59e 100644 --- a/mesonbuild/modules/cmake.py +++ b/mesonbuild/modules/cmake.py @@ -16,16 +16,12 @@ import os, os.path, pathlib import shutil import typing as T -from . import ExtensionModule, ModuleReturnValue +from . import ExtensionModule, ModuleReturnValue, ModuleObject from .. import build, mesonlib, mlog from ..cmake import SingleTargetOptions, TargetOptions, cmake_defines_to_args from ..interpreter import ConfigurationDataHolder, SubprojectHolder, DependencyHolder from ..interpreterbase import ( - InterpreterException, - InterpreterObject, - ObjectHolder, - FeatureNew, FeatureNewKwargs, FeatureDeprecatedKwargs, @@ -72,12 +68,12 @@ endmacro() #################################################################################### ''' -class CMakeSubprojectHolder(InterpreterObject, ObjectHolder): +class CMakeSubproject(ModuleObject): def __init__(self, subp, pv): assert(isinstance(subp, SubprojectHolder)) assert(hasattr(subp, 'cm_interpreter')) - InterpreterObject.__init__(self) - ObjectHolder.__init__(self, subp, pv) + super().__init__() + self.subp = subp self.methods.update({'get_variable': self.get_variable, 'dependency': self.dependency, 'include_directories': self.include_directories, @@ -92,7 +88,7 @@ class CMakeSubprojectHolder(InterpreterObject, ObjectHolder): raise InterpreterException('Exactly one argument is required.') tgt = args[0] - res = self.held_object.cm_interpreter.target_info(tgt) + res = self.subp.cm_interpreter.target_info(tgt) if res is None: raise InterpreterException(f'The CMake target {tgt} does not exist\n' + ' Use the following command in your meson.build to list all available targets:\n\n' + @@ -104,15 +100,15 @@ class CMakeSubprojectHolder(InterpreterObject, ObjectHolder): @noKwargs @stringArgs - def get_variable(self, args, kwargs): - return self.held_object.get_variable_method(args, kwargs) + def get_variable(self, state, args, kwargs): + return self.subp.get_variable_method(args, kwargs) @FeatureNewKwargs('dependency', '0.56.0', ['include_type']) @permittedKwargs({'include_type'}) @stringArgs - def dependency(self, args, kwargs): + def dependency(self, state, args, kwargs): info = self._args_to_info(args) - orig = self.get_variable([info['dep']], {}) + orig = self.get_variable(state, [info['dep']], {}) assert isinstance(orig, DependencyHolder) actual = orig.include_type_method([], {}) if 'include_type' in kwargs and kwargs['include_type'] != actual: @@ -122,35 +118,35 @@ class CMakeSubprojectHolder(InterpreterObject, ObjectHolder): @noKwargs @stringArgs - def include_directories(self, args, kwargs): + def include_directories(self, state, args, kwargs): info = self._args_to_info(args) - return self.get_variable([info['inc']], kwargs) + return self.get_variable(state, [info['inc']], kwargs) @noKwargs @stringArgs - def target(self, args, kwargs): + def target(self, state, args, kwargs): info = self._args_to_info(args) - return self.get_variable([info['tgt']], kwargs) + return self.get_variable(state, [info['tgt']], kwargs) @noKwargs @stringArgs - def target_type(self, args, kwargs): + def target_type(self, state, args, kwargs): info = self._args_to_info(args) return info['func'] @noPosargs @noKwargs - def target_list(self, args, kwargs): - return self.held_object.cm_interpreter.target_list() + def target_list(self, state, args, kwargs): + return self.subp.cm_interpreter.target_list() @noPosargs @noKwargs @FeatureNew('CMakeSubproject.found()', '0.53.2') - def found_method(self, args, kwargs): - return self.held_object is not None + def found_method(self, state, args, kwargs): + return self.subp is not None -class CMakeSubprojectOptions(InterpreterObject): +class CMakeSubprojectOptions(ModuleObject): def __init__(self) -> None: super().__init__() self.cmake_options = [] # type: T.List[str] @@ -173,39 +169,39 @@ class CMakeSubprojectOptions(InterpreterObject): return self.target_options.global_options @noKwargs - def add_cmake_defines(self, args, kwargs) -> None: + def add_cmake_defines(self, state, args, kwargs) -> None: self.cmake_options += cmake_defines_to_args(args) @stringArgs @permittedKwargs({'target'}) - def set_override_option(self, args, kwargs) -> None: + def set_override_option(self, state, args, kwargs) -> None: if len(args) != 2: raise InvalidArguments('set_override_option takes exactly 2 positional arguments') self._get_opts(kwargs).set_opt(args[0], args[1]) @permittedKwargs({'target'}) - def set_install(self, args, kwargs) -> None: + def set_install(self, state, args, kwargs) -> None: if len(args) != 1 or not isinstance(args[0], bool): raise InvalidArguments('set_install takes exactly 1 boolean argument') self._get_opts(kwargs).set_install(args[0]) @stringArgs @permittedKwargs({'target'}) - def append_compile_args(self, args, kwargs) -> None: + def append_compile_args(self, state, args, kwargs) -> None: if len(args) < 2: raise InvalidArguments('append_compile_args takes at least 2 positional arguments') self._get_opts(kwargs).append_args(args[0], args[1:]) @stringArgs @permittedKwargs({'target'}) - def append_link_args(self, args, kwargs) -> None: + def append_link_args(self, state, args, kwargs) -> None: if not args: raise InvalidArguments('append_link_args takes at least 1 positional argument') self._get_opts(kwargs).append_link_args(args) @noPosargs @noKwargs - def clear(self, args, kwargs) -> None: + def clear(self, state, args, kwargs) -> None: self.cmake_options.clear() self.target_options = TargetOptions() @@ -389,7 +385,7 @@ class CmakeModule(ExtensionModule): subp = self.interpreter.do_subproject(dirname, 'cmake', kwargs) if not subp.held_object: return subp - return CMakeSubprojectHolder(subp, dirname) + return CMakeSubproject(subp, dirname) @FeatureNew('subproject_options', '0.55.0') @noKwargs diff --git a/mesonbuild/modules/sourceset.py b/mesonbuild/modules/sourceset.py index 73cfbe1..1340959 100644 --- a/mesonbuild/modules/sourceset.py +++ b/mesonbuild/modules/sourceset.py @@ -15,10 +15,9 @@ from collections import namedtuple from .. import mesonlib from ..mesonlib import listify, OrderedSet -from . import ExtensionModule +from . import ExtensionModule, ModuleObject, MutableModuleObject from ..interpreterbase import ( noPosargs, noKwargs, permittedKwargs, - InterpreterObject, MutableInterpreterObject, ObjectHolder, InterpreterException, InvalidArguments, InvalidCode, FeatureNew, ) from ..interpreter import ( @@ -29,10 +28,10 @@ from ..interpreter import ( SourceSetRule = namedtuple('SourceSetRule', 'keys sources if_false sourcesets dependencies extra_deps') SourceFiles = namedtuple('SourceFiles', 'sources dependencies') -class SourceSetHolder(MutableInterpreterObject, ObjectHolder): +class SourceSet(MutableModuleObject): def __init__(self, interpreter): - MutableInterpreterObject.__init__(self) - ObjectHolder.__init__(self, list()) + super().__init__() + self.rules = [] self.subproject = interpreter.subproject self.environment = interpreter.environment self.subdir = interpreter.subdir @@ -77,7 +76,7 @@ class SourceSetHolder(MutableInterpreterObject, ObjectHolder): return keys, deps @permittedKwargs(['when', 'if_false', 'if_true']) - def add_method(self, args, kwargs): + def add_method(self, state, args, kwargs): if self.frozen: raise InvalidCode('Tried to use \'add\' after querying the source set') when = listify(kwargs.get('when', [])) @@ -90,10 +89,10 @@ class SourceSetHolder(MutableInterpreterObject, ObjectHolder): keys, dependencies = self.check_conditions(when) sources, extra_deps = self.check_source_files(if_true, True) if_false, _ = self.check_source_files(if_false, False) - self.held_object.append(SourceSetRule(keys, sources, if_false, [], dependencies, extra_deps)) + self.rules.append(SourceSetRule(keys, sources, if_false, [], dependencies, extra_deps)) @permittedKwargs(['when', 'if_true']) - def add_all_method(self, args, kwargs): + def add_all_method(self, state, args, kwargs): if self.frozen: raise InvalidCode('Tried to use \'add_all\' after querying the source set') when = listify(kwargs.get('when', [])) @@ -102,17 +101,18 @@ class SourceSetHolder(MutableInterpreterObject, ObjectHolder): if_true = args elif args: raise InterpreterException('add_all called with both positional and keyword arguments') + if_true = mesonlib.unholder(if_true) keys, dependencies = self.check_conditions(when) for s in if_true: - if not isinstance(s, SourceSetHolder): + if not isinstance(s, SourceSet): raise InvalidCode('Arguments to \'add_all\' after the first must be source sets') s.frozen = True - self.held_object.append(SourceSetRule(keys, [], [], if_true, dependencies, [])) + self.rules.append(SourceSetRule(keys, [], [], if_true, dependencies, [])) def collect(self, enabled_fn, all_sources, into=None): if not into: into = SourceFiles(OrderedSet(), OrderedSet()) - for entry in self.held_object: + for entry in self.rules: if all(x.found() for x in entry.dependencies) and \ all(enabled_fn(key) for key in entry.keys): into.sources.update(entry.sources) @@ -127,7 +127,7 @@ class SourceSetHolder(MutableInterpreterObject, ObjectHolder): @noKwargs @noPosargs - def all_sources_method(self, args, kwargs): + def all_sources_method(self, state, args, kwargs): self.frozen = True files = self.collect(lambda x: True, True) return list(files.sources) @@ -135,13 +135,13 @@ class SourceSetHolder(MutableInterpreterObject, ObjectHolder): @noKwargs @noPosargs @FeatureNew('source_set.all_dependencies() method', '0.52.0') - def all_dependencies_method(self, args, kwargs): + def all_dependencies_method(self, state, args, kwargs): self.frozen = True files = self.collect(lambda x: True, True) return list(files.dependencies) @permittedKwargs(['strict']) - def apply_method(self, args, kwargs): + def apply_method(self, state, args, kwargs): if len(args) != 1: raise InterpreterException('Apply takes exactly one argument') config_data = args[0] @@ -163,13 +163,13 @@ class SourceSetHolder(MutableInterpreterObject, ObjectHolder): return config_cache[key] files = self.collect(_get_from_config_data, False) - res = SourceFilesHolder(files) + res = SourceFilesObject(files) return res -class SourceFilesHolder(InterpreterObject, ObjectHolder): +class SourceFilesObject(ModuleObject): def __init__(self, files): - InterpreterObject.__init__(self) - ObjectHolder.__init__(self, files) + super().__init__() + self.files = files self.methods.update({ 'sources': self.sources_method, 'dependencies': self.dependencies_method, @@ -177,13 +177,13 @@ class SourceFilesHolder(InterpreterObject, ObjectHolder): @noPosargs @noKwargs - def sources_method(self, args, kwargs): - return list(self.held_object.sources) + def sources_method(self, state, args, kwargs): + return list(self.files.sources) @noPosargs @noKwargs - def dependencies_method(self, args, kwargs): - return list(self.held_object.dependencies) + def dependencies_method(self, state, args, kwargs): + return list(self.files.dependencies) class SourceSetModule(ExtensionModule): @FeatureNew('SourceSet module', '0.51.0') @@ -193,7 +193,7 @@ class SourceSetModule(ExtensionModule): @noKwargs @noPosargs def source_set(self, state, args, kwargs): - return SourceSetHolder(self.interpreter) + return SourceSet(self.interpreter) def initialize(*args, **kwargs): return SourceSetModule(*args, **kwargs) diff --git a/mesonbuild/modules/unstable_cuda.py b/mesonbuild/modules/unstable_cuda.py index 64e948a..a262503 100644 --- a/mesonbuild/modules/unstable_cuda.py +++ b/mesonbuild/modules/unstable_cuda.py @@ -19,14 +19,14 @@ from ..mesonlib import version_compare from ..interpreter import CompilerHolder from ..compilers import CudaCompiler -from . import ModuleObject +from . import ExtensionModule from ..interpreterbase import ( flatten, permittedKwargs, noKwargs, InvalidArguments, FeatureNew ) -class CudaModule(ModuleObject): +class CudaModule(ExtensionModule): @FeatureNew('CUDA module', '0.50.0') def __init__(self, *args, **kwargs): diff --git a/mesonbuild/modules/unstable_external_project.py b/mesonbuild/modules/unstable_external_project.py index 4d6f712..18b1931 100644 --- a/mesonbuild/modules/unstable_external_project.py +++ b/mesonbuild/modules/unstable_external_project.py @@ -16,11 +16,11 @@ import os, subprocess, shlex from pathlib import Path import typing as T -from . import ExtensionModule, ModuleReturnValue, ModuleState +from . import ExtensionModule, ModuleReturnValue, ModuleState, ModuleObject from .. import mlog, build from ..mesonlib import (MesonException, Popen_safe, MachineChoice, get_variable_regex, do_replacement, extract_as_list) -from ..interpreterbase import InterpreterObject, InterpreterException, FeatureNew +from ..interpreterbase import InterpreterException, FeatureNew from ..interpreterbase import permittedKwargs, typed_pos_args from ..interpreter import Interpreter, DependencyHolder from ..compilers.compilers import CFLAGS_MAPPING, CEXE_MAPPING @@ -28,7 +28,7 @@ from ..dependencies.base import InternalDependency, PkgConfigDependency from ..environment import Environment from ..mesonlib import OptionKey -class ExternalProject(InterpreterObject): +class ExternalProject(ModuleObject): def __init__(self, interpreter: Interpreter, subdir: str, @@ -42,7 +42,7 @@ class ExternalProject(InterpreterObject): cross_configure_options: T.List[str], env: build.EnvironmentVariables, verbose: bool): - InterpreterObject.__init__(self) + super().__init__() self.methods.update({'dependency': self.dependency_method, }) @@ -221,7 +221,7 @@ class ExternalProject(InterpreterObject): @permittedKwargs({'subdir'}) @typed_pos_args('external_project.dependency', str) - def dependency_method(self, args: T.Tuple[str], kwargs): + def dependency_method(self, state, args: T.Tuple[str], kwargs): libname = args[0] subdir = kwargs.get('subdir', '') |