Skip to content
Getting Started

C/C++ caching

kache can wrap C and C++ compilers in addition to rustc. This path is live for local object compiles and intentionally conservative: if kache cannot model an invocation safely, it passes through to the real compiler.

Setup

For Make, CMake, autotools, or build scripts that honor CC / CXX:

export CC="kache cc"
export CXX="kache c++"

For Cargo build scripts that use the Rust cc crate, also declare kache as a known wrapper so the crate keeps the real compiler argument:

export CC_KNOWN_WRAPPER_CUSTOM="kache"

For clang-cl / MSVC-driver mode:

set "CC=kache clang-cl"

kache recognizes cc, c++, gcc, g++, clang, clang++, versioned variants like gcc-13, target-prefixed cross compilers like arm-linux-gnueabihf-gcc, clang-cl, and clang --driver-mode=cl.

What Is Cached

kache caches single-source object compiles:

cc -c src/foo.c -o build/foo.o
c++ -c src/foo.cpp -o build/foo.o
clang-cl -c foo.c -Fofoo.obj

On a hit, kache restores the object file and dep-info sidecar without re-running the compiler. The key includes:

  • preprocessor output, so header edits invalidate the object
  • compiler identity and resolved target/codegen flags
  • source path normalization for gcc/clang
  • CodeView path inputs for clang-cl debug compiles (/Z7, -Z7, -g)

For gcc/clang, keys are portable across worktrees when paths normalize cleanly. Use KACHE_BASE_DIR for checkout, container mount, or shared source/build prefixes the automatic detection cannot strip.

For clang-cl debug builds, keys are machine-local. clang-cl embeds CodeView paths in the .obj and does not honor -ffile-prefix-map, so kache keeps those paths literal instead of pretending the object is portable.

Out-of-tree builds

kache supports out-of-tree C/C++ builds, including sibling CMake-style layouts:

cmake -S source -B build
cmake --build build

The cache key normalizes both source and build roots when kache can derive them from the compiler invocation. If generated sources, configured headers, or __FILE__ paths point above those roots, set KACHE_BASE_DIR to the common parent so the same object can hit across fresh checkouts:

KACHE_BASE_DIR="$PWD" cmake --build build

What Passes Through

These shapes compile normally but are not cached yet:

  • link or whole-program steps
  • multi-source or multi-arch invocations
  • response files (@file)
  • precompiled headers and modules
  • coverage and split-DWARF
  • clang-cl -bigobj and -showIncludes
  • flags kache has not classified

C/C++ artifacts are local-only today. S3 sync and remote sharing apply to Rust artifacts, not cc objects.

Diagnosing Passthroughs

Use kache monitor and open the Passthrough tab, or run with debug logging:

KACHE_LOG=kache=debug make

If a safe flag is missing from kache's built-in allow-list, opt it in locally:

[cc]
extra_allowlist_flags = ["-ffunction-sections", "-fdata-sections"]

The flag is folded into the key verbatim. Avoid host-dependent values like -march=native, because the same spelling can produce different objects on different CPUs.

Available for:
Apple macOS logomacOSMicrosoft Windows logoWindowsLinux logoLinux
Download Kunobi