From a53ede53dc8f3e9299c6a8db9344bfa01da7c1f3 Mon Sep 17 00:00:00 2001 From: Bernardo Meurer Date: Tue, 19 May 2026 10:14:34 -0400 Subject: [PATCH] buildRustCrate: remap crate source root to /- MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit buildRustCrate passes `--remap-path-prefix=$NIX_BUILD_TOP=/` so the sandbox build directory is not embedded in compiled artifacts. The resulting source path is `/$sourceRoot/src/...` — which works out to `/-/src/...` only because fetchCrate happens to unpack to a directory named after the crate. When `src` is supplied directly — `lib.fileset.toSource` (always `source`), `lib.cleanSource ./.`, a flake's `self`, or any `-source` store path — stdenv unpacks to `$NIX_BUILD_TOP/source/`, so every such crate ends up with `/source/src/lib.rs`. The crate identity is gone from panic backtraces, `file!()` expansions, debuginfo, and llvm-cov coverage maps. Workspace builds via crate2nix that source each member with a fileset see all members collapse to the same prefix, making per-crate coverage and backtrace attribution impossible without a per-crate remap override. Add a second, more specific remap of `$NIX_BUILD_TOP/$sourceRoot` to `/-`. rustc applies `--remap-path-prefix` flags last-match-wins, so this prefix wins for everything under the source root — which in a buildRustCrate build is effectively everything that would otherwise embed a sandbox path, including `OUT_DIR` (placed at `$sourceRoot/target/build/` by configure-crate.nix). The broader `$NIX_BUILD_TOP=/` remap stays as a fallback for any path outside `$sourceRoot`. This is safe with respect to the original remap's purpose: - Reproducibility: still maps the per-build sandbox path to a fixed, build-independent string. `crateName` and `version` are already derivation inputs, so the result is deterministic. - Closure size: still no store paths in the embedded strings. - fetchCrate sources: `$sourceRoot` is `-` there, so the new remap rewrites `/-` to itself — the output is byte-for-byte identical. Only custom-`src` crates change, and they change from a degenerate `/source/...` to the same shape fetchCrate crates already had. - The remap only affects path *strings* embedded in output (DWARF `DW_AT_comp_dir`/`DW_AT_name`, `file!()`, `Location::file()`, LLVM coverage filename tables). It does not change which files are read or compiled. Users who depend on the old `/source/...` prefix can restore it via `extraRustcOpts`, which is appended after these flags and therefore wins under last-match-wins. --- .../rust/build-rust-crate/build-crate.nix | 15 +++++++++++++++ .../rust/build-rust-crate/default.nix | 1 + 2 files changed, 16 insertions(+) diff --git a/pkgs/build-support/rust/build-rust-crate/build-crate.nix b/pkgs/build-support/rust/build-rust-crate/build-crate.nix index d5b7166207fa..4a337ddc2218 100644 --- a/pkgs/build-support/rust/build-rust-crate/build-crate.nix +++ b/pkgs/build-support/rust/build-rust-crate/build-crate.nix @@ -9,6 +9,7 @@ { crateName, + version, dependencies, crateFeatures, crateRenames, @@ -32,6 +33,20 @@ let (if release then "-C opt-level=3" else "-C debuginfo=2") "-C codegen-units=${toString codegenUnits}" "--remap-path-prefix=$NIX_BUILD_TOP=/" + # Map the unpacked source root to a stable, crate-identifying path. + # Sources from fetchCrate unpack to $NIX_BUILD_TOP/-, + # so the prefix above already yields /-/src/... and + # this remap is a no-op for them. Sources supplied via a custom `src` + # (lib.fileset.toSource, lib.cleanSource, a flake's `self`) all unpack to + # a fixed basename like `source`, so without this every such crate + # collapses to /source/src/... — losing crate identity in panic + # backtraces, file!() expansions, debuginfo, and coverage maps. rustc + # applies remaps last-match-wins, so this more-specific prefix wins + # for everything under the source root (including OUT_DIR, which + # configure-crate.nix places at $sourceRoot/target/build/); the + # broader $NIX_BUILD_TOP remap above remains as a fallback for any + # path that happens to fall outside $sourceRoot. + "--remap-path-prefix=$NIX_BUILD_TOP/$sourceRoot=/${crateName}-${version}" # When the rust-src component is present (common with rust-overlay # toolchains), rustc unvirtualises libstd source paths. Panic # locations from monomorphised generic std code then embed the diff --git a/pkgs/build-support/rust/build-rust-crate/default.nix b/pkgs/build-support/rust/build-rust-crate/default.nix index af1ec421da9b..799d8daec8b8 100644 --- a/pkgs/build-support/rust/build-rust-crate/default.nix +++ b/pkgs/build-support/rust/build-rust-crate/default.nix @@ -543,6 +543,7 @@ lib.makeOverridable buildPhase = buildCrate { inherit crateName + version dependencies crateFeatures crateRenames