Skip to content

Commit 478fc3a

Browse files
authored
Fix ambiguous native dependencies in proc_macros and staticlibs (#1611)
`rustc` doesn't know how to deal with native dependencies that have the same name (specifying the full path to the native library does not currently work). `rules_rust` deals with this issue in `bin` and `cdylib` crate types by appending a hash to the different dependencies, so instead of `-lnative-dep -lnative-dep` the linking command line ends up being `-lnative-dep-{hash1} -lnative-dep-{hash2}`. This PR also applies the mechanism to `staticlib` and `proc-macro` crate types.
1 parent 9e3d841 commit 478fc3a

File tree

11 files changed

+128
-6
lines changed

11 files changed

+128
-6
lines changed

rust/private/rustc.bzl

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -599,12 +599,7 @@ def collect_inputs(
599599
# flattened on each transitive rust_library dependency.
600600
additional_transitive_inputs = []
601601
ambiguous_libs = {}
602-
if crate_info.type in ("staticlib", "proc-macro"):
603-
additional_transitive_inputs = _collect_libs_from_linker_inputs(
604-
dep_info.transitive_noncrates.to_list(),
605-
use_pic,
606-
)
607-
elif crate_info.type in ("bin", "dylib", "cdylib"):
602+
if crate_info.type not in ("lib", "rlib"):
608603
linker_inputs = dep_info.transitive_noncrates.to_list()
609604
ambiguous_libs = _disambiguate_libs(ctx.actions, toolchain, crate_info, dep_info, use_pic)
610605
additional_transitive_inputs = _collect_libs_from_linker_inputs(linker_inputs, use_pic) + [

test/unit/ambiguous_libs/BUILD.bazel

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
load(":ambiguous_libs_test.bzl", "ambiguous_libs_test_suite")
2+
3+
############################ UNIT TESTS #############################
4+
ambiguous_libs_test_suite(name = "ambiguous_libs_test_suite")
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
"""Unittests for ambiguous native dependencies."""
2+
3+
load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
4+
load("//rust:defs.bzl", "rust_binary", "rust_library", "rust_proc_macro", "rust_shared_library", "rust_static_library")
5+
6+
def _ambiguous_deps_test_impl(ctx):
7+
env = analysistest.begin(ctx)
8+
tut = analysistest.target_under_test(env)
9+
rustc_action = [action for action in tut.actions if action.mnemonic == "Rustc"][0]
10+
11+
# We depend on two C++ libraries named "native_dep", which we need to pass to the command line
12+
# in the form of "-lstatic=native-dep-{hash}. The hash should differ.
13+
link_args = [arg for arg in rustc_action.argv if arg.startswith("-lstatic=native_dep-")]
14+
asserts.equals(env, 2, len(link_args))
15+
asserts.false(env, link_args[0] == link_args[1])
16+
17+
return analysistest.end(env)
18+
19+
ambiguous_deps_test = analysistest.make(_ambiguous_deps_test_impl)
20+
21+
def _create_test_targets():
22+
rust_library(
23+
name = "rlib_with_ambiguous_deps",
24+
srcs = ["foo.rs"],
25+
edition = "2018",
26+
deps = [
27+
"//test/unit/ambiguous_libs/first_dep:native_dep",
28+
"//test/unit/ambiguous_libs/second_dep:native_dep",
29+
],
30+
)
31+
32+
rust_binary(
33+
name = "binary",
34+
srcs = ["bin.rs"],
35+
edition = "2018",
36+
deps = [":rlib_with_ambiguous_deps"],
37+
)
38+
39+
rust_proc_macro(
40+
name = "proc_macro",
41+
srcs = ["foo.rs"],
42+
edition = "2018",
43+
deps = [":rlib_with_ambiguous_deps"],
44+
)
45+
46+
rust_shared_library(
47+
name = "shared_library",
48+
srcs = ["foo.rs"],
49+
edition = "2018",
50+
deps = [":rlib_with_ambiguous_deps"],
51+
)
52+
53+
rust_static_library(
54+
name = "static_library",
55+
srcs = ["foo.rs"],
56+
edition = "2018",
57+
deps = [":rlib_with_ambiguous_deps"],
58+
)
59+
60+
ambiguous_deps_test(
61+
name = "bin_with_ambiguous_deps_test",
62+
target_under_test = ":binary",
63+
)
64+
ambiguous_deps_test(
65+
name = "staticlib_with_ambiguous_deps_test",
66+
target_under_test = ":static_library",
67+
)
68+
ambiguous_deps_test(
69+
name = "proc_macro_with_ambiguous_deps_test",
70+
target_under_test = ":proc_macro",
71+
)
72+
ambiguous_deps_test(
73+
name = "cdylib_with_ambiguous_deps_test",
74+
target_under_test = ":shared_library",
75+
)
76+
77+
def ambiguous_libs_test_suite(name):
78+
"""Entry-point macro called from the BUILD file.
79+
80+
Args:
81+
name: Name of the macro.
82+
"""
83+
_create_test_targets()
84+
85+
native.test_suite(
86+
name = name,
87+
tests = [
88+
":bin_with_ambiguous_deps_test",
89+
":staticlib_with_ambiguous_deps_test",
90+
":proc_macro_with_ambiguous_deps_test",
91+
":cdylib_with_ambiguous_deps_test",
92+
],
93+
)

test/unit/ambiguous_libs/bin.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn main() {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
load("@rules_cc//cc:defs.bzl", "cc_library")
2+
3+
cc_library(
4+
name = "native_dep",
5+
srcs = ["first.cc"],
6+
hdrs = ["first.h"],
7+
visibility = ["//test/unit/ambiguous_libs:__pkg__"],
8+
)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include "first.h"
2+
3+
int get_one() {
4+
return 1;
5+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int get_one();

test/unit/ambiguous_libs/foo.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
load("@rules_cc//cc:defs.bzl", "cc_library")
2+
3+
cc_library(
4+
name = "native_dep",
5+
srcs = ["second.cc"],
6+
hdrs = ["second.h"],
7+
visibility = ["//test/unit/ambiguous_libs:__pkg__"],
8+
)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include "second.h"
2+
3+
int get_two() {
4+
return 2;
5+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int get_two();

0 commit comments

Comments
 (0)