I run my cargo test and cargo install both with --release, hoping to save recompiling scores of slow dependencies every time. However, it still unnecessarily recompiles most of them. Is there any way around this?
cargo install. Are you installing binaries locally, or what's going on?
Yes, these are my cargo test and cargo install commands:
cargo test --release -- --color always --nocapture cargo install -f --path . --root $HOME
Ideally, I do not want the second command to be recompiling anything (after successful tests).
And I certainly do not want everything recompiled and duplicated in 'Debug', as it takes me less time to find the bug(s) than to recompile. Not to mention all those voluminous dependencies being duplicated as well.
I do not think you can avoid the recompile when using
cargo install, but you can do a
cargo build --release instead and use an ordinary copy command to replace your installed binary when testing.
cargo tests builds and runs tests (unit/integration/doctests), not necessarily your application. Perhaps that's why you see some rebuilding happening.
Deps only need to be built once unless there's a change in
Cargo.lock file. Do consecutive
cargo build --release runs rebuild deps repeatedly?
That's not true. Same dependencies can be used with different sets of features flags, so it's pretty normal for cargo to compile some of dependencies separately for tests and for main release binary if some features are only enabled for dev enrionment (or only required by dev dependencies).
cargo install compiles binaries in a fresh directory by default. From this issue, it seems that setting
CARGO_TARGET_DIR should prevent that.
Yes, that's true but I had the impression that you use the same features, based on your examples above.
Depending on how much you don't want to rebuild one option could be to run
cargo test --release followed by
cargo build --release.
I haven't used
cargo install on my own projects but one way of reusing the same build directory is via docker bind mounts/volumes. We use something along the lines of "Compile your app inside the Docker container" in https://hub.docker.com/_/rust to reuse as much as possible. Haven't used it with
@alice @qaopm - I tried. Even with the same features,
cargo test --release puts everything in release/deps and
cargo build --release puts the same things in release/build, thus everything is compiled twice and kept twice and there is no synergy whatsoever. Not at all like good old makefiles.
I would not mind if the final executables were different, as they are, because of including/excluding the tests but for all their dependencies to be reduplicated seems totally unnecessary.
Hm, I don't know anything about cargo/rustc internals, in my case both
cargo build --release and
cargo test --release populate both
build. If I do
cargo test --release
first, then the build is a no-operation:
$ cargo build --release Finished release [optimized] target(s) in 0.37s
Doing it the other way round (build first, then test) is similar, except that test has dev deps so it needs to build them. It doesn't build shared deps.
For local crates, cargo install and cargo build should use the same caches (unlike cargo test —release, which might actually use a different profile).
cargo test --release uses the
If you want it to share artifacts with
cargo build --release, then you must make sure that the
bench profile and
release profile have the exact same compilation options.
Oh boy, what a lot of complications with hidden profiles. I never suspected that. Thanks for the information!
I understood some fairly complex things in the past but I can not make any sense out of this. There seems to be no way of telling for sure where those 'artifacts' will end up when.
The profile used depends on the command, the package, the Cargo target, and command-line flags like
That is a four dimensional defaults space in which I am lost.
Sometimes I can not help feeling that you Rust experts take pleasure in complicating things just for the sake of it.
Surely, the default should be that everything goes in one place and avoids slow voluminous compilations and only if you want lots of baroque 'profiles' in all kinds of different places, then you set them up. Not the other way round.
Ah, they do, but it is not that simple:
IMHO these default profiles are a total mess. I will just have to every time manually specify my own.
I have finally succeeded in forcing cargo into doing something sensible by sticking all the following duplicated profiles into my Cargo.toml file and using --release with both cargo test and cargo build. However, cargo install still insists on recompiling, for reasons that escape me. I will just have to use cargo build --release instead.
On the plus side, my executable has mysteriously lost one megabyte in the process.
[profile.test] opt-level = 3 debug = false debug-assertions = false overflow-checks = false lto = true incremental = true rpath = false [profile.release] opt-level = 3 debug = false debug-assertions = false overflow-checks = false lto = true panic = 'unwind' incremental = true rpath = false [profile.bench] opt-level = 3 debug = false debug-assertions = false overflow-checks = false lto = true incremental = true rpath = false