forked from mesonbuild/meson
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request mesonbuild#7860 from dcbaker/wip/2020-10/rust-module
Add a rust module
- Loading branch information
Showing
16 changed files
with
364 additions
and
51 deletions.
There are no files selected for viewing
Validating CODEOWNERS rules …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
--- | ||
short-description: Rust language integration module | ||
authors: | ||
- name: Dylan Baker | ||
email: dylan@pnwbakers.com | ||
years: [2020] | ||
... | ||
|
||
# Unstable Rust module | ||
|
||
*(new in 0.57.0)* | ||
|
||
**Note** Unstable modules make no backwards compatible API guarantees. | ||
|
||
The rust module provides helper to integrate rust code into meson. The goal | ||
is to make using rust in meson more pleasant, while still remaining mesonic, | ||
this means that it attempts to make rust work more like meson, rather than | ||
meson work more like rust. | ||
|
||
## Functions | ||
|
||
### test(name: string, target: library | executable, dependencies: []Dependency) | ||
|
||
This function creates a new rust unittest target from an existing rust based | ||
target, which may be a library or executable. It does this by copying the | ||
sources and arguments passed to the original target and adding the `--test` | ||
argument to the compilation, then creates a new test target which calls that | ||
executable, using the rust test protocol. | ||
|
||
This accepts all of the keyword arguments as the | ||
[`test`](Reference-manual.md#test) function except `protocol`, it will set | ||
that automatically. | ||
|
||
Additional, test only dependencies may be passed via the dependencies | ||
argument. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,3 +12,4 @@ | |
* [gnome](Gnome-module.md) | ||
* [i18n](i18n-module.md) | ||
* [pkgconfig](Pkgconfig-module.md) | ||
* [rust](Rust-module.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
## Meson test() now accepts `protocol : 'rust'` | ||
|
||
This allows native rust tests to be run and parsed by meson, simply set the | ||
protocol to `rust` and meson takes care of the rest. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
## Untable Rust module | ||
|
||
A new unstable module has been added to make using rust with meson easier. | ||
Currently it adds a single function to ease defining rust tests. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
# Copyright © 2020 Intel Corporation | ||
|
||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
|
||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import typing as T | ||
|
||
from . import ExtensionModule, ModuleReturnValue | ||
from .. import mlog | ||
from ..build import BuildTarget, Executable, InvalidArguments | ||
from ..dependencies import Dependency, ExternalLibrary | ||
from ..interpreter import ExecutableHolder, permitted_kwargs | ||
from ..interpreterbase import InterpreterException, permittedKwargs, FeatureNew | ||
from ..mesonlib import stringlistify, unholder, listify | ||
|
||
if T.TYPE_CHECKING: | ||
from ..interpreter import ModuleState, Interpreter | ||
|
||
|
||
class RustModule(ExtensionModule): | ||
|
||
"""A module that holds helper functions for rust.""" | ||
|
||
@FeatureNew('rust module', '0.57.0') | ||
def __init__(self, interpreter: 'Interpreter') -> None: | ||
super().__init__(interpreter) | ||
|
||
@permittedKwargs(permitted_kwargs['test'] | {'dependencies'} ^ {'protocol'}) | ||
def test(self, state: 'ModuleState', args: T.List, kwargs: T.Dict[str, T.Any]) -> ModuleReturnValue: | ||
"""Generate a rust test target from a given rust target. | ||
Rust puts it's unitests inside it's main source files, unlike most | ||
languages that put them in external files. This means that normally | ||
you have to define two seperate targets with basically the same | ||
arguments to get tests: | ||
```meson | ||
rust_lib_sources = [...] | ||
rust_lib = static_library( | ||
'rust_lib', | ||
rust_lib_sources, | ||
) | ||
rust_lib_test = executable( | ||
'rust_lib_test', | ||
rust_lib_sources, | ||
rust_args : ['--test'], | ||
) | ||
test( | ||
'rust_lib_test', | ||
rust_lib_test, | ||
protocol : 'rust', | ||
) | ||
``` | ||
This is all fine, but not very DRY. This method makes it much easier | ||
to define rust tests: | ||
```meson | ||
rust = import('unstable-rust') | ||
rust_lib = static_library( | ||
'rust_lib', | ||
[sources], | ||
) | ||
rust.test('rust_lib_test', rust_lib) | ||
``` | ||
""" | ||
if len(args) != 2: | ||
raise InterpreterException('rustmod.test() takes exactly 2 positional arguments') | ||
name: str = args[0] | ||
if not isinstance(name, str): | ||
raise InterpreterException('First positional argument to rustmod.test() must be a string') | ||
base_target: BuildTarget = unholder(args[1]) | ||
if not isinstance(base_target, BuildTarget): | ||
raise InterpreterException('Second positional argument to rustmod.test() must be a library or executable') | ||
if not base_target.get_using_rustc(): | ||
raise InterpreterException('Second positional argument to rustmod.test() must be a rust based target') | ||
extra_args = stringlistify(kwargs.get('args', [])) | ||
|
||
# Delete any arguments we don't want passed | ||
if '--test' in extra_args: | ||
mlog.warning('Do not add --test to rustmod.test arguments') | ||
extra_args.remove('--test') | ||
if '--format' in extra_args: | ||
mlog.warning('Do not add --format to rustmod.test arguments') | ||
i = extra_args.index('--format') | ||
# Also delete the argument to --format | ||
del extra_args[i + 1] | ||
del extra_args[i] | ||
for i, a in enumerate(extra_args): | ||
if 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') | ||
|
||
kwargs['args'] = extra_args + ['--test', '--format', 'pretty'] | ||
kwargs['protocol'] = 'rust' | ||
|
||
new_target_kwargs = base_target.kwargs.copy() | ||
# Don't mutate the shallow copied list, instead replace it with a new | ||
# one | ||
new_target_kwargs['rust_args'] = new_target_kwargs.get('rust_args', []) + ['--test'] | ||
new_target_kwargs['install'] = False | ||
new_target_kwargs['dependencies'] = new_target_kwargs.get('dependencies', []) + dependencies | ||
|
||
new_target = Executable( | ||
name, base_target.subdir, state.subproject, | ||
base_target.for_machine, base_target.sources, | ||
base_target.objects, base_target.environment, | ||
new_target_kwargs | ||
) | ||
|
||
e = ExecutableHolder(new_target, self.interpreter) | ||
test = self.interpreter.make_test( | ||
self.interpreter.current_node, [name, e], kwargs) | ||
|
||
return ModuleReturnValue([], [e, test]) | ||
|
||
|
||
def initialize(*args: T.List, **kwargs: T.Dict) -> RustModule: | ||
return RustModule(*args, **kwargs) # type: ignore |
Oops, something went wrong.