aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.com>2023-06-02 12:11:45 -0400
committerXavier Claessens <xclaesse@gmail.com>2023-10-09 21:13:58 -0400
commitdc329f0f04d917da5bf295e013f393caed4a85fc (patch)
tree00ec4bd14f1af655fa049ec102649dad9e53f0f7
parentea42d2d01999c00c7fe7846de38416b8693bfb79 (diff)
downloadmeson-dc329f0f04d917da5bf295e013f393caed4a85fc.zip
meson-dc329f0f04d917da5bf295e013f393caed4a85fc.tar.gz
meson-dc329f0f04d917da5bf295e013f393caed4a85fc.tar.bz2
interpreter: Add support for cargo subproject
-rw-r--r--docs/markdown/Wrap-dependency-system-manual.md21
-rw-r--r--docs/markdown/snippets/wrap.md3
-rw-r--r--mesonbuild/cargo/__init__.py5
-rw-r--r--mesonbuild/cargo/interpreter.py8
-rw-r--r--mesonbuild/interpreter/interpreter.py25
-rw-r--r--mesonbuild/wrap/wrap.py3
-rw-r--r--test cases/cmake/26 dependency fallback/meson.build2
-rw-r--r--test cases/rust/21 cargo subproject/main.c5
-rw-r--r--test cases/rust/21 cargo subproject/meson.build7
-rw-r--r--test cases/rust/21 cargo subproject/subprojects/bar-rs.wrap2
-rw-r--r--test cases/rust/21 cargo subproject/subprojects/bar-rs/Cargo.toml3
-rw-r--r--test cases/rust/21 cargo subproject/subprojects/bar-rs/src/lib.rs1
-rw-r--r--test cases/rust/21 cargo subproject/subprojects/foo-rs.wrap2
-rw-r--r--test cases/rust/21 cargo subproject/subprojects/foo-rs/Cargo.toml10
-rw-r--r--test cases/rust/21 cargo subproject/subprojects/foo-rs/src/lib.rs4
15 files changed, 91 insertions, 10 deletions
diff --git a/docs/markdown/Wrap-dependency-system-manual.md b/docs/markdown/Wrap-dependency-system-manual.md
index 9000c40..e1e9474 100644
--- a/docs/markdown/Wrap-dependency-system-manual.md
+++ b/docs/markdown/Wrap-dependency-system-manual.md
@@ -91,6 +91,7 @@ previously reserved to `wrap-file`:
Supported methods:
- `meson` requires `meson.build` file.
- `cmake` requires `CMakeLists.txt` file. [See details](#cmake-wraps).
+ - `cargo` requires `Cargo.toml` file. [See details](#cargo-wraps).
### Specific to wrap-file
- `source_url` - download url to retrieve the wrap-file source archive
@@ -313,6 +314,26 @@ method = cmake
[provide]
foo-bar-1.0 = foo_bar_dep
```
+### Cargo wraps
+
+Cargo subprojects automatically override the `<package_name>-rs` dependency name.
+`package_name` is defined in `[package] name = ...` section of the `Cargo.toml`
+and `-rs` suffix is added. That means the `.wrap` file should have
+`dependency_names = foo-rs` in their `[provide]` section when `Cargo.toml` has
+package name `foo`.
+
+Cargo subprojects require a toml parser. Python >= 3.11 have one built-in, older
+Python versions require either the external `tomli` module or `toml2json` program.
+
+For example, a Cargo project with the package name `foo-bar` would have a wrap
+file like that:
+```ini
+[wrap-file]
+...
+method = cargo
+[provide]
+dependency_names = foo-bar-rs
+```
## Using wrapped projects
diff --git a/docs/markdown/snippets/wrap.md b/docs/markdown/snippets/wrap.md
index 6e03c2e..3a5521e 100644
--- a/docs/markdown/snippets/wrap.md
+++ b/docs/markdown/snippets/wrap.md
@@ -1,4 +1,4 @@
-## Automatic fallback to `cmake` subproject
+## Automatic fallback to `cmake` and `cargo` subproject
CMake subprojects have been supported for a while using the `cmake.subproject()`
module method. However until now it was not possible to use a CMake subproject
@@ -10,3 +10,4 @@ key in the wrap file's first section. The method defaults to `meson`.
Supported methods:
- `meson` requires `meson.build` file.
- `cmake` requires `CMakeLists.txt` file. [See details](Wrap-dependency-system-manual.md#cmake-wraps).
+- `cargo` requires `Cargo.toml` file. [See details](Wrap-dependency-system-manual.md#cargo-wraps).
diff --git a/mesonbuild/cargo/__init__.py b/mesonbuild/cargo/__init__.py
index e69de29..0007b9d 100644
--- a/mesonbuild/cargo/__init__.py
+++ b/mesonbuild/cargo/__init__.py
@@ -0,0 +1,5 @@
+__all__ = [
+ 'interpret'
+]
+
+from .interpreter import interpret
diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py
index 68517ba..12365bb 100644
--- a/mesonbuild/cargo/interpreter.py
+++ b/mesonbuild/cargo/interpreter.py
@@ -457,7 +457,13 @@ def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CR
]
-def interpret(cargo: Manifest, env: Environment) -> mparser.CodeBlockNode:
+def interpret(subp_name: str, subdir: str, env: Environment) -> mparser.CodeBlockNode:
+ package_name = subp_name[:-3] if subp_name.endswith('-rs') else subp_name
+ manifests = _load_manifests(os.path.join(env.source_dir, subdir))
+ cargo = manifests.get(package_name)
+ if not cargo:
+ raise MesonException(f'Cargo package {package_name!r} not found in {subdir}')
+
filename = os.path.join(cargo.subdir, cargo.path, 'Cargo.toml')
build = builder.Builder(filename)
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index 23ce146..cc83cbd 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -930,13 +930,14 @@ class Interpreter(InterpreterBase, HoldableObject):
m += ['method', mlog.bold(method)]
mlog.log(*m, '\n', nested=False)
+ methods_map: T.Dict[wrap.Method, T.Callable[[str, str, T.Dict[OptionKey, str, kwtypes.DoSubproject]], SubprojectHolder]] = {
+ 'meson': self._do_subproject_meson,
+ 'cmake': self._do_subproject_cmake,
+ 'cargo': self._do_subproject_cargo,
+ }
+
try:
- if method == 'meson':
- return self._do_subproject_meson(subp_name, subdir, default_options, kwargs)
- elif method == 'cmake':
- return self._do_subproject_cmake(subp_name, subdir, default_options, kwargs)
- else:
- raise mesonlib.MesonBugException(f'The method {method} is invalid for the subproject {subp_name}')
+ return methods_map[method](subp_name, subdir, default_options, kwargs)
# Invalid code is always an error
except InvalidCode:
raise
@@ -1038,6 +1039,18 @@ class Interpreter(InterpreterBase, HoldableObject):
result.cm_interpreter = cm_int
return result
+ def _do_subproject_cargo(self, subp_name: str, subdir: str,
+ default_options: T.Dict[OptionKey, str],
+ kwargs: kwtypes.DoSubproject) -> SubprojectHolder:
+ from .. import cargo
+ FeatureNew.single_use('Cargo subproject', '1.3.0', self.subproject, location=self.current_node)
+ with mlog.nested(subp_name):
+ ast = cargo.interpret(subp_name, subdir, self.environment)
+ return self._do_subproject_meson(
+ subp_name, subdir, default_options, kwargs, ast,
+ # FIXME: Are there other files used by cargo interpreter?
+ [os.path.join(subdir, 'Cargo.toml')])
+
def get_option_internal(self, optname: str) -> coredata.UserOption:
key = OptionKey.from_string(optname).evolve(subproject=self.subproject)
diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py
index 21a5c5d..a5b4dc8 100644
--- a/mesonbuild/wrap/wrap.py
+++ b/mesonbuild/wrap/wrap.py
@@ -47,7 +47,7 @@ if T.TYPE_CHECKING:
import http.client
from typing_extensions import Literal
- Method = Literal['meson', 'cmake']
+ Method = Literal['meson', 'cmake', 'cargo']
try:
# Importing is just done to check if SSL exists, so all warnings
@@ -450,6 +450,7 @@ class Resolver:
methods_map: T.Dict[Method, str] = {
'meson': 'meson.build',
'cmake': 'CMakeLists.txt',
+ 'cargo': 'Cargo.toml',
}
# Check if this wrap forces a specific method, use meson otherwise.
diff --git a/test cases/cmake/26 dependency fallback/meson.build b/test cases/cmake/26 dependency fallback/meson.build
index b36aaac..871d70c 100644
--- a/test cases/cmake/26 dependency fallback/meson.build
+++ b/test cases/cmake/26 dependency fallback/meson.build
@@ -9,7 +9,7 @@ test('test1', exe1)
# to meson but wrap force cmake.
subproject('force_cmake')
-testcase expect_error('Wrap method \'notfound\' is not supported, must be one of: meson, cmake')
+testcase expect_error('Wrap method \'notfound\' is not supported, must be one of: meson, cmake, cargo')
subproject('broken_method')
endtestcase
diff --git a/test cases/rust/21 cargo subproject/main.c b/test cases/rust/21 cargo subproject/main.c
new file mode 100644
index 0000000..5daec64
--- /dev/null
+++ b/test cases/rust/21 cargo subproject/main.c
@@ -0,0 +1,5 @@
+int rust_func(void);
+
+int main(int argc, char *argv[]) {
+ return rust_func();
+}
diff --git a/test cases/rust/21 cargo subproject/meson.build b/test cases/rust/21 cargo subproject/meson.build
new file mode 100644
index 0000000..420e6e3
--- /dev/null
+++ b/test cases/rust/21 cargo subproject/meson.build
@@ -0,0 +1,7 @@
+project('cargo subproject', 'c')
+
+foo_dep = dependency('foo-rs')
+exe = executable('app', 'main.c',
+ dependencies: foo_dep,
+)
+test('cargo-test', exe)
diff --git a/test cases/rust/21 cargo subproject/subprojects/bar-rs.wrap b/test cases/rust/21 cargo subproject/subprojects/bar-rs.wrap
new file mode 100644
index 0000000..99686e9
--- /dev/null
+++ b/test cases/rust/21 cargo subproject/subprojects/bar-rs.wrap
@@ -0,0 +1,2 @@
+[wrap-file]
+method = cargo
diff --git a/test cases/rust/21 cargo subproject/subprojects/bar-rs/Cargo.toml b/test cases/rust/21 cargo subproject/subprojects/bar-rs/Cargo.toml
new file mode 100644
index 0000000..232b4d7
--- /dev/null
+++ b/test cases/rust/21 cargo subproject/subprojects/bar-rs/Cargo.toml
@@ -0,0 +1,3 @@
+[package]
+name = "bar"
+version = "0.1"
diff --git a/test cases/rust/21 cargo subproject/subprojects/bar-rs/src/lib.rs b/test cases/rust/21 cargo subproject/subprojects/bar-rs/src/lib.rs
new file mode 100644
index 0000000..5b64db8
--- /dev/null
+++ b/test cases/rust/21 cargo subproject/subprojects/bar-rs/src/lib.rs
@@ -0,0 +1 @@
+pub const VALUE: i32 = 0;
diff --git a/test cases/rust/21 cargo subproject/subprojects/foo-rs.wrap b/test cases/rust/21 cargo subproject/subprojects/foo-rs.wrap
new file mode 100644
index 0000000..99686e9
--- /dev/null
+++ b/test cases/rust/21 cargo subproject/subprojects/foo-rs.wrap
@@ -0,0 +1,2 @@
+[wrap-file]
+method = cargo
diff --git a/test cases/rust/21 cargo subproject/subprojects/foo-rs/Cargo.toml b/test cases/rust/21 cargo subproject/subprojects/foo-rs/Cargo.toml
new file mode 100644
index 0000000..214c327
--- /dev/null
+++ b/test cases/rust/21 cargo subproject/subprojects/foo-rs/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "foo"
+version = "0.0.1"
+edition = "2021"
+
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+mybar = { version = "0.1", package = "bar" }
diff --git a/test cases/rust/21 cargo subproject/subprojects/foo-rs/src/lib.rs b/test cases/rust/21 cargo subproject/subprojects/foo-rs/src/lib.rs
new file mode 100644
index 0000000..732d7d2
--- /dev/null
+++ b/test cases/rust/21 cargo subproject/subprojects/foo-rs/src/lib.rs
@@ -0,0 +1,4 @@
+#[no_mangle]
+pub extern "C" fn rust_func() -> i32 {
+ mybar::VALUE
+}