summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/cargo/interpreter.py79
-rw-r--r--test cases/rust/26 cargo system deps/main.rs5
-rw-r--r--test cases/rust/26 cargo system deps/meson.build11
-rw-r--r--test cases/rust/26 cargo system deps/subprojects/sub-1-rs.wrap2
-rw-r--r--test cases/rust/26 cargo system deps/subprojects/sub-1-rs/Cargo.toml16
-rw-r--r--test cases/rust/26 cargo system deps/subprojects/sub-1-rs/lib.rs15
6 files changed, 126 insertions, 2 deletions
diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py
index f8f73a3b2..00e713622 100644
--- a/mesonbuild/cargo/interpreter.py
+++ b/mesonbuild/cargo/interpreter.py
@@ -144,7 +144,7 @@ class Package:
exclude: T.List[str] = dataclasses.field(default_factory=list)
include: T.List[str] = dataclasses.field(default_factory=list)
publish: bool = True
- metadata: T.Dict[str, T.Dict[str, str]] = dataclasses.field(default_factory=dict)
+ metadata: T.Dict[str, T.Any] = dataclasses.field(default_factory=dict)
default_run: T.Optional[str] = None
autobins: bool = True
autoexamples: bool = True
@@ -156,6 +156,45 @@ class Package:
self.api = _version_to_api(self.version)
@dataclasses.dataclass
+class SystemDependency:
+
+ """ Representation of a Cargo system-deps entry
+ https://docs.rs/system-deps/latest/system_deps
+ """
+
+ name: str
+ version: T.List[str]
+ optional: bool = False
+ feature: T.Optional[str] = None
+ feature_overrides: T.Dict[str, T.Dict[str, str]] = dataclasses.field(default_factory=dict)
+
+ @classmethod
+ def from_raw(cls, name: str, raw: T.Any) -> SystemDependency:
+ if isinstance(raw, str):
+ return cls(name, SystemDependency.convert_version(raw))
+ name = raw.get('name', name)
+ version = SystemDependency.convert_version(raw.get('version'))
+ optional = raw.get('optional', False)
+ feature = raw.get('feature')
+ # Everything else are overrides when certain features are enabled.
+ feature_overrides = {k: v for k, v in raw.items() if k not in {'name', 'version', 'optional', 'feature'}}
+ return cls(name, version, optional, feature, feature_overrides)
+
+ @staticmethod
+ def convert_version(version: T.Optional[str]) -> T.List[str]:
+ vers = version.split(',') if version is not None else []
+ result: T.List[str] = []
+ for v in vers:
+ v = v.strip()
+ if v[0] not in '><=':
+ v = f'>={v}'
+ result.append(v)
+ return result
+
+ def enabled(self, features: T.Set[str]) -> bool:
+ return self.feature is None or self.feature in features
+
+@dataclasses.dataclass
class Dependency:
"""Representation of a Cargo Dependency Entry."""
@@ -289,6 +328,7 @@ class Manifest:
dependencies: T.Dict[str, Dependency]
dev_dependencies: T.Dict[str, Dependency]
build_dependencies: T.Dict[str, Dependency]
+ system_dependencies: T.Dict[str, SystemDependency] = dataclasses.field(init=False)
lib: Library
bin: T.List[Binary]
test: T.List[Test]
@@ -300,6 +340,7 @@ class Manifest:
def __post_init__(self) -> None:
self.features.setdefault('default', [])
+ self.system_dependencies = {k: SystemDependency.from_raw(k, v) for k, v in self.package.metadata.get('system-deps', {}).items()}
def _convert_manifest(raw_manifest: manifest.Manifest, subdir: str, path: str = '') -> Manifest:
@@ -563,8 +604,38 @@ class Interpreter:
for depname in pkg.required_deps:
dep = pkg.manifest.dependencies[depname]
ast += self._create_dependency(dep, build)
+ ast.append(build.assign(build.array([]), 'system_deps_args'))
+ for name, sys_dep in pkg.manifest.system_dependencies.items():
+ if sys_dep.enabled(pkg.features):
+ ast += self._create_system_dependency(name, sys_dep, build)
return ast
+ def _create_system_dependency(self, name: str, dep: SystemDependency, build: builder.Builder) -> T.List[mparser.BaseNode]:
+ kw = {
+ 'version': build.array([build.string(s) for s in dep.version]),
+ 'required': build.bool(not dep.optional),
+ }
+ varname = f'{fixup_meson_varname(name)}_system_dep'
+ cfg = f'system_deps_have_{fixup_meson_varname(name)}'
+ return [
+ build.assign(
+ build.function(
+ 'dependency',
+ [build.string(dep.name)],
+ kw,
+ ),
+ varname,
+ ),
+ build.if_(
+ build.method('found', build.identifier(varname)), build.block([
+ build.plusassign(
+ build.array([build.string('--cfg'), build.string(cfg)]),
+ 'system_deps_args'
+ ),
+ ])
+ ),
+ ]
+
def _create_dependency(self, dep: Dependency, build: builder.Builder) -> T.List[mparser.BaseNode]:
pkg = self._dep_package(dep)
kw = {
@@ -654,10 +725,14 @@ class Interpreter:
dep_pkg = self._dep_package(dep)
dep_lib_name = dep_pkg.manifest.lib.name
dependency_map[build.string(fixup_meson_varname(dep_lib_name))] = build.string(name)
+ for name, sys_dep in pkg.manifest.system_dependencies.items():
+ if sys_dep.enabled(pkg.features):
+ dependencies.append(build.identifier(f'{fixup_meson_varname(name)}_system_dep'))
rust_args: T.List[mparser.BaseNode] = [
build.identifier('features_args'),
- build.identifier(_extra_args_varname())
+ build.identifier(_extra_args_varname()),
+ build.identifier('system_deps_args'),
]
dependencies.append(build.identifier(_extra_deps_varname()))
diff --git a/test cases/rust/26 cargo system deps/main.rs b/test cases/rust/26 cargo system deps/main.rs
new file mode 100644
index 000000000..25e3b2fb8
--- /dev/null
+++ b/test cases/rust/26 cargo system deps/main.rs
@@ -0,0 +1,5 @@
+extern crate sub;
+
+pub fn main() {
+ sub::func();
+}
diff --git a/test cases/rust/26 cargo system deps/meson.build b/test cases/rust/26 cargo system deps/meson.build
new file mode 100644
index 000000000..9545bb452
--- /dev/null
+++ b/test cases/rust/26 cargo system deps/meson.build
@@ -0,0 +1,11 @@
+project('cargo system-deps', 'rust')
+
+glib = dependency('glib-2.0', required: false)
+if not glib.found()
+ error('MESON_SKIP_TEST: Need glib system dependency')
+endif
+
+sub_dep = dependency('sub-1-rs')
+exe = executable('main', 'main.rs', dependencies : sub_dep)
+test('main', exe)
+
diff --git a/test cases/rust/26 cargo system deps/subprojects/sub-1-rs.wrap b/test cases/rust/26 cargo system deps/subprojects/sub-1-rs.wrap
new file mode 100644
index 000000000..99686e90e
--- /dev/null
+++ b/test cases/rust/26 cargo system deps/subprojects/sub-1-rs.wrap
@@ -0,0 +1,2 @@
+[wrap-file]
+method = cargo
diff --git a/test cases/rust/26 cargo system deps/subprojects/sub-1-rs/Cargo.toml b/test cases/rust/26 cargo system deps/subprojects/sub-1-rs/Cargo.toml
new file mode 100644
index 000000000..88d5445f6
--- /dev/null
+++ b/test cases/rust/26 cargo system deps/subprojects/sub-1-rs/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = 'sub'
+version = '1'
+
+[build-dependencies]
+system-deps = "6"
+
+[lib]
+name = "sub"
+path = "lib.rs"
+
+[package.metadata.system-deps]
+glib = { name = "glib-2.0", version=" 2.0 , 2.1 , <3 ", feature="default" }
+gobject = { name = "gobject-2.0", version=">=99", optional=true }
+notfound = { feature="notfound" }
+libffi = "1.0"
diff --git a/test cases/rust/26 cargo system deps/subprojects/sub-1-rs/lib.rs b/test cases/rust/26 cargo system deps/subprojects/sub-1-rs/lib.rs
new file mode 100644
index 000000000..6e39d2365
--- /dev/null
+++ b/test cases/rust/26 cargo system deps/subprojects/sub-1-rs/lib.rs
@@ -0,0 +1,15 @@
+extern "C" {
+ fn g_get_tmp_dir() -> *mut std::ffi::c_void;
+}
+
+#[cfg(system_deps_have_glib)]
+#[cfg(not(system_deps_have_gobject))]
+pub fn func() {
+ unsafe {
+ g_get_tmp_dir();
+ }
+}
+
+pub fn func1() {
+ func()
+}