Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions docs/markdown/Wrap-dependency-system-manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,10 +331,9 @@ Cargo subprojects automatically call `override_dependency` with the name
* `0.0.x` -> '0'
It allows to make different dependencies for incompatible versions of the same
crate.
- the suffix is `-rs` for `rlib` and `dylib` crate types, otherwise it is the
crate type (e.g. `staticlib` or `cdylib`). The suffix is added to distinguish
Rust crates from regular system dependencies; for example `gstreamer-1.0` is a
system pkg-config dependency and `gstreamer-0.22-rs` is a Cargo dependency.
- the suffix is `-rs` for `rlib` and `dylib` crate types. The suffix is added to
distinguish Rust crates from C-ABI dependencies; for example `gstreamer-1.0`
is a system pkg-config dependency and `gstreamer-0.22-rs` is a Cargo dependency.

That means the `.wrap` file should have `dependency_names = foo-1-rs` in their
`[provide]` section when `Cargo.toml` has package name `foo` and version `1.2`.
Expand Down
2 changes: 1 addition & 1 deletion mesonbuild/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -2428,7 +2428,7 @@ def get_default_install_dir(self) -> T.Union[T.Tuple[str, str], T.Tuple[None, No
return self.environment.get_static_lib_dir(), '{libdir_static}'

def type_suffix(self):
return "@sta"
return "@rlib" if self.uses_rust_abi() else "@sta"

def process_kwargs(self, kwargs: StaticLibraryKeywordArguments) -> None:
super().process_kwargs(kwargs)
Expand Down
39 changes: 26 additions & 13 deletions mesonbuild/cargo/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@
from ..interpreterbase import SubProject
from ..compilers.rust import RustCompiler

from typing_extensions import Literal

def _dependency_name(package_name: str, api: str, suffix: str = '-rs') -> str:
basename = package_name[:-len(suffix)] if package_name.endswith(suffix) else package_name
basename = package_name[:-len(suffix)] if suffix and package_name.endswith(suffix) else package_name
return f'{basename}-{api}{suffix}'


Expand Down Expand Up @@ -139,8 +141,19 @@ def _create_package(self, pkg: PackageState, build: builder.Builder, subdir: str
ast += self._create_meson_subdir(build)

if pkg.manifest.lib:
for crate_type in pkg.manifest.lib.crate_type:
ast.extend(self._create_lib(pkg, build, crate_type))
crate_type = pkg.manifest.lib.crate_type
if 'dylib' in crate_type and 'cdylib' in crate_type:
raise MesonException('Cannot build both dylib and cdylib due to file name conflict')
if 'proc-macro' in crate_type:
ast.extend(self._create_lib(pkg, build, 'proc-macro', shared=True))
if any(x in crate_type for x in ['lib', 'rlib', 'dylib']):
ast.extend(self._create_lib(pkg, build, 'rust',
static=('lib' in crate_type or 'rlib' in crate_type),
shared='dylib' in crate_type))
if any(x in crate_type for x in ['staticlib', 'cdylib']):
ast.extend(self._create_lib(pkg, build, 'c',
static='staticlib' in crate_type,
shared='cdylib' in crate_type))

return ast

Expand Down Expand Up @@ -560,7 +573,9 @@ def _create_meson_subdir(self, build: builder.Builder) -> T.List[mparser.BaseNod
build.block([build.function('subdir', [build.string('meson')])]))
]

def _create_lib(self, pkg: PackageState, build: builder.Builder, crate_type: raw.CRATE_TYPE) -> T.List[mparser.BaseNode]:
def _create_lib(self, pkg: PackageState, build: builder.Builder,
lib_type: Literal['rust', 'c', 'proc-macro'],
static: bool = False, shared: bool = False) -> T.List[mparser.BaseNode]:
dependencies: T.List[mparser.BaseNode] = []
dependency_map: T.Dict[mparser.BaseNode, mparser.BaseNode] = {}
for name in pkg.required_deps:
Expand Down Expand Up @@ -593,21 +608,19 @@ def _create_lib(self, pkg: PackageState, build: builder.Builder, crate_type: raw
'rust_args': build.array(rust_args),
}

depname_suffix = '-rs' if crate_type in {'lib', 'rlib', 'proc-macro'} else f'-{crate_type}'
depname_suffix = '' if lib_type == 'c' else '-rs'
depname = _dependency_name(pkg.manifest.package.name, pkg.manifest.package.api, depname_suffix)

lib: mparser.BaseNode
if pkg.manifest.lib.proc_macro or crate_type == 'proc-macro':
if lib_type == 'proc-macro':
lib = build.method('proc_macro', build.identifier('rust'), posargs, kwargs)
else:
if crate_type in {'lib', 'rlib', 'staticlib'}:
target_type = 'static_library'
elif crate_type in {'dylib', 'cdylib'}:
target_type = 'shared_library'
if static and shared:
target_type = 'both_libraries'
else:
raise MesonException(f'Unsupported crate type {crate_type}')
if crate_type in {'staticlib', 'cdylib'}:
kwargs['rust_abi'] = build.string('c')
target_type = 'shared_library' if shared else 'static_library'

kwargs['rust_abi'] = build.string(lib_type)
lib = build.function(target_type, posargs, kwargs)

features_args: T.List[mparser.BaseNode] = []
Expand Down
5 changes: 3 additions & 2 deletions mesonbuild/cargo/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,13 +347,14 @@ class Library(BuildTarget):
@classmethod
def from_raw(cls, raw: raw.LibTarget, pkg: Package) -> Self:
name = raw.get('name', fixup_meson_varname(pkg.name))
# If proc_macro is True, it takes precedence and sets crate_type to proc-macro
proc_macro = raw.get('proc-macro', False)
crate_type = 'proc-macro' if proc_macro else 'lib'
return _raw_to_dataclass(raw, cls, f'Library entry {name}',
name=DefaultValue(name),
path=DefaultValue('src/lib.rs'),
edition=DefaultValue(pkg.edition),
crate_type=DefaultValue([crate_type]))
crate_type=ConvertValue(lambda x: ['proc-macro'] if proc_macro else x,
['lib']))


@dataclasses.dataclass
Expand Down
2 changes: 1 addition & 1 deletion test cases/rust/22 cargo subproject/meson.build
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
project('cargo subproject', 'c')

foo_dep = dependency('foo-0-cdylib')
foo_dep = dependency('foo-0')
exe = executable('app', 'main.c',
dependencies: foo_dep,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
method = cargo

[provide]
dependency_names = foo-0-cdylib
dependency_names = foo-0
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.0.1"
edition = "2021"

[lib]
crate-type = ["cdylib"]
crate-type = ["lib", "staticlib", "cdylib"]
path = "lib.rs"

# This dependency does not exist, verify optional works.
Expand Down
2 changes: 1 addition & 1 deletion test cases/rust/30 cargo workspace/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ e = executable('test-foo-1-rs', 'test_foo_1.rs',
)
test('test-foo-1-rs', e)

foo_cdylib = dependency('foo-1-cdylib')
foo_cdylib = dependency('foo-1')
e = executable('test-foo-1-cdylib', 'test_foo_1.c',
dependencies: [foo_cdylib],
)
Expand Down
25 changes: 25 additions & 0 deletions unittests/cargotests.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,18 @@ class CargoTomlTest(unittest.TestCase):
]
''')

CARGO_TOML_3 = textwrap.dedent('''\
[package]
name = "bits"
edition = "2021"
rust-version = "1.70"
version = "0.1.0"

[lib]
proc-macro = true
crate-type = ["lib"] # ignored
''')

CARGO_TOML_WS = textwrap.dedent('''\
[workspace]
resolver = "2"
Expand Down Expand Up @@ -406,6 +418,19 @@ def test_cargo_toml_dependencies(self) -> None:
self.assertEqual(manifest.dev_dependencies['gir-format-check'].meson_version, ['>= 0.1', '< 0.2'])
self.assertEqual(manifest.dev_dependencies['gir-format-check'].api, '0.1')

def test_cargo_toml_proc_macro(self) -> None:
with tempfile.TemporaryDirectory() as tmpdir:
fname = os.path.join(tmpdir, 'Cargo.toml')
with open(fname, 'w', encoding='utf-8') as f:
f.write(self.CARGO_TOML_3)
manifest_toml = load_toml(fname)
manifest = Manifest.from_raw(manifest_toml, 'Cargo.toml')

self.assertEqual(manifest.lib.name, 'bits')
self.assertEqual(manifest.lib.crate_type, ['proc-macro'])
self.assertEqual(manifest.lib.path, 'src/lib.rs')
self.assertEqual(manifest.lib.proc_macro, True)

def test_cargo_toml_targets(self) -> None:
with tempfile.TemporaryDirectory() as tmpdir:
fname = os.path.join(tmpdir, 'Cargo.toml')
Expand Down
Loading