Description
If you have lto
enabled in the profile, then cargo build
followed by cargo test
can result in all dependencies being rebuilt. This is probably not what people want or expect.
#[cargo_test]
fn build_test_rebuild() {
Package::new("bar", "1.0.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar = "1.0"
[profile.release]
lto = true
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("build --release -v")
.with_stderr(
"\
[UPDATING] [..]
[DOWNLOADING] crates ...
[DOWNLOADED] bar v1.0.0 [..]
[COMPILING] bar v1.0.0
[RUNNING] `rustc --crate-name bar [..]-C linker-plugin-lto[..]
[COMPILING] foo v0.1.0 [..]
[RUNNING] `rustc --crate-name foo [..]-C linker-plugin-lto[..]
[FINISHED] [..]
",
)
.run();
// FIXME: this rebuilds `bar`, but that is probably undesired.
p.cargo("test --release -v")
.with_stderr(
"\
[COMPILING] bar v1.0.0
[RUNNING] `rustc --crate-name bar [..]-C embed-bitcode=no[..]
[COMPILING] foo v0.1.0 [..]
[RUNNING] `rustc --crate-name foo src/lib.rs [..]-C embed-bitcode=no [..]
[RUNNING] `rustc --crate-name foo src/lib.rs [..]-C embed-bitcode=no [..]--test[..]
[FINISHED] [..]
[RUNNING] [..]
[DOCTEST] foo
[RUNNING] `rustdoc --crate-type lib --test [..]-C embed-bitcode=no[..]
",
)
.run();
}
The exact scenario depends on the structure of the project and the flags used, but for the above example:
build
builds dependencies with bitcode, because that's all LTO needs.test
builds only with object code, because tests need that to link, but there isn't anything that actually needs LTO.
A similar scenario, if you have a main.rs
in the project, it is slightly different:
build
builds dependencies with bitcode, because that's all LTO needs.test
builds dependencies with both bitcode and object code, because the tests need object code, and the binary needs bitcode for LTO.
The user can fix this by adding lto
to the test or bench profile (depending on whether you use the --release
flag). Alternatively, one can just not assume that test --release
will share artifacts. I guess another option would be to give the user the ability to disable the bitcode-only optimization.
This particular scenario will be fixed by named-profiles, because the test/bench profiles implicitly inherit the dev/release profile settings. Of course, that means tests will then be LTO'd, which can be quite expensive.
I think it should be fine to wait for named-profiles to be stabilized to resolve this issue. However, I wanted to file it to track the concern. I also think it might warrant having a higher priority for moving named-profiles forward.
A real-world example of this is rustup's CI setup.