aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Cython.md2
-rw-r--r--docs/markdown/SimpleStart.md48
-rwxr-xr-xdocs/markdown/images/meson_mac1.pngbin0 -> 62177 bytes
-rwxr-xr-xdocs/markdown/images/meson_mac2.pngbin0 -> 90454 bytes
-rwxr-xr-xdocs/markdown/images/meson_mac3.pngbin0 -> 122178 bytes
-rwxr-xr-xdocs/markdown/images/meson_mac4.pngbin0 -> 77246 bytes
-rwxr-xr-xdocs/markdown/images/meson_mac5.pngbin0 -> 198834 bytes
-rw-r--r--docs/markdown/images/osx_download.pngbin177582 -> 0 bytes
-rw-r--r--docs/markdown/images/osx_working.pngbin152087 -> 0 bytes
-rw-r--r--docs/markdown/images/osx_xcode.pngbin242557 -> 0 bytes
-rw-r--r--mesonbuild/backend/backends.py2
-rw-r--r--mesonbuild/backend/ninjabackend.py2
-rw-r--r--mesonbuild/environment.py6
-rw-r--r--mesonbuild/interpreter/__init__.py2
-rw-r--r--mesonbuild/interpreter/interpreter.py130
-rw-r--r--mesonbuild/interpreter/kwargs.py37
-rw-r--r--mesonbuild/interpreterbase/decorators.py30
-rw-r--r--mesonbuild/modules/unstable_rust.py51
-rwxr-xr-xrun_unittests.py40
-rw-r--r--test cases/cython/2 generated sources/libdir/gen.py14
-rw-r--r--test cases/cython/2 generated sources/libdir/meson.build10
-rw-r--r--test cases/cython/2 generated sources/meson.build9
-rw-r--r--test cases/failing/23 rel testdir/test.json2
23 files changed, 257 insertions, 128 deletions
diff --git a/docs/markdown/Cython.md b/docs/markdown/Cython.md
index be05271..1d30c1f 100644
--- a/docs/markdown/Cython.md
+++ b/docs/markdown/Cython.md
@@ -1,7 +1,7 @@
---
title: Cython
short-description: Support for Cython in Meson
----
+...
# Cython
diff --git a/docs/markdown/SimpleStart.md b/docs/markdown/SimpleStart.md
index 2c18dc4..371f1be 100644
--- a/docs/markdown/SimpleStart.md
+++ b/docs/markdown/SimpleStart.md
@@ -91,47 +91,31 @@ versions.
### macOS
-Due to the way Apple has set things up, getting macOS working is a bit
-more complicated. The first thing you need to do is to install the
-newest version of Python 3 [from the project's web
-site](https://www.python.org/downloads/mac-osx/).
-
-![Downloading the Python for macOS installer](images/osx_download.png)
-
-Once you have a working Python you can install the necessary bits
-using Python's Pip package manager.
-
- pip install --user meson ninja
+Start by downloading the installation package from [the Releases
+page](https://github.com/mesonbuild/meson/releases).
-This will install the necessary files in your home directory, but
-sadly they are not directly usable. You need to add the directory they
-are written to in the system's `PATH` environment variable so the
-programs can be used directly from the terminal. This requires editing
-a text configuration file.
+![Downloading the macOS installer](images/meson_mac1.png)
-The correct file to edit depends on which shell you are currently
-using. If you have an old macOS install it is probably Bash and the
-file you need to edit is `.bash_profile`. If, on the other hand, you
-have a new macOS install then you are probably using Zsh and the file
-to edit is `.zshrc`. In either case the file should be in your home
-directory.
+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:
-For Bash the line you need to add is this:
+![A macOS signing warning](images/mac_meson2.png)
- PATH=$PATH:/Users/username/Library/Python/3.9/bin
+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.
-whereas for Zsh it is this:
+![Security settings](images/mac_meson3.png)
- export PATH=$PATH:/Users/username/Library/Python/3.9/bin
+Now the installer should start. If not, double click on the downloaded
+installer file again.
-In both case you need to change the values for `username` and `3.9`.
-The former needs to be substituted with your Unix username while the
-latter needs to contain the actual Python version you installed.
+![Installer running](images/mac_meson4.png)
-Once this is done close the terminal application and start it again.
-Now you should be able to run the `meson` command.
+Once the installation is finished you can verify that the system is working via the terminal app.
-![A working macOS install](images/osx_working.png)
+![A successful install](images/mac_meson5.png)
## Running Meson
diff --git a/docs/markdown/images/meson_mac1.png b/docs/markdown/images/meson_mac1.png
new file mode 100755
index 0000000..17eae0a
--- /dev/null
+++ b/docs/markdown/images/meson_mac1.png
Binary files differ
diff --git a/docs/markdown/images/meson_mac2.png b/docs/markdown/images/meson_mac2.png
new file mode 100755
index 0000000..e5c434d
--- /dev/null
+++ b/docs/markdown/images/meson_mac2.png
Binary files differ
diff --git a/docs/markdown/images/meson_mac3.png b/docs/markdown/images/meson_mac3.png
new file mode 100755
index 0000000..babada1
--- /dev/null
+++ b/docs/markdown/images/meson_mac3.png
Binary files differ
diff --git a/docs/markdown/images/meson_mac4.png b/docs/markdown/images/meson_mac4.png
new file mode 100755
index 0000000..e8089ad
--- /dev/null
+++ b/docs/markdown/images/meson_mac4.png
Binary files differ
diff --git a/docs/markdown/images/meson_mac5.png b/docs/markdown/images/meson_mac5.png
new file mode 100755
index 0000000..507fcda
--- /dev/null
+++ b/docs/markdown/images/meson_mac5.png
Binary files differ
diff --git a/docs/markdown/images/osx_download.png b/docs/markdown/images/osx_download.png
deleted file mode 100644
index 3315886..0000000
--- a/docs/markdown/images/osx_download.png
+++ /dev/null
Binary files differ
diff --git a/docs/markdown/images/osx_working.png b/docs/markdown/images/osx_working.png
deleted file mode 100644
index 0b1320f..0000000
--- a/docs/markdown/images/osx_working.png
+++ /dev/null
Binary files differ
diff --git a/docs/markdown/images/osx_xcode.png b/docs/markdown/images/osx_xcode.png
deleted file mode 100644
index 14a6282..0000000
--- a/docs/markdown/images/osx_xcode.png
+++ /dev/null
Binary files differ
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 4c61abf..64e0b18 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -159,7 +159,7 @@ class ExecutableSerialisation:
self.subproject = ''
class TestSerialisation:
- def __init__(self, name: str, project: str, suite: str, fname: T.List[str],
+ def __init__(self, name: str, project: str, suite: T.List[str], fname: T.List[str],
is_cross_built: bool, exe_wrapper: T.Optional[programs.ExternalProgram],
needs_exe_wrapper: bool, is_parallel: bool, cmd_args: T.List[str],
env: build.EnvironmentVariables, should_fail: bool,
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index db50f6a..688149b 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1583,6 +1583,8 @@ int dummy;
for ssrc in gen.get_outputs():
if isinstance(gen, GeneratedList):
ssrc = os.path.join(self.get_target_private_dir(target) , ssrc)
+ else:
+ ssrc = os.path.join(gen.get_subdir(), ssrc)
if ssrc.endswith('.pyx'):
args = args.copy()
output = os.path.join(self.get_target_private_dir(target), f'{ssrc}.c')
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 03cd16e..6248c58 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -246,7 +246,9 @@ def get_llvm_tool_names(tool: str) -> T.List[str]:
# unless it becomes a stable release.
suffixes = [
'', # base (no suffix)
- '-10', '100',
+ '-12', '12',
+ '-11', '11',
+ '-10', '10',
'-9', '90',
'-8', '80',
'-7', '70',
@@ -258,7 +260,7 @@ def get_llvm_tool_names(tool: str) -> T.List[str]:
'-3.7', '37',
'-3.6', '36',
'-3.5', '35',
- '-11', # Debian development snapshot
+ '-13', # Debian development snapshot
'-devel', # FreeBSD development snapshot
]
names = []
diff --git a/mesonbuild/interpreter/__init__.py b/mesonbuild/interpreter/__init__.py
index 3d49857..58ee729 100644
--- a/mesonbuild/interpreter/__init__.py
+++ b/mesonbuild/interpreter/__init__.py
@@ -16,7 +16,7 @@
"""Meson interpreter."""
-from .interpreter import Interpreter, permitted_test_kwargs, permitted_dependency_kwargs
+from .interpreter import Interpreter, permitted_dependency_kwargs
from .compiler import CompilerHolder
from .interpreterobjects import (ExecutableHolder, BuildTargetHolder, CustomTargetHolder,
CustomTargetIndexHolder, MachineHolder, Test,
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index 65ad321..1a7d2fc 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -188,17 +188,24 @@ known_build_target_kwargs = (
{'target_type'}
)
-permitted_test_kwargs = {
- 'args',
- 'depends',
- 'env',
- 'priority',
- 'protocol',
- 'should_fail',
- 'suite',
- 'timeout',
- 'workdir',
-}
+TEST_KWARGS: T.List[KwargInfo] = [
+ KwargInfo('args', ContainerTypeInfo(list, (str, mesonlib.File, TargetHolder)),
+ listify=True, default=[]),
+ KwargInfo('should_fail', bool, default=False),
+ KwargInfo('timeout', int, default=30),
+ KwargInfo('workdir', str, default=None,
+ validator=lambda x: 'must be an absolute path' if not os.path.isabs(x) else None),
+ KwargInfo('protocol', str,
+ default='exitcode',
+ validator=lambda x: 'value must be one of "exitcode", "tap", "gtest", "rust"' if x not in {'exitcode', 'tap', 'gtest', 'rust'} else None,
+ since_values={'gtest': '0.55.0', 'rust': '0.57.0'}),
+ KwargInfo('depends', ContainerTypeInfo(list, (CustomTargetHolder, BuildTargetHolder)),
+ listify=True, default=[], since='0.46.0'),
+ KwargInfo('priority', int, default=0, since='0.52.0'),
+ # TODO: env needs reworks of the way the environment variable holder itself works probably
+ KwargInfo('env', (EnvironmentVariablesHolder, list, dict, str)),
+ KwargInfo('suite', ContainerTypeInfo(list, str), listify=True, default=['']), # yes, a list of empty string
+]
permitted_dependency_kwargs = {
'allow_fallback',
@@ -1952,24 +1959,21 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
self.generators.append(gen)
return gen
- @FeatureNewKwargs('benchmark', '0.46.0', ['depends'])
- @FeatureNewKwargs('benchmark', '0.52.0', ['priority'])
- @permittedKwargs(permitted_test_kwargs)
- def func_benchmark(self, node, args, kwargs):
- # is_parallel isn't valid here, so make sure it isn't passed
- if 'is_parallel' in kwargs:
- del kwargs['is_parallel']
+ @typed_pos_args('benchmark', str, (ExecutableHolder, JarHolder, ExternalProgramHolder, mesonlib.File))
+ @typed_kwargs('benchmark', *TEST_KWARGS)
+ def func_benchmark(self, node: mparser.BaseNode,
+ args: T.Tuple[str, T.Union[ExecutableHolder, JarHolder, ExternalProgramHolder, mesonlib.File]],
+ kwargs: 'kwargs.FuncBenchmark') -> None:
self.add_test(node, args, kwargs, False)
- @FeatureNewKwargs('test', '0.46.0', ['depends'])
- @FeatureNewKwargs('test', '0.52.0', ['priority'])
- @permittedKwargs(permitted_test_kwargs | {'is_parallel'})
- def func_test(self, node, args, kwargs):
- if kwargs.get('protocol') == 'gtest':
- FeatureNew.single_use('"gtest" protocol for tests', '0.55.0', self.subproject)
+ @typed_pos_args('test', str, (ExecutableHolder, JarHolder, ExternalProgramHolder, mesonlib.File))
+ @typed_kwargs('benchmark', *TEST_KWARGS, KwargInfo('is_parallel', bool, default=True))
+ def func_test(self, node: mparser.BaseNode,
+ args: T.Tuple[str, T.Union[ExecutableHolder, JarHolder, ExternalProgramHolder, mesonlib.File]],
+ kwargs: 'kwargs.FuncTest') -> None:
self.add_test(node, args, kwargs, True)
- def unpack_env_kwarg(self, kwargs) -> build.EnvironmentVariables:
+ def unpack_env_kwarg(self, kwargs: T.Union[EnvironmentVariablesHolder, T.Dict[str, str], T.List[str]]) -> build.EnvironmentVariables:
envlist = kwargs.get('env', EnvironmentVariablesHolder())
if isinstance(envlist, EnvironmentVariablesHolder):
env = envlist.held_object
@@ -1983,64 +1987,44 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
env = env.held_object
return env
- def make_test(self, node: mparser.BaseNode, args: T.List, kwargs: T.Dict[str, T.Any]):
- if len(args) != 2:
- raise InterpreterException('test expects 2 arguments, {} given'.format(len(args)))
+ def make_test(self, node: mparser.BaseNode,
+ args: T.Tuple[str, T.Union[ExecutableHolder, JarHolder, ExternalProgramHolder, mesonlib.File]],
+ kwargs: 'kwargs.BaseTest') -> Test:
name = args[0]
- if not isinstance(name, str):
- raise InterpreterException('First argument of test must be a string.')
if ':' in name:
mlog.deprecation(f'":" is not allowed in test name "{name}", it has been replaced with "_"',
location=node)
name = name.replace(':', '_')
exe = args[1]
- if not isinstance(exe, (ExecutableHolder, JarHolder, ExternalProgramHolder)):
- if isinstance(exe, mesonlib.File):
- exe = self.func_find_program(node, args[1], {})
- else:
- raise InterpreterException('Second argument must be executable.')
- par = kwargs.get('is_parallel', True)
- if not isinstance(par, bool):
- raise InterpreterException('Keyword argument is_parallel must be a boolean.')
- cmd_args = unholder(extract_as_list(kwargs, 'args'))
- for i in cmd_args:
- if not isinstance(i, (str, mesonlib.File, build.Target)):
- raise InterpreterException('Command line arguments must be strings, files or targets.')
+ if isinstance(exe, mesonlib.File):
+ exe = self.func_find_program(node, args[1], {})
+
env = self.unpack_env_kwarg(kwargs)
- should_fail = kwargs.get('should_fail', False)
- if not isinstance(should_fail, bool):
- raise InterpreterException('Keyword argument should_fail must be a boolean.')
- timeout = kwargs.get('timeout', 30)
- if not isinstance(timeout, int):
- raise InterpreterException('Timeout must be an integer.')
- if timeout <= 0:
- FeatureNew('test() timeout <= 0', '0.57.0').use(self.subproject)
- if 'workdir' in kwargs:
- workdir = kwargs['workdir']
- if not isinstance(workdir, str):
- raise InterpreterException('Workdir keyword argument must be a string.')
- if not os.path.isabs(workdir):
- raise InterpreterException('Workdir keyword argument must be an absolute path.')
- else:
- workdir = None
- protocol = kwargs.get('protocol', 'exitcode')
- if protocol not in {'exitcode', 'tap', 'gtest', 'rust'}:
- raise InterpreterException('Protocol must be one of "exitcode", "tap", "gtest", or "rust".')
- suite = []
+
+ if kwargs['timeout'] <= 0:
+ FeatureNew.single_use('test() timeout <= 0', '0.57.0', self.subproject)
+
prj = self.subproject if self.is_subproject() else self.build.project_name
- for s in mesonlib.stringlistify(kwargs.get('suite', '')):
- if len(s) > 0:
+
+ suite: T.List[str] = []
+ for s in kwargs['suite']:
+ if s:
s = ':' + s
suite.append(prj.replace(' ', '_').replace(':', '_') + s)
- depends = unholder(extract_as_list(kwargs, 'depends'))
- for dep in depends:
- if not isinstance(dep, (build.CustomTarget, build.BuildTarget)):
- raise InterpreterException('Depends items must be build targets.')
- priority = kwargs.get('priority', 0)
- if not isinstance(priority, int):
- raise InterpreterException('Keyword argument priority must be an integer.')
- return Test(name, prj, suite, exe.held_object, depends, par, cmd_args,
- env, should_fail, timeout, workdir, protocol, priority)
+
+ return Test(name,
+ prj,
+ suite,
+ exe.held_object,
+ [d.held_object for d in kwargs['depends']],
+ kwargs.get('is_parallel', False),
+ [c.held_object if isinstance(c, ObjectHolder) else c for c in kwargs['args']],
+ env,
+ kwargs['should_fail'],
+ kwargs['timeout'],
+ kwargs['workdir'],
+ kwargs['protocol'],
+ kwargs['priority'])
def add_test(self, node: mparser.BaseNode, args: T.List, kwargs: T.Dict[str, T.Any], is_base_test: bool):
t = self.make_test(node, args, kwargs)
diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py
index d5d9990..db6b02b 100644
--- a/mesonbuild/interpreter/kwargs.py
+++ b/mesonbuild/interpreter/kwargs.py
@@ -6,9 +6,10 @@
import typing as T
-from typing_extensions import TypedDict
+from typing_extensions import TypedDict, Literal
-from ..mesonlib import MachineChoice
+from ..mesonlib import MachineChoice, File
+from .interpreterobjects import BuildTargetHolder, CustomTargetHolder, EnvironmentVariablesHolder, TargetHolder
class FuncAddProjectArgs(TypedDict):
@@ -24,3 +25,35 @@ class FuncAddProjectArgs(TypedDict):
native: MachineChoice
language: T.List[str]
+
+
+class BaseTest(TypedDict):
+
+ """Shared base for the Rust module."""
+
+ args: T.List[T.Union[str, File, TargetHolder]]
+ should_fail: bool
+ timeout: int
+ workdir: T.Optional[str]
+ depends: T.List[T.Union[CustomTargetHolder, BuildTargetHolder]]
+ priority: int
+ env: T.Union[EnvironmentVariablesHolder, T.List[str], T.Dict[str, str], str]
+ suite: T.List[str]
+
+
+class FuncBenchmark(BaseTest):
+
+ """Keyword Arguments shared between `test` and `benchmark`."""
+
+ protocol: Literal['exitcode', 'tap', 'gtest', 'rust']
+
+
+class FuncTest(FuncBenchmark):
+
+ """Keyword Arguments for `test`
+
+ `test` only adds the `is_prallel` argument over benchmark, so inherintance
+ is helpful here.
+ """
+
+ is_parallel: bool
diff --git a/mesonbuild/interpreterbase/decorators.py b/mesonbuild/interpreterbase/decorators.py
index f997111..b82a413 100644
--- a/mesonbuild/interpreterbase/decorators.py
+++ b/mesonbuild/interpreterbase/decorators.py
@@ -290,13 +290,19 @@ class KwargInfo(T.Generic[_T]):
different type. This is intended for cases such as the meson DSL using a
string, but the implementation using an Enum. This should not do
validation, just converstion.
+ :param deprecated_values: a dictionary mapping a value to the version of
+ meson it was deprecated in.
+ :param since: a dictionary mapping a value to the version of meson it was
+ added in.
"""
def __init__(self, name: str, types: T.Union[T.Type[_T], T.Tuple[T.Type[_T], ...], ContainerTypeInfo],
*, required: bool = False, listify: bool = False,
default: T.Optional[_T] = None,
since: T.Optional[str] = None,
+ since_values: T.Optional[T.Dict[str, str]] = None,
deprecated: T.Optional[str] = None,
+ deprecated_values: T.Optional[T.Dict[str, str]] = None,
validator: T.Optional[T.Callable[[_T], T.Optional[str]]] = None,
convertor: T.Optional[T.Callable[[_T], TYPE_nvar]] = None):
self.name = name
@@ -304,8 +310,10 @@ class KwargInfo(T.Generic[_T]):
self.required = required
self.listify = listify
self.default = default
+ self.since_values = since_values
self.since = since
self.deprecated = deprecated
+ self.deprecated_values = deprecated_values
self.validator = validator
self.convertor = convertor
@@ -368,6 +376,28 @@ def typed_kwargs(name: str, *types: KwargInfo) -> T.Callable[..., T.Any]:
msg = info.validator(value)
if msg is not None:
raise InvalidArguments(f'{name} keyword argument "{info.name}" {msg}')
+
+ warn: bool
+ if info.deprecated_values is not None:
+ for n, version in info.deprecated_values.items():
+ if isinstance(value, (dict, list)):
+ warn = n in value
+ else:
+ warn = n == value
+
+ if warn:
+ FeatureDeprecated.single_use(f'"{name}" keyword argument "{info.name}" value "{n}"', version, subproject)
+
+ if info.since_values is not None:
+ for n, version in info.since_values.items():
+ if isinstance(value, (dict, list)):
+ warn = n in value
+ else:
+ warn = n == value
+
+ if warn:
+ FeatureNew.single_use(f'"{name}" keyword argument "{info.name}" value "{n}"', version, subproject)
+
elif info.required:
raise InvalidArguments(f'{name} is missing required keyword argument "{info.name}"')
else:
diff --git a/mesonbuild/modules/unstable_rust.py b/mesonbuild/modules/unstable_rust.py
index 1418309..d5678ea 100644
--- a/mesonbuild/modules/unstable_rust.py
+++ b/mesonbuild/modules/unstable_rust.py
@@ -18,16 +18,28 @@ import typing as T
from . import ExtensionModule, ModuleReturnValue
from .. import mlog
from ..build import BuildTarget, CustomTargetIndex, Executable, GeneratedList, InvalidArguments, IncludeDirs, CustomTarget
-from ..dependencies import Dependency, ExternalLibrary
-from ..interpreter import ExecutableHolder, BuildTargetHolder, CustomTargetHolder, permitted_test_kwargs
-from ..interpreterbase import InterpreterException, permittedKwargs, FeatureNew, typed_pos_args, noPosargs
+from ..interpreter.interpreter import TEST_KWARGS
+from ..interpreter.interpreterobjects import (
+ BuildTargetHolder,
+ CustomTargetHolder,
+ DependencyHolder,
+ ExecutableHolder,
+ ExternalLibraryHolder,
+)
+from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, permittedKwargs, FeatureNew, typed_kwargs, typed_pos_args, noPosargs
from ..mesonlib import stringlistify, unholder, listify, typeslistify, File
if T.TYPE_CHECKING:
from . import ModuleState
from ..interpreter import Interpreter
- from ..programs import ExternalProgram
+ from ..interpreter import kwargs as _kwargs
from ..interpreter.interpreter import SourceOutputs
+ from ..programs import ExternalProgram
+
+ class FuncTest(_kwargs.BaseTest):
+
+ dependencies: T.List[T.Union[DependencyHolder, ExternalLibraryHolder]]
+ is_parallel: bool
class RustModule(ExtensionModule):
@@ -43,9 +55,18 @@ class RustModule(ExtensionModule):
'bindgen': self.bindgen,
})
- @permittedKwargs(permitted_test_kwargs | {'dependencies'} ^ {'protocol'})
@typed_pos_args('rust.test', str, BuildTargetHolder)
- def test(self, state: 'ModuleState', args: T.Tuple[str, BuildTargetHolder], kwargs: T.Dict[str, T.Any]) -> ModuleReturnValue:
+ @typed_kwargs(
+ 'rust.test',
+ *TEST_KWARGS,
+ KwargInfo('is_parallel', bool, default=False),
+ KwargInfo(
+ 'dependencies',
+ ContainerTypeInfo(list, (DependencyHolder, ExternalLibraryHolder)),
+ listify=True,
+ default=[]),
+ )
+ def test(self, state: 'ModuleState', args: T.Tuple[str, BuildTargetHolder], kwargs: 'FuncTest') -> ModuleReturnValue:
"""Generate a rust test target from a given rust target.
Rust puts it's unitests inside it's main source files, unlike most
@@ -91,7 +112,7 @@ class RustModule(ExtensionModule):
base_target: BuildTarget = unholder(args[1])
if not base_target.uses_rust():
raise InterpreterException('Second positional argument to rustmod.test() must be a rust based target')
- extra_args = stringlistify(kwargs.get('args', []))
+ extra_args = kwargs['args']
# Delete any arguments we don't want passed
if '--test' in extra_args:
@@ -104,17 +125,17 @@ class RustModule(ExtensionModule):
del extra_args[i + 1]
del extra_args[i]
for i, a in enumerate(extra_args):
- if a.startswith('--format='):
+ if isinstance(a, str) and a.startswith('--format='):
del extra_args[i]
break
- dependencies = unholder(listify(kwargs.get('dependencies', [])))
- for d in dependencies:
- if not isinstance(d, (Dependency, ExternalLibrary)):
- raise InvalidArguments('dependencies must be a dependency or external library')
+ dependencies = [d.held_object for d in kwargs['dependencies']]
+
+ # We need to cast here, as currently these don't have protocol in them, but test itself does.
+ tkwargs = T.cast('_kwargs.FuncTest', kwargs.copy())
- kwargs['args'] = extra_args + ['--test', '--format', 'pretty']
- kwargs['protocol'] = 'rust'
+ tkwargs['args'] = extra_args + ['--test', '--format', 'pretty']
+ tkwargs['protocol'] = 'rust'
new_target_kwargs = base_target.kwargs.copy()
# Don't mutate the shallow copied list, instead replace it with a new
@@ -132,7 +153,7 @@ class RustModule(ExtensionModule):
e = ExecutableHolder(new_target, self.interpreter)
test = self.interpreter.make_test(
- self.interpreter.current_node, [name, e], kwargs)
+ self.interpreter.current_node, (name, e), tkwargs)
return ModuleReturnValue(None, [e, test])
diff --git a/run_unittests.py b/run_unittests.py
index b2b7367..d17c243 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -1599,6 +1599,7 @@ class InternalTests(unittest.TestCase):
_(None, mock.Mock(), [], {'input': ['a']})
self.assertEqual(str(cm.exception), "testfunc keyword argument \"input\" container should be of even length, but is not")
+ @mock.patch.dict(mesonbuild.mesonlib.project_meson_versions, {})
def test_typed_kwarg_since(self) -> None:
@typed_kwargs(
'testfunc',
@@ -1654,6 +1655,45 @@ class InternalTests(unittest.TestCase):
_(None, mock.Mock(), tuple(), dict(native=True))
+ @mock.patch.dict(mesonbuild.mesonlib.project_meson_versions, {'': '1.0'})
+ def test_typed_kwarg_since_values(self) -> None:
+ @typed_kwargs(
+ 'testfunc',
+ KwargInfo('input', ContainerTypeInfo(list, str), listify=True, default=[], deprecated_values={'foo': '0.9'}, since_values={'bar': '1.1'}),
+ KwargInfo('output', ContainerTypeInfo(dict, str), default={}, deprecated_values={'foo': '0.9'}, since_values={'bar': '1.1'}),
+ KwargInfo(
+ 'mode', str,
+ validator=lambda x: 'Should be one of "clean", "build", "rebuild"' if x not in {'clean', 'build', 'rebuild', 'deprecated', 'since'} else None,
+ deprecated_values={'deprecated': '1.0'},
+ since_values={'since': '1.1'}),
+ )
+ def _(obj, node, args: T.Tuple, kwargs: T.Dict[str, str]) -> None:
+ pass
+
+ with mock.patch('sys.stdout', io.StringIO()) as out:
+ _(None, mock.Mock(subproject=''), [], {'input': ['foo']})
+ self.assertRegex(out.getvalue(), r"""WARNING:.Project targeting '1.0'.*deprecated since '0.9': "testfunc" keyword argument "input" value "foo".*""")
+
+ with mock.patch('sys.stdout', io.StringIO()) as out:
+ _(None, mock.Mock(subproject=''), [], {'input': ['bar']})
+ self.assertRegex(out.getvalue(), r"""WARNING:.Project targeting '1.0'.*introduced in '1.1': "testfunc" keyword argument "input" value "bar".*""")
+
+ with mock.patch('sys.stdout', io.StringIO()) as out:
+ _(None, mock.Mock(subproject=''), [], {'output': {'foo': 'a'}})
+ self.assertRegex(out.getvalue(), r"""WARNING:.Project targeting '1.0'.*deprecated since '0.9': "testfunc" keyword argument "output" value "foo".*""")
+
+ with mock.patch('sys.stdout', io.StringIO()) as out:
+ _(None, mock.Mock(subproject=''), [], {'output': {'bar': 'b'}})
+ self.assertRegex(out.getvalue(), r"""WARNING:.Project targeting '1.0'.*introduced in '1.1': "testfunc" keyword argument "output" value "bar".*""")
+
+ with mock.patch('sys.stdout', io.StringIO()) as out:
+ _(None, mock.Mock(subproject=''), [], {'mode': 'deprecated'})
+ self.assertRegex(out.getvalue(), r"""WARNING:.Project targeting '1.0'.*deprecated since '1.0': "testfunc" keyword argument "mode" value "deprecated".*""")
+
+ with mock.patch('sys.stdout', io.StringIO()) as out:
+ _(None, mock.Mock(subproject=''), [], {'mode': 'since'})
+ self.assertRegex(out.getvalue(), r"""WARNING:.Project targeting '1.0'.*introduced in '1.1': "testfunc" keyword argument "mode" value "since".*""")
+
@unittest.skipIf(is_tarball(), 'Skipping because this is a tarball release')
class DataTests(unittest.TestCase):
diff --git a/test cases/cython/2 generated sources/libdir/gen.py b/test cases/cython/2 generated sources/libdir/gen.py
new file mode 100644
index 0000000..5c0a82d
--- /dev/null
+++ b/test cases/cython/2 generated sources/libdir/gen.py
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: Apache-2.0
+
+import argparse
+import textwrap
+
+parser = argparse.ArgumentParser()
+parser.add_argument('output')
+args = parser.parse_args()
+
+with open(args.output, 'w') as f:
+ f.write(textwrap.dedent('''\
+ cpdef func():
+ return "Hello, World!"
+ '''))
diff --git a/test cases/cython/2 generated sources/libdir/meson.build b/test cases/cython/2 generated sources/libdir/meson.build
new file mode 100644
index 0000000..e9259bd
--- /dev/null
+++ b/test cases/cython/2 generated sources/libdir/meson.build
@@ -0,0 +1,10 @@
+ct2 = custom_target(
+ 'ct2',
+ input : 'gen.py',
+ output : 'ct2.pyx',
+ command : [py3, '@INPUT@', '@OUTPUT@'],
+)
+
+ct2_ext = py3.extension_module('ct2', ct2, dependencies : py3_dep)
+
+pydir = meson.current_build_dir()
diff --git a/test cases/cython/2 generated sources/meson.build b/test cases/cython/2 generated sources/meson.build
index c9a9b6a..89dacfa 100644
--- a/test cases/cython/2 generated sources/meson.build
+++ b/test cases/cython/2 generated sources/meson.build
@@ -59,3 +59,12 @@ test(
args : [files('test.py'), 'g'],
env : ['PYTHONPATH=' + meson.current_build_dir()]
)
+
+subdir('libdir')
+
+test(
+ 'custom target in subdir',
+ py3,
+ args : [files('test.py'), 'ct2'],
+ env : ['PYTHONPATH=' + pydir]
+)
diff --git a/test cases/failing/23 rel testdir/test.json b/test cases/failing/23 rel testdir/test.json
index ba983ab..79ab48a 100644
--- a/test cases/failing/23 rel testdir/test.json
+++ b/test cases/failing/23 rel testdir/test.json
@@ -1,7 +1,7 @@
{
"stdout": [
{
- "line": "test cases/failing/23 rel testdir/meson.build:4:0: ERROR: Workdir keyword argument must be an absolute path."
+ "line": "test cases/failing/23 rel testdir/meson.build:4:0: ERROR: benchmark keyword argument \"workdir\" must be an absolute path"
}
]
}