From 022e197e6fa30bfbab01c1a054ef8e8bb674a664 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 5 May 2026 09:24:56 +0000 Subject: [PATCH 1/2] Remap relative bin-dir prefix for file!() and log macros When transform_sources() symlinks sources into bazel-out//bin/, file!(), Location::caller(), and tracing/log macros embed the literal relative path rustc received on the command line. The existing ${pwd} remap only matches absolute paths in debug info. Add a second --remap-path-prefix for the relative bazel-out//bin/ prefix (without ${pwd}) so these compile-time paths are also clean. Add analysis tests verifying the flag is present for generated sources and absent for plain sources, plus a runtime test confirming file!() returns a clean path. --- rust/private/rustc.bzl | 8 +++ test/unit/remap_path_prefix/BUILD.bazel | 27 +++++++++ .../unit/remap_path_prefix/file_macro_test.rs | 8 +++ .../remap_path_prefix_test.bzl | 55 +++++++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 test/unit/remap_path_prefix/file_macro_test.rs diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl index ad84f1066f..ce69da218a 100644 --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl @@ -1193,6 +1193,14 @@ def construct_arguments( 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 not crate_info.root.is_source: + # Also remap the relative bazel-out//bin/ prefix. + # file!(), Location::caller(), and tracing/log macros embed + # the literal relative path that rustc received on the command + # line. The ${pwd} remap above only matches absolute paths in + # debug info, so a second remap without ${pwd} is needed to + # strip the bin-dir prefix from these compile-time paths. + rustc_flags.add("--remap-path-prefix={}/=".format(ctx.bin_dir.path)) emit_without_paths = [] for kind in emit: diff --git a/test/unit/remap_path_prefix/BUILD.bazel b/test/unit/remap_path_prefix/BUILD.bazel index fa77ac8256..bbdb4e9fb5 100644 --- a/test/unit/remap_path_prefix/BUILD.bazel +++ b/test/unit/remap_path_prefix/BUILD.bazel @@ -1,3 +1,4 @@ +load("@bazel_skylib//rules:write_file.bzl", "write_file") load("//rust:defs.bzl", "rust_binary", "rust_library", "rust_test") load(":debug_transition.bzl", "dbg_rust_binary") load(":remap_path_prefix_test.bzl", "remap_path_prefix_test_suite") @@ -37,6 +38,32 @@ rust_test( deps = ["//rust/runfiles"], ) +# Library with generated source to trigger transform_sources(). +# Exposes file!() so a runtime test can verify the path is clean. +write_file( + name = "remap_file_macro_lib_src", + out = "remap_file_macro_lib.rs", + content = [ + "pub fn get_file_path() -> &'static str {", + " file!()", + "}", + "", + ], +) + +rust_library( + name = "remap_file_macro_lib", + srcs = [":remap_file_macro_lib.rs"], + edition = "2021", +) + +rust_test( + name = "file_macro_test", + srcs = ["file_macro_test.rs"], + edition = "2021", + deps = [":remap_file_macro_lib"], +) + remap_path_prefix_test_suite( name = "remap_path_prefix_test_suite", ) diff --git a/test/unit/remap_path_prefix/file_macro_test.rs b/test/unit/remap_path_prefix/file_macro_test.rs new file mode 100644 index 0000000000..b79cb6c0a4 --- /dev/null +++ b/test/unit/remap_path_prefix/file_macro_test.rs @@ -0,0 +1,8 @@ +#[test] +fn file_macro_has_no_bazel_out_prefix() { + let path = remap_file_macro_lib::get_file_path(); + assert!( + !path.contains("bazel-out"), + "file!() should not contain 'bazel-out' prefix, got: {path}", + ); +} diff --git a/test/unit/remap_path_prefix/remap_path_prefix_test.bzl b/test/unit/remap_path_prefix/remap_path_prefix_test.bzl index a5e4d6728c..a0b4919e89 100644 --- a/test/unit/remap_path_prefix/remap_path_prefix_test.bzl +++ b/test/unit/remap_path_prefix/remap_path_prefix_test.bzl @@ -6,6 +6,9 @@ load("//rust:defs.bzl", "rust_binary", "rust_library") load( "//test/unit:common.bzl", "assert_action_mnemonic", + "assert_argv_contains", + "assert_argv_contains_prefix_not", + "assert_argv_contains_prefix_suffix", "assert_list_contains_adjacent_elements", ) @@ -26,6 +29,38 @@ def _remap_path_prefix_test_impl(ctx): _remap_path_prefix_test = analysistest.make(_remap_path_prefix_test_impl) +def _remap_path_prefix_source_test_impl(ctx): + """Verify that source targets do NOT get the relative bin-dir remap.""" + env = analysistest.begin(ctx) + target = analysistest.target_under_test(env) + + action = target.actions[0] + assert_action_mnemonic(env, action, "Rustc") + + assert_argv_contains(env, action, "--remap-path-prefix=${pwd}=.") + assert_argv_contains(env, action, "--remap-path-prefix=${exec_root}=.") + assert_argv_contains(env, action, "--remap-path-prefix=${output_base}=.") + assert_argv_contains_prefix_not(env, action, "--remap-path-prefix=bazel-out/") + + return analysistest.end(env) + +_remap_path_prefix_source_test = analysistest.make(_remap_path_prefix_source_test_impl) + +def _remap_file_macro_generated_test_impl(ctx): + """Verify that generated-source targets get a relative bin-dir remap for file!().""" + env = analysistest.begin(ctx) + target = analysistest.target_under_test(env) + + action = target.actions[0] + assert_action_mnemonic(env, action, "Rustc") + + # Should have the relative bin-dir remap (e.g. --remap-path-prefix=bazel-out/k8-fastbuild/bin/=) + assert_argv_contains_prefix_suffix(env, action, "--remap-path-prefix=bazel-out/", "/bin/=") + + return analysistest.end(env) + +_remap_file_macro_generated_test = analysistest.make(_remap_file_macro_generated_test_impl) + def _subst_flags_test_impl(ctx): """Verify that process wrapper --subst flags are present.""" env = analysistest.begin(ctx) @@ -88,6 +123,23 @@ def remap_path_prefix_test_suite(name): target_under_test = ":remap_bin", ) + # Verify source targets do NOT get the relative bin-dir remap. + _remap_path_prefix_source_test( + name = "remap_path_prefix_source_lib_test", + target_under_test = ":dep", + ) + + # Verify generated-source targets get the relative bin-dir remap for file!(). + _remap_file_macro_generated_test( + name = "remap_file_macro_generated_lib_test", + target_under_test = ":remap_lib", + ) + + _remap_file_macro_generated_test( + name = "remap_file_macro_generated_bin_test", + target_under_test = ":remap_bin", + ) + _subst_flags_test( name = "subst_flags_lib_test", target_under_test = ":remap_lib", @@ -101,6 +153,9 @@ def remap_path_prefix_test_suite(name): tests = [ ":remap_path_prefix_lib_test", ":remap_path_prefix_bin_test", + ":remap_path_prefix_source_lib_test", + ":remap_file_macro_generated_lib_test", + ":remap_file_macro_generated_bin_test", ":subst_flags_lib_test", ":subst_flags_bin_test", ] From 905bedc4cc63aa38f66607dc5403c44958a8a00b Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Fri, 8 May 2026 08:05:28 +0000 Subject: [PATCH 2/2] Fix bin-dir remap to work with --experimental_output_paths=strip Use add_all with the crate root File and a map_each callback instead of a hardcoded ctx.bin_dir.path string. This lets Bazel's path mapping rewrite the config portion of the bin-dir prefix (e.g. k8-fastbuild -> cfg), so the remap flag matches the actual source file path at execution time. --- rust/private/rustc.bzl | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl index ce69da218a..dfd767c738 100644 --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl @@ -1200,7 +1200,11 @@ def construct_arguments( # line. The ${pwd} remap above only matches absolute paths in # debug info, so a second remap without ${pwd} is needed to # strip the bin-dir prefix from these compile-time paths. - rustc_flags.add("--remap-path-prefix={}/=".format(ctx.bin_dir.path)) + # + # 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_remap_prefix) emit_without_paths = [] for kind in emit: @@ -2714,6 +2718,25 @@ def _add_native_link_flags( format_each = "-lstatic=%s", ) +def _get_bin_dir_remap_prefix(file): + """Derives a --remap-path-prefix flag that strips the bin-dir prefix. + + For a generated file, file.path is "bazel-out//bin//" + and file.short_path is "/". The difference is the bin-dir + prefix that needs to be stripped from file!() and similar macros. + + Using the File object with add_all/map_each lets Bazel apply path mapping + (--experimental_output_paths=strip) to the config portion of the path. + + Args: + file (File): The crate root file (must be a generated file). + + Returns: + str: A --remap-path-prefix flag that maps the bin-dir prefix to empty. + """ + prefix = file.path[:len(file.path) - len(file.short_path)] + return "--remap-path-prefix={}=".format(prefix) + def _get_dirname(file): """A helper function for `_add_native_link_flags`.