I tested my codebase with currently favors 'ccache gcc-6 -flto' over 'ccache clang-3.9 -flto' with zapcc.
It's a pure C project.
* Build-time went from 58s to 37s with zapcc. I didn't use zapcc with ccache and shouldn't.
* Run-time went from 371s down to 204s. Almost double speed!
So it's clearly an effect of clang-4 over gcc-6, and not so much zapcc.
Then I crosschecked with clang-4. The run-time is entirely based on clang-4, confirmed.
But the build-time with clang-4 was 44s, still 20% slower than with zapcc.
What I learned:
* ccache is horrible. zapcc is much better.
* clang-4 is fantastic, even if their lto is still too broken to be usable, regarding visibility and inlining.
I found great bugs with new clang-4 warnings.
I had no time yet to use it on C++, where the real advantages come up. On pure C there are just side-effects.
One thing that always confused me about ccache was that it doesn't cache lib generation and executable generation. I know that the authors have insisted (until they were blue in the face) that supporting lib/exe caching would require rewriting ccache... I just don't understand why. Once you know about about -frandom=0, and you've removed all aspects of non-determinisim (__TIME__ & co.), then all that's left is the moral equivalent of `dwarfdump -u <exe>` for each compiler, and you're good-to-go for deterministic caching.
The architecture of ccache maps preprocessed sources to object files; it uses the compiler to preprocess the source, and it hashes the result, knowing that nothing other than the compiler, command line, and preprocessed source determines the output.
Linking involves far more complexity, with the input files harder to determine. There's no equivalent of -E or -fdirectives-only for linking. A ccache for linking would have to identify and hash all library, object file, and linker script inputs, including those pulled in indirectly by linker scripts, in addition to the toolchain, the command line, and any linker plugins.
It's absolutely possible, and I'd love to see someone do so, but it seems significantly harder than caching compilation.
You'd also want to time the result, and figure out how long the reading and hashing takes compared to linking. ccache misses take only slightly longer than a normal compilation; link-cache misses may take much longer than normal.
On top of that, unlike a compilation cache that seems very likely to hit on the 99% of files not changed in a build, a linker cache would only hit when absolutely nothing has changed in the entire build. It might help for a project that links numerous tiny libraries or binaries (which seems relatively uncommon), but for a project that primarily builds a single library or binary, it'd only help if you rebuild entirely identical sources twice.
(It might, however, speed up Linux kernel builds if you've only changed the code for a couple of modules and not anything in the core kernel.)