kache 0.8.0 — zero-copy restores on Windows, and a self-healing cache
kache is a content-addressed build cache that plugs in as a RUSTC_WRAPPER (and a C/C++ compiler wrapper). 0.7.0 made big real-world C/C++ trees cache; 0.8.0 makes restoring them fast on Windows and makes the cache resilient — it heals a corrupt index instead of bricking, and keeps converging keys across clones.
Why
The zero-copy restore story was a Linux/macOS story (reflink/CoW). On Windows it fell back to copying every byte. And a single corrupt on-disk index — easy to hit when a cache home is shared across hosts — could take out every command. 0.8.0 closes both gaps.
What's new
- Zero-copy restores on Windows. On a ReFS volume (e.g. a Windows 11 Dev Drive) restores now use block-cloning (copy-on-write) for an independent, zero-copy file — the Windows analog of reflink. NTFS gets a clear warning;
KACHE_WINDOWS_HARDLINKopts into hardlinks where appropriate. - Self-healing index. A corrupt cache index now self-heals to a miss instead of failing every command — meta files on disk are the source of truth. Plus a clear warning when the index can't be opened at all.
- Steadier cross-clone keys. Native
static=libs are content-hashed (an in-place rebuild is no longer a stale hit), dependency-file flags are dropped from the cc key (a cross-clone key race), andrustc-envinclude paths underOUT_DIRare normalized (Substrate cascade). - Richer traces. Perfetto trace lanes are named and show hit/miss right in the slice.
Hardening
More modeled C/C++ codegen knobs so more TUs cache (-Xclang-forwarded knobs, -fomit-frame-pointer + x86 ISA, bare -fansi-escape-codes); SOURCE_DATE_EPOCH pinned on the real compile, not just the key probe; a retry on transient Windows ACCESS_DENIED during blob materialize; and daemon doctor checks are now informational when no daemon is needed.
These notes were drafted with LLM assistance and edited by the maintainers (@jleni, @emmanuelm41).
What's Changed
- refactor(cc): polarity-aware codegen-knob stems + LLVM-shaped Ninja canary by @jleni in #430
- fix(cc): cache -Xclang-forwarded modeled codegen knobs (#428, -ffp-contract=off) by @jleni in #433
- fix(link): copy on Windows restore so consumers can delete/rewrite output (#429) by @jleni in #432
- build(windows): statically link the MSVC CRT (crt-static) by @emmanuelm41 in #434
- feat(link): ReFS block-clone restore on Windows + NTFS warning + hardlink opt-in by @jleni in #435
- fix(key): normalize rustc-env include paths under OUT_DIR (substrate cascade seed) by @jleni in #436
- ci(macos): pin self-hosted macOS jobs to the mac-mini runners by @jleni in #437
- fix(cc): restore bare -fansi-escape-codes classification (#438) by @jleni in #439
- test: raise product-code coverage above 90% by @jleni in #440
- bench(firefox): add Windows (clang-cl) scenario + dispatch job by @jleni in #444
- test(e2e): feature-coverage matrix + cc refusal scenarios by @jleni in #445
- feat(doctor): make daemon checks informational when daemon isn't needed (#443) by @emmanuelm41 in #448
- ci(windows): point runner-provisioning refs at the real ans-runners path by @emmanuelm41 in #449
- fix(cc): drop dependency-file flags from the cc cache key (cross-clone keyrace) by @jleni in #450
- ci(bench): serialize Linux bench arms (max-parallel: 1) — probe for #447 by @emmanuelm41 in #452
- ci(bench): drop max-parallel cap; rely on runner anti-affinity (#447) by @emmanuelm41 in #453
- test(bench): surface filtered TU-matching artifacts in the key-diff report by @jleni in #451
- test(e2e): cross-clone cascade fixtures + cc dep-info keytrace by @jleni in #454
- chore(release): bump version to 0.8.0-rc.1 by @emmanuelm41 in #455
- fix(bench): mach bootstrap --no-system-changes on Windows (#447 follow-up) by @pecorino-bot in #457
- docs: mention cc wrapper env by @DaniPopes in #459
- fix(bench): disambiguate firefox profile by exact name; drop misleading os:linux tag (#458) by @jleni in #461
- fix(cc): pin SOURCE_DATE_EPOCH on the real compile, not just the -E key probe (#423) by @jleni in #462
- fix(store): retry materialize_blob rename on transient Windows ACCESS_DENIED under concurrent put/remove (#441) by @jleni in #463
- fix(store): self-heal a corrupt index instead of bricking every command (#415, phase 1) by @jleni in #465
- feat(report): name Perfetto trace lanes and surface hit/miss in the slice (#456) by @jleni in #466
- fix(cache-key): content-hash native static= libs so an in-place rebuild isn't a stale hit (#421) by @jleni in #464
- test(bench): add SurrealDB compile-cache scenario to the bench suite by @emmanuelm41 in #467
- fix(bench): don't degrade a run on tolerated wrapped-compile failures by @emmanuelm41 in #468
- fix(bench): don't over-report content-identical static libs in key-diff by @emmanuelm41 in #472
- feat(wrapper): clear warning when the cache index can't be opened (#469) by @emmanuelm41 in #473
- bench(surrealdb): byte-reproducible native libs across clones (partial #471) by @emmanuelm41 in #474
- chore(release): bump workspace version to 0.8.0 by @emmanuelm41 in #475
New Contributors
- @pecorino-bot made their first contribution in #457
Full Changelog: v0.7.0...v0.8.0