diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index fb20d5cc1960..b084ac9baf40 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -149,6 +149,24 @@ class Package: autobenches: bool = True +@dataclasses.dataclass +class SystemDependency: + name: T.Optional[str] + version: T.Optional[T.List[str]] = None + features: T.Dict[str, T.Dict[str, str]] = dataclasses.field(default_factory=dict) + + @classmethod + def from_raw(cls, k: str, raw: manifest.DependencyV) -> Dependency: + """Create a dependency from a raw cargo dictionary""" + fixed = _fixup_raw_mappings(raw) + fixed = { + 'name': fixed.get('name', k), + 'version': fixed.get('version'), + 'features': {k: v for k, v in fixed.items() if k not in ['name', 'version']} + } + + return cls(**fixed) + @dataclasses.dataclass class Dependency: @@ -283,6 +301,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] lib: Library bin: T.List[Binary] test: T.List[Test] @@ -313,6 +332,7 @@ def _convert_manifest(raw_manifest: manifest.Manifest, subdir: str, path: str = {k: Dependency.from_raw(v, k) for k, v in raw_manifest.get('dependencies', {}).items()}, {k: Dependency.from_raw(v, k) for k, v in raw_manifest.get('dev-dependencies', {}).items()}, {k: Dependency.from_raw(v, k) for k, v in raw_manifest.get('build-dependencies', {}).items()}, + {k: SystemDependency.from_raw(k, d) for k, d in raw_manifest['package'].get('metadata', {}).get('system-deps', {}).items()}, Library(**lib), [Binary(**_fixup_raw_mappings(b)) for b in raw_manifest.get('bin', {})], [Test(**_fixup_raw_mappings(b)) for b in raw_manifest.get('test', {})], @@ -536,7 +556,7 @@ def _create_cfg(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseN has_build_deps_message = None if cargo.build_dependencies: has_build_deps_message = build.block([ - build.function('error', [ + build.function('warning', [ build.string('Cannot use build.rs with build-dependencies. It should be ported manually in meson/meson.build'), ]), ]) @@ -681,6 +701,20 @@ def _create_dependencies(cargo: Manifest, build: builder.Builder) -> T.List[mpar ast.append(build.if_(cfg_to_meson(condition, build), build.block(ifblock), build.block(elseblock))) for name, dep in cargo.dependencies.items(): ast += _create_dependency(name, dep, build) + for name, dep in cargo.system_dependencies.items(): + kw = {} + if dep.version is not None: + kw['version'] = build.array([build.string(s) for s in dep.version]) + ast.extend([ + build.assign( + build.function( + 'dependency', + [build.string(dep.name)], + kw, + ), + f'{name}_system_dep', + ), + ]) return ast @@ -693,6 +727,8 @@ def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CR dependencies.append(build.identifier(_dependency_varname(dep.package))) if name != dep.package: dependency_map[build.string(fixup_meson_varname(dep.package))] = build.string(name) + for name, dep in cargo.system_dependencies.items(): + dependencies.append(build.identifier(f'{name}_system_dep')) rust_args: T.List[mparser.BaseNode] = [ build.identifier('features_args'), diff --git a/test cases/cargo/06 system deps link/main.rs b/test cases/cargo/06 system deps link/main.rs new file mode 100644 index 000000000000..b93347ad252b --- /dev/null +++ b/test cases/cargo/06 system deps link/main.rs @@ -0,0 +1,5 @@ +extern crate sub; + +pub fn main() { + std::process::exit(sub::func()); +} diff --git a/test cases/cargo/06 system deps link/meson.build b/test cases/cargo/06 system deps link/meson.build new file mode 100644 index 000000000000..db844a1e3372 --- /dev/null +++ b/test cases/cargo/06 system deps link/meson.build @@ -0,0 +1,10 @@ +project('cargo system-deps', 'rust') + +rust = import('unstable-rust') + +sub = rust.cargo('sub') + +exe = executable('main', 'main.rs', dependencies : sub.get_variable('dep')) + +test('main', exe) + diff --git a/test cases/cargo/06 system deps link/subprojects/sub/Cargo.toml b/test cases/cargo/06 system deps link/subprojects/sub/Cargo.toml new file mode 100644 index 000000000000..9b74c784f255 --- /dev/null +++ b/test cases/cargo/06 system deps link/subprojects/sub/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = 'sub' +version = '0.1.1' +edition = '2021' +description = 'a project with a system dependency' + +[build-dependencies] +system-deps = "6" + +[lib] +name = "sub" + +[package.metadata.system-deps.system] +version = "0.1" diff --git a/test cases/cargo/06 system deps link/subprojects/sub/src/lib.rs b/test cases/cargo/06 system deps link/subprojects/sub/src/lib.rs new file mode 100644 index 000000000000..d966dba19538 --- /dev/null +++ b/test cases/cargo/06 system deps link/subprojects/sub/src/lib.rs @@ -0,0 +1,12 @@ +mod ffi { + extern "C" { + pub fn func() -> i32; + } +} + +pub fn func() -> i32 { + unsafe { + ffi::func() + } +} + diff --git a/test cases/cargo/06 system deps link/subprojects/system.wrap b/test cases/cargo/06 system deps link/subprojects/system.wrap new file mode 100644 index 000000000000..8d434ab994aa --- /dev/null +++ b/test cases/cargo/06 system deps link/subprojects/system.wrap @@ -0,0 +1,5 @@ +[wrap-file] +path = 'system' + +[provide] +system = system_dep diff --git a/test cases/cargo/06 system deps link/subprojects/system/lib.c b/test cases/cargo/06 system deps link/subprojects/system/lib.c new file mode 100644 index 000000000000..7306f768f7f2 --- /dev/null +++ b/test cases/cargo/06 system deps link/subprojects/system/lib.c @@ -0,0 +1,5 @@ +#include + +int func() { + return 0; +} diff --git a/test cases/cargo/06 system deps link/subprojects/system/meson.build b/test cases/cargo/06 system deps link/subprojects/system/meson.build new file mode 100644 index 000000000000..12d3be4eaa10 --- /dev/null +++ b/test cases/cargo/06 system deps link/subprojects/system/meson.build @@ -0,0 +1,5 @@ +project('system', 'c', version: '0.2') + + +system_dep = declare_dependency(link_with: library('system', 'lib.c')) +meson.override_dependency('system', system_dep)