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
2 changes: 2 additions & 0 deletions cargo/private/cargo_build_script.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,8 @@ def _cargo_build_script_impl(ctx):
env["CARGO_ENCODED_RUSTFLAGS"] = "\\x1f".join([
# Allow build scripts to locate the generated sysroot
"--sysroot=${{pwd}}/{}".format(toolchain.sysroot),
# Keep build scripts from baking the exec root into their output
"--remap-path-prefix=${pwd}=.",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is mapping pwd to . correct? Won't this be the CARGO_MANIFEST_DIR which is not going to be correct outside of this action? Shouldn't there be some other mapping that the build script determines based on the OUT_DIR path location relative to the execroot for the action?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, thanks for taking a look.

From my understanding --remap-path-prefix should only be changing what rustc writes into its own output, so it doesn't participate in the token substitution that makes build script output portable between actions.

${pwd} is resolved to the exec root on the way in, before the script runs, and the .env/.depenv files are built only from cargo:-prefixed lines on the script's stdout, which this shouldn't touch.

The thing being fixed is that OUT_DIR is a TreeArtifact hashed into every downstream rustc cache key. rustix's feature probe writes a --emit=metadata file in there and only reads the exit code, but rustc folds its working directory into the metadata hash, so the file's bytes differ between checkouts and re-key everything downstream. It forwards CARGO_ENCODED_RUSTFLAGS to that rustc, which is how the remap reaches it.

re: deriving the prefix from OUT_DIR - I'm unsure that'd work, OUT_DIR and the script's cwd are siblings rather than nested:

<exec_root>/bazel-out/<cfg>/bin/<pkg>/<name>.out_dir/
<exec_root>/bazel-out/<cfg>/bin/<pkg>/<name>.cargo_runfiles/<ws>/

The path that actually leaks is the working directory, and an OUT_DIR-derived prefix diverges from it at that last segment. The exec root is their only common ancestor, and since --remap-path-prefix matches on prefix it covers both. . is the same value rustc.bzl uses for non-build-script compiles.

While looking at this I realised there's another alternative if you'd prefer to avoid touching rustflags. remove_nondeterministic_out_dir_files already targets this class of issue, so adding rustix_test_can_compile to out_dir_volatile_file_basenames should fix this specific crate. I went with the remap because it'll cover any build script that forwards rustflags to rustc rather than needing an entry per crate, but happy to do that version instead if you want.

] + ctx.attr.rustc_flags)

for f in ctx.attr.crate_features:
Expand Down
7 changes: 5 additions & 2 deletions cargo/tests/cargo_build_script/tools_exec/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ fn test_encoded_rustflags() {
.split('\x1f')
.map(str::to_string)
.collect();
assert_eq!(flags.len(), 2);
assert_eq!(flags.len(), 3);

assert!(flags[0].starts_with("--sysroot"));

// Ensure the `pwd` template has been resolved
assert!(!flags[0].contains("${pwd}"));

assert_eq!(flags[1], "--cfg=foo=\"bar\"");
assert!(flags[1].starts_with("--remap-path-prefix"));
assert!(!flags[1].contains("${pwd}"));

assert_eq!(flags[2], "--cfg=foo=\"bar\"");
}

/// Ensure Make variables provided by the `toolchains` attribute are expandable.
Expand Down