diff --git a/rs/toolchains/BUILD.bazel b/rs/toolchains/BUILD.bazel index e6bf17e..98877aa 100644 --- a/rs/toolchains/BUILD.bazel +++ b/rs/toolchains/BUILD.bazel @@ -44,6 +44,7 @@ bzl_library( ":toolchain_utils", "//rs/platforms:triples", "//rs/private:bpf_linker_repository", + "@bazel_skylib//lib:versions", "@default_rust_toolchains//rustc:component_labels.bzl", "@rules_rust//rust:bzl_lib", "@rules_rust//rust/platform:bzl_lib", diff --git a/rs/toolchains/declare_rustc_toolchains.bzl b/rs/toolchains/declare_rustc_toolchains.bzl index 264a232..41ef6aa 100644 --- a/rs/toolchains/declare_rustc_toolchains.bzl +++ b/rs/toolchains/declare_rustc_toolchains.bzl @@ -1,5 +1,6 @@ """Definitions for declaring Rust compiler toolchains.""" +load("@bazel_skylib//lib:versions.bzl", "versions") load("@default_rust_toolchains//rustc:component_labels.bzl", "rust_toolchain_component_label") load("@rules_rust//rust:rust_toolchain.bzl", "rust_toolchain") load("@rules_rust//rust/platform:triple.bzl", _parse_triple = "triple") @@ -20,6 +21,23 @@ def _rustc_flags_to_select(rustc_flags_by_triple): {"//conditions:default": []}, ) +def _default_rustc_flags(version): + # Rust >= 1.90 defaults to self-contained LLD for x86_64-unknown-linux-gnu. + # When linking via Bazel C++ toolchain wrappers (e.g. cc_wrapper.sh), rustc + # fails to recognize the wrapper as a C compiler driver and attempts to invoke + # its bundled gcc-ld/rust-lld, failing in hermetic/sandboxed environments where + # the undeclared linker is not in the sandbox, or overriding the C++ toolchain's + # configured linker. Disabling the LLD linker feature leaves linking entirely to + # the Bazel C++ toolchain. + # Prior to 1.90, rustc did not default to LLD and the -Clinker-features option did not exist. + if _channel(version) == "stable" and not versions.is_at_least("1.90.0", version): + return [] + + return select({ + "@rules_rs//rs/platforms/config:x86_64-unknown-linux-gnu": ["-Clinker-features=-lld"], + "//conditions:default": [], + }) + def _component(component, triple, default): component = component.get(triple) if type(component) == "dict" else component return component or rust_toolchain_component_label(default) @@ -193,8 +211,8 @@ def declare_rustc_toolchains( "//conditions:default": [], }), default_edition = edition, - extra_exec_rustc_flags = _rustc_flags_to_select(extra_exec_rustc_flags), - extra_rustc_flags = _rustc_flags_to_select(extra_rustc_flags), + extra_exec_rustc_flags = _default_rustc_flags(version) + _rustc_flags_to_select(extra_exec_rustc_flags), + extra_rustc_flags = _default_rustc_flags(version) + _rustc_flags_to_select(extra_rustc_flags), exec_triple = triple, target_triple = select(target_triple_select), visibility = ["//visibility:public"], diff --git a/test/BUILD.bazel b/test/BUILD.bazel index cd4d852..d095f64 100644 --- a/test/BUILD.bazel +++ b/test/BUILD.bazel @@ -14,6 +14,7 @@ load("@workspace_default_features//:data.bzl", workspace_default_features_dep_da load("@workspace_hyphen_dep_aliases//:defs.bzl", workspace_hyphen_dep_aliases_aliases = "aliases") load("@workspace_renamed_path_dep_aliases//:defs.bzl", workspace_renamed_path_dep_aliases_aliases = "aliases") load("//:rustdoc_musl_unwind_test.bzl", "rustdoc_musl_unwind_link_flags_test") +load("//:self_contained_linker_test.bzl", "self_contained_linker_aarch64_test", "self_contained_linker_x86_64_test") load("//:target_triple_constraints_test.bzl", "target_triple_constraints_test") load("//:verify_aliases.bzl", "verify_alias", "verify_alias_absent", "verify_crate_feature_absent", "verify_crate_feature_present", "verify_dep_absent", "verify_dep_present", "verify_dev_dep_absent") load("//:workspace_lints_test.bzl", "inherited_workspace_lints_test", "opted_out_workspace_lints_test", "package_lints_test") @@ -36,6 +37,23 @@ sh_test( }), ) +rust_binary( + name = "self_contained_linker_sample_bin", + srcs = ["main.rs"], + edition = "2021", + tags = ["manual"], +) + +self_contained_linker_x86_64_test( + name = "self_contained_linker_x86_64_test", + target_under_test = ":self_contained_linker_sample_bin", +) + +self_contained_linker_aarch64_test( + name = "self_contained_linker_aarch64_test", + target_under_test = ":self_contained_linker_sample_bin", +) + cc_library( name = "rustdoc_musl_unwind_cc", srcs = ["rustdoc_musl_unwind.cc"], diff --git a/test/self_contained_linker_test.bzl b/test/self_contained_linker_test.bzl new file mode 100644 index 0000000..2cc5f4e --- /dev/null +++ b/test/self_contained_linker_test.bzl @@ -0,0 +1,51 @@ +"""Analysis test verifying that Linux x86_64 targets disable self-contained LLD via -Clinker-features=-lld.""" + +load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") + +def _get_action_by_mnemonic(env, tut, mnemonic): + actions = [action for action in tut.actions if action.mnemonic == mnemonic] + asserts.equals( + env, + 1, + len(actions), + "Expected exactly one {} action, got {}".format(mnemonic, [action.mnemonic for action in tut.actions]), + ) + return actions[0] + +def _self_contained_linker_x86_64_test_impl(ctx): + env = analysistest.begin(ctx) + tut = analysistest.target_under_test(env) + action = _get_action_by_mnemonic(env, tut, "Rustc") + + asserts.true( + env, + "-Clinker-features=-lld" in action.argv, + "Expected '-Clinker-features=-lld' in Rustc action argv for x86_64-unknown-linux-gnu, but it was missing: {}".format(action.argv), + ) + return analysistest.end(env) + +def _self_contained_linker_aarch64_test_impl(ctx): + env = analysistest.begin(ctx) + tut = analysistest.target_under_test(env) + action = _get_action_by_mnemonic(env, tut, "Rustc") + + asserts.false( + env, + "-Clinker-features=-lld" in action.argv, + "Did not expect '-Clinker-features=-lld' in Rustc action argv for aarch64-unknown-linux-gnu: {}".format(action.argv), + ) + return analysistest.end(env) + +self_contained_linker_x86_64_test = analysistest.make( + _self_contained_linker_x86_64_test_impl, + config_settings = { + "//command_line_option:platforms": str(Label("@rules_rs//rs/platforms:x86_64-unknown-linux-gnu")), + }, +) + +self_contained_linker_aarch64_test = analysistest.make( + _self_contained_linker_aarch64_test_impl, + config_settings = { + "//command_line_option:platforms": str(Label("@rules_rs//rs/platforms:aarch64-unknown-linux-gnu")), + }, +)