Skip to content

Commit 4124305

Browse files
committed
Fix path mapping for generated linker paths
When --experimental_output_paths=strip is enabled, path mapping added in 175bf94 rewrites File-backed action arguments, but the rustc action still adds its linker as a string. Generated Rust linkers and C/C++ linker wrappers therefore retain their original bazel-out configuration paths and cannot be found inside mapped execution sandboxes. Pass the selected Rust linker as its File and recover generated C/C++ linker Files from the C toolchain before constructing --codegen=linker. Normalize external-repository short paths when matching selected tools against linker inputs from different configurations. Keep get_linker_and_args string-valued for Cargo build scripts, and cover local and external C/C++ linkers with mapped and unmapped output paths. Assisted-by: Codex
1 parent 0105631 commit 4124305

5 files changed

Lines changed: 71 additions & 4 deletions

File tree

rust/private/rustc.bzl

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1411,7 +1411,18 @@ def construct_arguments(
14111411
if sdkroot != None:
14121412
env["SDKROOT"] = sdkroot
14131413

1414-
rustc_flags.add(ld, format = "--codegen=linker=%s")
1414+
# Keep generated linker paths File-backed so Bazel can rewrite them.
1415+
linker = ld
1416+
if toolchain.linker and ld == toolchain.linker.path:
1417+
linker = toolchain.linker
1418+
elif cc_toolchain and ld.startswith("bazel-out/"):
1419+
linker_files = cc_toolchain._linker_files if hasattr(cc_toolchain, "_linker_files") else cc_toolchain.linker_files()
1420+
for linker_file in linker_files.to_list():
1421+
if linker_file.path == ld or ld.endswith("/" + linker_file.short_path.removeprefix("../")):
1422+
linker = linker_file
1423+
break
1424+
1425+
rustc_flags.add(linker, format = "--codegen=linker=%s")
14151426

14161427
# Split link args into individual "--codegen=link-arg=" flags to handle nested spaces.
14171428
# Additional context: https://github.com/rust-lang/rust/pull/36574

test/generated_inputs/external_repo.bzl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ write_file(
1010
content = ["pub fn forty_two() -> i32 { 42 }"],
1111
)
1212
13+
write_file(
14+
name = "linker",
15+
out = "link-wrapper",
16+
content = ["#!/bin/sh", "exit 0"],
17+
is_executable = True,
18+
visibility = ["//visibility:public"],
19+
)
20+
1321
rust_library(
1422
name = "generated_inputs_external_repo",
1523
srcs = [
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
load(":cc_toolchain_runtime_lib_test.bzl", "runtime_libs_test")
22

33
runtime_libs_test(name = "runtime_libs_test")
4+
5+
runtime_libs_test(
6+
name = "external_runtime_libs_test",
7+
linker = "@generated_inputs_in_external_repo//lib:linker",
8+
)

test/unit/cc_toolchain_runtime_lib/cc_toolchain_runtime_lib_test.bzl

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ Tests for handling of cc_toolchain's static_runtime_lib/dynamic_runtime_lib.
33
"""
44

55
load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
6-
load("@rules_cc//cc:cc_toolchain_config_lib.bzl", "feature")
6+
load("@bazel_skylib//rules:write_file.bzl", "write_file")
7+
load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES")
8+
load("@rules_cc//cc:cc_toolchain_config_lib.bzl", "action_config", "feature", "tool")
79
load("@rules_cc//cc:defs.bzl", "cc_toolchain")
810
load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
911
load("@rules_cc//cc/toolchains:cc_toolchain_config_info.bzl", "CcToolchainConfigInfo")
1012
load("//rust:defs.bzl", "rust_shared_library", "rust_static_library")
13+
load("//test/unit:common.bzl", "get_bin_dir_from_action")
1114

1215
def _test_cc_config_impl(ctx):
1316
config_info = cc_common.create_cc_toolchain_config_info(
@@ -20,6 +23,16 @@ def _test_cc_config_impl(ctx):
2023
compiler = "unknown",
2124
abi_version = "unknown",
2225
abi_libc_version = "unknown",
26+
action_configs = [
27+
action_config(
28+
action_name = action_name,
29+
tools = [tool(tool = ctx.file.linker)],
30+
)
31+
for action_name in [
32+
ACTION_NAMES.cpp_link_dynamic_library,
33+
ACTION_NAMES.cpp_link_static_library,
34+
]
35+
],
2336
features = [
2437
feature(name = "static_link_cpp_runtimes", enabled = True),
2538
],
@@ -28,6 +41,7 @@ def _test_cc_config_impl(ctx):
2841

2942
test_cc_config = rule(
3043
implementation = _test_cc_config_impl,
44+
attrs = {"linker": attr.label(allow_single_file = True, cfg = "exec")},
3145
provides = [CcToolchainConfigInfo],
3246
)
3347

@@ -106,6 +120,18 @@ def _inputs_analysis_test_impl(ctx):
106120
"error: expected '{}' to be in runfiles: '{}'".format(expected, runfiles),
107121
)
108122

123+
linker_files = [file for file in inputs if file.basename == "link-wrapper"]
124+
asserts.equals(env, 1, len(linker_files))
125+
126+
linker_args = [arg for arg in action.argv if arg.startswith("--codegen=linker=")]
127+
asserts.equals(env, 1, len(linker_args))
128+
129+
bin_dir = get_bin_dir_from_action(action)
130+
linker_path = (
131+
"{}/{}".format(bin_dir, linker_files[0].path.split("/bin/", 1)[1]) if bin_dir == "bazel-out/cfg/bin" else linker_files[0].path
132+
)
133+
asserts.equals(env, "--codegen=linker={}".format(linker_path), linker_args[0])
134+
109135
return analysistest.end(env)
110136

111137
inputs_analysis_test = analysistest.make(
@@ -120,22 +146,34 @@ inputs_analysis_test = analysistest.make(
120146
},
121147
)
122148

123-
def runtime_libs_test(name):
149+
def runtime_libs_test(name, linker = None):
124150
"""Produces test shared and static library targets that are set up to use a custom cc_toolchain with custom runtime libs.
125151
126152
Args:
127153
name: The name of the test target.
154+
linker: An optional generated linker from another repository.
128155
"""
129156

157+
if linker == None:
158+
write_file(
159+
name = "%s/linker" % name,
160+
out = "%s/link-wrapper" % name,
161+
content = ["#!/bin/sh", "exit 0"],
162+
is_executable = True,
163+
)
164+
165+
linker_label = linker if linker != None else ":%s/linker" % name
166+
130167
test_cc_config(
131168
name = "%s/cc_toolchain_config" % name,
169+
linker = linker_label,
132170
)
133171
cc_toolchain(
134172
name = "%s/test_cc_toolchain_impl" % name,
135173
all_files = ":empty",
136174
compiler_files = ":empty",
137175
dwp_files = ":empty",
138-
linker_files = ":empty",
176+
linker_files = linker_label,
139177
objcopy_files = ":empty",
140178
strip_files = ":empty",
141179
supports_param_files = 0,

test/unit/native_deps/native_deps_test.bzl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,11 @@ def _bin_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
191191
toolchain = _get_toolchain(ctx)
192192
link_args = _extract_linker_args(action.argv)
193193
bin_dir = get_bin_dir_from_action(action)
194+
linker_args = [arg for arg in action.argv if arg.startswith("--codegen=linker=")]
195+
196+
asserts.equals(env, 1, len(linker_args))
197+
if bin_dir == "bazel-out/cfg/bin" and linker_args[0].startswith("--codegen=linker=bazel-out/"):
198+
assert_argv_contains_prefix(env, action, "--codegen=linker={}/".format(bin_dir))
194199

195200
# Validate bin_dir structure (ignoring ST-{hash} suffix from config transitions)
196201
_assert_bin_dir_structure(env, ctx, bin_dir, toolchain)

0 commit comments

Comments
 (0)