aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.com>2021-03-03 12:48:30 -0500
committerXavier Claessens <xclaesse@gmail.com>2021-05-28 15:17:10 -0400
commit3340284805b96a4b9b62405f626020276341944c (patch)
tree83ff4cbaed7db7d89360eedbfa63930c2e0c68a6 /mesonbuild
parent723c5227a471aff3a1a5a3bc481984c99bf592aa (diff)
downloadmeson-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.
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/interpreter/interpreter.py10
-rw-r--r--mesonbuild/interpreter/interpreterobjects.py7
-rw-r--r--mesonbuild/modules/__init__.py16
-rw-r--r--mesonbuild/modules/cmake.py56
-rw-r--r--mesonbuild/modules/sourceset.py46
-rw-r--r--mesonbuild/modules/unstable_cuda.py4
-rw-r--r--mesonbuild/modules/unstable_external_project.py10
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', '')