diff --git a/proto/proto.bzl b/proto/proto.bzl index 45207cb7ea..30952f90ff 100644 --- a/proto/proto.bzl +++ b/proto/proto.bzl @@ -234,6 +234,7 @@ def _rust_proto_compile(protos, descriptor_sets, imports, crate_name, ctx, is_gr edition = proto_toolchain.edition, rustc_env = {}, is_test = False, + compile_data = depset([target.files for target in getattr(ctx.attr, "compile_data", [])]), wrapped_crate_type = None, ), output_hash = output_hash, diff --git a/rust/private/providers.bzl b/rust/private/providers.bzl index a05f3d2fc3..adb209ef10 100644 --- a/rust/private/providers.bzl +++ b/rust/private/providers.bzl @@ -18,6 +18,7 @@ CrateInfo = provider( doc = "A provider containing general Crate information.", fields = { "aliases": "Dict[Label, String]: Renamed and aliased crates", + "compile_data": "depset[File]: Compile data required by this crate.", "deps": "depset[Provider]: This crate's (rust or cc) dependencies' providers.", "edition": "str: The edition of this crate.", "is_test": "bool: If the crate is being compiled in a test context", @@ -39,7 +40,7 @@ DepInfo = provider( doc = "A provider containing information about a Crate's dependencies.", fields = { "dep_env": "File: File with environment variables direct dependencies build scripts rely upon.", - "direct_crates": "depset[CrateInfo]", + "direct_crates": "depset[AliasableDepInfo]", "transitive_build_infos": "depset[BuildInfo]", "transitive_crates": "depset[CrateInfo]", "transitive_libs": "List[File]: All transitive dependencies, not filtered by type.", diff --git a/rust/private/rust.bzl b/rust/private/rust.bzl index 32fcfdfc55..f59a0945d4 100644 --- a/rust/private/rust.bzl +++ b/rust/private/rust.bzl @@ -266,6 +266,7 @@ def _rust_library_common(ctx, crate_type): edition = get_edition(ctx.attr, toolchain), rustc_env = ctx.attr.rustc_env, is_test = False, + compile_data = depset(ctx.files.compile_data), ), output_hash = output_hash, ) @@ -301,6 +302,7 @@ def _rust_binary_impl(ctx): edition = get_edition(ctx.attr, toolchain), rustc_env = ctx.attr.rustc_env, is_test = False, + compile_data = depset(ctx.files.compile_data), ), ) @@ -404,8 +406,15 @@ def _rust_test_common(ctx, toolchain, output): crate_type = "bin" if ctx.attr.crate: # Target is building the crate in `test` config - # Build the test binary using the dependency's srcs. crate = ctx.attr.crate[rust_common.crate_info] + + # Optionally join compile data + if crate.compile_data: + compile_data = depset(ctx.files.compile_data, transitive = [crate.compile_data]) + else: + compile_data = depset(ctx.files.compile_data) + + # Build the test binary using the dependency's srcs. crate_info = rust_common.create_crate_info( name = crate_name, type = crate_type, @@ -418,6 +427,7 @@ def _rust_test_common(ctx, toolchain, output): edition = crate.edition, rustc_env = ctx.attr.rustc_env, is_test = True, + compile_data = compile_data, wrapped_crate_type = crate.type, ) else: @@ -434,6 +444,7 @@ def _rust_test_common(ctx, toolchain, output): edition = get_edition(ctx.attr, toolchain), rustc_env = ctx.attr.rustc_env, is_test = True, + compile_data = depset(ctx.files.compile_data), ) providers = rustc_compile_action( diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl index abbd20f7ad..bed2c1b291 100644 --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl @@ -268,7 +268,7 @@ def collect_inputs( Args: ctx (ctx): The rule's context object. file (struct): A struct containing files defined in label type attributes marked as `allow_single_file`. - files (list): A list of all inputs. + files (list): A list of all inputs (`ctx.files`). toolchain (rust_toolchain): The current `rust_toolchain`. cc_toolchain (CcToolchainInfo): The current `cc_toolchain`. crate_info (CrateInfo): The Crate information of the crate to process build scripts for. @@ -284,7 +284,6 @@ def collect_inputs( compile_inputs = depset( getattr(files, "data", []) + - getattr(files, "compile_data", []) + [toolchain.rustc] + toolchain.crosstool_files + ([build_info.rustc_env, build_info.flags] if build_info else []) + @@ -295,6 +294,7 @@ def collect_inputs( linker_depset, crate_info.srcs, dep_info.transitive_libs, + crate_info.compile_data, ], ) build_env_files = getattr(files, "rustc_env_files", []) diff --git a/test/unit/compile_data/BUILD.bazel b/test/unit/compile_data/BUILD.bazel new file mode 100644 index 0000000000..8fce69a694 --- /dev/null +++ b/test/unit/compile_data/BUILD.bazel @@ -0,0 +1,5 @@ +load(":compile_data_test.bzl", "compile_data_test_suite") + +compile_data_test_suite( + name = "compile_data_test_suite", +) diff --git a/test/unit/compile_data/compile_data.rs b/test/unit/compile_data/compile_data.rs new file mode 100644 index 0000000000..ad3eb920a9 --- /dev/null +++ b/test/unit/compile_data/compile_data.rs @@ -0,0 +1,26 @@ +/// Data loaded from compile data +pub const COMPILE_DATA: &str = include_str!("compile_data.txt"); + +#[cfg(test)] +mod test { + use super::*; + + /// A test that is expected to be compiled from a target that does not + /// directly populate the `compile_data` attribute + #[test] + fn test_compile_data_contents() { + assert_eq!(COMPILE_DATA, "compile data contents\n"); + } + + /// An extra module that tests the `rust_test` rule wrapping the + /// `rust_library` is able to provide it's own compile data. + #[cfg(test_compile_data)] + mod test_compile_data { + const TEST_COMPILE_DATA: &str = include_str!("test_compile_data.txt"); + + #[test] + fn test_compile_data_contents() { + assert_eq!(TEST_COMPILE_DATA, "test compile data contents\n"); + } + } +} diff --git a/test/unit/compile_data/compile_data.txt b/test/unit/compile_data/compile_data.txt new file mode 100644 index 0000000000..6d8daa7138 --- /dev/null +++ b/test/unit/compile_data/compile_data.txt @@ -0,0 +1 @@ +compile data contents diff --git a/test/unit/compile_data/compile_data_test.bzl b/test/unit/compile_data/compile_data_test.bzl new file mode 100644 index 0000000000..43782cd8a4 --- /dev/null +++ b/test/unit/compile_data/compile_data_test.bzl @@ -0,0 +1,99 @@ +"""Unittest to verify compile_data (attribute) propagation""" + +load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") +load("//rust:defs.bzl", "rust_common", "rust_library", "rust_test") + +def _target_has_compile_data(ctx, expected): + env = analysistest.begin(ctx) + target = analysistest.target_under_test(env) + + # Extract compile_data from a target expected to have a `CrateInfo` provider + crate_info = target[rust_common.crate_info] + compile_data = crate_info.compile_data.to_list() + + # Ensure compile data was correctly propagated to the provider + asserts.equals( + env, + sorted([data.short_path for data in compile_data]), + expected, + ) + + return analysistest.end(env) + +def _compile_data_propagates_to_crate_info_test_impl(ctx): + return _target_has_compile_data( + ctx, + ["test/unit/compile_data/compile_data.txt"], + ) + +def _wrapper_rule_propagates_to_crate_info_test_impl(ctx): + return _target_has_compile_data( + ctx, + ["test/unit/compile_data/compile_data.txt"], + ) + +def _wrapper_rule_propagates_and_joins_compile_data_test_impl(ctx): + return _target_has_compile_data( + ctx, + [ + "test/unit/compile_data/compile_data.txt", + "test/unit/compile_data/test_compile_data.txt", + ], + ) + +compile_data_propagates_to_crate_info_test = analysistest.make(_compile_data_propagates_to_crate_info_test_impl) +wrapper_rule_propagates_to_crate_info_test = analysistest.make(_wrapper_rule_propagates_to_crate_info_test_impl) +wrapper_rule_propagates_and_joins_compile_data_test = analysistest.make(_wrapper_rule_propagates_and_joins_compile_data_test_impl) + +def _define_test_targets(): + rust_library( + name = "compile_data", + srcs = ["compile_data.rs"], + compile_data = ["compile_data.txt"], + edition = "2018", + ) + + rust_test( + name = "compile_data_unit_test", + crate = ":compile_data", + ) + + rust_test( + name = "test_compile_data_unit_test", + compile_data = ["test_compile_data.txt"], + crate = ":compile_data", + rustc_flags = ["--cfg=test_compile_data"], + ) + +def compile_data_test_suite(name): + """Entry-point macro called from the BUILD file. + + Args: + name (str): Name of the macro. + """ + + _define_test_targets() + + compile_data_propagates_to_crate_info_test( + name = "compile_data_propagates_to_crate_info_test", + target_under_test = ":compile_data", + ) + + wrapper_rule_propagates_to_crate_info_test( + name = "wrapper_rule_propagates_to_crate_info_test", + target_under_test = ":compile_data_unit_test", + ) + + wrapper_rule_propagates_and_joins_compile_data_test( + name = "wrapper_rule_propagates_and_joins_compile_data_test", + target_under_test = ":test_compile_data_unit_test", + ) + + native.test_suite( + name = name, + tests = [ + ":compile_data_propagates_to_crate_info_test", + ":wrapper_rule_propagates_to_crate_info_test", + ":wrapper_rule_propagates_and_joins_compile_data_test", + ], + ) diff --git a/test/unit/compile_data/test_compile_data.txt b/test/unit/compile_data/test_compile_data.txt new file mode 100644 index 0000000000..31ce1d31a2 --- /dev/null +++ b/test/unit/compile_data/test_compile_data.txt @@ -0,0 +1 @@ +test compile data contents