Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 52 additions & 4 deletions rust/private/rustc.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -1185,14 +1185,45 @@ def construct_arguments(
rustc_flags.add(compilation_mode.strip_level, format = "--codegen=strip=%s")

# For determinism to help with build distribution and such
#
# --remap-path-prefix tells rustc to replace a path prefix in all
# embedded paths (debug info, dep-info, panic locations, backtraces)
# so that absolute sandbox paths never leak into binaries or logs.
#
# When all sources are plain workspace files, remapping ${pwd} (the exec
# root) to remap_path_prefix (default ".") is enough.
#
# However, when a target mixes generated and non-generated sources (e.g.
# proto compile_data), transform_sources() symlinks every source file into
# bazel-out/<config>/bin/... so they sit next to the generated files. In
# that case the crate root is no longer a source file and its path starts
# with ctx.bin_dir.path (e.g. "bazel-out/k8-fastbuild/bin"). We detect
# this via crate_info.root.is_source and use a more specific remap that
# also strips the bin-dir component, giving clean workspace-relative paths
# in panic messages and backtraces.
if remap_path_prefix != None:
# `--remap-path-prefix` flags are applied in reverse order. We need to
# specify the outermost directory (output_base) first, so that it's
# remapped last. Otherwise we can end up with a partial rewrite where
# "/path/to/output_base/execroot" becomes "./execroot" rather than ".".
rustc_flags.add("--remap-path-prefix=${{output_base}}={}".format(remap_path_prefix))
rustc_flags.add("--remap-path-prefix=${{pwd}}={}".format(remap_path_prefix))
rustc_flags.add("--remap-path-prefix=${{exec_root}}={}".format(remap_path_prefix))
if crate_info.root.is_source:
rustc_flags.add("--remap-path-prefix=${{pwd}}={}".format(remap_path_prefix))
rustc_flags.add("--remap-path-prefix=${{exec_root}}={}".format(remap_path_prefix))
else:
# Use add_all with the crate root File and a map_each callback
# so Bazel's path mapping (--experimental_output_paths=strip)
# can rewrite the config portion of the bin-dir prefix.
rustc_flags.add_all(
[crate_info.root],
map_each = _get_bin_dir_prefix,
format_each = "--remap-path-prefix=${pwd}/%s=" + remap_path_prefix,
)
rustc_flags.add_all(
[crate_info.root],
map_each = _get_bin_dir_prefix,
format_each = "--remap-path-prefix=${exec_root}/%s=" + remap_path_prefix,
)

emit_without_paths = []
for kind in emit:
Expand Down Expand Up @@ -1288,11 +1319,12 @@ def construct_arguments(
if remap_path_prefix != None and _should_add_oso_prefix(
toolchain,
):
oso_prefix = "${pwd}/" if crate_info.root.is_source else "${pwd}/" + ctx.bin_dir.path + "/"
if ld_is_direct_driver:
rustc_flags.add("--codegen=link-arg=-oso_prefix")
rustc_flags.add("${pwd}/", format = "--codegen=link-arg=%s")
rustc_flags.add(oso_prefix, format = "--codegen=link-arg=%s")
else:
rustc_flags.add("--codegen=link-arg=-Wl,-oso_prefix,${pwd}/")
rustc_flags.add("--codegen=link-arg=-Wl,-oso_prefix," + oso_prefix)

_add_native_link_flags(
rustc_flags,
Expand Down Expand Up @@ -2706,6 +2738,22 @@ def _add_native_link_flags(
format_each = "-lstatic=%s",
)

def _get_bin_dir_prefix(file):
"""Returns the bin-dir prefix (without trailing slash) from a generated file.

For a generated file, file.path is "bazel-out/<config>/bin/<pkg>/<name>"
and file.short_path is "<pkg>/<name>". The difference is the bin-dir
prefix. Using the File object with add_all/map_each lets Bazel apply
path mapping (--experimental_output_paths=strip) to the config portion.

Args:
file (File): A generated file (e.g. the crate root).

Returns:
str: The bin-dir prefix, e.g. "bazel-out/k8-fastbuild/bin".
"""
return file.path[:len(file.path) - len(file.short_path)].rstrip("/")

def _get_dirname(file):
"""A helper function for `_add_native_link_flags`.

Expand Down
70 changes: 50 additions & 20 deletions test/unit/remap_path_prefix/remap_path_prefix_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ load("//rust:defs.bzl", "rust_binary", "rust_library")
load(
"//test/unit:common.bzl",
"assert_action_mnemonic",
"assert_argv_contains",
"assert_argv_contains_prefix_suffix",
"assert_list_contains_adjacent_elements",
)

def _remap_path_prefix_test_impl(ctx):
def _remap_path_prefix_source_test_impl(ctx):
"""Verify remap flags for targets with plain source files."""
env = analysistest.begin(ctx)
target = analysistest.target_under_test(env)

Expand All @@ -24,7 +27,23 @@ def _remap_path_prefix_test_impl(ctx):

return analysistest.end(env)

_remap_path_prefix_test = analysistest.make(_remap_path_prefix_test_impl)
_remap_path_prefix_source_test = analysistest.make(_remap_path_prefix_source_test_impl)

def _remap_path_prefix_generated_test_impl(ctx):
"""Verify remap flags for targets with generated sources (symlinked into bin dir)."""
env = analysistest.begin(ctx)
target = analysistest.target_under_test(env)

action = target.actions[0]
assert_action_mnemonic(env, action, "Rustc")

assert_argv_contains_prefix_suffix(env, action, "--remap-path-prefix=${pwd}/bazel-out/", "/bin=.")
assert_argv_contains_prefix_suffix(env, action, "--remap-path-prefix=${exec_root}/bazel-out/", "/bin=.")
assert_argv_contains(env, action, "--remap-path-prefix=${output_base}=.")

return analysistest.end(env)

_remap_path_prefix_generated_test = analysistest.make(_remap_path_prefix_generated_test_impl)

def _subst_flags_test_impl(ctx):
"""Verify that process wrapper --subst flags are present."""
Expand All @@ -48,59 +67,70 @@ def remap_path_prefix_test_suite(name):
Args:
name (str): The name of the test suite.
"""

# Targets with generated sources (write_file produces non-source files,
# triggering transform_sources which symlinks into bin dir).
write_file(
name = "remap_lib_src",
out = "remap_lib.rs",
name = "remap_lib_generated_src",
out = "remap_lib_generated.rs",
content = [
"pub fn hello() {}",
"",
],
)

rust_library(
name = "remap_lib",
srcs = [":remap_lib.rs"],
name = "remap_lib_generated",
srcs = [":remap_lib_generated.rs"],
edition = "2021",
)

write_file(
name = "remap_bin_src",
out = "remap_bin.rs",
name = "remap_bin_generated_src",
out = "remap_bin_generated.rs",
content = [
"fn main() {}",
"",
],
)

rust_binary(
name = "remap_bin",
srcs = [":remap_bin.rs"],
name = "remap_bin_generated",
srcs = [":remap_bin_generated.rs"],
edition = "2021",
)

_remap_path_prefix_test(
name = "remap_path_prefix_lib_test",
target_under_test = ":remap_lib",
# Tests for plain source files (using existing dep.rs from the package).
_remap_path_prefix_source_test(
name = "remap_path_prefix_source_lib_test",
target_under_test = ":dep",
)

# Tests for generated sources (symlinked into bin dir).
_remap_path_prefix_generated_test(
name = "remap_path_prefix_generated_lib_test",
target_under_test = ":remap_lib_generated",
)

_remap_path_prefix_test(
name = "remap_path_prefix_bin_test",
target_under_test = ":remap_bin",
_remap_path_prefix_generated_test(
name = "remap_path_prefix_generated_bin_test",
target_under_test = ":remap_bin_generated",
)

_subst_flags_test(
name = "subst_flags_lib_test",
target_under_test = ":remap_lib",
target_under_test = ":remap_lib_generated",
)

_subst_flags_test(
name = "subst_flags_bin_test",
target_under_test = ":remap_bin",
target_under_test = ":remap_bin_generated",
)

tests = [
":remap_path_prefix_lib_test",
":remap_path_prefix_bin_test",
":remap_path_prefix_source_lib_test",
":remap_path_prefix_generated_lib_test",
":remap_path_prefix_generated_bin_test",
":subst_flags_lib_test",
":subst_flags_bin_test",
]
Expand Down
Loading