aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Reference-manual.md20
-rw-r--r--docs/markdown/SimpleStart.md8
-rw-r--r--docs/markdown/Users.md2
-rw-r--r--docs/markdown/images/osx_xcode.pngbin0 -> 186012 bytes
-rw-r--r--docs/markdown/snippets/required_and_disabled_import.md5
-rw-r--r--mesonbuild/backend/ninjabackend.py3
-rw-r--r--mesonbuild/compilers/detect.py2
-rw-r--r--mesonbuild/interpreter/interpreter.py55
-rw-r--r--mesonbuild/interpreter/interpreterobjects.py8
-rw-r--r--mesonbuild/interpreter/kwargs.py5
-rw-r--r--mesonbuild/interpreterbase/__init__.py4
-rw-r--r--mesonbuild/interpreterbase/_unholder.py4
-rw-r--r--mesonbuild/interpreterbase/decorators.py4
-rw-r--r--mesonbuild/interpreterbase/interpreterbase.py5
-rw-r--r--mesonbuild/linkers/linkers.py4
-rw-r--r--mesonbuild/mdist.py10
-rw-r--r--mesonbuild/modules/__init__.py56
-rw-r--r--mesonbuild/modules/unstable_cuda.py5
-rw-r--r--mesonbuild/modules/unstable_external_project.py4
-rwxr-xr-xmesonbuild/msubprojects.py8
-rw-r--r--mesonbuild/wrap/wrap.py4
-rwxr-xr-xrun_unittests.py38
-rw-r--r--test cases/common/242 set and get variable/meson.build6
-rw-r--r--test cases/common/67 modules/meson.build10
-rw-r--r--test cases/common/67 modules/meson_options.txt6
-rw-r--r--test cases/common/93 suites/meson.build2
-rw-r--r--test cases/failing/57 kwarg in module/meson.build5
-rw-r--r--test cases/failing/57 kwarg in module/test.json7
28 files changed, 220 insertions, 70 deletions
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index 16fcbbf..e96a6fc 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -973,19 +973,21 @@ a non-existing variable will cause a fatal error.
### import()
-``` meson
- module_object import(module_name)
+```
+ module_object import(string, required : bool | feature, disabler : bool)
```
-Imports the given extension module. Returns an opaque object that can
-be used to call the methods of the module. Here's an example for a
-hypothetical `testmod` module.
+Imports the given extension module. Returns an object that can be used to call
+the methods of the module. Here's an example for a hypothetical `testmod`
+module.
```meson
tmod = import('testmod')
tmod.do_something()
```
+*Since 0.59.0* the required and disabler keyword arguments
+
### include_directories()
``` meson
@@ -2911,3 +2913,11 @@ sample piece of code with [`compiler.run()`](#compiler-object) or
- `returncode()`: the return code of executing the compiled binary
- `stderr()`: the standard error produced when the command was run
- `stdout()`: the standard out produced when the command was run
+
+### `module` object
+
+Modules provide their own specific implementation methods, but all modules
+proivide the following methods:
+
+- `bool found()`: returns True if the module was successfully imported,
+ otherwise false. *Since 0.59.0*
diff --git a/docs/markdown/SimpleStart.md b/docs/markdown/SimpleStart.md
index 371f1be..bf0d7ae 100644
--- a/docs/markdown/SimpleStart.md
+++ b/docs/markdown/SimpleStart.md
@@ -100,22 +100,22 @@ Double click the downloaded installer to start. If you are running a
new macOS version, it might refuse to run the application with the
following error message:
-![A macOS signing warning](images/mac_meson2.png)
+![A macOS signing warning](images/meson_mac2.png)
This can be fixed by starting System Preferences, selecting the
Security and Privacy entry. At the bottom it shows the blocked app and
you can enable it by clicking on the "Open anyway" button.
-![Security settings](images/mac_meson3.png)
+![Security settings](images/meson_mac3.png)
Now the installer should start. If not, double click on the downloaded
installer file again.
-![Installer running](images/mac_meson4.png)
+![Installer running](images/meson_mac4.png)
Once the installation is finished you can verify that the system is working via the terminal app.
-![A successful install](images/mac_meson5.png)
+![A successful install](images/meson_mac5.png)
## Running Meson
diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md
index d6df32c..032ec1e 100644
--- a/docs/markdown/Users.md
+++ b/docs/markdown/Users.md
@@ -108,7 +108,7 @@ format files
- [OTS](https://github.com/khaledhosny/ots), the OpenType Sanitizer, parses and serializes OpenType files (OTF, TTF) and WOFF and WOFF2 font files, validating and sanitizing them as it goes. Used by Chromium and Firefox
- [Outlier](https://github.com/kerolasa/outlier), a small Hello World style Meson example project
- [p11-kit](https://github.com/p11-glue/p11-kit), PKCS#11 module aggregator
- - [Pacman](https://git.archlinux.org/pacman.git/tree/), a package manager for Arch Linux
+ - [Pacman](https://gitlab.archlinux.org/pacman/pacman.git), a package manager for Arch Linux
- [Pango](https://git.gnome.org/browse/pango/), an Internationalized text layout and rendering library
- [Parzip](https://github.com/jpakkane/parzip), a multithreaded reimplementation of Zip
- [Peek](https://github.com/phw/peek), simple animated GIF screen recorder with an easy to use interface
diff --git a/docs/markdown/images/osx_xcode.png b/docs/markdown/images/osx_xcode.png
new file mode 100644
index 0000000..89075f3
--- /dev/null
+++ b/docs/markdown/images/osx_xcode.png
Binary files differ
diff --git a/docs/markdown/snippets/required_and_disabled_import.md b/docs/markdown/snippets/required_and_disabled_import.md
new file mode 100644
index 0000000..39ca307
--- /dev/null
+++ b/docs/markdown/snippets/required_and_disabled_import.md
@@ -0,0 +1,5 @@
+## The `import()` function gains `required` and `disabler` arguments
+
+In addition, modules now have a `found()` method, like programs and
+dependencies. This allows them to be conditionally required, and used in most
+places that an object with a `found()` method can be.
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index d6b535b..44e5228 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -3103,7 +3103,8 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
def get_user_option_args(self):
cmds = []
for (k, v) in self.environment.coredata.options.items():
- cmds.append('-D' + str(k) + '=' + (v.value if isinstance(v.value, str) else str(v.value).lower()))
+ if k.is_project():
+ cmds.append('-D' + str(k) + '=' + (v.value if isinstance(v.value, str) else str(v.value).lower()))
# The order of these arguments must be the same between runs of Meson
# to ensure reproducible output. The order we pass them shouldn't
# affect behavior in any other way.
diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py
index 59eac85..a86366a 100644
--- a/mesonbuild/compilers/detect.py
+++ b/mesonbuild/compilers/detect.py
@@ -616,7 +616,7 @@ def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: Machin
if 'TMS320C2000 C/C++' in out:
cls = C2000CCompiler if lang == 'c' else C2000CPPCompiler
env.coredata.add_lang_args(cls.language, cls, for_machine, env)
- linker = C2000DynamicLinker(for_machine, version=version)
+ linker = C2000DynamicLinker(compiler, for_machine, version=version)
return cls(
ccache + compiler, version, for_machine, is_cross, info,
exe_wrap, full_version=full_version, linker=linker)
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index 693924f..860fd98 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -26,13 +26,13 @@ from ..programs import ExternalProgram, NonExistingExternalProgram
from ..dependencies import Dependency
from ..depfile import DepFile
from ..interpreterbase import ContainerTypeInfo, InterpreterBase, KwargInfo, typed_kwargs, typed_pos_args
-from ..interpreterbase import noPosargs, noKwargs, stringArgs, permittedKwargs, noArgsFlattening, noSecondLevelHolderResolving, unholder_return
+from ..interpreterbase import noPosargs, noKwargs, stringArgs, permittedKwargs, noArgsFlattening, noSecondLevelHolderResolving, permissive_unholder_return
from ..interpreterbase import InterpreterException, InvalidArguments, InvalidCode, SubdirDoneRequest
from ..interpreterbase import Disabler, disablerIfNotFound
from ..interpreterbase import FeatureNew, FeatureDeprecated, FeatureNewKwargs, FeatureDeprecatedKwargs
from ..interpreterbase import ObjectHolder, RangeHolder
from ..interpreterbase import TYPE_nkwargs, TYPE_nvar, TYPE_var
-from ..modules import ModuleObject, MutableModuleObject
+from ..modules import ExtensionModule, ModuleObject, MutableModuleObject, NewExtensionModule, NotFoundExtensionModule
from ..cmake import CMakeInterpreter
from ..backend.backends import Backend, ExecutableSerialisation
@@ -161,6 +161,13 @@ _INSTALL_MODE_KW = KwargInfo(
convertor=_install_mode_convertor,
)
+_REQUIRED_KW = KwargInfo(
+ 'required',
+ (bool, coredata.UserFeatureOption),
+ default=True,
+ # TODO: extract_required_kwarg could be converted to a convertor
+)
+
def stringifyUserArguments(args, quote=False):
if isinstance(args, list):
@@ -304,7 +311,7 @@ class Interpreter(InterpreterBase, HoldableObject):
subproject: str = '',
subdir: str = '',
subproject_dir: str = 'subprojects',
- modules: T.Optional[T.Dict[str, ModuleObject]] = None,
+ modules: T.Optional[T.Dict[str, T.Union[ExtensionModule, NewExtensionModule, NotFoundExtensionModule]]] = None,
default_project_options: T.Optional[T.Dict[str, str]] = None,
mock: bool = False,
ast: T.Optional[mparser.CodeBlockNode] = None,
@@ -601,35 +608,47 @@ class Interpreter(InterpreterBase, HoldableObject):
dep = df.lookup(kwargs, force_fallback=True)
self.build.stdlibs[for_machine][l] = dep
- def import_module(self, modname):
+ def _import_module(self, modname: str, required: bool) -> T.Union[ExtensionModule, NewExtensionModule, NotFoundExtensionModule]:
if modname in self.modules:
- return
+ return self.modules[modname]
try:
module = importlib.import_module('mesonbuild.modules.' + modname)
except ImportError:
- raise InvalidArguments(f'Module "{modname}" does not exist')
- ext_module = module.initialize(self)
- assert isinstance(ext_module, ModuleObject)
+ if required:
+ raise InvalidArguments(f'Module "{modname}" does not exist')
+ ext_module = NotFoundExtensionModule()
+ else:
+ ext_module = module.initialize(self)
+ assert isinstance(ext_module, (ExtensionModule, NewExtensionModule))
self.modules[modname] = ext_module
+ return ext_module
- @stringArgs
- @noKwargs
- def func_import(self, node, args, kwargs):
- if len(args) != 1:
- raise InvalidCode('Import takes one argument.')
+ @typed_pos_args('import', str)
+ @typed_kwargs(
+ 'import',
+ _REQUIRED_KW.evolve(since='0.59.0'),
+ KwargInfo('disabler', bool, default=False, since='0.59.0'),
+ )
+ @disablerIfNotFound
+ def func_import(self, node: mparser.BaseNode, args: T.Tuple[str],
+ kwargs: 'kwargs.FuncImportModule') -> T.Union[ExtensionModule, NewExtensionModule, NotFoundExtensionModule]:
modname = args[0]
+ disabled, required, _ = extract_required_kwarg(kwargs, self.subproject)
+ if disabled:
+ return NotFoundExtensionModule()
+
if modname.startswith('unstable-'):
plainname = modname.split('-', 1)[1]
try:
# check if stable module exists
- self.import_module(plainname)
+ mod = self._import_module(plainname, required)
+ # XXX: this is acutally not helpful, since it doesn't do a version check
mlog.warning(f'Module {modname} is now stable, please use the {plainname} module instead.')
- modname = plainname
+ return mod
except InvalidArguments:
mlog.warning('Module %s has no backwards or forwards compatibility and might not exist in future releases.' % modname, location=node)
modname = 'unstable_' + plainname
- self.import_module(modname)
- return self.modules[modname]
+ return self._import_module(modname, required)
@stringArgs
@noKwargs
@@ -2722,7 +2741,7 @@ This will become a hard error in the future.''', location=self.current_node)
@noKwargs
@noArgsFlattening
- @unholder_return
+ @permissive_unholder_return
def func_get_variable(self, node, args, kwargs):
if len(args) < 1 or len(args) > 2:
raise InvalidCode('Get_variable takes one or two arguments.')
diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py
index 03725b9..ef1aae3 100644
--- a/mesonbuild/interpreter/interpreterobjects.py
+++ b/mesonbuild/interpreter/interpreterobjects.py
@@ -17,8 +17,8 @@ from ..interpreterbase import (
ContainerTypeInfo, KwargInfo,
InterpreterObject, MesonInterpreterObject, ObjectHolder, MutableInterpreterObject,
FeatureCheckBase, FeatureNewKwargs, FeatureNew, FeatureDeprecated,
- typed_pos_args, typed_kwargs, KwargInfo, stringArgs, permittedKwargs,
- noArgsFlattening, noPosargs, noKwargs, unholder_return, TYPE_var, TYPE_kwargs, TYPE_nvar, TYPE_nkwargs,
+ typed_pos_args, typed_kwargs, stringArgs, permittedKwargs,
+ noArgsFlattening, noPosargs, noKwargs, permissive_unholder_return, TYPE_var, TYPE_kwargs, TYPE_nvar, TYPE_nkwargs,
flatten, resolve_second_level_holders, InterpreterException, InvalidArguments, InvalidCode)
from ..dependencies import Dependency, ExternalLibrary, InternalDependency
from ..programs import ExternalProgram
@@ -675,7 +675,7 @@ class Test(MesonInterpreterObject):
priority: int):
super().__init__()
self.name = name
- self.suite = suite
+ self.suite = listify(suite)
self.project_name = project
self.exe = exe
self.depends = depends
@@ -727,7 +727,7 @@ class SubprojectHolder(MesonInterpreterObject):
@noKwargs
@noArgsFlattening
- @unholder_return
+ @permissive_unholder_return
def get_variable_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.Union[TYPE_var, InterpreterObject]:
if len(args) < 1 or len(args) > 2:
raise InterpreterException('Get_variable takes one or two arguments.')
diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py
index 3c3ecf6..b92b66f 100644
--- a/mesonbuild/interpreter/kwargs.py
+++ b/mesonbuild/interpreter/kwargs.py
@@ -132,3 +132,8 @@ class FuncInstallMan(TypedDict):
install_dir: T.Optional[str]
install_mode: FileMode
locale: T.Optional[str]
+
+
+class FuncImportModule(ExtractRequired):
+
+ disabler: bool
diff --git a/mesonbuild/interpreterbase/__init__.py b/mesonbuild/interpreterbase/__init__.py
index 298a034..8e45cdb 100644
--- a/mesonbuild/interpreterbase/__init__.py
+++ b/mesonbuild/interpreterbase/__init__.py
@@ -41,7 +41,7 @@ __all__ = [
'stringArgs',
'noArgsFlattening',
'noSecondLevelHolderResolving',
- 'unholder_return',
+ 'permissive_unholder_return',
'disablerIfNotFound',
'permittedKwargs',
'typed_pos_args',
@@ -94,7 +94,7 @@ from .decorators import (
stringArgs,
noArgsFlattening,
noSecondLevelHolderResolving,
- unholder_return,
+ permissive_unholder_return,
disablerIfNotFound,
permittedKwargs,
typed_pos_args,
diff --git a/mesonbuild/interpreterbase/_unholder.py b/mesonbuild/interpreterbase/_unholder.py
index b5663a5..7e95232 100644
--- a/mesonbuild/interpreterbase/_unholder.py
+++ b/mesonbuild/interpreterbase/_unholder.py
@@ -18,7 +18,7 @@ from ..mesonlib import HoldableObject, MesonBugException
import typing as T
-def _unholder(obj: T.Union[TYPE_var, InterpreterObject]) -> TYPE_var:
+def _unholder(obj: T.Union[TYPE_var, InterpreterObject], *, permissive: bool = False) -> TYPE_var:
if isinstance(obj, (int, bool, str)):
return obj
elif isinstance(obj, list):
@@ -30,6 +30,8 @@ def _unholder(obj: T.Union[TYPE_var, InterpreterObject]) -> TYPE_var:
return obj.held_object
elif isinstance(obj, MesonInterpreterObject):
return obj
+ elif isinstance(obj, HoldableObject) and permissive:
+ return obj
elif isinstance(obj, HoldableObject):
raise MesonBugException(f'Argument {obj} of type {type(obj).__name__} is not held by an ObjectHolder.')
elif isinstance(obj, InterpreterObject):
diff --git a/mesonbuild/interpreterbase/decorators.py b/mesonbuild/interpreterbase/decorators.py
index b91e9d5..eabc6d8 100644
--- a/mesonbuild/interpreterbase/decorators.py
+++ b/mesonbuild/interpreterbase/decorators.py
@@ -72,11 +72,11 @@ def noSecondLevelHolderResolving(f: TV_func) -> TV_func:
setattr(f, 'no-second-level-holder-flattening', True) # noqa: B010
return f
-def unholder_return(f: TV_func) -> T.Callable[..., TYPE_var]:
+def permissive_unholder_return(f: TV_func) -> T.Callable[..., TYPE_var]:
@wraps(f)
def wrapped(*wrapped_args: T.Any, **wrapped_kwargs: T.Any) -> T.Any:
res = f(*wrapped_args, **wrapped_kwargs)
- return _unholder(res)
+ return _unholder(res, permissive=True)
return T.cast(T.Callable[..., TYPE_var], wrapped)
def disablerIfNotFound(f: TV_func) -> TV_func:
diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py
index d66fb9c..91cb7aa 100644
--- a/mesonbuild/interpreterbase/interpreterbase.py
+++ b/mesonbuild/interpreterbase/interpreterbase.py
@@ -268,7 +268,7 @@ class InterpreterBase:
return True
def evaluate_in(self, val1: T.Any, val2: T.Any) -> bool:
- if not isinstance(val1, (str, int, float, ObjectHolder)):
+ if not isinstance(val1, (str, int, float, mesonlib.HoldableObject)):
raise InvalidArguments('lvalue of "in" operator must be a string, integer, float, or object')
if not isinstance(val2, (list, dict)):
raise InvalidArguments('rvalue of "in" operator must be an array or a dict')
@@ -281,6 +281,9 @@ class InterpreterBase:
val2 = self.evaluate_statement(node.right)
if isinstance(val2, Disabler):
return val2
+ # Do not compare the ObjectHolders but the actual held objects
+ val1 = _unholder(val1)
+ val2 = _unholder(val2)
if node.ctype == 'in':
return self.evaluate_in(val1, val2)
elif node.ctype == 'notin':
diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py
index 6ebdbcb..4457330 100644
--- a/mesonbuild/linkers/linkers.py
+++ b/mesonbuild/linkers/linkers.py
@@ -982,9 +982,9 @@ class C2000DynamicLinker(DynamicLinker):
id = 'cl2000'
- def __init__(self, for_machine: mesonlib.MachineChoice,
+ def __init__(self, exelist: T.List[str], for_machine: mesonlib.MachineChoice,
*, version: str = 'unknown version'):
- super().__init__(['cl2000.exe'], for_machine, '', [],
+ super().__init__(exelist or ['cl2000.exe'], for_machine, '', [],
version=version)
def get_link_whole_for(self, args: T.List[str]) -> T.List[str]:
diff --git a/mesonbuild/mdist.py b/mesonbuild/mdist.py
index 22196d8..e63ab17 100644
--- a/mesonbuild/mdist.py
+++ b/mesonbuild/mdist.py
@@ -56,11 +56,13 @@ def create_hash(fname):
def del_gitfiles(dirname):
+ gitfiles = ('.git', '.gitattributes', '.gitignore', '.gitmodules')
for f in glob(os.path.join(dirname, '.git*')):
- if os.path.isdir(f) and not os.path.islink(f):
- windows_proof_rmtree(f)
- else:
- os.unlink(f)
+ if os.path.split(f)[1] in gitfiles:
+ if os.path.isdir(f) and not os.path.islink(f):
+ windows_proof_rmtree(f)
+ else:
+ os.unlink(f)
def process_submodules(dirname):
module_file = os.path.join(dirname, '.gitmodules')
diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py
index 2b53de5..19de1bd 100644
--- a/mesonbuild/modules/__init__.py
+++ b/mesonbuild/modules/__init__.py
@@ -16,10 +16,11 @@
# are UI-related.
import os
+import typing as T
from .. import build
from ..mesonlib import relpath, HoldableObject
-import typing as T
+from ..interpreterbase.decorators import noKwargs, noPosargs
if T.TYPE_CHECKING:
from ..interpreter import Interpreter
@@ -91,18 +92,21 @@ class ModuleState:
wanted: T.Optional[str] = None) -> 'ExternalProgram':
return self._interpreter.find_program_impl(prog, required=required, version_func=version_func, wanted=wanted)
+
class ModuleObject(HoldableObject):
"""Base class for all objects returned by modules
"""
def __init__(self) -> None:
self.methods: T.Dict[
str,
- T.Callable[[ModuleState, T.List[TYPE_var], TYPE_kwargs], T.Union[ModuleReturnValue, TYPE_var]]
+ T.Callable[[ModuleState, T.List['TYPE_var'], 'TYPE_kwargs'], T.Union[ModuleReturnValue, 'TYPE_var']]
] = {}
+
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.
@@ -110,6 +114,54 @@ class ExtensionModule(ModuleObject):
def __init__(self, interpreter: 'Interpreter') -> None:
super().__init__()
self.interpreter = interpreter
+ self.methods.update({
+ 'found': self.found_method,
+ })
+
+ @noPosargs
+ @noKwargs
+ def found_method(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
+ return self.found()
+
+ @staticmethod
+ def found() -> bool:
+ return True
+
+
+class NewExtensionModule(ModuleObject):
+
+ """Class for modern modules
+
+ provides the found method.
+ """
+
+ def __init__(self) -> None:
+ super().__init__()
+ self.methods.update({
+ 'found': self.found_method,
+ })
+
+ @noPosargs
+ @noKwargs
+ def found_method(self, state: 'ModuleState', args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> bool:
+ return self.found()
+
+ @staticmethod
+ def found() -> bool:
+ return True
+
+
+class NotFoundExtensionModule(NewExtensionModule):
+
+ """Class for modern modules
+
+ provides the found method.
+ """
+
+ @staticmethod
+ def found() -> bool:
+ return False
+
def is_module_library(fname):
'''
diff --git a/mesonbuild/modules/unstable_cuda.py b/mesonbuild/modules/unstable_cuda.py
index a80f9ca..9e8aa63 100644
--- a/mesonbuild/modules/unstable_cuda.py
+++ b/mesonbuild/modules/unstable_cuda.py
@@ -18,14 +18,14 @@ import re
from ..mesonlib import version_compare
from ..compilers import CudaCompiler, Compiler
-from . import ModuleObject
+from . import NewExtensionModule
from ..interpreterbase import (
flatten, permittedKwargs, noKwargs,
InvalidArguments, FeatureNew
)
-class CudaModule(ModuleObject):
+class CudaModule(NewExtensionModule):
@FeatureNew('CUDA module', '0.50.0')
def __init__(self, *args, **kwargs):
@@ -50,6 +50,7 @@ class CudaModule(ModuleObject):
cuda_version = args[0]
driver_version_table = [
+ {'cuda_version': '>=11.4.0', 'windows': '471.11', 'linux': '470.42.01'},
{'cuda_version': '>=11.3.0', 'windows': '465.89', 'linux': '465.19.01'},
{'cuda_version': '>=11.2.2', 'windows': '461.33', 'linux': '460.32.03'},
{'cuda_version': '>=11.2.1', 'windows': '461.09', 'linux': '460.32.03'},
diff --git a/mesonbuild/modules/unstable_external_project.py b/mesonbuild/modules/unstable_external_project.py
index 4f8ac56..f866e75 100644
--- a/mesonbuild/modules/unstable_external_project.py
+++ b/mesonbuild/modules/unstable_external_project.py
@@ -16,7 +16,7 @@ import os, subprocess, shlex
from pathlib import Path
import typing as T
-from . import ExtensionModule, ModuleReturnValue, ModuleState, ModuleObject
+from . import ExtensionModule, ModuleReturnValue, ModuleState, NewExtensionModule
from .. import mlog, build
from ..mesonlib import (MesonException, Popen_safe, MachineChoice,
get_variable_regex, do_replacement, extract_as_list)
@@ -26,7 +26,7 @@ from ..compilers.compilers import CFLAGS_MAPPING, CEXE_MAPPING
from ..dependencies import InternalDependency, PkgConfigDependency
from ..mesonlib import OptionKey
-class ExternalProject(ModuleObject):
+class ExternalProject(NewExtensionModule):
def __init__(self,
state: ModuleState,
configure_command: str,
diff --git a/mesonbuild/msubprojects.py b/mesonbuild/msubprojects.py
index 63ea98a..5d1fb72 100755
--- a/mesonbuild/msubprojects.py
+++ b/mesonbuild/msubprojects.py
@@ -386,6 +386,12 @@ class Runner:
if not self.wrap.type:
return True
+ if self.wrap.redirected:
+ redirect_file = Path(self.wrap.original_filename).resolve()
+ if self.options.confirm:
+ redirect_file.unlink()
+ mlog.log(f'Deleting {redirect_file}')
+
if self.wrap.type == 'redirect':
redirect_file = Path(self.wrap.filename).resolve()
if self.options.confirm:
@@ -416,7 +422,7 @@ class Runner:
# parallelized, another thread could have deleted it already.
try:
if not any(packagecache.iterdir()):
- packagecache.rmdir()
+ windows_proof_rmtree(str(packagecache))
except FileNotFoundError:
pass
diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py
index 4a6583f..6c145ab 100644
--- a/mesonbuild/wrap/wrap.py
+++ b/mesonbuild/wrap/wrap.py
@@ -101,6 +101,8 @@ class PackageDefinition:
self.name = self.basename[:-5] if self.has_wrap else self.basename
self.directory = self.name
self.provided_deps[self.name] = None
+ self.original_filename = fname
+ self.redirected = False
if self.has_wrap:
self.parse_wrap()
self.directory = self.values.get('directory', self.name)
@@ -109,6 +111,7 @@ class PackageDefinition:
if self.type and self.type not in ALL_TYPES:
raise WrapException(f'Unknown wrap type {self.type!r}')
self.filesdir = os.path.join(os.path.dirname(self.filename), 'packagefiles')
+ # What the original file name was before redirection
def parse_wrap(self) -> None:
try:
@@ -137,6 +140,7 @@ class PackageDefinition:
raise WrapException(f'wrap-redirect {fname} filename does not exist')
self.filename = str(fname)
self.parse_wrap()
+ self.redirected = True
return
self.parse_provide_section(config)
diff --git a/run_unittests.py b/run_unittests.py
index 99c56e2..e8f453d 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -10181,7 +10181,20 @@ class SubprojectsCommandTests(BasePlatformTests):
self._git_create_local_repo('sub_git')
self._wrap_create_git('sub_git')
- def deleting(s) -> T.List[str]:
+ sub_file_subprojects_dir = self.subprojects_dir / 'sub_file' / 'subprojects'
+ sub_file_subprojects_dir.mkdir(exist_ok=True, parents=True)
+ real_dir = Path('sub_file') / 'subprojects' / 'real'
+
+ self._wrap_create_file(real_dir, tarball='dummy2.tar.gz')
+
+ with open(str((self.subprojects_dir / 'redirect').with_suffix('.wrap')), 'w', encoding='utf-8') as f:
+ f.write(textwrap.dedent(
+ f'''
+ [wrap-redirect]
+ filename = {real_dir}.wrap
+ '''))
+
+ def deleting(s: str) -> T.List[str]:
ret = []
prefix = 'Deleting '
for l in s.splitlines():
@@ -10190,14 +10203,31 @@ class SubprojectsCommandTests(BasePlatformTests):
return sorted(ret)
out = self._subprojects_cmd(['purge'])
- self.assertEqual(deleting(out), [str(self.subprojects_dir / 'sub_file'), str(self.subprojects_dir / 'sub_git')])
+ self.assertEqual(deleting(out), sorted([
+ str(self.subprojects_dir / 'redirect.wrap'),
+ str(self.subprojects_dir / 'sub_file'),
+ str(self.subprojects_dir / 'sub_git'),
+ ]))
out = self._subprojects_cmd(['purge', '--include-cache'])
- self.assertEqual(deleting(out), [str(self.subprojects_dir / 'packagecache' / 'dummy.tar.gz'), str(self.subprojects_dir / 'sub_file'), str(self.subprojects_dir / 'sub_git')])
+ self.assertEqual(deleting(out), sorted([
+ str(self.subprojects_dir / 'sub_git'),
+ str(self.subprojects_dir / 'redirect.wrap'),
+ str(self.subprojects_dir / 'packagecache' / 'dummy.tar.gz'),
+ str(self.subprojects_dir / 'packagecache' / 'dummy2.tar.gz'),
+ str(self.subprojects_dir / 'sub_file'),
+ ]))
out = self._subprojects_cmd(['purge', '--include-cache', '--confirm'])
- self.assertEqual(deleting(out), [str(self.subprojects_dir / 'packagecache' / 'dummy.tar.gz'), str(self.subprojects_dir / 'sub_file'), str(self.subprojects_dir / 'sub_git')])
+ self.assertEqual(deleting(out), sorted([
+ str(self.subprojects_dir / 'sub_git'),
+ str(self.subprojects_dir / 'redirect.wrap'),
+ str(self.subprojects_dir / 'packagecache' / 'dummy.tar.gz'),
+ str(self.subprojects_dir / 'packagecache' / 'dummy2.tar.gz'),
+ str(self.subprojects_dir / 'sub_file'),
+ ]))
self.assertFalse(Path(self.subprojects_dir / 'packagecache' / 'dummy.tar.gz').exists())
self.assertFalse(Path(self.subprojects_dir / 'sub_file').exists())
self.assertFalse(Path(self.subprojects_dir / 'sub_git').exists())
+ self.assertFalse(Path(self.subprojects_dir / 'redirect.wrap').exists())
def _clang_at_least(compiler: 'Compiler', minver: str, apple_minver: T.Optional[str]) -> bool:
"""
diff --git a/test cases/common/242 set and get variable/meson.build b/test cases/common/242 set and get variable/meson.build
index 6023e88..7c8dcf7 100644
--- a/test cases/common/242 set and get variable/meson.build
+++ b/test cases/common/242 set and get variable/meson.build
@@ -14,6 +14,10 @@ set_variable('var4', files('test2.txt')[0])
assert(var3 == 'test2.txt')
assert(not is_disabler(var4))
+# Test Equality
+assert(var1 == get_variable('var1'))
+assert(var2 == get_variable('var2'))
+
# Test get_variable directly
assert(get_variable('var1') == 'test1.txt')
assert(not is_disabler(get_variable('var2')))
@@ -35,6 +39,8 @@ assert(var7 == 'test2.txt')
assert(not is_disabler(var8))
assert(get_variable('var9') == 'test2.txt')
assert(not is_disabler(get_variable('var0')))
+assert(not is_disabler(get_variable('var0', var8)))
+assert(not is_disabler(get_variable('----', var8)))
# test dict get
dict = {'a': var2}
diff --git a/test cases/common/67 modules/meson.build b/test cases/common/67 modules/meson.build
index e9750cd..ad33ed6 100644
--- a/test cases/common/67 modules/meson.build
+++ b/test cases/common/67 modules/meson.build
@@ -2,3 +2,13 @@ project('module test', 'c')
modtest = import('modtest')
modtest.print_hello()
+assert(modtest.found())
+
+modtest = import('modtest', required : get_option('disabled'))
+assert(not modtest.found())
+
+notfound = import('not-found', required : false)
+assert(not notfound.found())
+
+disabled = import('not-found', required : false, disabler : true)
+assert(is_disabler(disabled))
diff --git a/test cases/common/67 modules/meson_options.txt b/test cases/common/67 modules/meson_options.txt
new file mode 100644
index 0000000..0671144
--- /dev/null
+++ b/test cases/common/67 modules/meson_options.txt
@@ -0,0 +1,6 @@
+option(
+ 'disabled',
+ type : 'feature',
+ value : 'disabled',
+ description : 'test disabled'
+)
diff --git a/test cases/common/93 suites/meson.build b/test cases/common/93 suites/meson.build
index 057e059..2346b5b 100644
--- a/test cases/common/93 suites/meson.build
+++ b/test cases/common/93 suites/meson.build
@@ -6,4 +6,4 @@ exe1 = executable('exe1', 'exe1.c')
exe2 = executable('exe2', 'exe2.c')
test('exe1', exe1)
-test('exe2', exe2, suite : ['suite2', 'super-special'])
+test('exe2', exe2, suite : ['suite2', ['super-special']])
diff --git a/test cases/failing/57 kwarg in module/meson.build b/test cases/failing/57 kwarg in module/meson.build
deleted file mode 100644
index b105db1..0000000
--- a/test cases/failing/57 kwarg in module/meson.build
+++ /dev/null
@@ -1,5 +0,0 @@
-project('module test', 'c')
-
-modtest = import('modtest', i_cause: 'a_build_failure')
-modtest.print_hello()
-
diff --git a/test cases/failing/57 kwarg in module/test.json b/test cases/failing/57 kwarg in module/test.json
deleted file mode 100644
index cafb3ab..0000000
--- a/test cases/failing/57 kwarg in module/test.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "stdout": [
- {
- "line": "test cases/failing/57 kwarg in module/meson.build:3:0: ERROR: Function does not take keyword arguments."
- }
- ]
-}