Skip to content

rust: support SCCACHE_BASEDIRS across checkout roots - #2794

Open
pamarcos wants to merge 7 commits into
mozilla:mainfrom
pamarcos:rust-basedirs
Open

rust: support SCCACHE_BASEDIRS across checkout roots #2794
pamarcos wants to merge 7 commits into
mozilla:mainfrom
pamarcos:rust-basedirs

Conversation

@pamarcos

@pamarcos pamarcos commented Aug 5, 2026

Copy link
Copy Markdown

First, I want to point that I've used GPT-5.6 Sol to assist me with the work. However, I've reviewed the code and tested it.

Rust compilation currently includes checkout-specific paths in its cache key, so the existing SCCACHE_BASEDIRS support does not provide cross-checkout cache hits for Rust crates.

This adds Rust support while preserving location sensitivity for path inputs that are not safely covered by compiler remapping. In particular, normalization requires an effective --remap-path-prefix covering the working directory with the default or all remap scope. Without that compiler-side remapping, the working directory and other path-sensitive inputs remain exact.

This work is based on #2678 (Matt remains the author of the imported baseline commit). I also found that there's a similar PR at johnkferguson#1. Not sure why a PR upstream was never created.

So, I decided to create this PR because the other ones seem not to be followed up, but I'm happy to close this as a duplicate if the others are planned to be merged.

Implementation details
  • normalizes only the source side of parsed --remap-path-prefix values, preserving the destination,
    mapping precedence, component matching, and final remap scope;
  • hashes the effective remapped identity of every source file and preserves original identity when
    multiple sources map to the same virtual path;
  • keeps env!, option_env!, profiles, plugins, and unremapped paths location-sensitive;
  • normalizes a small allowlist of path-valued CARGO_* variables, including
    CARGO_INSTALL_ROOT, only when the working directory is remapped, there are no explicit externs,
    and crate search paths contain no dynamic libraries;
  • frames normalized values and advances the Rust cache-key version from 6 to 7;
  • falls back to local compilation when a distributed path transformer cannot safely preserve a user
    remap; and
  • declines SCCACHE_BASEDIRS prefix stripping for non-ASCII Windows values.

This deliberately avoids scanning arbitrary argument, linker, environment, or replacement-path bytes. Those values may affect compiler output without being rewritten by rustc, so stripping them from the key could return an artifact containing paths or semantics from another checkout.

Full provenance and related discussions

Direct lineage

Reference Relevance
#35 Original request for a CCACHE_BASEDIR equivalent.
#104 Early unmerged basedir implementation.
#2521 Mikhail Shiryaev's merged SCCACHE_BASEDIRS foundation for C/C++.
#2270 Made Rust --remap-path-prefix compilations cacheable.
#2651 Stopped separately hashing CARGO_ENCODED_RUSTFLAGS, which often carries the remap.
#2652 Weihang Lo's direct request for Rust support and warning that key-only normalization is unsafe.
vercel#10 Matt Mastracci's original Rust prototype.
#2678 Matt Mastracci's direct upstream implementation and the baseline for this PR.

Independent implementations and experiments

Reference Relevance
johnkferguson#1 Glob/worktree experiment, per-token argument diagnosis, CARGO_INSTALL_ROOT, and reported 98.6% hit rate.
manoelcalixto#1 Independent opt-in linked-worktree implementation with extensive safety and CI coverage.
zackees/zccache#229 Related request for safe Rust cache sharing across source roots.
zackees/zccache#237 Root-covering remap gate and path-sensitive Rust integration tests in zccache.
https://github.com/moriyoshi/sccache-wrapper Standalone normalized-artifact cache wrapper for cross-worktree reuse.
NVIDIA/OpenShell#2379 Operational evidence of zero Rust cross-worktree hits before normalization.
NVIDIA/OpenShell#2475 Follow-up experiment using SCCACHE_BASEDIRS.

Cache-key and artifact-safety context

