diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index edf9c1f56756..50cc4e059583 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1836,6 +1836,27 @@ def _get_rust_dependency_name(self, target: build.BuildTarget, dependency: LibTy # in Rust return target.rust_dependency_map.get(dependency.name, dependency.name).replace('-', '_') + def _add_rust_indirect_dependency_linkdirs(self, linkdirs: OrderedSet[str], dependency: LibTypes): + # Add all the linkdirs of indirect dependencies to the linkdirs if + # they're rlib/proc-macro/dylib dependencies. rustc requires this to + # be able to find the indirect dependencies during the build. + indirect_rust_deps = [dependency] + + # Instead of actually recursing over the dependencies use a stack here + while indirect_rust_deps: + indirect_dep = indirect_rust_deps.pop() + if not indirect_dep.uses_rust() or indirect_dep.rust_crate_type in ['staticlib', 'cdylib']: + continue + for d in indirect_dep.kwargs.get('dependencies', []): + if not hasattr(d, 'libraries'): + continue + indirect_rust_deps += d.libraries + indirect_rust_deps += d.whole_libraries + indirect_rust_deps += indirect_dep.link_targets + indirect_rust_deps += indirect_dep.link_whole_targets + + linkdirs.add(indirect_dep.subdir) + def generate_rust_target(self, target: build.BuildTarget) -> None: rustc = target.compilers['rust'] # Rust compiler takes only the main file as input and @@ -1945,6 +1966,7 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: d_name = self._get_rust_dependency_name(target, d) args += ['--extern', '{}={}'.format(d_name, os.path.join(d.subdir, d.filename))] project_deps.append(RustDep(d_name, self.rust_crates[d.name].order)) + self._add_rust_indirect_dependency_linkdirs(linkdirs, d) elif isinstance(d, build.StaticLibrary): # Rustc doesn't follow Meson's convention that static libraries # are called .a, and import libraries are .lib, so we have to @@ -1984,6 +2006,7 @@ def generate_rust_target(self, target: build.BuildTarget) -> None: d_name = self._get_rust_dependency_name(target, d) args += ['--extern', '{}={}'.format(d_name, os.path.join(d.subdir, d.filename))] project_deps.append(RustDep(d_name, self.rust_crates[d.name].order)) + self._add_rust_indirect_dependency_linkdirs(linkdirs, d) else: if rustc.linker.id in {'link', 'lld-link'}: if verbatim: diff --git a/test cases/rust/20 transitive dependencies/liba/lib.rs b/test cases/rust/20 transitive dependencies/liba/lib.rs new file mode 100644 index 000000000000..0fc8ce55f90a --- /dev/null +++ b/test cases/rust/20 transitive dependencies/liba/lib.rs @@ -0,0 +1,3 @@ +pub fn foo() -> i32 { + 123 +} diff --git a/test cases/rust/20 transitive dependencies/liba/meson.build b/test cases/rust/20 transitive dependencies/liba/meson.build new file mode 100644 index 000000000000..b32822db995f --- /dev/null +++ b/test cases/rust/20 transitive dependencies/liba/meson.build @@ -0,0 +1,5 @@ +liba = static_library('liba', 'lib.rs', + rust_crate_type : 'rlib', +) + +liba_dep = declare_dependency(link_with : liba) diff --git a/test cases/rust/20 transitive dependencies/libb/lib.rs b/test cases/rust/20 transitive dependencies/libb/lib.rs new file mode 100644 index 000000000000..e97463b92eb9 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/libb/lib.rs @@ -0,0 +1,3 @@ +pub fn bar() -> i32 { + 2 * liba::foo() +} diff --git a/test cases/rust/20 transitive dependencies/libb/meson.build b/test cases/rust/20 transitive dependencies/libb/meson.build new file mode 100644 index 000000000000..67947e73afa2 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/libb/meson.build @@ -0,0 +1,6 @@ +libb = static_library('libb', 'lib.rs', + rust_crate_type : 'rlib', + dependencies : [liba_dep], +) + +libb_dep = declare_dependency(link_with : libb) diff --git a/test cases/rust/20 transitive dependencies/main.rs b/test cases/rust/20 transitive dependencies/main.rs new file mode 100644 index 000000000000..4b248456c148 --- /dev/null +++ b/test cases/rust/20 transitive dependencies/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("{}", libb::bar()); +} diff --git a/test cases/rust/20 transitive dependencies/meson.build b/test cases/rust/20 transitive dependencies/meson.build new file mode 100644 index 000000000000..2f378f88fecd --- /dev/null +++ b/test cases/rust/20 transitive dependencies/meson.build @@ -0,0 +1,12 @@ +project('transitive dependencies', 'rust', + version : '1.0.0', + meson_version : '>= 1.0.0', + default_options : ['rust_std=2018'], +) + +subdir('liba') +subdir('libb') + +main = executable('main', 'main.rs', + dependencies : [libb_dep], +)