Ccache speeds up recompilation by caching previous compiler outputs and reusing them when the same inputs appear again. Properly configured, it produces identical output to a no‑cache build—the only difference should be speed.
Why use ccache
Faster rebuilds: Recompiling unchanged files becomes near‑instant thanks to cache hits.
Safe by design: Aims to match compiler output exactly, with documented caveats when that’s not possible.
Fits team workflows: Works as a transparent wrapper around compilers; can be enabled per‑project or system‑wide.
Install and basic configuration
Install ccache (pkg or ports):
pkg install ccache
This provides the ccache binary and libexec wrappers for use with system or ports builds.
Set cache directory and PATH (shell env):
export CCACHE_DIR=/var/cache/ccache export CCACHE_LOGFILE=/var/log/ccache.log export PATH=/usr/local/libexec/ccache:$PATH
Using the libexec path ensures the compiler calls go through ccache; setting a shared cache dir/log helps with observability.
Now we create a /var/cache/ccache in zfs
# zfs create -o mountpoint=/var/cache/ccache zroot/ccache # zfs set dedup=on compression=lz4 atime=off recordsize=128K zroot/ccache
Now we set permissions for system-wide builds:
# chown -R root:wheel /var/cache/ccache # chmod 775 /var/cache/ccache
Initialize ccache:
# ccache -M 10G Set cache size limit to 10.0 GB
Adjust size based on disk; larger caches yield more hits for big codebases.
System builds and ports: enabling ccache
World/kernel builds
Enable ccache for buildworld/buildkernel: Add to /etc/src.conf:
WITH_CCACHE_BUILD=yes CCACHE_DIR=/var/cache/ccache
Alternatively, export CC/CXX via wrappers for targeted use:
export CC=/usr/local/libexec/ccache/cc export CXX=/usr/local/libexec/ccache/c++
Wrapping compilers is the canonical approach; many setups use libexec wrappers for world builds to gain cache hits across iterative rebuilds.
Ports tree builds
Enable ccache in /etc/make.conf:
.if !defined(NO_CCACHE)
CC=/usr/local/libexec/ccache/cc
CXX=/usr/local/libexec/ccache/c++
.endif
# Avoid recursive ccache when building the ccache port itself:
.if ${.CURDIR:M*/ports/devel/ccache}
NO_CCACHE=yes
.endif
This standard pattern enables ccache for ports while skipping the ccache port to avoid weird recursion.
Best practices for FreeBSD setups
Put cache on fast storage: SSD or a dedicated ZFS dataset improves hit latency; pair with an adequate cache size for large trees.
Match compilers and flags: Cache keys include compiler, flags, and environment; consistent toolchains maximize hit rate.
Use logs to tune: CCACHE_LOGFILE helps diagnose misses (e.g., preprocessor differences, path mismatches).
Combine with meta mode (advanced): For kernel/module work, META_MODE reduces redundant rebuilds; ccache then accelerates the remaining compiles. Use both judiciously and expect diminishing returns for tiny modules that already build fast.
Common caveats and troubleshooting
Non‑deterministic inputs: Build steps that embed timestamps, randomized macros, or absolute paths can reduce cache hits.
Compiler masquerade issues: Ensure the PATH or CC/CXX wrappers are consistent across invocations; mismatched paths lead to misses.
Building ccache itself: Exclude ccache from being wrapped during its own build to avoid recursion and logging noise.
Kernel modules: For single‑module development, linking often dominates; ccache helps compile times but won’t speed the link step.
Quick commands cheat sheet
Enable globally (session):
export PATH=/usr/local/libexec/ccache:$PATH export CCACHE_DIR=/var/cache/ccache ccache -M 10G
World build with ccache:
make -C /usr/src buildworld buildkernel
Check stats:
ccache -s
If you missed my article on new ports setup, here are the ports after portsnap, git how-to, and zfs tips