Reference Relevance
#196 Historical report of shared Rust dependencies missing across projects.
#206 Earlier path-independent Rust key attempt, left unmerged because artifacts differed by path.
#345 Added Rust working-directory hashing because the path is embedded in rlibs.
#986 Discussion of whether and why the working directory belongs in cache keys.
#2494 Discussion of which CARGO_* variables should affect Rust keys.
#2495 Alternative proposal to stop hashing redundant or irrelevant CARGO_* variables.
#2673 Analogous parsed source-side normalization for C/C++ prefix-map arguments.
#2711 Related C/C++ argument normalization and per-argument key framing.
#2763 Demonstrates the debugger/source-path consequence of serving an artifact from another checkout.
#2765 Daniel Colascione's direct request to normalize congruent Rust --remap-path-prefix values.
#2595 Worktree workflow and dynamic basedir discovery requirements.
#2737 Windows basedir matching bug report.
#2736 Windows escaped-separator fix in shared basedir handling.
rust-lang/cargo#10915 Upstream evidence that moving CARGO_HOME changes path-sensitive artifacts/fingerprints.
rust-lang/cargo#12137 Cargo trim-paths and remap-scope tracking issue.

Benchmarks building ClickHouse

Running on a AMD Ryzen 9 9950X with 96G

Scenario Average build time Sample SD C/C++ hits C/C++ misses Rust hits Rust misses
ccache 142.73s 2.03s 16,614 2 Not wrapped Not wrapped
sccache with Rust 54.91s 0.63s 16,730 2 822 0
sccache with Rust, client-side 154.72s 0.27s 16,730 2 808 0
sccache C/C++ only 144.03s 0.78s 16,614 2 Not wrapped Not wrapped

The interesting part here is that using the new client-side architecture, it slows down a lot. I'll probably create a separate issue to point that.

Closes: #2652
Closes: #2765
Related: #2678
Related: #2595

mmastrac and others added 5 commits July 31, 2026 13:25
SCCACHE_BASEDIRS now normalizes cwd, CARGO_MANIFEST_DIR,
CARGO_WORKSPACE_DIR, CARGO_TARGET_TMPDIR, CARGO_MANIFEST_PATH,
CARGO_BIN_EXE_*, dep-info env var values, and the concatenated
argument string in the Rust compiler's hash key computation. This
enables cache hits when the same crate is compiled from different
absolute paths on different machines (e.g., CI runners with
different checkout roots).

strip_basedir_prefix now also matches when the value equals the
basedir minus its trailing '/', so `cwd == basedir` strips to the
empty string rather than passing through. Without this, two
machines with different checkout paths produced different hashes
even with matching basedirs -- the feature's central claim.
mozilla#2652
mozilla#2678

Keep rustc-reported environment dependencies location-sensitive and hash
PGO data and LLVM plugins before normalizing their paths. Preserve non-path
argument bytes on Windows and use conservative matching for non-ASCII input.

Handle exact and overlapping basedirs consistently, bump the Rust cache-key
version, and document that embedded paths still require compiler remapping.
mozilla#2652
mozilla#2678

Replace broad Rust argument scanning with normalization of explicit remap
prefixes and path-valued Cargo variables. Hash the actual path produced by
rustc remapping, honoring scope and mapping precedence, while keeping
unremapped working directories location-sensitive.

Frame normalized values to prevent absolute and relative inputs from sharing
a key. Reduce the mock and integration-test changes, and leave profile and
plugin paths location-sensitive.
Hash effective source paths without conflating duplicate remaps, and preserve Cargo path values whenever procedural macros can run.

Honor rustc remap-scope precedence, keep non-identity distributed path transforms local, add CARGO_INSTALL_ROOT coverage, and bump the key version.
Version 7 was introduced by this unmerged change series, so later refinements do not require another upstream cache-key version.
@sylvestre

Copy link
Copy Markdown
Collaborator

Long comment #0 written by a llm isn't useful... Please make it shorter

@codecov-commenter

codecov-commenter commented Aug 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.51412% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.23%. Comparing base (c037e11) to head (928dbf6).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
src/compiler/rust.rs 98.39% 10 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2794      +/-   ##
==========================================
- Coverage   74.32%   74.23%   -0.10%     
==========================================
  Files          71       72       +1     
  Lines       40789    40555     -234     
==========================================
- Hits        30318    30107     -211     
+ Misses      10471    10448      -23     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@pamarcos

pamarcos commented Aug 5, 2026

Copy link
Copy Markdown
Author

Long comment #0 written by a llm isn't useful... Please make it shorter

Roger. I cut most of it. Left the implementation details available in case someone's interested, though.

Build expected remapped paths with Path::join because rustc uses platform-native separators. This fixes the Windows test matrix without changing remap behavior.
Exercise malformed and nonmatching remap values, separated scope syntax, and absolute source arguments.

Coverage report: https://app.codecov.io/gh/mozilla/sccache/pull/2794?src=pr&el=tree
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Should exclude --remap-path-prefix from cache key Wire SCCACHE_BASEDIRS into Rust hash key

4 participants