Compilation issues in a multi-crate project

My project has the following structure:

.
├── Cargo.lock
├── Cargo.toml
├── build.rs
├── clippy.toml
├── core
│  ├── Cargo.toml
│  └── src
├── graph
│  ├── Cargo.toml
│  └── src
├── rustfmt.toml
├── sanitize
│  ├── Cargo.toml
│  └── src
├── tools
│  ├── Cargo.toml
│  └── src

Apart from external public crates, the direct dependencies among my crates are:

core: 
sanitize: core
graph: core
tools: graph, sanitize, core

And the relevant settings in toml files are:

./Cargo.toml:
[workspace]
members = ["tools"]

./tools/Cargo.toml
[dependencies]
my_core = {path = "../core"}
my_graph = {path = "../graph"}
my_sanitize = {path = "../sanitize"}

./graph/Cargo.toml
[dependencies]
my_core = {path = "../core"}

./sanitize/Cargo.toml:
[dependencies]
my_core = {path = "../core"}

I'm using cargo-watch to monitor and rebuild on changes.

There are some issues as to my workflow:

  1. Source code changes in graph/ directory usually triggers
Blocking waiting for file lock on the git checkouts
Blocking waiting for file lock on build directory

which I need to wait for 1~10s to continue.

  1. Source code changes in "tools" directory seem to recompile everything (tools/graph/sanitize/core), which takes ~30s in debug build mode.
    CARGO_INCREMENTAL=1 does not work either: it still recompiles everything and takes ~26s.

My questions:

  • What are the root causes of the "blocking"?
  • Why changes in "tools" (top crate) only recompiles everything still?
  • Any suggestions to boost the compilation time?

Two relevant posts:

I bet the build script does not use rerun-if-changed

https://doc.rust-lang.org/cargo/reference/build-scripts.html

No, I didn't print anything in build.rs.
What should I do to make a difference? Adding something like println!("cargo:rerun-if-changed=README.md");?

What should I do to make a difference?

It depends on which files does build.rs read. If it reads only README.md, than cargo:rerun-if-changed=README.md should work. If it doesn't read anything, cargo:rerun-if-changed=build.rs is the right output I think.

My build.rs doesn't read anything, but write a file that includes the version information (like what rustc/cargo does). I changed to cargo:rerun-if-changed=build.rs now, however there seem no obvious differences, e.g., source changes inside "tools" directory only, like adding a comment line, will incur blocking directory+recompiling everything.