Don't emit `CrateInfo` from `rust_static_library` and `rust_shared_library` (#1298)
These rules emit a `staticlib` and `cdylib` which are not meant for consumption by other rust targets.
However, one should still be able to write a `rust_test` for `rust_shared_library` and `rust_static_library` targets, which needs a `CrateInfo`. For this purpose we provide a `CrateInfo` wrapped in a `TestCrateInfo` provider, that `rust_test` understands.
diff --git a/rust/private/common.bzl b/rust/private/common.bzl
index 021a197..ebf2b7e 100644
--- a/rust/private/common.bzl
+++ b/rust/private/common.bzl
@@ -23,7 +23,7 @@
In the Bazel lingo, `rust_common` gives the access to the Rust Sandwich API.
"""
-load(":providers.bzl", "CrateInfo", "DepInfo", "StdLibInfo")
+load(":providers.bzl", "CrateInfo", "DepInfo", "StdLibInfo", "TestCrateInfo")
# This constant only represents the default value for attributes and macros
# defined in `rules_rust`. Like any attribute public attribute, it can be
@@ -54,5 +54,6 @@
crate_info = CrateInfo,
dep_info = DepInfo,
stdlib_info = StdLibInfo,
+ test_crate_info = TestCrateInfo,
default_version = DEFAULT_RUST_VERSION,
)
diff --git a/rust/private/providers.bzl b/rust/private/providers.bzl
index b471ac0..3f5d8fc 100644
--- a/rust/private/providers.bzl
+++ b/rust/private/providers.bzl
@@ -107,3 +107,15 @@
"output": "File with the clippy output.",
},
)
+
+TestCrateInfo = provider(
+ doc = "A wrapper around a CrateInfo. " +
+ "Certain rule types, like rust_static_library and rust_shared_library " +
+ "are not intended for consumption by other Rust targets, and should not " +
+ "provide a CrateInfo. However, one should still be able to write a rust_test " +
+ "for them. Thus, we create a CrateInfo, but do not advertise it as such, " +
+ "but rather through this provider, that rust_test understands.",
+ fields = {
+ "crate": "CrateInfo: The underlying CrateInfo of the dependency",
+ },
+)
diff --git a/rust/private/rust.bzl b/rust/private/rust.bzl
index 6a7f230..f3a874a 100644
--- a/rust/private/rust.bzl
+++ b/rust/private/rust.bzl
@@ -353,7 +353,7 @@
if ctx.attr.crate:
# Target is building the crate in `test` config
- crate = ctx.attr.crate[rust_common.crate_info]
+ crate = ctx.attr.crate[rust_common.crate_info] if rust_common.crate_info in ctx.attr.crate else ctx.attr.crate[rust_common.test_crate_info].crate
# Optionally join compile data
if crate.compile_data:
@@ -745,7 +745,6 @@
rust_static_library = rule(
implementation = _rust_static_library_impl,
- provides = _common_providers,
attrs = dict(_common_attrs.items()),
fragments = ["cpp"],
host_fragments = ["cpp"],
@@ -769,7 +768,6 @@
rust_shared_library = rule(
implementation = _rust_shared_library_impl,
- provides = _common_providers,
attrs = dict(_common_attrs.items()),
fragments = ["cpp"],
host_fragments = ["cpp"],
diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl
index 2055f25..b8428f2 100644
--- a/rust/private/rustc.bzl
+++ b/rust/private/rustc.bzl
@@ -986,8 +986,6 @@
out_binary = getattr(attr, "out_binary", False)
providers = [
- crate_info,
- dep_info,
DefaultInfo(
# nb. This field is required for cc_library to depend on our output.
files = depset(outputs),
@@ -995,6 +993,16 @@
executable = crate_info.output if crate_info.type == "bin" or crate_info.is_test or out_binary else None,
),
]
+
+ if crate_info.type in ["staticlib", "cdylib"]:
+ # These rules are not supposed to be depended on by other rust targets, and
+ # as such they shouldn't provide a CrateInfo. However, one may still want to
+ # write a rust_test for them, so we provide the CrateInfo wrapped in a provider
+ # that rust_test understands.
+ providers.extend([rust_common.test_crate_info(crate = crate_info), dep_info])
+ else:
+ providers.extend([crate_info, dep_info])
+
if toolchain.target_arch != "wasm32":
providers += establish_cc_info(ctx, attr, crate_info, toolchain, cc_toolchain, feature_configuration, interface_library)
if pdb_file:
diff --git a/test/unit/crate_info/BUILD.bazel b/test/unit/crate_info/BUILD.bazel
new file mode 100644
index 0000000..98a3ef0
--- /dev/null
+++ b/test/unit/crate_info/BUILD.bazel
@@ -0,0 +1,4 @@
+load(":crate_info_test.bzl", "crate_info_test_suite")
+
+############################ UNIT TESTS #############################
+crate_info_test_suite(name = "crate_info_test_suite")
diff --git a/test/unit/crate_info/crate_info_test.bzl b/test/unit/crate_info/crate_info_test.bzl
new file mode 100644
index 0000000..0f6dfd0
--- /dev/null
+++ b/test/unit/crate_info/crate_info_test.bzl
@@ -0,0 +1,102 @@
+"""Unittests for rust rules."""
+
+load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
+load(
+ "//rust:defs.bzl",
+ "rust_common",
+ "rust_library",
+ "rust_proc_macro",
+ "rust_shared_library",
+ "rust_static_library",
+)
+
+def _rule_provides_crate_info_test_impl(ctx):
+ env = analysistest.begin(ctx)
+ tut = analysistest.target_under_test(env)
+ asserts.true(
+ env,
+ rust_common.crate_info in tut,
+ "{} should provide CrateInfo".format(tut.label.name),
+ )
+ return analysistest.end(env)
+
+def _rule_does_not_provide_crate_info_test_impl(ctx):
+ env = analysistest.begin(ctx)
+ tut = analysistest.target_under_test(env)
+ asserts.false(
+ env,
+ rust_common.crate_info in tut,
+ "{} should not provide CrateInfo".format(tut.label.name),
+ )
+ asserts.true(
+ env,
+ rust_common.test_crate_info in tut,
+ "{} should provide a TestCrateInfo".format(tut.label.name),
+ )
+ return analysistest.end(env)
+
+rule_provides_crate_info_test = analysistest.make(_rule_provides_crate_info_test_impl)
+rule_does_not_provide_crate_info_test = analysistest.make(_rule_does_not_provide_crate_info_test_impl)
+
+def _crate_info_test():
+ rust_library(
+ name = "rlib",
+ srcs = ["lib.rs"],
+ edition = "2018",
+ )
+
+ rust_proc_macro(
+ name = "proc_macro",
+ srcs = ["lib.rs"],
+ edition = "2018",
+ )
+
+ rust_static_library(
+ name = "staticlib",
+ srcs = ["lib.rs"],
+ edition = "2018",
+ )
+
+ rust_shared_library(
+ name = "cdylib",
+ srcs = ["lib.rs"],
+ edition = "2018",
+ )
+
+ rule_provides_crate_info_test(
+ name = "rlib_provides_crate_info_test",
+ target_under_test = ":rlib",
+ )
+
+ rule_provides_crate_info_test(
+ name = "proc_macro_provides_crate_info_test",
+ target_under_test = ":proc_macro",
+ )
+
+ rule_does_not_provide_crate_info_test(
+ name = "cdylib_does_not_provide_crate_info_test",
+ target_under_test = ":cdylib",
+ )
+
+ rule_does_not_provide_crate_info_test(
+ name = "staticlib_does_not_provide_crate_info_test",
+ target_under_test = ":staticlib",
+ )
+
+def crate_info_test_suite(name):
+ """Entry-point macro called from the BUILD file.
+
+ Args:
+ name: Name of the macro.
+ """
+ _crate_info_test()
+
+ native.test_suite(
+ name = name,
+ tests = [
+ ":rlib_provides_crate_info_test",
+ ":proc_macro_provides_crate_info_test",
+ ":cdylib_does_not_provide_crate_info_test",
+ ":staticlib_does_not_provide_crate_info_test",
+ ],
+ )
diff --git a/test/unit/crate_info/lib.rs b/test/unit/crate_info/lib.rs
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/test/unit/crate_info/lib.rs
@@ -0,0 +1 @@
+