|  | # Using `ccache` to build IREE | 
|  |  | 
|  | [`ccache`](https://ccache.dev/) is a compilation cache. In principle, just | 
|  | prepending compiler invocations with `ccache` is all one needs to enable it, | 
|  | e.g. | 
|  | ```shell | 
|  | ccache clang foo.c -c -o foo.o | 
|  | ``` | 
|  | takes care of executing `clang` with these arguments and caches the output file | 
|  | `foo.o`. The next invocation then skips executing `clang` altogether. | 
|  |  | 
|  | When the cache is hit, the speedup is such that the "compilation" becomes | 
|  | essentially free. However, `ccache` only caches compilation, [not linking](https://stackoverflow.com/a/29828811). | 
|  |  | 
|  | Here a few scenarios where `ccache` helps: | 
|  | * Incremental rebuilds. While `cmake` always tries to avoid unnecessary work in | 
|  | incremental rebuilds, it can only make simple decisions based on file | 
|  | timestamps. `ccache` sees deeper: if the raw source code isn't readily | 
|  | a cache hit, it will then try again after preprocessing and discarding | 
|  | comments. | 
|  | * One pain point with `cmake` is having to start over from a clean build | 
|  | directory from time to time, which by default means paying again the full cost | 
|  | of a cold build. Thankfully `ccache` keeps its cache outside of any `cmake` | 
|  | build directory, so the first build in the new clean build directory may be | 
|  | very fast. | 
|  |  | 
|  |  | 
|  | ## Installing and setting up `ccache` | 
|  |  | 
|  | `ccache` is available on most platforms. On Debian-based Linux distributions, | 
|  | do: | 
|  | ```shell | 
|  | sudo apt install ccache | 
|  | ``` | 
|  |  | 
|  | The one `ccache` setting that you probably need to configure is the maximum | 
|  | cache size. The default `5G` is too small for our purposes. To set the cache max | 
|  | size, do this once: | 
|  | ```shell | 
|  | ccache --max-size=20G | 
|  | ``` | 
|  |  | 
|  | **Tip:** At the moment (late 2020), most of the code we're building is | 
|  | `third_party/llvm-project` so the fundamental limiting factor to how far we can | 
|  | cache away rebuilds is how often that dependency gets updated. Given how | 
|  | frequently it currently is updated, I'm finding that `20G` is enough to make the | 
|  | `ccache` size not be the limiting factor. | 
|  |  | 
|  | ## Telling CMake to use `ccache` | 
|  |  | 
|  | In the initial CMake configuration step, set the `IREE_ENABLE_CCACHE` and | 
|  | `LLVM_CCACHE_BUILD` options, like this: | 
|  | ```shell | 
|  | cmake -G Ninja \ | 
|  | -DIREE_ENABLE_CCACHE=ON \ | 
|  | -DLLVM_CCACHE_BUILD=ON \ | 
|  | ... other options as usual | 
|  | ``` | 
|  |  | 
|  | Notes: | 
|  | * This approach only works with the `Ninja` and `Makefile` generators (`cmake | 
|  | -G` flag). When using other generators, another approach is needed, based on | 
|  | wrapping the compiler in a script that prepends `ccache`. See this | 
|  | [article](https://crascit.com/2016/04/09/using-ccache-with-cmake/). | 
|  | * We do need two separate options `IREE_ENABLE_CCACHE` and `LLVM_CCACHE_BUILD`, | 
|  | because of how CMake leaves it up to each project to define how to control the | 
|  | use of `ccache`, and `llvm-project` is a `third_party/` project in IREE. Note | 
|  | that most of the compilation time is spent in `llvm-project`, so | 
|  | `LLVM_CCACHE_BUILD` is the most important flag here. | 
|  |  | 
|  | ## Ensuring that `ccache` is used and monitoring cache hits | 
|  |  | 
|  | The `ccache -s` command dumps statistics, including a cache hit count and ratio. | 
|  | It's convenient to run periodically with `watch` in a separate terminal: | 
|  | ```shell | 
|  | watch -n 0.1 ccache -s  # update the stats readout every 0.1 seconds | 
|  | ``` |