skip to content

How do you enable ccache for a React Native app on Android and on iOS, and how do you confirm it is actually working?

level: middleimportance: should knowfreq 28%

answer

  1. wraps the C/C++ compiler
  2. Android CMake picks it up automatically
  3. iOS: ccache_enabled in the Podfile
  4. ccache -s shows hits and misses
  5. CI: compiler_check content

basics

~20 s

Install ccache; React Native's Android CMake setup uses it automatically, and on iOS you turn on ccache_enabled in the Podfile's react_native_post_install (or run pod install with USE_CCACHE=1). Confirm with ccache -s: a second clean build should show mostly hits.

solid answer

~50 s

ccache wraps the C and C++ compilers, stores each compilation result, and returns it instead of compiling again when the same input comes back. On Android, React Native's application CMake setup looks for `ccache` and uses it as the compiler launcher when it is installed, so there is nothing else to switch on. On iOS I uncomment `:ccache_enabled => true` in `react_native_post_install` in the Podfile, or run `USE_CCACHE=1 bundle exec pod install`; the pods then compile through React Native's `ccache-clang.sh` wrappers. To confirm, I run `ccache --zero-stats`, do a clean build, delete the build output, build again, and read `ccache -s`: the second build should be mostly hits and take seconds instead of minutes. On CI, ccache's timestamp checks miss because files are freshly checked out, so the React Native docs recommend `compiler_check content` or clean builds.

code

ruby · 8 lines
ruby
post_install do |installer|
  react_native_post_install(
    installer,
    config[:reactNativePath],
    :mac_catalyst_enabled => false,
    :ccache_enabled => true
  )
end

go deeper

for a junior

Know that ccache caches compiled native code, that Android picks it up automatically, and that iOS needs ccache_enabled in the Podfile.

for a middle

Explain how to verify hits with ccache -s and --zero-stats, and why timestamps defeat it on CI.

for a senior

Decide when ccache is worth it given prebuilt iOS core, how to keep CI caches from being poisoned, and when to consider sccache.

for a principal

Weigh local versus distributed caching for a large team: shared storage, trust in cached artefacts, and the maintenance each option demands.

## What ccache does **ccache** is a compiler cache. It sits in front of the C and C++ compilers: for each compilation it computes a key from the source, the compiler and the flags, and if that key has been seen before it returns the stored object file instead of compiling again. It helps whenever the **same native sources are compiled repeatedly** — clean builds, switching branches, deleting build folders — which is common in a React Native project. ## Enabling it | Platform | What to do | Why it works | |---|---|---| | Android | install `ccache` (for example `brew install ccache`) | React Native's application CMake setup finds `ccache` and sets it as the compile launcher | | iOS | set `:ccache_enabled => true` in `react_native_post_install`, or run `pod install` with `USE_CCACHE=1` | the pods are configured to compile through React Native's `ccache-clang.sh` and `ccache-clang++.sh` wrappers | On iOS, `pod install` prints whether it found ccache. The wrappers point ccache at a configuration file shipped with React Native, unless you set `CCACHE_CONFIGPATH` yourself. ## Confirming it works 1. **Reset the statistics** with `ccache --zero-stats`, so the numbers describe only this experiment. 2. **Do a clean build** — for Android, run the app, delete `android/app/build`, run it again. 3. **Read `ccache -s`.** The first build is mostly misses; the second should be mostly hits and take seconds rather than minutes. 4. **If hits stay low**, check that ccache is on the `PATH` used by the build, that the iOS pods were re-installed after changing the flag, and that flags or paths are not changing between builds. `ccache --clear` empties the cache when you suspect a bad entry. ## Reading `ccache -s` The summary the React Native docs show has a few lines worth knowing: - **Hits / Misses** — how many compilations were served from the cache versus compiled; a warm repeat build should be dominated by hits. - **Direct / Preprocessed** — the two ways ccache can find a match; either counts as a hit. - **Uncacheable** — invocations ccache cannot cache at all, such as some linking or unusual flags; a handful is normal. - **Cache size** — current size against the configured maximum; a cache that is always full evicts entries you still need. Statistics accumulate across builds, which is why resetting them before an experiment matters. ## Using it on CI The React Native docs flag two problems: - **Timestamps.** By default ccache also considers file modification times. On CI, every run checks files out fresh, so timestamps always change and lookups miss. Setting ccache's `compiler_check` option to `content` makes it hash contents instead. - **Poisoned caches.** A corrupted or stale entry restored into every run can produce hard-to-explain failures. The docs recommend full clean builds on CI and parallelising Android ABIs instead, noting that you will then most likely not need ccache there. On macOS the cache lives in `~/Library/Caches/ccache`, which is the folder a CI job would save and restore. ## When a local cache is not enough: sccache For larger organisations doing frequent native builds, the docs point to **sccache** as a **distributed** compiler cache: many machines share one cache, so one developer's or runner's compilation benefits everyone. It needs shared storage and setup; the docs defer to sccache's own quickstart. ## Knowing what it can and cannot speed up - **It caches C, C++ and Objective-C compilation.** Swift, Kotlin and Java compilation are not accelerated by it. - **Its value shrinks with prebuilt iOS core.** Since 0.84, React Native core arrives as precompiled xcframeworks, so far less C++ is compiled on iOS; heavy third-party native modules or a source build of core are where it still pays. - **It cannot help a first build** on an empty cache — only repeats. ## Common mistakes - Installing ccache and never re-running `pod install` with ccache enabled on iOS. - Reading cumulative statistics without `--zero-stats` and concluding the hit rate is poor. - Restoring a ccache folder on CI without changing `compiler_check`, then seeing no hits. - Expecting ccache to speed up Swift or Kotlin.

  • Your React Native CI job restores the ccache folder but ccache -s shows almost no hits. Why?
    ccache's default checks include file timestamps, and a CI checkout gives every file a new timestamp, so keys never match. Set ccache's `compiler_check` option to `content` so it hashes file contents. Also make sure paths and flags are stable between runs; otherwise consider clean CI builds, as the React Native docs suggest.
  • When would a team move from ccache to sccache for React Native native builds?
    When many developers or runners compile the same native code and each local cache starts cold. sccache shares one distributed cache across machines, so a compilation done once benefits everyone. It needs shared storage and configuration, so it pays off in larger organisations with frequent native builds.

saying these in an interview costs you the question

  • On Android you must also edit build.gradle to turn ccache on
  • ccache speeds up Swift and Kotlin compilation too
  • A restored ccache folder gives hits on CI with default settings
  • The first build after installing ccache is already faster
  • Prebuilt iOS core makes ccache more valuable, not less