From b25b50834858efdec4a9752ab2edd57e2d38819d Mon Sep 17 00:00:00 2001 From: scentini Date: Fri, 29 Oct 2021 17:08:38 +0200 Subject: [PATCH] Obtain the "CARGO_CRATE_NAME" value from the CrateInfo (#999) At this point we have a `CrateInfo` for the target which contains the name of the crate, regardless whether it's been derived from the `ctx.attr.crate_name` or explicitly assigned. The code without this PR works well for the `rules_rust`, because the `CrateInfo.crate_name` is obtained by calling the `get_crate_name_from_attr` function. However, this is not sufficient for aspects, as they may be attached to a target that doesn't specify crate name, or one may want to assign a modified name to crates created by aspects. --- rust/private/rustc.bzl | 8 +- test/unit/common.bzl | 11 +++ test/unit/consistent_crate_name/BUILD.bazel | 4 + .../consistent_crate_name_test.bzl | 46 ++++++++++++ test/unit/consistent_crate_name/lib.rs | 1 + .../with_modified_crate_name.bzl | 75 +++++++++++++++++++ 6 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 test/unit/consistent_crate_name/BUILD.bazel create mode 100644 test/unit/consistent_crate_name/consistent_crate_name_test.bzl create mode 100644 test/unit/consistent_crate_name/lib.rs create mode 100644 test/unit/consistent_crate_name/with_modified_crate_name.bzl diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl index 617c0227a6..84ccc60994 100644 --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl @@ -22,7 +22,6 @@ load("//rust/private:common.bzl", "rust_common") load("//rust/private:providers.bzl", _BuildInfo = "BuildInfo") load( "//rust/private:utils.bzl", - "crate_name_from_attr", "expand_dict_value_locations", "expand_list_element_locations", "find_cc_toolchain", @@ -55,12 +54,13 @@ ExtraRustcFlagsInfo = provider( fields = {"extra_rustc_flags": "List[string] Extra flags to pass to rustc"}, ) -def _get_rustc_env(attr, toolchain): +def _get_rustc_env(attr, toolchain, crate_name): """Gathers rustc environment variables Args: attr (struct): The current target's attributes toolchain (rust_toolchain): The current target's rust toolchain context + crate_name (str): The name of the crate to be compiled Returns: dict: Rustc environment variables @@ -74,7 +74,7 @@ def _get_rustc_env(attr, toolchain): return { "CARGO_CFG_TARGET_ARCH": toolchain.target_arch, "CARGO_CFG_TARGET_OS": toolchain.os, - "CARGO_CRATE_NAME": crate_name_from_attr(attr), + "CARGO_CRATE_NAME": crate_name, "CARGO_PKG_AUTHORS": "", "CARGO_PKG_DESCRIPTION": "", "CARGO_PKG_HOMEPAGE": "", @@ -487,7 +487,7 @@ def construct_arguments( linker_script = getattr(file, "linker_script") if hasattr(file, "linker_script") else None - env = _get_rustc_env(attr, toolchain) + env = _get_rustc_env(attr, toolchain, crate_info.name) # Wrapper args first process_wrapper_flags = ctx.actions.args() diff --git a/test/unit/common.bzl b/test/unit/common.bzl index 5e8c95ab7c..da07db6ce7 100644 --- a/test/unit/common.bzl +++ b/test/unit/common.bzl @@ -97,3 +97,14 @@ def assert_list_contains_adjacent_elements_not(env, list_under_test, adjacent_el actual = list_under_test, ), ) + +def assert_env_value(env, action, key, value): + asserts.true( + env, + action.env[key] == value, + "Expected env[{key}] to be equal to '{value}', got '{real_value}'".format( + key = key, + value = value, + real_value = action.env[key], + ), + ) diff --git a/test/unit/consistent_crate_name/BUILD.bazel b/test/unit/consistent_crate_name/BUILD.bazel new file mode 100644 index 0000000000..274e273aab --- /dev/null +++ b/test/unit/consistent_crate_name/BUILD.bazel @@ -0,0 +1,4 @@ +load(":consistent_crate_name_test.bzl", "consistent_crate_name_test_suite") + +############################ UNIT TESTS ############################# +consistent_crate_name_test_suite(name = "consistent_crate_name_test_suite") diff --git a/test/unit/consistent_crate_name/consistent_crate_name_test.bzl b/test/unit/consistent_crate_name/consistent_crate_name_test.bzl new file mode 100644 index 0000000000..1ea86ad019 --- /dev/null +++ b/test/unit/consistent_crate_name/consistent_crate_name_test.bzl @@ -0,0 +1,46 @@ +"""Unittest to verify that we can treat all dependencies as direct dependencies""" + +load("@bazel_skylib//lib:unittest.bzl", "analysistest") +load("//test/unit:common.bzl", "assert_action_mnemonic", "assert_env_value") +load("//test/unit/consistent_crate_name:with_modified_crate_name.bzl", "with_modified_crate_name") + +def _consistent_crate_name_env_test(ctx): + env = analysistest.begin(ctx) + tut = analysistest.target_under_test(env) + action = tut.actions[0] + assert_action_mnemonic(env, action, "Rustc") + assert_env_value( + env, + action, + "CARGO_CRATE_NAME", + "lib_my_custom_crate_suffix", + ) + return analysistest.end(env) + +consistent_crate_name_env_test = analysistest.make(_consistent_crate_name_env_test) + +def _consistent_crate_name_test(): + with_modified_crate_name( + name = "lib", + src = "lib.rs", + ) + + consistent_crate_name_env_test( + name = "consistent_crate_name_env_test", + target_under_test = ":lib", + ) + +def consistent_crate_name_test_suite(name): + """Entry-point macro called from the BUILD file. + + Args: + name: Name of the macro. + """ + _consistent_crate_name_test() + + native.test_suite( + name = name, + tests = [ + ":consistent_crate_name_env_test", + ], + ) diff --git a/test/unit/consistent_crate_name/lib.rs b/test/unit/consistent_crate_name/lib.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/test/unit/consistent_crate_name/lib.rs @@ -0,0 +1 @@ + diff --git a/test/unit/consistent_crate_name/with_modified_crate_name.bzl b/test/unit/consistent_crate_name/with_modified_crate_name.bzl new file mode 100644 index 0000000000..f30d8be8dc --- /dev/null +++ b/test/unit/consistent_crate_name/with_modified_crate_name.bzl @@ -0,0 +1,75 @@ +"""A custom rule that threats all its dependencies as direct dependencies.""" + +load("//rust:defs.bzl", "rust_common") + +# buildifier: disable=bzl-visibility +load("//rust/private:providers.bzl", "BuildInfo", "CrateInfo", "DepInfo", "DepVariantInfo") + +# buildifier: disable=bzl-visibility +load("//rust/private:rustc.bzl", "rustc_compile_action") + +def _with_modified_crate_name_impl(ctx): + toolchain = ctx.toolchains[Label("//rust:toolchain")] + + crate_root = ctx.attr.src.files.to_list()[0] + output_hash = repr(hash(crate_root.path)) + crate_name = ctx.label.name + "_my_custom_crate_suffix" + crate_type = "rlib" + + rust_lib_name = "{prefix}{name}-{lib_hash}{extension}".format( + prefix = "lib", + name = crate_name, + lib_hash = output_hash, + extension = ".rlib", + ) + + deps = [DepVariantInfo( + crate_info = dep[CrateInfo] if CrateInfo in dep else None, + dep_info = dep[DepInfo] if DepInfo in dep else None, + build_info = dep[BuildInfo] if BuildInfo in dep else None, + cc_info = dep[CcInfo] if CcInfo in dep else None, + ) for dep in ctx.attr.deps] + + rust_lib = ctx.actions.declare_file(rust_lib_name) + return rustc_compile_action( + ctx = ctx, + attr = ctx.attr, + toolchain = toolchain, + crate_info = rust_common.create_crate_info( + name = crate_name, + type = crate_type, + root = crate_root, + srcs = ctx.attr.src.files, + deps = depset(deps), + proc_macro_deps = depset([]), + aliases = {}, + output = rust_lib, + owner = ctx.label, + edition = "2018", + compile_data = depset([]), + rustc_env = {}, + is_test = False, + ), + output_hash = output_hash, + ) + +with_modified_crate_name = rule( + implementation = _with_modified_crate_name_impl, + attrs = { + "deps": attr.label_list(), + "src": attr.label(allow_single_file = [".rs"]), + "_cc_toolchain": attr.label( + default = "@bazel_tools//tools/cpp:current_cc_toolchain", + ), + "_error_format": attr.label(default = "@rules_rust//:error_format"), + "_process_wrapper": attr.label( + default = Label("@rules_rust//util/process_wrapper"), + executable = True, + allow_single_file = True, + cfg = "exec", + ), + }, + toolchains = ["@rules_rust//rust:toolchain", "@bazel_tools//tools/cpp:toolchain_type"], + incompatible_use_toolchain_transition = True, + fragments = ["cpp"], +)