2020-06-10 22:31:36 +00:00
|
|
|
use cargo::core::compiler::Lto;
|
2020-04-01 18:41:27 +00:00
|
|
|
use cargo_test_support::registry::Package;
|
2020-08-27 23:41:43 +00:00
|
|
|
use cargo_test_support::{basic_manifest, project, Project};
|
2020-06-10 22:31:36 +00:00
|
|
|
use std::process::Output;
|
2020-04-01 18:41:27 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn with_deps() {
|
|
|
|
Package::new("bar", "0.0.1").publish();
|
|
|
|
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "test"
|
|
|
|
version = "0.0.0"
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
bar = "*"
|
|
|
|
|
|
|
|
[profile.release]
|
|
|
|
lto = true
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("src/main.rs", "extern crate bar; fn main() {}")
|
|
|
|
.build();
|
2020-04-30 19:24:50 +00:00
|
|
|
p.cargo("build -v --release")
|
2020-08-25 13:05:25 +00:00
|
|
|
.with_stderr_contains("[..]`rustc[..]--crate-name bar[..]-C linker-plugin-lto[..]`")
|
2020-04-30 19:24:50 +00:00
|
|
|
.with_stderr_contains("[..]`rustc[..]--crate-name test[..]-C lto[..]`")
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn shared_deps() {
|
|
|
|
Package::new("bar", "0.0.1").publish();
|
|
|
|
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "test"
|
|
|
|
version = "0.0.0"
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
bar = "*"
|
|
|
|
|
|
|
|
[build-dependencies]
|
|
|
|
bar = "*"
|
|
|
|
|
|
|
|
[profile.release]
|
|
|
|
lto = true
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("build.rs", "extern crate bar; fn main() {}")
|
|
|
|
.file("src/main.rs", "extern crate bar; fn main() {}")
|
|
|
|
.build();
|
|
|
|
p.cargo("build -v --release")
|
|
|
|
.with_stderr_contains("[..]`rustc[..]--crate-name test[..]-C lto[..]`")
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn build_dep_not_ltod() {
|
|
|
|
Package::new("bar", "0.0.1").publish();
|
|
|
|
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "test"
|
|
|
|
version = "0.0.0"
|
|
|
|
|
|
|
|
[build-dependencies]
|
|
|
|
bar = "*"
|
|
|
|
|
|
|
|
[profile.release]
|
|
|
|
lto = true
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("build.rs", "extern crate bar; fn main() {}")
|
|
|
|
.file("src/main.rs", "fn main() {}")
|
|
|
|
.build();
|
|
|
|
p.cargo("build -v --release")
|
2020-08-25 13:05:25 +00:00
|
|
|
.with_stderr_contains("[..]`rustc[..]--crate-name bar[..]-C embed-bitcode=no[..]`")
|
2020-04-30 19:24:50 +00:00
|
|
|
.with_stderr_contains("[..]`rustc[..]--crate-name test[..]-C lto[..]`")
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn complicated() {
|
|
|
|
Package::new("dep-shared", "0.0.1")
|
|
|
|
.file("src/lib.rs", "pub fn foo() {}")
|
|
|
|
.publish();
|
|
|
|
Package::new("dep-normal2", "0.0.1")
|
|
|
|
.file("src/lib.rs", "pub fn foo() {}")
|
|
|
|
.publish();
|
|
|
|
Package::new("dep-normal", "0.0.1")
|
|
|
|
.dep("dep-shared", "*")
|
|
|
|
.dep("dep-normal2", "*")
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
"
|
|
|
|
pub fn foo() {
|
|
|
|
dep_shared::foo();
|
|
|
|
dep_normal2::foo();
|
|
|
|
}
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
Package::new("dep-build2", "0.0.1")
|
|
|
|
.file("src/lib.rs", "pub fn foo() {}")
|
|
|
|
.publish();
|
|
|
|
Package::new("dep-build", "0.0.1")
|
|
|
|
.dep("dep-shared", "*")
|
|
|
|
.dep("dep-build2", "*")
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
"
|
|
|
|
pub fn foo() {
|
|
|
|
dep_shared::foo();
|
|
|
|
dep_build2::foo();
|
|
|
|
}
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
Package::new("dep-proc-macro2", "0.0.1")
|
|
|
|
.file("src/lib.rs", "pub fn foo() {}")
|
|
|
|
.publish();
|
|
|
|
Package::new("dep-proc-macro", "0.0.1")
|
|
|
|
.proc_macro(true)
|
|
|
|
.dep("dep-shared", "*")
|
|
|
|
.dep("dep-proc-macro2", "*")
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
"
|
|
|
|
extern crate proc_macro;
|
|
|
|
use proc_macro::TokenStream;
|
|
|
|
|
|
|
|
#[proc_macro_attribute]
|
|
|
|
pub fn foo(_: TokenStream, a: TokenStream) -> TokenStream {
|
|
|
|
dep_shared::foo();
|
|
|
|
dep_proc_macro2::foo();
|
|
|
|
a
|
|
|
|
}
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.publish();
|
|
|
|
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "test"
|
|
|
|
version = "0.0.0"
|
|
|
|
|
|
|
|
[lib]
|
|
|
|
crate-type = ['cdylib', 'staticlib']
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
dep-normal = "*"
|
|
|
|
dep-proc-macro = "*"
|
|
|
|
|
|
|
|
[build-dependencies]
|
|
|
|
dep-build = "*"
|
|
|
|
|
|
|
|
[profile.release]
|
|
|
|
lto = true
|
Build host dependencies with opt-level 0 by default
This commit updates Cargo's build of host dependencies to build them
with optimization level 0 by default instead of matching the profile of
the final binary.
Since Cargo's inception build dependencies have, by default, been built
in a profile that largely matches the profile of the final target
artifact. Build dependencies, however, rarely actually need to be
optimized and are often executing very small tasks, which means that
optimizing them often wastes a lot of build time. A great example of
this is procedural macros where `syn` and friends are pretty heavyweight
to optimize, and the amount of Rust code they're parsing is typically
quite small, so the time spent optimizing rarely comes as a benefit.
The goal of this PR is to improve build times on average in the
community by not spending time optimizing build dependencies (build
scripts, procedural macros, and their transitive dependencies). The PR
will not be a universal win for everyone, however. There's some
situations where your build time may actually increase:
* In some cases build scripts and procedural macros can take quite a
long time to run!
* Cargo may not build dependencies more than once if they're shared with
the main build. This only applies to builds without `--target` where
the same crate is used in the final binary as in a build script.
In these cases, however, the `build-override` profile has existed for
some time know and allows giving a knob to tweak this behavior. For
example to get back the previous build behavior of Cargo you would
specify, in `Cargo.toml`:
[profile.release.build-override]
opt-level = 3
or you can configure this via the environment:
export CARGO_PROFILE_RELEASE_BUILD_OVERRIDE_OPT_LEVEL=3
There are two notable features we would like to add in the future which
would make the impact of a change like this smaller, but they're not
implemented at this time (nor do we have concrete plans to implement
them). First we would like crates to have a way of specifying they
should be optimized by default, despite default profile options. Often
crates, like lalrpop historically, have abysmal performance in debug
mode and almost always (even in debug builds) want to be built in
release mode. The second feature is that ideally crate authors would be
able to tell Cargo to minimize the number of crates built, unifying
profiles where possible to avoid double-compiling crates.
At this time though the Cargo team feels that the benefit of changing
the defaults is well worth this change. Neither today nor directly after
this change will be a perfect world, but it's hoped that this change
makes things less bad!
2020-07-17 19:39:41 +00:00
|
|
|
|
|
|
|
# force build deps to share an opt-level with the rest of the
|
|
|
|
# graph so they only get built once.
|
|
|
|
[profile.release.build-override]
|
|
|
|
opt-level = 3
|
2020-04-30 19:24:50 +00:00
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("build.rs", "fn main() { dep_build::foo() }")
|
|
|
|
.file(
|
2021-11-29 18:04:15 +00:00
|
|
|
"src/bin/foo-bin.rs",
|
2020-04-30 19:24:50 +00:00
|
|
|
"#[dep_proc_macro::foo] fn main() { dep_normal::foo() }",
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
"#[dep_proc_macro::foo] pub fn foo() { dep_normal::foo() }",
|
|
|
|
)
|
|
|
|
.build();
|
|
|
|
p.cargo("build -v --release")
|
|
|
|
// normal deps and their transitive dependencies do not need object
|
|
|
|
// code, so they should have linker-plugin-lto specified
|
2020-08-25 13:05:25 +00:00
|
|
|
.with_stderr_contains(
|
|
|
|
"[..]`rustc[..]--crate-name dep_normal2 [..]-C linker-plugin-lto[..]`",
|
|
|
|
)
|
|
|
|
.with_stderr_contains("[..]`rustc[..]--crate-name dep_normal [..]-C linker-plugin-lto[..]`")
|
2020-04-30 19:24:50 +00:00
|
|
|
// build dependencies and their transitive deps don't need any bitcode,
|
|
|
|
// so embedding should be turned off
|
2020-08-25 13:05:25 +00:00
|
|
|
.with_stderr_contains("[..]`rustc[..]--crate-name dep_build2 [..]-C embed-bitcode=no[..]`")
|
|
|
|
.with_stderr_contains("[..]`rustc[..]--crate-name dep_build [..]-C embed-bitcode=no[..]`")
|
2020-04-30 19:24:50 +00:00
|
|
|
.with_stderr_contains(
|
2020-08-25 13:05:25 +00:00
|
|
|
"[..]`rustc[..]--crate-name build_script_build [..]-C embed-bitcode=no[..]`",
|
2020-04-30 19:24:50 +00:00
|
|
|
)
|
|
|
|
// proc macro deps are the same as build deps here
|
|
|
|
.with_stderr_contains(
|
2020-08-25 13:05:25 +00:00
|
|
|
"[..]`rustc[..]--crate-name dep_proc_macro2 [..]-C embed-bitcode=no[..]`",
|
2020-04-30 19:24:50 +00:00
|
|
|
)
|
|
|
|
.with_stderr_contains(
|
2020-08-25 13:05:25 +00:00
|
|
|
"[..]`rustc[..]--crate-name dep_proc_macro [..]-C embed-bitcode=no[..]`",
|
2020-04-30 19:24:50 +00:00
|
|
|
)
|
2021-11-29 18:04:15 +00:00
|
|
|
.with_stderr_contains(
|
|
|
|
"[..]`rustc[..]--crate-name foo_bin [..]--crate-type bin[..]-C lto[..]`",
|
|
|
|
)
|
2020-04-30 19:24:50 +00:00
|
|
|
.with_stderr_contains(
|
|
|
|
"[..]`rustc[..]--crate-name test [..]--crate-type cdylib[..]-C lto[..]`",
|
|
|
|
)
|
|
|
|
.with_stderr_contains("[..]`rustc[..]--crate-name dep_shared [..]`")
|
|
|
|
.with_stderr_does_not_contain("[..]--crate-name dep_shared[..]-C lto[..]")
|
2020-08-25 13:05:25 +00:00
|
|
|
.with_stderr_does_not_contain("[..]--crate-name dep_shared[..]-C linker-plugin-lto[..]")
|
|
|
|
.with_stderr_does_not_contain("[..]--crate-name dep_shared[..]-C embed-bitcode[..]")
|
2020-04-30 19:24:50 +00:00
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn off_in_manifest_works() {
|
|
|
|
Package::new("bar", "0.0.1")
|
|
|
|
.file("src/lib.rs", "pub fn foo() {}")
|
|
|
|
.publish();
|
|
|
|
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "test"
|
|
|
|
version = "0.0.0"
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
bar = "*"
|
|
|
|
|
|
|
|
[profile.release]
|
|
|
|
lto = "off"
|
|
|
|
"#,
|
|
|
|
)
|
2020-06-10 22:31:36 +00:00
|
|
|
.file("src/lib.rs", "pub fn foo() {}")
|
|
|
|
.file(
|
|
|
|
"src/main.rs",
|
|
|
|
"fn main() {
|
|
|
|
test::foo();
|
|
|
|
bar::foo();
|
|
|
|
}",
|
|
|
|
)
|
2020-04-30 19:24:50 +00:00
|
|
|
.build();
|
2020-06-10 22:31:36 +00:00
|
|
|
p.cargo("build -v --release")
|
|
|
|
.with_stderr(
|
|
|
|
"\
|
|
|
|
[UPDATING] [..]
|
|
|
|
[DOWNLOADING] [..]
|
|
|
|
[DOWNLOADED] [..]
|
|
|
|
[COMPILING] bar v0.0.1
|
2021-02-17 19:40:38 +00:00
|
|
|
[RUNNING] `rustc --crate-name bar [..]--crate-type lib [..]-C lto=off -C embed-bitcode=no[..]
|
2020-06-10 22:31:36 +00:00
|
|
|
[COMPILING] test [..]
|
2021-02-17 19:40:38 +00:00
|
|
|
[RUNNING] `rustc --crate-name test [..]--crate-type lib [..]-C lto=off -C embed-bitcode=no[..]
|
2020-06-10 22:31:36 +00:00
|
|
|
[RUNNING] `rustc --crate-name test src/main.rs [..]--crate-type bin [..]-C lto=off[..]
|
|
|
|
[FINISHED] [..]
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
2020-04-30 19:24:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn between_builds() {
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "test"
|
|
|
|
version = "0.0.0"
|
|
|
|
|
|
|
|
[profile.release]
|
|
|
|
lto = true
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("src/lib.rs", "pub fn foo() {}")
|
|
|
|
.file("src/main.rs", "fn main() { test::foo() }")
|
|
|
|
.build();
|
2020-06-10 22:31:36 +00:00
|
|
|
p.cargo("build -v --release --lib")
|
|
|
|
.with_stderr(
|
|
|
|
"\
|
|
|
|
[COMPILING] test [..]
|
2020-08-25 13:05:25 +00:00
|
|
|
[RUNNING] `rustc [..]--crate-type lib[..]-C linker-plugin-lto[..]
|
2020-06-10 22:31:36 +00:00
|
|
|
[FINISHED] [..]
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
p.cargo("build -v --release")
|
|
|
|
.with_stderr_contains(
|
|
|
|
"\
|
|
|
|
[COMPILING] test [..]
|
|
|
|
[RUNNING] `rustc [..]--crate-type bin[..]-C lto[..]
|
|
|
|
[FINISHED] [..]
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
2020-04-01 18:41:27 +00:00
|
|
|
}
|
2020-05-08 15:23:31 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn test_all() {
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.0.0"
|
|
|
|
|
|
|
|
[profile.release]
|
|
|
|
lto = true
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("src/main.rs", "fn main() {}")
|
|
|
|
.file("tests/a.rs", "")
|
|
|
|
.file("tests/b.rs", "")
|
|
|
|
.build();
|
|
|
|
p.cargo("test --release -v")
|
|
|
|
.with_stderr_contains("[RUNNING] `rustc[..]--crate-name foo[..]-C lto[..]")
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn test_all_and_bench() {
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.0.0"
|
|
|
|
|
|
|
|
[profile.release]
|
|
|
|
lto = true
|
|
|
|
[profile.bench]
|
|
|
|
lto = true
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("src/main.rs", "fn main() {}")
|
|
|
|
.file("tests/a.rs", "")
|
|
|
|
.file("tests/b.rs", "")
|
|
|
|
.build();
|
|
|
|
p.cargo("test --release -v")
|
|
|
|
.with_stderr_contains("[RUNNING] `rustc[..]--crate-name a[..]-C lto[..]")
|
|
|
|
.with_stderr_contains("[RUNNING] `rustc[..]--crate-name b[..]-C lto[..]")
|
|
|
|
.with_stderr_contains("[RUNNING] `rustc[..]--crate-name foo[..]-C lto[..]")
|
|
|
|
.run();
|
|
|
|
}
|
2020-05-18 12:37:23 +00:00
|
|
|
|
2021-09-24 04:55:42 +00:00
|
|
|
/// Basic setup:
|
|
|
|
///
|
|
|
|
/// foo v0.0.0
|
|
|
|
/// ├── bar v0.0.0
|
|
|
|
/// │ ├── registry v0.0.1
|
|
|
|
/// │ └── registry-shared v0.0.1
|
|
|
|
/// └── registry-shared v0.0.1
|
|
|
|
///
|
|
|
|
/// Where `bar` will have the given crate types.
|
2020-06-10 22:31:36 +00:00
|
|
|
fn project_with_dep(crate_types: &str) -> Project {
|
2020-05-18 12:37:23 +00:00
|
|
|
Package::new("registry", "0.0.1")
|
2020-06-10 22:31:36 +00:00
|
|
|
.file("src/lib.rs", r#"pub fn foo() { println!("registry"); }"#)
|
2020-05-18 12:37:23 +00:00
|
|
|
.publish();
|
|
|
|
Package::new("registry-shared", "0.0.1")
|
2020-06-10 22:31:36 +00:00
|
|
|
.file("src/lib.rs", r#"pub fn foo() { println!("shared"); }"#)
|
2020-05-18 12:37:23 +00:00
|
|
|
.publish();
|
|
|
|
|
2020-06-10 22:31:36 +00:00
|
|
|
project()
|
2020-05-18 12:37:23 +00:00
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.0.0"
|
|
|
|
|
|
|
|
[workspace]
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
bar = { path = 'bar' }
|
|
|
|
registry-shared = "*"
|
|
|
|
|
|
|
|
[profile.release]
|
|
|
|
lto = true
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/main.rs",
|
|
|
|
"
|
|
|
|
fn main() {
|
|
|
|
bar::foo();
|
|
|
|
registry_shared::foo();
|
|
|
|
}
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"bar/Cargo.toml",
|
2020-06-10 22:31:36 +00:00
|
|
|
&format!(
|
|
|
|
r#"
|
2020-09-27 00:59:58 +00:00
|
|
|
[package]
|
|
|
|
name = "bar"
|
|
|
|
version = "0.0.0"
|
2020-05-18 12:37:23 +00:00
|
|
|
|
2020-09-27 00:59:58 +00:00
|
|
|
[dependencies]
|
|
|
|
registry = "*"
|
|
|
|
registry-shared = "*"
|
2020-05-18 12:37:23 +00:00
|
|
|
|
2020-09-27 00:59:58 +00:00
|
|
|
[lib]
|
|
|
|
crate-type = [{}]
|
|
|
|
"#,
|
2020-06-10 22:31:36 +00:00
|
|
|
crate_types
|
|
|
|
),
|
2020-05-18 12:37:23 +00:00
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"bar/src/lib.rs",
|
2020-06-10 22:31:36 +00:00
|
|
|
r#"
|
2020-05-18 12:37:23 +00:00
|
|
|
pub fn foo() {
|
2020-06-10 22:31:36 +00:00
|
|
|
println!("bar");
|
2020-05-18 12:37:23 +00:00
|
|
|
registry::foo();
|
|
|
|
registry_shared::foo();
|
|
|
|
}
|
2020-06-10 22:31:36 +00:00
|
|
|
"#,
|
2020-05-18 12:37:23 +00:00
|
|
|
)
|
|
|
|
.file("tests/a.rs", "")
|
|
|
|
.file("bar/tests/b.rs", "")
|
2020-06-10 22:31:36 +00:00
|
|
|
.build()
|
|
|
|
}
|
|
|
|
|
2021-09-24 04:55:42 +00:00
|
|
|
/// Helper for checking which LTO behavior is used for a specific crate.
|
|
|
|
///
|
|
|
|
/// `krate_info` is extra compiler flags used to distinguish this if the same
|
|
|
|
/// crate name is being built multiple times.
|
2020-06-10 22:31:36 +00:00
|
|
|
fn verify_lto(output: &Output, krate: &str, krate_info: &str, expected_lto: Lto) {
|
|
|
|
let stderr = std::str::from_utf8(&output.stderr).unwrap();
|
|
|
|
let mut matches = stderr.lines().filter(|line| {
|
|
|
|
line.contains("Running")
|
|
|
|
&& line.contains(&format!("--crate-name {} ", krate))
|
|
|
|
&& line.contains(krate_info)
|
|
|
|
});
|
|
|
|
let line = matches.next().unwrap_or_else(|| {
|
|
|
|
panic!(
|
|
|
|
"expected to find crate `{}` info: `{}`, not found in output:\n{}",
|
|
|
|
krate, krate_info, stderr
|
|
|
|
);
|
|
|
|
});
|
|
|
|
if let Some(line2) = matches.next() {
|
|
|
|
panic!(
|
|
|
|
"found multiple lines matching crate `{}` info: `{}`:\nline1:{}\nline2:{}\noutput:\n{}",
|
|
|
|
krate, krate_info, line, line2, stderr
|
|
|
|
);
|
|
|
|
}
|
|
|
|
let actual_lto = if let Some(index) = line.find("-C lto=") {
|
|
|
|
let s = &line[index..];
|
|
|
|
let end = s.find(' ').unwrap();
|
|
|
|
let mode = &line[index..index + end];
|
|
|
|
if mode == "off" {
|
|
|
|
Lto::Off
|
|
|
|
} else {
|
|
|
|
Lto::Run(Some(mode.into()))
|
|
|
|
}
|
|
|
|
} else if line.contains("-C lto") {
|
|
|
|
Lto::Run(None)
|
2020-08-25 13:05:25 +00:00
|
|
|
} else if line.contains("-C linker-plugin-lto") {
|
2020-06-10 22:31:36 +00:00
|
|
|
Lto::OnlyBitcode
|
2020-08-25 13:05:25 +00:00
|
|
|
} else if line.contains("-C embed-bitcode=no") {
|
2020-06-10 22:31:36 +00:00
|
|
|
Lto::OnlyObject
|
|
|
|
} else {
|
|
|
|
Lto::ObjectAndBitcode
|
|
|
|
};
|
|
|
|
assert_eq!(
|
|
|
|
actual_lto, expected_lto,
|
|
|
|
"did not find expected LTO in line: {}",
|
|
|
|
line
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn cdylib_and_rlib() {
|
|
|
|
let p = project_with_dep("'cdylib', 'rlib'");
|
|
|
|
let output = p.cargo("build --release -v").exec_with_output().unwrap();
|
2022-10-26 04:15:45 +00:00
|
|
|
// `registry` is ObjectAndBitcode because it needs Object for the
|
2021-09-24 04:55:42 +00:00
|
|
|
// rlib, and Bitcode for the cdylib (which doesn't support LTO).
|
2020-06-10 22:31:36 +00:00
|
|
|
verify_lto(
|
|
|
|
&output,
|
|
|
|
"registry",
|
|
|
|
"--crate-type lib",
|
|
|
|
Lto::ObjectAndBitcode,
|
|
|
|
);
|
2021-09-24 04:55:42 +00:00
|
|
|
// Same as `registry`
|
2020-06-10 22:31:36 +00:00
|
|
|
verify_lto(
|
|
|
|
&output,
|
|
|
|
"registry_shared",
|
|
|
|
"--crate-type lib",
|
|
|
|
Lto::ObjectAndBitcode,
|
|
|
|
);
|
2021-09-24 04:55:42 +00:00
|
|
|
// Same as `registry`
|
2020-06-10 22:31:36 +00:00
|
|
|
verify_lto(
|
|
|
|
&output,
|
|
|
|
"bar",
|
|
|
|
"--crate-type cdylib --crate-type rlib",
|
|
|
|
Lto::ObjectAndBitcode,
|
|
|
|
);
|
|
|
|
verify_lto(&output, "foo", "--crate-type bin", Lto::Run(None));
|
|
|
|
p.cargo("test --release -v")
|
|
|
|
.with_stderr_unordered(
|
|
|
|
"\
|
|
|
|
[FRESH] registry v0.0.1
|
|
|
|
[FRESH] registry-shared v0.0.1
|
|
|
|
[FRESH] bar v0.0.0 [..]
|
|
|
|
[COMPILING] foo [..]
|
2021-09-24 04:55:42 +00:00
|
|
|
[RUNNING] `rustc --crate-name foo [..]-C lto [..]--test[..]
|
|
|
|
[RUNNING] `rustc --crate-name a [..]-C lto [..]--test[..]
|
2020-06-10 22:31:36 +00:00
|
|
|
[FINISHED] [..]
|
|
|
|
[RUNNING] [..]
|
|
|
|
[RUNNING] [..]
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
2020-05-18 12:37:23 +00:00
|
|
|
p.cargo("build --release -v --manifest-path bar/Cargo.toml")
|
2020-06-10 22:31:36 +00:00
|
|
|
.with_stderr_unordered(
|
|
|
|
"\
|
|
|
|
[FRESH] registry-shared v0.0.1
|
|
|
|
[FRESH] registry v0.0.1
|
|
|
|
[FRESH] bar v0.0.0 [..]
|
|
|
|
[FINISHED] [..]
|
|
|
|
",
|
|
|
|
)
|
2020-05-18 12:37:23 +00:00
|
|
|
.run();
|
|
|
|
p.cargo("test --release -v --manifest-path bar/Cargo.toml")
|
2020-06-10 22:31:36 +00:00
|
|
|
.with_stderr_unordered(
|
|
|
|
"\
|
2021-09-24 04:55:42 +00:00
|
|
|
[FRESH] registry-shared v0.0.1
|
|
|
|
[FRESH] registry v0.0.1
|
2020-06-10 22:31:36 +00:00
|
|
|
[COMPILING] bar [..]
|
2021-09-24 04:55:42 +00:00
|
|
|
[RUNNING] `rustc --crate-name bar [..]-C lto[..]--test[..]
|
|
|
|
[RUNNING] `rustc --crate-name b [..]-C lto[..]--test[..]
|
2020-06-10 22:31:36 +00:00
|
|
|
[FINISHED] [..]
|
2020-08-27 23:41:43 +00:00
|
|
|
[RUNNING] [..]target/release/deps/bar-[..]
|
|
|
|
[RUNNING] [..]target/release/deps/b-[..]
|
2020-06-10 22:31:36 +00:00
|
|
|
[DOCTEST] bar
|
2021-09-24 04:55:42 +00:00
|
|
|
[RUNNING] `rustdoc --crate-type cdylib --crate-type rlib --crate-name bar --test [..]-C lto[..]
|
2020-06-10 22:31:36 +00:00
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn dylib() {
|
|
|
|
let p = project_with_dep("'dylib'");
|
|
|
|
let output = p.cargo("build --release -v").exec_with_output().unwrap();
|
2021-09-24 04:55:42 +00:00
|
|
|
// `registry` is OnlyObject because rustc doesn't support LTO with dylibs.
|
2020-06-10 22:31:36 +00:00
|
|
|
verify_lto(&output, "registry", "--crate-type lib", Lto::OnlyObject);
|
2021-09-24 04:55:42 +00:00
|
|
|
// `registry_shared` is both because it is needed by both bar (Object) and
|
|
|
|
// foo (Bitcode for LTO).
|
2020-06-10 22:31:36 +00:00
|
|
|
verify_lto(
|
|
|
|
&output,
|
|
|
|
"registry_shared",
|
|
|
|
"--crate-type lib",
|
|
|
|
Lto::ObjectAndBitcode,
|
|
|
|
);
|
2021-09-24 04:55:42 +00:00
|
|
|
// `bar` is OnlyObject because rustc doesn't support LTO with dylibs.
|
2020-06-10 22:31:36 +00:00
|
|
|
verify_lto(&output, "bar", "--crate-type dylib", Lto::OnlyObject);
|
2021-09-24 04:55:42 +00:00
|
|
|
// `foo` is LTO because it is a binary, and the profile specifies `lto=true`.
|
2020-06-10 22:31:36 +00:00
|
|
|
verify_lto(&output, "foo", "--crate-type bin", Lto::Run(None));
|
2021-09-24 04:55:42 +00:00
|
|
|
// `cargo test` should not rebuild dependencies. It builds the test
|
|
|
|
// executables with `lto=true` because the tests are built with the
|
|
|
|
// `--release` flag.
|
2020-06-10 22:31:36 +00:00
|
|
|
p.cargo("test --release -v")
|
|
|
|
.with_stderr_unordered(
|
|
|
|
"\
|
|
|
|
[FRESH] registry v0.0.1
|
|
|
|
[FRESH] registry-shared v0.0.1
|
|
|
|
[FRESH] bar v0.0.0 [..]
|
|
|
|
[COMPILING] foo [..]
|
2021-09-24 04:55:42 +00:00
|
|
|
[RUNNING] `rustc --crate-name foo [..]-C lto [..]--test[..]
|
|
|
|
[RUNNING] `rustc --crate-name a [..]-C lto [..]--test[..]
|
2020-06-10 22:31:36 +00:00
|
|
|
[FINISHED] [..]
|
|
|
|
[RUNNING] [..]
|
|
|
|
[RUNNING] [..]
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
2021-09-24 04:55:42 +00:00
|
|
|
// Building just `bar` causes `registry-shared` to get rebuilt because it
|
|
|
|
// switches to OnlyObject because it is now only being used with a dylib
|
|
|
|
// which does not support LTO.
|
|
|
|
//
|
|
|
|
// `bar` gets rebuilt because `registry_shared` got rebuilt.
|
2020-06-10 22:31:36 +00:00
|
|
|
p.cargo("build --release -v --manifest-path bar/Cargo.toml")
|
|
|
|
.with_stderr_unordered(
|
|
|
|
"\
|
|
|
|
[COMPILING] registry-shared v0.0.1
|
|
|
|
[FRESH] registry v0.0.1
|
2020-08-25 13:05:25 +00:00
|
|
|
[RUNNING] `rustc --crate-name registry_shared [..]-C embed-bitcode=no[..]
|
2022-11-21 17:39:02 +00:00
|
|
|
[DIRTY] bar v0.0.0 ([..]): dependency info changed
|
2020-06-10 22:31:36 +00:00
|
|
|
[COMPILING] bar [..]
|
2020-08-25 13:05:25 +00:00
|
|
|
[RUNNING] `rustc --crate-name bar [..]--crate-type dylib [..]-C embed-bitcode=no[..]
|
2020-06-10 22:31:36 +00:00
|
|
|
[FINISHED] [..]
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
2021-09-24 04:55:42 +00:00
|
|
|
// Testing just `bar` causes `registry` to get rebuilt because it switches
|
|
|
|
// to needing both Object (for the `bar` dylib) and Bitcode (for the test
|
|
|
|
// built with LTO).
|
|
|
|
//
|
|
|
|
// `bar` the dylib gets rebuilt because `registry` got rebuilt.
|
2020-06-10 22:31:36 +00:00
|
|
|
p.cargo("test --release -v --manifest-path bar/Cargo.toml")
|
|
|
|
.with_stderr_unordered(
|
|
|
|
"\
|
|
|
|
[FRESH] registry-shared v0.0.1
|
2021-09-24 04:55:42 +00:00
|
|
|
[COMPILING] registry v0.0.1
|
|
|
|
[RUNNING] `rustc --crate-name registry [..]
|
2022-11-21 17:39:02 +00:00
|
|
|
[DIRTY] bar v0.0.0 ([..]): dependency info changed
|
2020-06-10 22:31:36 +00:00
|
|
|
[COMPILING] bar [..]
|
2021-09-24 04:55:42 +00:00
|
|
|
[RUNNING] `rustc --crate-name bar [..]--crate-type dylib [..]-C embed-bitcode=no[..]
|
|
|
|
[RUNNING] `rustc --crate-name bar [..]-C lto [..]--test[..]
|
|
|
|
[RUNNING] `rustc --crate-name b [..]-C lto [..]--test[..]
|
2020-06-10 22:31:36 +00:00
|
|
|
[FINISHED] [..]
|
|
|
|
[RUNNING] [..]
|
|
|
|
[RUNNING] [..]
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn test_profile() {
|
|
|
|
Package::new("bar", "0.0.1")
|
|
|
|
.file("src/lib.rs", "pub fn foo() -> i32 { 123 } ")
|
|
|
|
.publish();
|
|
|
|
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
edition = "2018"
|
|
|
|
|
|
|
|
[profile.test]
|
|
|
|
lto = 'thin'
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
bar = "*"
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
#[test]
|
|
|
|
fn t1() {
|
|
|
|
assert_eq!(123, bar::foo());
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("test -v")
|
2020-07-29 05:25:45 +00:00
|
|
|
// unordered because the two `foo` builds start in parallel
|
|
|
|
.with_stderr_unordered("\
|
2020-06-10 22:31:36 +00:00
|
|
|
[UPDATING] [..]
|
|
|
|
[DOWNLOADING] [..]
|
|
|
|
[DOWNLOADED] [..]
|
|
|
|
[COMPILING] bar v0.0.1
|
|
|
|
[RUNNING] `rustc --crate-name bar [..]crate-type lib[..]
|
|
|
|
[COMPILING] foo [..]
|
2020-08-27 23:41:43 +00:00
|
|
|
[RUNNING] `rustc --crate-name foo [..]--crate-type lib --emit=dep-info,metadata,link -C linker-plugin-lto[..]
|
2020-06-10 22:31:36 +00:00
|
|
|
[RUNNING] `rustc --crate-name foo [..]--emit=dep-info,link -C lto=thin [..]--test[..]
|
|
|
|
[FINISHED] [..]
|
|
|
|
[RUNNING] [..]
|
|
|
|
[DOCTEST] foo
|
|
|
|
[RUNNING] `rustdoc [..]
|
|
|
|
")
|
|
|
|
.run();
|
|
|
|
}
|
|
|
|
|
2020-08-27 23:41:43 +00:00
|
|
|
#[cargo_test]
|
|
|
|
fn doctest() {
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
edition = "2018"
|
|
|
|
|
|
|
|
[profile.release]
|
|
|
|
lto = true
|
|
|
|
|
|
|
|
[dependencies]
|
|
|
|
bar = { path = "bar" }
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file(
|
|
|
|
"src/lib.rs",
|
|
|
|
r#"
|
|
|
|
/// Foo!
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// foo::foo();
|
|
|
|
/// ```
|
|
|
|
pub fn foo() { bar::bar(); }
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
|
|
|
|
.file(
|
|
|
|
"bar/src/lib.rs",
|
|
|
|
r#"
|
|
|
|
pub fn bar() { println!("hi!"); }
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
p.cargo("test --doc --release -v")
|
2021-09-24 04:55:42 +00:00
|
|
|
.with_stderr_contains("[..]`rustc --crate-name bar[..]-C linker-plugin-lto[..]")
|
|
|
|
.with_stderr_contains("[..]`rustc --crate-name foo[..]-C linker-plugin-lto[..]")
|
2020-08-27 23:41:43 +00:00
|
|
|
// embed-bitcode should be harmless here
|
2021-09-24 04:55:42 +00:00
|
|
|
.with_stderr_contains("[..]`rustdoc [..]-C lto[..]")
|
2020-08-27 23:41:43 +00:00
|
|
|
.run();
|
|
|
|
|
|
|
|
// Try with bench profile.
|
|
|
|
p.cargo("test --doc --release -v")
|
|
|
|
.env("CARGO_PROFILE_BENCH_LTO", "true")
|
2021-09-24 04:55:42 +00:00
|
|
|
.with_stderr_unordered(
|
|
|
|
"\
|
|
|
|
[FRESH] bar v0.1.0 [..]
|
|
|
|
[FRESH] foo v0.1.0 [..]
|
|
|
|
[FINISHED] release [..]
|
|
|
|
[DOCTEST] foo
|
|
|
|
[RUNNING] `rustdoc [..]-C lto[..]
|
|
|
|
",
|
|
|
|
)
|
2020-08-27 23:41:43 +00:00
|
|
|
.run();
|
|
|
|
}
|
2020-10-05 15:15:32 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn dylib_rlib_bin() {
|
|
|
|
// dylib+rlib linked with a binary
|
|
|
|
let p = project()
|
|
|
|
.file(
|
|
|
|
"Cargo.toml",
|
|
|
|
r#"
|
|
|
|
[package]
|
|
|
|
name = "foo"
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
|
|
[lib]
|
|
|
|
crate-type = ["dylib", "rlib"]
|
|
|
|
|
|
|
|
[profile.release]
|
|
|
|
lto = true
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.file("src/lib.rs", "pub fn foo() { println!(\"hi!\"); }")
|
2021-11-29 18:04:15 +00:00
|
|
|
.file("src/bin/ferret.rs", "fn main() { foo::foo(); }")
|
2020-10-05 15:15:32 +00:00
|
|
|
.build();
|
|
|
|
|
|
|
|
let output = p.cargo("build --release -v").exec_with_output().unwrap();
|
|
|
|
verify_lto(
|
|
|
|
&output,
|
|
|
|
"foo",
|
|
|
|
"--crate-type dylib --crate-type rlib",
|
|
|
|
Lto::ObjectAndBitcode,
|
|
|
|
);
|
2021-11-29 18:04:15 +00:00
|
|
|
verify_lto(&output, "ferret", "--crate-type bin", Lto::Run(None));
|
2020-10-05 15:15:32 +00:00
|
|
|
}
|
2020-10-05 15:56:22 +00:00
|
|
|
|
|
|
|
#[cargo_test]
|
|
|
|
fn fresh_swapping_commands() {
|
|
|
|
// In some rare cases, different commands end up building dependencies
|
|
|
|
// with different LTO settings. This checks that it doesn't cause the
|
|
|
|
// cache to thrash in that scenario.
|
|
|
|
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", "pub fn foo() { println!(\"hi!\"); }")
|
|
|
|
.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 src/lib.rs [..]-C linker-plugin-lto[..]
|
|
|
|
[FINISHED] [..]
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
p.cargo("test --release -v")
|
|
|
|
.with_stderr_unordered(
|
|
|
|
"\
|
2021-09-24 04:55:42 +00:00
|
|
|
[FRESH] bar v1.0.0
|
2020-10-05 15:56:22 +00:00
|
|
|
[COMPILING] foo v0.1.0 [..]
|
2021-09-24 04:55:42 +00:00
|
|
|
[RUNNING] `rustc --crate-name foo src/lib.rs [..]-C lto[..]--test[..]
|
2020-10-05 15:56:22 +00:00
|
|
|
[FINISHED] [..]
|
|
|
|
[RUNNING] `[..]/foo[..]`
|
|
|
|
[DOCTEST] foo
|
2021-09-24 04:55:42 +00:00
|
|
|
[RUNNING] `rustdoc [..]-C lto[..]
|
2020-10-05 15:56:22 +00:00
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
|
|
|
|
p.cargo("build --release -v")
|
|
|
|
.with_stderr(
|
|
|
|
"\
|
|
|
|
[FRESH] bar v1.0.0
|
|
|
|
[FRESH] foo [..]
|
|
|
|
[FINISHED] [..]
|
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
p.cargo("test --release -v --no-run -v")
|
|
|
|
.with_stderr(
|
|
|
|
"\
|
|
|
|
[FRESH] bar v1.0.0
|
|
|
|
[FRESH] foo [..]
|
|
|
|
[FINISHED] [..]
|
2021-10-04 21:52:02 +00:00
|
|
|
[EXECUTABLE] `[..]/target/release/deps/foo-[..][EXE]`
|
2020-10-05 15:56:22 +00:00
|
|
|
",
|
|
|
|
)
|
|
|
|
.run();
|
|
|
|
}
|