I think a lot of the pain described in this thread may come from the same underlying issue: a shared target directory behaves like a build directory, not like a real cache.
That would explain several of the symptoms people mentioned: lock contention, cargo clean wiping everything, RUSTFLAGS changes causing rebuilds, and feature-set changes rebuilding dependencies. They look like separate problems, but they are all different ways of running into the same artifact-collision problem.
Cargo fingerprints artifacts using inputs like the resolved feature set, RUSTFLAGS, the rustc version, and the build profile. It also bakes a hash of that into -Cmetadata. So if two projects share one target/ directory but differ in any of those inputs, they can produce different artifacts that all land in the same shared build area. That is where the relocking, rebuilding, and general confusion come from.
A content-addressed cache is a better fit for that problem, because each fingerprint becomes its own key instead of competing for the same build directory. sccache is the off-the-shelf option here. For example, project A using one Tokio version and feature set, and project B using another, just become two separate cache entries. cargo clean also will not wipe the cache store.
There are a couple of caveats: sccache generally wants CARGO_INCREMENTAL=0, and it will not cache absolutely everything. Build scripts and proc-macro codegen can still be tricky.
That said, I do not think this makes your CLI idea unnecessary. It sounds like you are solving more than just caching. Custom compiler flags, linker or allocator swapping, and the fcomptime reflection workflow are all good reasons for a dedicated tool.
The cleanest mental model might be two layers:
- A content-addressed cache for “do not compile the same thing twice.”
- Your CLI for “drive the flags, linker, allocator, and reflection workflow the way I want.”
That way the cache layer stops being something you have to manually manage by version or feature set.
One separate trick, if the main pain is a single heavy dependency dominating cold builds inside one project: put it behind a small facade crate and make that facade its own workspace member. Then it tends to compile once and stay out of the way during normal incremental rebuilds, because your day-to-day edits stop touching it. I have seen that take warm rebuilds from minutes down to seconds.