diff options
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/). - - - -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. + -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: + - 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: + - 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. + -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. - + ## Running Meson diff --git a/docs/markdown/images/meson_mac1.png b/docs/markdown/images/meson_mac1.png Binary files differnew file mode 100755 index 0000000..17eae0a --- /dev/null +++ b/docs/markdown/images/meson_mac1.png diff --git a/docs/markdown/images/meson_mac2.png b/docs/markdown/images/meson_mac2.png Binary files differnew file mode 100755 index 0000000..e5c434d --- /dev/null +++ b/docs/markdown/images/meson_mac2.png diff --git a/docs/markdown/images/meson_mac3.png b/docs/markdown/images/meson_mac3.png Binary files differnew file mode 100755 index 0000000..babada1 --- /dev/null +++ b/docs/markdown/images/meson_mac3.png diff --git a/docs/markdown/images/meson_mac4.png b/docs/markdown/images/meson_mac4.png Binary files differnew file mode 100755 index 0000000..e8089ad --- /dev/null +++ b/docs/markdown/images/meson_mac4.png diff --git a/docs/markdown/images/meson_mac5.png b/docs/markdown/images/meson_mac5.png Binary files differnew file mode 100755 index 0000000..507fcda --- /dev/null +++ b/docs/markdown/images/meson_mac5.png diff --git a/docs/markdown/images/osx_download.png b/docs/markdown/images/osx_download.png Binary files differdeleted file mode 100644 index 3315886..0000000 --- a/docs/markdown/images/osx_download.png +++ /dev/null diff --git a/docs/markdown/images/osx_working.png b/docs/markdown/images/osx_working.png Binary files differdeleted file mode 100644 index 0b1320f..0000000 --- a/docs/markdown/images/osx_working.png +++ /dev/null diff --git a/docs/markdown/images/osx_xcode.png b/docs/markdown/images/osx_xcode.png Binary files differdeleted file mode 100644 index 14a6282..0000000 --- a/docs/markdown/images/osx_xcode.png +++ /dev/null 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" } ] } |