diff --git a/docs/markdown/Rust.md b/docs/markdown/Rust.md index 452dad6e6ccd..67bbdec5bdf3 100644 --- a/docs/markdown/Rust.md +++ b/docs/markdown/Rust.md @@ -98,3 +98,11 @@ target is a proc macro or dylib, or it depends on a dylib, in which case [`-C prefer-dynamic`](https://doc.rust-lang.org/rustc/codegen-options/index.html#prefer-dynamic) will be passed to the Rust compiler, and the standard libraries will be dynamically linked. + +## Multiple targets for the same crate name + +For library targets that have `rust_abi: 'rust'`, the crate name is derived from the +target name. First, dashes, spaces and dots are replaced with underscores. Second, +*since 1.10.0* anything after the first `+` is dropped. This allows creating multiple +targets for the same crate name, for example when the same crate is built multiple +times with different features, or for both the build and the host machine. diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 50917aeef216..95946ea2bc99 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1946,11 +1946,17 @@ def _add_rust_project_entry(self, name: str, main_rust_file: str, args: Compiler self.rust_crates[name] = crate - def _get_rust_dependency_name(self, target: build.BuildTarget, dependency: LibTypes) -> str: - # Convert crate names with dashes to underscores by default like - # cargo does as dashes can't be used as parts of identifiers - # in Rust - return target.rust_dependency_map.get(dependency.name, dependency.name).replace('-', '_') + @staticmethod + def _get_rust_crate_name(target_name: str) -> str: + # Rustc replaces - with _. spaces or dots are not allowed, so we replace them with underscores + # Also +SUFFIX is dropped, which can be used to distinguish host from build crates + crate_name = target_name.replace('-', '_').replace(' ', '_').replace('.', '_') + return crate_name.split('+', 1)[0] + + @staticmethod + def _get_rust_dependency_name(target: build.BuildTarget, dependency: LibTypes) -> str: + crate_name_raw = target.rust_dependency_map.get(dependency.name, dependency.name) + return NinjaBackend._get_rust_crate_name(crate_name_raw) def generate_rust_sources(self, target: build.BuildTarget) -> T.Tuple[T.List[str], str]: orderdeps: T.List[str] = [] @@ -2025,8 +2031,7 @@ def get_rust_compiler_args(self, target: build.BuildTarget, rustc: Compiler, src args.extend(rustc.get_linker_always_args()) args += self.generate_basic_compiler_args(target, rustc) - # Rustc replaces - with _. spaces or dots are not allowed, so we replace them with underscores - args += ['--crate-name', target.name.replace('-', '_').replace(' ', '_').replace('.', '_')] + args += ['--crate-name', self._get_rust_crate_name(target.name)] if depfile: args += rustc.get_dependency_gen_args(target_name, depfile) args += rustc.get_output_args(target_name) diff --git a/test cases/rust/30 both machines/lib.rs b/test cases/rust/30 both machines/lib.rs new file mode 100644 index 000000000000..432593368f90 --- /dev/null +++ b/test cases/rust/30 both machines/lib.rs @@ -0,0 +1,3 @@ +pub fn answer() -> u32 { + 42 +} diff --git a/test cases/rust/30 both machines/meson.build b/test cases/rust/30 both machines/meson.build new file mode 100644 index 000000000000..511518a7bb6d --- /dev/null +++ b/test cases/rust/30 both machines/meson.build @@ -0,0 +1,36 @@ +project( + 'testproj', + 'rust', + version : '0.1', + meson_version : '>= 1.9.0', + default_options : ['rust_std=2021'], +) + +lib_host = static_library( + 'lib', + 'lib.rs', + rust_abi: 'rust' +) + +lib_build = static_library( + 'lib+build', + 'lib.rs', + rust_abi: 'rust', + native: true, +) + +exe_host = executable( + 'test-host', + 'test.rs', + link_with: lib_host, +) + +exe_build = executable( + 'test-build', + 'test.rs', + link_with: lib_build, + native: true, +) + +test('host', exe_host) +test('build', exe_build) diff --git a/test cases/rust/30 both machines/test.rs b/test cases/rust/30 both machines/test.rs new file mode 100644 index 000000000000..c9679d452d34 --- /dev/null +++ b/test cases/rust/30 both machines/test.rs @@ -0,0 +1,5 @@ +use lib::answer; + +fn main() { + println!("The answer is {}.\n", answer()); +}