I think in general, external caching tools are not that useful of a model here, and only Cargo, at most, could interface with the compiler closely enough to orchestrate any sort of complex compilation “dataflow” graph.
(I also think it’s kind of sad Cargo still doesn’t compile crates.io dependencies user-wide, or at least in a configurable fashion, but that’s another story)
The reason tools like ccache exist is entirely historical, IMO, and it has to do with the often opaque architecture of C compilers, and the simplistic file-based compilation model, meaning it was much easier for a third-party program to pretend to be a C compiler while acting as a “caching proxy”.
To soundly do this for Rust, you need the compiler’s help, and considering how incremental works inside the compiler (the “query” system), you can build much more flexible systems, depending on where/how you’re willing to split things up.
For example, you could have a purely incremental online cache of many crates.io crate*version combinations (including popular choices for feature flags), with rustc sending requests for any external information it requires. This might seem slow at first, but it’s locally cacheable, and could give you really quick starts (think IDE code browsing with type information, or a REPL).