ccache
is great on your laptop.
sccache
adds a daemon and a remote cache.
distcc
farms compiles across machines. They all assume the worker is trusted shared-kernel infrastructure. hpcc assumes it isn't.
A bwrap sandbox is not. A KVM boundary is. That single distinction is the entire reason hpcc exists — and the reason every existing OSS distributed compiler stalls at the regulated-enterprise door.
The worker is trusted shared-kernel infrastructure. Isolation is best-effort: a bubblewrap namespace, a Linux user, a chroot. Defensible on a laptop, indefensible in a regulated multi-tenant environment.
The worker is hostile-by-default, multi-tenant, and on the audit trail. One Firecracker microVM per tenant session. Separate kernel. KVM boundary. No NIC. Every compile produces a single audit row reproducible from one line of a TSV.
A cell-by-cell view of the boundary your auditor can recognise — and the operational pieces that fall out of it.
| ccache | sccache-dist | distcc | hpcc | |
|---|---|---|---|---|
| Worker isolation | none local user, no remote |
bwrap shared kernel namespace |
none worker is the host |
Firecracker · KVM per-tenant microVM, separate kernel |
| Network on worker | — | full NIC | full NIC | no NIC · vsock only |
| Toolchain identity | compiler binary hash | compiler binary hash | operator-managed | OCI image digest |
| Preprocessing | client-side | client- or server-side | client-side | client-side · canonical bytes via image-pinned env + auto-injected flags |
| Audit trail | — | logs | logs | per-job row · 9-tuple · reproducible |
| Reproducibility | by ceremony | by ceremony | by ceremony | auto-injected flags · pinned env |
| Cache poisoning | laptop-trusted | client writes cache | — | paranoid mode · worker-only writes |
| Windows path | — | — | — | Hyper-V isolated · MSVC behind same RPC |
Driven directly by hpcc — no firecracker-containerd dependency. The VM stays warm across compiles, snapshotted on idle timeout. Separate kernel. KVM boundary.
There is no exfiltration argument to have, because there is no network device. Full stop. Host↔guest is one vsock device carrying a single bidirectional gRPC stream.
No "hash the gcc binary" dance. 50 developers sharing one image produce one cache bucket. CI and laptops cannot silently diverge.
The scheduler is a lookup service — never touches compile payloads or artifact bytes. The client dials the worker directly. No proxy hop, no bottleneck, no scheduler holding cache keys it doesn't need.
Auto-injected -Werror=date-time, -ffile-prefix-map, -frandom-seed; pinned locale, timezone, hostname inside the VM. Byte-identical outputs by default — not by ceremony.
(image_digest, source_digest, flags, output_digest, tenant, worker, vm, duration, exit) — every compile, reproducible from a single line. The table format auditors want to see.
hpcc explain <file> names which header or which flag changed the cache key. Not a debug log you have to grep.
Preprocessed C++ compresses 5–10×. The single largest perf lever, and it's on by default.
Cache reads and writes happen only on the worker. Clients never touch cache stores, never hold remote-store credentials. A compromised laptop cannot poison the cache.
The scheduler returns a worker address and TLS trust info — it never touches compile payloads. The client dials the worker directly. The worker dispatches into a tenant-pinned Firecracker VM via a single bidirectional gRPC stream over a vsock device. No NIC ever appears in the guest.
Every job emits a 9-tuple. hpcc inspect <hash> reads it back. hpcc explain <file> tells you which header or flag broke the key — not a log to grep.
When a build that should have hit the cache misses, the question stops being "where do I start?" and starts being "what changed?" hpcc answers the second question directly.
The cache loop and the daemon are table stakes — sccache does those well. hpcc's bet is on phase 4: the place existing tools can't follow without rebuilding their isolation model from scratch.