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?
You mention 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 Docker to reuse as much as possible. Haven't used it with install
though.
@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 deps
and 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 bench
profile.
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
--release
.
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:
Note that when using the
cargo test
andcargo bench
commands, thetest
/bench
profiles only apply to the final test executable. Dependencies will continue to use thedev
/release
profiles.
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
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.