Symptom
fbuild's CI infrastructure, Docker setup, and documentation still reference standalone zccache.exe / zccache-daemon.exe / zccache-fp.exe binaries. This was correct under the pre-2026-06 soldr architecture (where soldr fetched a standalone zccache.exe and used it as RUSTC_WRAPPER), but is stale now:
None of the stale references in fbuild actively break the build today (all four sites are defensively guarded — [ -f ... ] checks, || true, test data that the parser correctly handles, doc strings nobody runs). But:
- The Docker step silently produces a smaller image than intended (the loop body never copies anything for the zccache entries because the files no longer exist in the upstream tarball).
- The CI pkill step is dead code masquerading as live housekeeping.
- The setup.py docstring is documentation that describes a fiction.
- The test data cements an outdated mental model that will misdirect future debugging.
Smoking guns
1. Dockerfile copies non-existent binaries
File: ci/docker-mac-cross/Dockerfile:68-70
RUN for bin in soldr cargo-chef crgx zccache zccache-daemon zccache-fp; do \
[ -f "/opt/soldr-bin/$bin" ] && cp "/opt/soldr-bin/$bin" "/usr/local/bin/$bin" && chmod +x "/usr/local/bin/$bin"; \
done
The [ -f ... ] guard means missing files silently skip, but the intent was to ship zccache zccache-daemon zccache-fp alongside soldr. The pinned SOLDR_VERSION=0.7.59 on line 60 predates the embedded-zccache transition, so the upstream tarball still has those binaries today — but once SOLDR_VERSION gets bumped past the next release (≥ 0.7.72 or wherever the zccache-soldr shim ships), the copy will silently no-op for all three zccache entries.
2. CI workflow kills a daemon that no longer exists
File: .github/workflows/template_build.yml:71-72
- name: Reset zccache daemon after cache warm
run: pkill -f '[z]ccache-daemon' || true
With embedded zccache, there is no zccache-daemon process running separately. The daemon is soldr-daemon (which embeds zccache), and the lifecycle is owned by soldr — fbuild shouldn't be pkilling it.
3. setup.py docstring describes the legacy architecture
File: setup.py:29
- soldr auto-sets `RUSTC_WRAPPER` to zccache, so rebuilds across `pip
install .` invocations are incremental + dep-cached.
This is no longer accurate. soldr now sets RUSTC_WRAPPER = <current soldr binary path>; the new dedicated shim is zccache-soldr (not zccache). The user-visible behavior (incremental rebuilds across pip install invocations) is unchanged — only the underlying mechanism. But the doc misleads anyone debugging the wrapper chain.
4. Test data uses legacy zccache.exe wrap shape
File: crates/fbuild-build/src/compile_database/tests/cache_wrapper.rs:28-39
#[test]
fn test_strip_zccache_wrap_mode() {
let args = vec![
"C:\\tools\\zccache.exe".to_string(),
"wrap".to_string(),
"C:\\tc\\bin\\xtensa-esp32-elf-g++.exe".to_string(),
...
];
The test isn't broken — strip_cache_wrapper should still be able to parse historical command lines. But hardcoded C:\tools\zccache.exe test data + the wrap subcommand is the legacy pattern. Should be either deleted (if no production code paths still emit this shape) or relabeled with a doc comment explaining it's a backward-compat parse test for a deprecated pattern.
Note: fbuild's core integration is already correct
crates/fbuild-build/Cargo.toml already depends on zccache as a library directly, mirroring soldr's embedded model. The infrastructure-side staleness above is purely vestigial — fbuild has the right architecture; it just has dead code from the old one.
Proposed fix
Four mechanical changes:
ci/docker-mac-cross/Dockerfile: remove zccache zccache-daemon zccache-fp from the for-loop on line 68. Keep soldr cargo-chef crgx.
.github/workflows/template_build.yml: delete the "Reset zccache daemon after cache warm" step (lines 71-72). soldr-daemon's lifecycle is owned by soldr; fbuild should not be pkilling it. If a daemon reset between cache warm and build is genuinely needed, replace with soldr daemon stop (which goes through the IPC shutdown path).
setup.py:29: update the docstring to: soldr auto-sets RUSTC_WRAPPER to itself (or the zccache-soldr shim, per soldr 1081), which talks to soldr-daemon's embedded zccache — rebuilds across "pip install ." invocations are incremental + dep-cached.
crates/fbuild-build/src/compile_database/tests/cache_wrapper.rs:28-39: either delete the test (if no production callers still emit zccache wrap) OR add a // Legacy pre-embedded zccache.exe wrap-mode parse test; retained for backwards-compat parsing only. doc comment above the #[test] so future readers know the shape is intentional historical test data.
Acceptance criteria
References
Symptom
fbuild's CI infrastructure, Docker setup, and documentation still reference standalone
zccache.exe/zccache-daemon.exe/zccache-fp.exebinaries. This was correct under the pre-2026-06 soldr architecture (where soldr fetched a standalonezccache.exeand used it asRUSTC_WRAPPER), but is stale now:zccache.exe. The library is embedded into soldr-daemon (Adopt zccache embedded service (drop the IPC roundtrip + zccache subprocess) zackees/soldr#977 / ci(release): cross-build x64 Windows artifacts on Linux #980 L1).zccache-soldr.exeshim binary (RUSTC_WRAPPER=zccache.exe broken on Windows — zccache-1.12.11 dropped the standalone binary when daemon embedded zccache; need a zccache-soldr shim zackees/soldr#1081 / PR harden(rp2040): deploy robustness across host setups (hub chains, drive-scan stalls, timeout policy) #1082) is the dedicated RUSTC_WRAPPER and talks to soldr-daemon over IPC.None of the stale references in fbuild actively break the build today (all four sites are defensively guarded —
[ -f ... ]checks,|| true, test data that the parser correctly handles, doc strings nobody runs). But:Smoking guns
1. Dockerfile copies non-existent binaries
File:
ci/docker-mac-cross/Dockerfile:68-70The
[ -f ... ]guard means missing files silently skip, but the intent was to shipzccache zccache-daemon zccache-fpalongside soldr. The pinnedSOLDR_VERSION=0.7.59on line 60 predates the embedded-zccache transition, so the upstream tarball still has those binaries today — but once SOLDR_VERSION gets bumped past the next release (≥ 0.7.72 or wherever the zccache-soldr shim ships), the copy will silently no-op for all three zccache entries.2. CI workflow kills a daemon that no longer exists
File:
.github/workflows/template_build.yml:71-72With embedded zccache, there is no
zccache-daemonprocess running separately. The daemon issoldr-daemon(which embeds zccache), and the lifecycle is owned by soldr — fbuild shouldn't be pkilling it.3. setup.py docstring describes the legacy architecture
File:
setup.py:29This is no longer accurate. soldr now sets
RUSTC_WRAPPER = <current soldr binary path>; the new dedicated shim iszccache-soldr(notzccache). The user-visible behavior (incremental rebuilds across pip install invocations) is unchanged — only the underlying mechanism. But the doc misleads anyone debugging the wrapper chain.4. Test data uses legacy
zccache.exe wrapshapeFile:
crates/fbuild-build/src/compile_database/tests/cache_wrapper.rs:28-39The test isn't broken —
strip_cache_wrappershould still be able to parse historical command lines. But hardcodedC:\tools\zccache.exetest data + thewrapsubcommand is the legacy pattern. Should be either deleted (if no production code paths still emit this shape) or relabeled with a doc comment explaining it's a backward-compat parse test for a deprecated pattern.Note: fbuild's core integration is already correct
crates/fbuild-build/Cargo.tomlalready depends onzccacheas a library directly, mirroring soldr's embedded model. The infrastructure-side staleness above is purely vestigial — fbuild has the right architecture; it just has dead code from the old one.Proposed fix
Four mechanical changes:
ci/docker-mac-cross/Dockerfile: removezccache zccache-daemon zccache-fpfrom the for-loop on line 68. Keepsoldr cargo-chef crgx..github/workflows/template_build.yml: delete the "Reset zccache daemon after cache warm" step (lines 71-72). soldr-daemon's lifecycle is owned by soldr; fbuild should not be pkilling it. If a daemon reset between cache warm and build is genuinely needed, replace withsoldr daemon stop(which goes through the IPC shutdown path).setup.py:29: update the docstring to:soldr auto-sets RUSTC_WRAPPER to itself (or the zccache-soldr shim, per soldr 1081), which talks to soldr-daemon's embedded zccache — rebuilds across "pip install ." invocations are incremental + dep-cached.crates/fbuild-build/src/compile_database/tests/cache_wrapper.rs:28-39: either delete the test (if no production callers still emitzccache wrap) OR add a// Legacy pre-embedded zccache.exe wrap-mode parse test; retained for backwards-compat parsing only.doc comment above the#[test]so future readers know the shape is intentional historical test data.Acceptance criteria
grep -r 'zccache-daemon\|zccache\.exe\|zccache-fp' --include='*.yml' --include='*.py' --include='Dockerfile*' .returns zero matches inci/and.github/workflows/(test data exception above is documented).SOLDR_VERSIONin the cross-mac Dockerfile to the latest release (post zccache-soldr shim landing) doesn't silently degrade the image's content.setup.pydocstring describes the currentRUSTC_WRAPPER = soldr / zccache-soldrarchitecture, not the legacyRUSTC_WRAPPER = zccache.exeone.References