rust-analyzer: Rust analyzer "cargo check" blocks debug builds
I’m working on a project where iterative compile times are important. If i make a change, save it, and immediately start a debug build then it will almost always get blocked by rust analyzer’s invocation of the “cargo check” command. My build then needs to wait until cargo check completes.
Blocking doesn’t occur if I run a release build. This creates the weird situation where release builds are actually faster to complete:
Finished release [optimized] target(s) in 0.80s
vs
Finished dev [unoptimized + debuginfo] target(s) in 1.31s
This is especially troublesome for initial cargo check runs, which can block builds for minutes at a time.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 6
- Comments: 30 (15 by maintainers)
The workarounds are:
"rust-analyzer.checkOnSave.enable": false(you should still get errors in the editor if you invoke build manually)"rust-analyzer.checkOnSave.extraArgs": ["--target-dir", "/path/to/proect/target/check"]I think it’s fair to close this: although the probelm is real, I don’t think we’ll be able to come up with anything better than the current set of work-arounds.
Documenting for anyone else running into this issue:
I was having lots of spurious rebuilds for the openssl-sys package (and some dependees of it). It turned out to be because I was setting $PKG_CONFIG_PATH to something custom in my .bashrc. I run VSCode via the Unity launcher, not from a terminal, so it was not getting the setting from .bashrc… But as soon as I opened a terminal, whether within VSCode or not, that terminal had a different $PKG_CONFIG_PATH and so triggered a rebuild.
Removing the line in my .bashrc that sets $PKG_CONFIG_PATH fixed it.
Here’s a minimal project to reproduce:
src/main.rs
src/Cargo.toml
~/.bashrc
cargo 1.67.0-nightly (eb5d35917 2022-11-17) VSCode 1.73.1
And here’s how I debugged:
In an editor pane, change the program in a trivial way and save.
Note that
cargo checktakes a few seconds.In a terminal pane, run
cargo build. Note that it takes a few seconds, and rebuilds openssl-sys.Repeat back-and-forth, noting the slowness each time.
In the terminal pane, run:
CARGO_LOG=cargo::core::compiler::fingerprint=info RUST_LOG=trace cargo -vv build > ~/slow-rebuild-log-1.txt 2>&1
In ~/slow-rebuild-log-1.txt, notice the lines:
Note the mention of PKG_CONFIG_PATH. This happens because openssl-sys has a build script: build.rs. That invokes pkg-config, which emits a bunch of
rerun-if-changedcommands for Cargo, includingcargo:rerun-if-env-changed=PKG_CONFIG.I noticed that the “new” version of PKG_CONFIG_PATH included some directories that were specific to my user, which led me to look for that variable in my dotfiles and find it in .bashrc.
Hope this is helpful to someone in the future!
Bonus helpful link: https://doc.rust-lang.org/stable/cargo/faq.html#why-is-cargo-rebuilding-my-code
slow-rebuild-log-1.txt
This is continuing to be a (very frustrating) problem. It looks like every time RA declares it’s “loading metadata”, it clobbers my debug compile cache. This happens at least once every time I launch vscode, and often at other times, sometimes several times in a row (maybe every time I touch a Cargo.toml? but also sometimes when I haven’t…). My environment is set consistently between my terminal and
rust-analyzer.server.extraEnv; it seems like RA is ignoring the latter for some of its operations.Tried that, now it’s clobbering my cache every time I try to build instead of every startup 😦
e: that seems to have stopped for now, might have involved the “loading metadata” step rather than the check?
I wonder, if you let it share the target folders, does the
cargo buildthat runs after check has finished have to rebuild all dependencies? Otherwise you might spend some time waiting for the lock, but it’s maybe just time you’d otherwise spend waiting for the dependencies to build?Brilliant. The second option is exactly what I was looking for. My first instinct was “why isn’t this the default?”, but then I looked at the target folder doubling in size. The current default behavior seems like the right choice for most people. Then people (like me) who are willing to trade some disk space for non-blocking behavior can do so. Ideally theres a way to avoid duplicate artifacts, have check on save enabled, and avoid blocks, but I understand that such an ask might be outside the bounds of the constraints rust-analyzer operates in. Maybe RA could detect when there is a user-initiated cargo lock contention and force-stop its internal cargo check execution?
Thanks for your help! I consider this issue solved for me.