From 20be516bcbb13d8bb49a109cfdb5c93beb655be3 Mon Sep 17 00:00:00 2001 From: Luca Della Vedova Date: Thu, 20 Aug 2026 11:50:06 +0800 Subject: [PATCH 1/8] Allow indirect linking for non wasm / RISC-V targets Signed-off-by: Luca Della Vedova --- rs/toolchains/declare_rustc_toolchains.bzl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/rs/toolchains/declare_rustc_toolchains.bzl b/rs/toolchains/declare_rustc_toolchains.bzl index 264a232..ae7223b 100644 --- a/rs/toolchains/declare_rustc_toolchains.bzl +++ b/rs/toolchains/declare_rustc_toolchains.bzl @@ -138,7 +138,13 @@ def declare_rustc_toolchains( "@platforms//cpu:wasm64": lld_label, "//conditions:default": None, }), - linker_type = "direct", + linker_type = select({ + "@rules_rs//rs/platforms/config:riscv32imac-unknown-none-elf": "direct", + "@rules_rs//rs/platforms/config:riscv32imc-unknown-none-elf": "direct", + "@platforms//cpu:wasm32": "direct", + "@platforms//cpu:wasm64": "direct", + "//conditions:default": "indirect", + }), rust_objcopy = _component(rust_objcopy, triple, rustc_repo_label + "rust-objcopy"), rustc_lib = _component(rustc_lib, triple, rustc_repo_label + "rustc_lib"), allocator_library = None, From fbfa8a55396e06a649e9fe23df33484e0a775fa5 Mon Sep 17 00:00:00 2001 From: Luca Della Vedova Date: Thu, 20 Aug 2026 15:21:22 +0800 Subject: [PATCH 2/8] TEST pass extra rust flags Signed-off-by: Luca Della Vedova --- rs/toolchains/declare_rustc_toolchains.bzl | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/rs/toolchains/declare_rustc_toolchains.bzl b/rs/toolchains/declare_rustc_toolchains.bzl index ae7223b..fb8af7e 100644 --- a/rs/toolchains/declare_rustc_toolchains.bzl +++ b/rs/toolchains/declare_rustc_toolchains.bzl @@ -199,8 +199,20 @@ 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 = select({ + "@rules_rs//rs/platforms/config:riscv32imac-unknown-none-elf": [], + "@rules_rs//rs/platforms/config:riscv32imc-unknown-none-elf": [], + "@platforms//cpu:wasm32": [], + "@platforms//cpu:wasm64": [], + "//conditions:default": ["-Clink-self-contained=no"], + }) + _rustc_flags_to_select(extra_exec_rustc_flags), + extra_rustc_flags = select({ + "@rules_rs//rs/platforms/config:riscv32imac-unknown-none-elf": [], + "@rules_rs//rs/platforms/config:riscv32imc-unknown-none-elf": [], + "@platforms//cpu:wasm32": [], + "@platforms//cpu:wasm64": [], + "//conditions:default": ["-Clink-self-contained=no"], + }) + _rustc_flags_to_select(extra_rustc_flags), exec_triple = triple, target_triple = select(target_triple_select), visibility = ["//visibility:public"], From 005f4492802f8ce2588a84b6b5ae141ee5797328 Mon Sep 17 00:00:00 2001 From: Luca Della Vedova Date: Thu, 20 Aug 2026 16:52:48 +0800 Subject: [PATCH 3/8] Only disable self contained linking in Linux x86 Signed-off-by: Luca Della Vedova --- rs/toolchains/declare_rustc_toolchains.bzl | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/rs/toolchains/declare_rustc_toolchains.bzl b/rs/toolchains/declare_rustc_toolchains.bzl index fb8af7e..53542e6 100644 --- a/rs/toolchains/declare_rustc_toolchains.bzl +++ b/rs/toolchains/declare_rustc_toolchains.bzl @@ -200,18 +200,12 @@ def declare_rustc_toolchains( }), default_edition = edition, extra_exec_rustc_flags = select({ - "@rules_rs//rs/platforms/config:riscv32imac-unknown-none-elf": [], - "@rules_rs//rs/platforms/config:riscv32imc-unknown-none-elf": [], - "@platforms//cpu:wasm32": [], - "@platforms//cpu:wasm64": [], - "//conditions:default": ["-Clink-self-contained=no"], + "@rules_rs//rs/platforms/config:x86_64-unknown-linux-gnu": ["-Clink-self-contained=no"], + "//conditions:default": [], }) + _rustc_flags_to_select(extra_exec_rustc_flags), extra_rustc_flags = select({ - "@rules_rs//rs/platforms/config:riscv32imac-unknown-none-elf": [], - "@rules_rs//rs/platforms/config:riscv32imc-unknown-none-elf": [], - "@platforms//cpu:wasm32": [], - "@platforms//cpu:wasm64": [], - "//conditions:default": ["-Clink-self-contained=no"], + "@rules_rs//rs/platforms/config:x86_64-unknown-linux-gnu": ["-Clink-self-contained=no"], + "//conditions:default": [], }) + _rustc_flags_to_select(extra_rustc_flags), exec_triple = triple, target_triple = select(target_triple_select), From ac7ec9ade3063d4338bb00ad42087b98755f371e Mon Sep 17 00:00:00 2001 From: Luca Della Vedova Date: Thu, 3 Sep 2026 14:28:55 +0800 Subject: [PATCH 4/8] Remove linker_type, gate linker to rustc version Signed-off-by: Luca Della Vedova --- rs/toolchains/BUILD.bazel | 1 + rs/toolchains/declare_rustc_toolchains.bzl | 24 ++++++++-------------- 2 files changed, 10 insertions(+), 15 deletions(-) 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 53542e6..aeaf095 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") @@ -112,6 +113,11 @@ def declare_rustc_toolchains( "//conditions:default": rust_std_label, }) + default_linux_flags = select({ + "@rules_rs//rs/platforms/config:x86_64-unknown-linux-gnu": ["-Clink-self-contained=no"], + "//conditions:default": [], + }) if versions.is_at_least("1.90.0", version) else [] + for triple in exec_triples: exec_triple = _parse_triple(triple) triple_suffix = exec_triple.system + "_" + exec_triple.arch @@ -138,13 +144,7 @@ def declare_rustc_toolchains( "@platforms//cpu:wasm64": lld_label, "//conditions:default": None, }), - linker_type = select({ - "@rules_rs//rs/platforms/config:riscv32imac-unknown-none-elf": "direct", - "@rules_rs//rs/platforms/config:riscv32imc-unknown-none-elf": "direct", - "@platforms//cpu:wasm32": "direct", - "@platforms//cpu:wasm64": "direct", - "//conditions:default": "indirect", - }), + linker_type = "direct", rust_objcopy = _component(rust_objcopy, triple, rustc_repo_label + "rust-objcopy"), rustc_lib = _component(rustc_lib, triple, rustc_repo_label + "rustc_lib"), allocator_library = None, @@ -199,14 +199,8 @@ def declare_rustc_toolchains( "//conditions:default": [], }), default_edition = edition, - extra_exec_rustc_flags = select({ - "@rules_rs//rs/platforms/config:x86_64-unknown-linux-gnu": ["-Clink-self-contained=no"], - "//conditions:default": [], - }) + _rustc_flags_to_select(extra_exec_rustc_flags), - extra_rustc_flags = select({ - "@rules_rs//rs/platforms/config:x86_64-unknown-linux-gnu": ["-Clink-self-contained=no"], - "//conditions:default": [], - }) + _rustc_flags_to_select(extra_rustc_flags), + extra_exec_rustc_flags = default_linux_flags + _rustc_flags_to_select(extra_exec_rustc_flags), + extra_rustc_flags = default_linux_flags + _rustc_flags_to_select(extra_rustc_flags), exec_triple = triple, target_triple = select(target_triple_select), visibility = ["//visibility:public"], From 222964ab41a8eb0c8d725d1d7e6e96f02f601d32 Mon Sep 17 00:00:00 2001 From: Luca Della Vedova Date: Thu, 3 Sep 2026 15:46:53 +0800 Subject: [PATCH 5/8] Revert all logic changes Signed-off-by: Luca Della Vedova --- rs/toolchains/BUILD.bazel | 1 - rs/toolchains/declare_rustc_toolchains.bzl | 10 ++-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/rs/toolchains/BUILD.bazel b/rs/toolchains/BUILD.bazel index 98877aa..e6bf17e 100644 --- a/rs/toolchains/BUILD.bazel +++ b/rs/toolchains/BUILD.bazel @@ -44,7 +44,6 @@ 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 aeaf095..264a232 100644 --- a/rs/toolchains/declare_rustc_toolchains.bzl +++ b/rs/toolchains/declare_rustc_toolchains.bzl @@ -1,6 +1,5 @@ """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") @@ -113,11 +112,6 @@ def declare_rustc_toolchains( "//conditions:default": rust_std_label, }) - default_linux_flags = select({ - "@rules_rs//rs/platforms/config:x86_64-unknown-linux-gnu": ["-Clink-self-contained=no"], - "//conditions:default": [], - }) if versions.is_at_least("1.90.0", version) else [] - for triple in exec_triples: exec_triple = _parse_triple(triple) triple_suffix = exec_triple.system + "_" + exec_triple.arch @@ -199,8 +193,8 @@ def declare_rustc_toolchains( "//conditions:default": [], }), default_edition = edition, - extra_exec_rustc_flags = default_linux_flags + _rustc_flags_to_select(extra_exec_rustc_flags), - extra_rustc_flags = default_linux_flags + _rustc_flags_to_select(extra_rustc_flags), + extra_exec_rustc_flags = _rustc_flags_to_select(extra_exec_rustc_flags), + extra_rustc_flags = _rustc_flags_to_select(extra_rustc_flags), exec_triple = triple, target_triple = select(target_triple_select), visibility = ["//visibility:public"], From 16008514a9c6f5259691bbc3dbdecc10fb26e079 Mon Sep 17 00:00:00 2001 From: Luca Della Vedova Date: Thu, 3 Sep 2026 15:52:53 +0800 Subject: [PATCH 6/8] Add analysis test Signed-off-by: Luca Della Vedova --- test/BUILD.bazel | 18 +++++++++++++ test/self_contained_linker_test.bzl | 40 +++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 test/self_contained_linker_test.bzl 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..8b8891e --- /dev/null +++ b/test/self_contained_linker_test.bzl @@ -0,0 +1,40 @@ +"""Analysis test verifying that Linux targets include rust-lld/gcc-ld in action inputs.""" + +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_inputs_test_impl(ctx): + env = analysistest.begin(ctx) + tut = analysistest.target_under_test(env) + action = _get_action_by_mnemonic(env, tut, "Rustc") + + input_basenames = [f.basename for f in action.inputs.to_list()] + asserts.true( + env, + "rust-lld" in input_basenames, + "Expected 'rust-lld' in Rustc action inputs for Linux target, but it was missing.", + ) + return analysistest.end(env) + +self_contained_linker_x86_64_test = analysistest.make( + _self_contained_linker_inputs_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_inputs_test_impl, + config_settings = { + "//command_line_option:platforms": str(Label("@rules_rs//rs/platforms:aarch64-unknown-linux-gnu")), + }, +) From 6120dfcb2a2ae0fd41e4d1fbdc04077e6b2a8699 Mon Sep 17 00:00:00 2001 From: Luca Della Vedova Date: Thu, 3 Sep 2026 15:53:26 +0800 Subject: [PATCH 7/8] Add fix Signed-off-by: Luca Della Vedova --- rs/toolchains/declare_rustc_toolchains.bzl | 1 + 1 file changed, 1 insertion(+) diff --git a/rs/toolchains/declare_rustc_toolchains.bzl b/rs/toolchains/declare_rustc_toolchains.bzl index 264a232..efcc57a 100644 --- a/rs/toolchains/declare_rustc_toolchains.bzl +++ b/rs/toolchains/declare_rustc_toolchains.bzl @@ -136,6 +136,7 @@ def declare_rustc_toolchains( "@rules_rs//rs/platforms/config:riscv32imc-unknown-none-elf": lld_label, "@platforms//cpu:wasm32": lld_label, "@platforms//cpu:wasm64": lld_label, + "@platforms//os:linux": lld_label, "//conditions:default": None, }), linker_type = "direct", From 2d856b20102c582187c0ad2228ea172178608258 Mon Sep 17 00:00:00 2001 From: Luca Della Vedova Date: Mon, 7 Sep 2026 16:14:04 +0800 Subject: [PATCH 8/8] Only disable builtin rust linker for rustc > 1.90 Signed-off-by: Luca Della Vedova --- rs/toolchains/BUILD.bazel | 1 + rs/toolchains/declare_rustc_toolchains.bzl | 23 +++++++++++++++++--- test/self_contained_linker_test.bzl | 25 ++++++++++++++++------ 3 files changed, 39 insertions(+), 10 deletions(-) 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 efcc57a..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) @@ -136,7 +154,6 @@ def declare_rustc_toolchains( "@rules_rs//rs/platforms/config:riscv32imc-unknown-none-elf": lld_label, "@platforms//cpu:wasm32": lld_label, "@platforms//cpu:wasm64": lld_label, - "@platforms//os:linux": lld_label, "//conditions:default": None, }), linker_type = "direct", @@ -194,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/self_contained_linker_test.bzl b/test/self_contained_linker_test.bzl index 8b8891e..2cc5f4e 100644 --- a/test/self_contained_linker_test.bzl +++ b/test/self_contained_linker_test.bzl @@ -1,4 +1,4 @@ -"""Analysis test verifying that Linux targets include rust-lld/gcc-ld in action inputs.""" +"""Analysis test verifying that Linux x86_64 targets disable self-contained LLD via -Clinker-features=-lld.""" load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") @@ -12,28 +12,39 @@ def _get_action_by_mnemonic(env, tut, mnemonic): ) return actions[0] -def _self_contained_linker_inputs_test_impl(ctx): +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") - input_basenames = [f.basename for f in action.inputs.to_list()] asserts.true( env, - "rust-lld" in input_basenames, - "Expected 'rust-lld' in Rustc action inputs for Linux target, but it was missing.", + "-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_inputs_test_impl, + _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_inputs_test_impl, + _self_contained_linker_aarch64_test_impl, config_settings = { "//command_line_option:platforms": str(Label("@rules_rs//rs/platforms:aarch64-unknown-linux-gnu")), },