Remove uses of `DepInfo.transitive_libs` (#1054)
This is a step further towards https://github.com/bazelbuild/rules_rust/issues/1051.
With this change, `rules_rust` doesn't need `DepInfo.transitive_libs` anymore. The only place where this field was used was to pass the files it contains as inputs to rust compile actions. We use `DepInfo.transitive_crate_outputs` for that now. For non-rlib compile actions, which need non-crate inputs as well, we add those inputs to the `additional_transitive_inputs` variable.
diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl
index 0c141a3..89aa097 100644
--- a/rust/private/rustc.bzl
+++ b/rust/private/rustc.bzl
@@ -179,11 +179,9 @@
transitive_build_infos.append(dep_info.transitive_build_infos)
elif cc_info:
# This dependency is a cc_library
-
- # TODO: We could let the user choose how to link, instead of always preferring to link static libraries.
- linker_inputs = cc_info.linking_context.linker_inputs.to_list()
- libs = [get_preferred_artifact(lib) for li in linker_inputs for lib in li.libraries]
- transitive_noncrate_libs.append(depset(libs))
+ transitive_noncrate_libs.append(depset(
+ _collect_libs_from_linker_inputs(cc_info.linking_context.linker_inputs.to_list()),
+ ))
transitive_noncrates.append(cc_info.linking_context.linker_inputs)
elif dep_build_info:
if build_info:
@@ -218,6 +216,14 @@
depset(transitive = linkstamps),
)
+def _collect_libs_from_linker_inputs(linker_inputs):
+ # TODO: We could let the user choose how to link, instead of always preferring to link static libraries.
+ return [
+ get_preferred_artifact(lib)
+ for li in linker_inputs
+ for lib in li.libraries
+ ]
+
def _get_crate_and_dep_info(dep):
if type(dep) == "Target" and rust_common.crate_info in dep:
return (dep[rust_common.crate_info], dep[rust_common.dep_info])
@@ -369,15 +375,19 @@
linker_depset = cc_toolchain.all_files
- # Pass linker additional inputs (e.g., linker scripts) only for linking-like
- # actions, not for example where the output is rlib. This avoids quadratic
- # behavior where transitive noncrates are flattened on each transitive
- # rust_library dependency.
+ # Pass linker inputs only for linking-like actions, not for example where
+ # the output is rlib. This avoids quadratic behavior where transitive noncrates are
+ # flattened on each transitive rust_library dependency.
additional_transitive_inputs = []
- if crate_info.type in ("bin", "dylib", "cdylib"):
- additional_transitive_inputs = [
+ if crate_info.type in ("staticlib", "proc-macro"):
+ additional_transitive_inputs = _collect_libs_from_linker_inputs(
+ dep_info.transitive_noncrates.to_list(),
+ )
+ elif crate_info.type in ("bin", "dylib", "cdylib"):
+ linker_inputs = dep_info.transitive_noncrates.to_list()
+ additional_transitive_inputs = _collect_libs_from_linker_inputs(linker_inputs) + [
additional_input
- for linker_input in dep_info.transitive_noncrates.to_list()
+ for linker_input in linker_inputs
for additional_input in linker_input.additional_inputs
]
@@ -398,7 +408,7 @@
toolchain.rust_lib.files,
linker_depset,
crate_info.srcs,
- dep_info.transitive_libs,
+ dep_info.transitive_crate_outputs,
depset(additional_transitive_inputs),
crate_info.compile_data,
],
diff --git a/test/unit/native_deps/BUILD.bazel b/test/unit/native_deps/BUILD.bazel
index 7864dfb..cfb6557 100644
--- a/test/unit/native_deps/BUILD.bazel
+++ b/test/unit/native_deps/BUILD.bazel
@@ -1,4 +1,7 @@
+load(":native_action_inputs_test.bzl", "native_action_inputs_test_suite")
load(":native_deps_test.bzl", "native_deps_test_suite")
############################ UNIT TESTS #############################
native_deps_test_suite(name = "native_deps_test_suite")
+
+native_action_inputs_test_suite(name = "native_action_inputs_test_suite")
diff --git a/test/unit/native_deps/bar.cc b/test/unit/native_deps/bar.cc
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/test/unit/native_deps/bar.cc
@@ -0,0 +1 @@
+
diff --git a/test/unit/native_deps/foo.rs b/test/unit/native_deps/foo.rs
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/test/unit/native_deps/foo.rs
@@ -0,0 +1 @@
+
diff --git a/test/unit/native_deps/foo_main.rs b/test/unit/native_deps/foo_main.rs
new file mode 100644
index 0000000..f328e4d
--- /dev/null
+++ b/test/unit/native_deps/foo_main.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/test/unit/native_deps/native_action_inputs_test.bzl b/test/unit/native_deps/native_action_inputs_test.bzl
new file mode 100644
index 0000000..2363e1e
--- /dev/null
+++ b/test/unit/native_deps/native_action_inputs_test.bzl
@@ -0,0 +1,155 @@
+"""Unittests for rust rules."""
+
+load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
+load(
+ "//rust:defs.bzl",
+ "rust_binary",
+ "rust_library",
+ "rust_proc_macro",
+ "rust_shared_library",
+ "rust_static_library",
+)
+load("//test/unit:common.bzl", "assert_action_mnemonic")
+
+def _native_action_inputs_present_test_impl(ctx):
+ env = analysistest.begin(ctx)
+ tut = analysistest.target_under_test(env)
+ action = tut.actions[0]
+ assert_action_mnemonic(env, action, "Rustc")
+ inputs = action.inputs.to_list()
+ lib_name = _native_dep_lib_name(ctx)
+
+ asserts.true(
+ env,
+ _has_action_input(lib_name, inputs),
+ "Expected to contain {lib_name} as action input, got {inputs}".format(
+ lib_name = lib_name,
+ inputs = inputs,
+ ),
+ )
+
+ return analysistest.end(env)
+
+def _native_action_inputs_not_present_test_impl(ctx):
+ env = analysistest.begin(ctx)
+ tut = analysistest.target_under_test(env)
+ action = tut.actions[0]
+ assert_action_mnemonic(env, action, "Rustc")
+ inputs = action.inputs.to_list()
+ lib_name = _native_dep_lib_name(ctx)
+
+ asserts.false(
+ env,
+ _has_action_input(lib_name, inputs),
+ "Expected not to contain {lib_name}".format(lib_name = lib_name),
+ )
+
+ return analysistest.end(env)
+
+def _native_dep_lib_name(ctx):
+ if ctx.target_platform_has_constraint(
+ ctx.attr._windows_constraint[platform_common.ConstraintValueInfo],
+ ):
+ return "bar.lib"
+ else:
+ return "libbar.a"
+
+def _has_action_input(name, inputs):
+ for file in inputs:
+ if file.basename == name:
+ return True
+ return False
+
+native_action_inputs_present_test = analysistest.make(
+ _native_action_inputs_present_test_impl,
+ attrs = {
+ "_windows_constraint": attr.label(default = Label("@platforms//os:windows")),
+ },
+)
+native_action_inputs_not_present_test = analysistest.make(
+ _native_action_inputs_not_present_test_impl,
+ attrs = {
+ "_windows_constraint": attr.label(default = Label("@platforms//os:windows")),
+ },
+)
+
+def _native_action_inputs_test():
+ rust_library(
+ name = "foo_lib",
+ srcs = ["foo.rs"],
+ deps = [":bar"],
+ )
+
+ rust_binary(
+ name = "foo_bin",
+ srcs = ["foo_main.rs"],
+ deps = [":bar"],
+ )
+
+ rust_shared_library(
+ name = "foo_dylib",
+ srcs = ["foo.rs"],
+ deps = [":bar"],
+ )
+
+ rust_static_library(
+ name = "foo_static",
+ srcs = ["foo.rs"],
+ deps = [":bar"],
+ )
+
+ rust_proc_macro(
+ name = "foo_proc_macro",
+ srcs = ["foo.rs"],
+ deps = [":bar"],
+ )
+
+ # buildifier: disable=native-cc
+ native.cc_library(
+ name = "bar",
+ srcs = ["bar.cc"],
+ )
+
+ native_action_inputs_not_present_test(
+ name = "native_action_inputs_lib_test",
+ target_under_test = ":foo_lib",
+ )
+
+ native_action_inputs_present_test(
+ name = "native_action_inputs_bin_test",
+ target_under_test = ":foo_bin",
+ )
+
+ native_action_inputs_present_test(
+ name = "native_action_inputs_dylib_test",
+ target_under_test = ":foo_dylib",
+ )
+
+ native_action_inputs_present_test(
+ name = "native_action_inputs_static_test",
+ target_under_test = ":foo_static",
+ )
+
+ native_action_inputs_present_test(
+ name = "native_action_inputs_proc_macro_test",
+ target_under_test = ":foo_proc_macro",
+ )
+
+def native_action_inputs_test_suite(name):
+ """Entry-point macro called from the BUILD file.
+
+ Args:
+ name: Name of the macro.
+ """
+ _native_action_inputs_test()
+
+ native.test_suite(
+ name = name,
+ tests = [
+ ":native_action_inputs_lib_test",
+ ":native_action_inputs_bin_test",
+ ":native_action_inputs_dylib_test",
+ ":native_action_inputs_static_test",
+ ":native_action_inputs_proc_macro_test",
+ ],
+ )