"""Unittests for rust linkstamp support.""" load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") load("@rules_cc//cc:defs.bzl", "cc_library") load("//rust:defs.bzl", "rust_binary", "rust_common", "rust_library", "rust_test") load("//test/unit:common.bzl", "assert_action_mnemonic") def _is_running_on_linux(ctx): return ctx.target_platform_has_constraint(ctx.attr._linux[platform_common.ConstraintValueInfo]) def _supports_linkstamps_test(ctx): env = analysistest.begin(ctx) tut = analysistest.target_under_test(env) if not _is_running_on_linux(ctx): # Skipping linkstamps tests on an unsupported (non-Linux) platform return analysistest.end(env) linkstamp_action = tut.actions[0] assert_action_mnemonic(env, linkstamp_action, "CppLinkstampCompile") linkstamp_out = linkstamp_action.outputs.to_list()[0] asserts.equals(env, linkstamp_out.basename, "linkstamp.o") tut_out = tut.files.to_list()[0] is_test = tut[rust_common.crate_info].is_test workspace_prefix = "" if ctx.workspace_name == "rules_rust" else "/external/rules_rust" # Rust compilation outputs coming from a test are put in test-{hash} directory # which we need to remove in order to obtain the linkstamp file path. dirname = "/".join(tut_out.dirname.split("/")[:-1]) if is_test else tut_out.dirname expected_linkstamp_path = dirname + "/_objs/" + tut_out.basename + workspace_prefix + "/test/unit/linkstamps/linkstamp.o" asserts.equals( env, linkstamp_out.path, expected_linkstamp_path, "Expected linkstamp output '{actual_path}' to match '{expected_path}'".format( actual_path = linkstamp_out.path, expected_path = expected_linkstamp_path, ), ) rustc_action = tut.actions[1] assert_action_mnemonic(env, rustc_action, "Rustc") rustc_inputs = rustc_action.inputs.to_list() asserts.true( env, linkstamp_out in rustc_inputs, "Expected linkstamp output '{output}' to be among the binary inputs '{inputs}'".format( output = linkstamp_out, inputs = rustc_inputs, ), ) return analysistest.end(env) supports_linkstamps_test = analysistest.make( _supports_linkstamps_test, attrs = { "_linux": attr.label(default = Label("@platforms//os:linux")), }, ) def _linkstamps_test(): # Native linkstamps are only supported by the builtin Linux C++ toolchain. Ideally, # we would be able to inspect the feature_configuration of the target to see if # it has the "linkstamp" feature, but there is no way to get that feature # configuration. cc_library( name = "cc_lib_with_linkstamp", linkstamp = select({ "//rust/platform:linux": "linkstamp.cc", "//conditions:default": None, }), ) rust_binary( name = "some_rust_binary", srcs = ["foo.rs"], edition = "2018", deps = [":cc_lib_with_linkstamp"], ) supports_linkstamps_test( name = "rust_binary_supports_linkstamps_test", target_under_test = ":some_rust_binary", ) rust_library( name = "some_rust_library_with_linkstamp_transitively", srcs = ["foo.rs"], edition = "2018", deps = [":cc_lib_with_linkstamp"], ) rust_binary( name = "some_rust_binary_with_linkstamp_transitively", srcs = ["foo.rs"], edition = "2018", deps = [":some_rust_library_with_linkstamp_transitively"], ) supports_linkstamps_test( name = "rust_binary_with_linkstamp_transitively", target_under_test = ":some_rust_binary_with_linkstamp_transitively", ) cc_library( name = "cc_lib_with_linkstamp_transitively", deps = [":cc_lib_with_linkstamp"], ) rust_binary( name = "some_rust_binary_with_multiple_paths_to_a_linkstamp", srcs = ["foo.rs"], edition = "2018", deps = [":cc_lib_with_linkstamp", ":cc_lib_with_linkstamp_transitively"], ) supports_linkstamps_test( name = "rust_binary_supports_duplicated_linkstamps", target_under_test = ":some_rust_binary_with_multiple_paths_to_a_linkstamp", ) rust_test( name = "some_rust_test1", srcs = ["foo.rs"], edition = "2018", deps = [":cc_lib_with_linkstamp"], ) supports_linkstamps_test( name = "rust_test_supports_linkstamps_test1", target_under_test = ":some_rust_test1", ) rust_test( name = "some_rust_test2", srcs = ["foo.rs"], edition = "2018", deps = [":cc_lib_with_linkstamp"], ) supports_linkstamps_test( name = "rust_test_supports_linkstamps_test2", target_under_test = ":some_rust_test2", ) def linkstamps_test_suite(name): """Entry-point macro called from the BUILD file. Args: name: Name of the macro. """ # Older versions of Bazel do not support Starlark linkstamps. if not hasattr(cc_common, "register_linkstamp_compile_action"): # buildifier: disable=print print("Skipping linkstamps tests since this Bazel version does not support Starlark linkstamps.") return _linkstamps_test() native.test_suite( name = name, tests = [ ":rust_binary_supports_linkstamps_test", ":rust_binary_supports_duplicated_linkstamps", ":rust_test_supports_linkstamps_test1", ":rust_test_supports_linkstamps_test2", ], )