| use cargo::core::compiler::Lto; |
| use cargo_test_support::registry::Package; |
| use cargo_test_support::{basic_manifest, project, Project}; |
| use std::process::Output; |
| |
| #[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(); |
| p.cargo("build -v --release") |
| .with_stderr_contains("[..]`rustc[..]--crate-name bar[..]-C linker-plugin-lto[..]`") |
| .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") |
| .with_stderr_contains("[..]`rustc[..]--crate-name bar[..]-C embed-bitcode=no[..]`") |
| .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 |
| |
| # 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 |
| "#, |
| ) |
| .file("build.rs", "fn main() { dep_build::foo() }") |
| .file( |
| "src/bin/foo-bin.rs", |
| "#[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 |
| .with_stderr_contains( |
| "[..]`rustc[..]--crate-name dep_normal2 [..]-C linker-plugin-lto[..]`", |
| ) |
| .with_stderr_contains("[..]`rustc[..]--crate-name dep_normal [..]-C linker-plugin-lto[..]`") |
| // build dependencies and their transitive deps don't need any bitcode, |
| // so embedding should be turned off |
| .with_stderr_contains("[..]`rustc[..]--crate-name dep_build2 [..]-C embed-bitcode=no[..]`") |
| .with_stderr_contains("[..]`rustc[..]--crate-name dep_build [..]-C embed-bitcode=no[..]`") |
| .with_stderr_contains( |
| "[..]`rustc[..]--crate-name build_script_build [..]-C embed-bitcode=no[..]`", |
| ) |
| // proc macro deps are the same as build deps here |
| .with_stderr_contains( |
| "[..]`rustc[..]--crate-name dep_proc_macro2 [..]-C embed-bitcode=no[..]`", |
| ) |
| .with_stderr_contains( |
| "[..]`rustc[..]--crate-name dep_proc_macro [..]-C embed-bitcode=no[..]`", |
| ) |
| .with_stderr_contains( |
| "[..]`rustc[..]--crate-name foo_bin [..]--crate-type bin[..]-C lto[..]`", |
| ) |
| .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[..]") |
| .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[..]") |
| .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" |
| "#, |
| ) |
| .file("src/lib.rs", "pub fn foo() {}") |
| .file( |
| "src/main.rs", |
| "fn main() { |
| test::foo(); |
| bar::foo(); |
| }", |
| ) |
| .build(); |
| p.cargo("build -v --release") |
| .with_stderr( |
| "\ |
| [UPDATING] [..] |
| [DOWNLOADING] [..] |
| [DOWNLOADED] [..] |
| [COMPILING] bar v0.0.1 |
| [RUNNING] `rustc --crate-name bar [..]--crate-type lib [..]-C lto=off -C embed-bitcode=no[..] |
| [COMPILING] test [..] |
| [RUNNING] `rustc --crate-name test [..]--crate-type lib [..]-C lto=off -C embed-bitcode=no[..] |
| [RUNNING] `rustc --crate-name test src/main.rs [..]--crate-type bin [..]-C lto=off[..] |
| [FINISHED] [..] |
| ", |
| ) |
| .run(); |
| } |
| |
| #[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(); |
| p.cargo("build -v --release --lib") |
| .with_stderr( |
| "\ |
| [COMPILING] test [..] |
| [RUNNING] `rustc [..]--crate-type lib[..]-C linker-plugin-lto[..] |
| [FINISHED] [..] |
| ", |
| ) |
| .run(); |
| p.cargo("build -v --release") |
| .with_stderr_contains( |
| "\ |
| [COMPILING] test [..] |
| [RUNNING] `rustc [..]--crate-type bin[..]-C lto[..] |
| [FINISHED] [..] |
| ", |
| ) |
| .run(); |
| } |
| |
| #[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(); |
| } |
| |
| /// 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. |
| fn project_with_dep(crate_types: &str) -> Project { |
| Package::new("registry", "0.0.1") |
| .file("src/lib.rs", r#"pub fn foo() { println!("registry"); }"#) |
| .publish(); |
| Package::new("registry-shared", "0.0.1") |
| .file("src/lib.rs", r#"pub fn foo() { println!("shared"); }"#) |
| .publish(); |
| |
| project() |
| .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", |
| &format!( |
| r#" |
| [package] |
| name = "bar" |
| version = "0.0.0" |
| |
| [dependencies] |
| registry = "*" |
| registry-shared = "*" |
| |
| [lib] |
| crate-type = [{}] |
| "#, |
| crate_types |
| ), |
| ) |
| .file( |
| "bar/src/lib.rs", |
| r#" |
| pub fn foo() { |
| println!("bar"); |
| registry::foo(); |
| registry_shared::foo(); |
| } |
| "#, |
| ) |
| .file("tests/a.rs", "") |
| .file("bar/tests/b.rs", "") |
| .build() |
| } |
| |
| /// 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. |
| 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((_, line)) = line.split_once("-C lto=") { |
| let mode = line.splitn(2, ' ').next().unwrap(); |
| if mode == "off" { |
| Lto::Off |
| } else { |
| Lto::Run(Some(mode.into())) |
| } |
| } else if line.contains("-C lto") { |
| Lto::Run(None) |
| } else if line.contains("-C linker-plugin-lto") { |
| Lto::OnlyBitcode |
| } else if line.contains("-C embed-bitcode=no") { |
| 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(); |
| // `registry` is ObjectAndBitcode because it needs Object for the |
| // rlib, and Bitcode for the cdylib (which doesn't support LTO). |
| verify_lto( |
| &output, |
| "registry", |
| "--crate-type lib", |
| Lto::ObjectAndBitcode, |
| ); |
| // Same as `registry` |
| verify_lto( |
| &output, |
| "registry_shared", |
| "--crate-type lib", |
| Lto::ObjectAndBitcode, |
| ); |
| // Same as `registry` |
| 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 [..] |
| [RUNNING] `rustc --crate-name foo [..]-C lto [..]--test[..] |
| [RUNNING] `rustc --crate-name a [..]-C lto [..]--test[..] |
| [FINISHED] [..] |
| [RUNNING] [..] |
| [RUNNING] [..] |
| ", |
| ) |
| .run(); |
| p.cargo("build --release -v --manifest-path bar/Cargo.toml") |
| .with_stderr_unordered( |
| "\ |
| [FRESH] registry-shared v0.0.1 |
| [FRESH] registry v0.0.1 |
| [FRESH] bar v0.0.0 [..] |
| [FINISHED] [..] |
| ", |
| ) |
| .run(); |
| p.cargo("test --release -v --manifest-path bar/Cargo.toml") |
| .with_stderr_unordered( |
| "\ |
| [FRESH] registry-shared v0.0.1 |
| [FRESH] registry v0.0.1 |
| [COMPILING] bar [..] |
| [RUNNING] `rustc --crate-name bar [..]-C lto[..]--test[..] |
| [RUNNING] `rustc --crate-name b [..]-C lto[..]--test[..] |
| [FINISHED] [..] |
| [RUNNING] [..]target/release/deps/bar-[..] |
| [RUNNING] [..]target/release/deps/b-[..] |
| [DOCTEST] bar |
| [RUNNING] `rustdoc --crate-type cdylib --crate-type rlib --crate-name bar --test [..]-C lto[..] |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn dylib() { |
| let p = project_with_dep("'dylib'"); |
| let output = p.cargo("build --release -v").exec_with_output().unwrap(); |
| // `registry` is OnlyObject because rustc doesn't support LTO with dylibs. |
| verify_lto(&output, "registry", "--crate-type lib", Lto::OnlyObject); |
| // `registry_shared` is both because it is needed by both bar (Object) and |
| // foo (Bitcode for LTO). |
| verify_lto( |
| &output, |
| "registry_shared", |
| "--crate-type lib", |
| Lto::ObjectAndBitcode, |
| ); |
| // `bar` is OnlyObject because rustc doesn't support LTO with dylibs. |
| verify_lto(&output, "bar", "--crate-type dylib", Lto::OnlyObject); |
| // `foo` is LTO because it is a binary, and the profile specifies `lto=true`. |
| verify_lto(&output, "foo", "--crate-type bin", Lto::Run(None)); |
| // `cargo test` should not rebuild dependencies. It builds the test |
| // executables with `lto=true` because the tests are built with the |
| // `--release` flag. |
| 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 [..] |
| [RUNNING] `rustc --crate-name foo [..]-C lto [..]--test[..] |
| [RUNNING] `rustc --crate-name a [..]-C lto [..]--test[..] |
| [FINISHED] [..] |
| [RUNNING] [..] |
| [RUNNING] [..] |
| ", |
| ) |
| .run(); |
| // 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. |
| p.cargo("build --release -v --manifest-path bar/Cargo.toml") |
| .with_stderr_unordered( |
| "\ |
| [COMPILING] registry-shared v0.0.1 |
| [FRESH] registry v0.0.1 |
| [RUNNING] `rustc --crate-name registry_shared [..]-C embed-bitcode=no[..] |
| [DIRTY] bar v0.0.0 ([..]): dependency info changed |
| [COMPILING] bar [..] |
| [RUNNING] `rustc --crate-name bar [..]--crate-type dylib [..]-C embed-bitcode=no[..] |
| [FINISHED] [..] |
| ", |
| ) |
| .run(); |
| // 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. |
| p.cargo("test --release -v --manifest-path bar/Cargo.toml") |
| .with_stderr_unordered( |
| "\ |
| [FRESH] registry-shared v0.0.1 |
| [COMPILING] registry v0.0.1 |
| [RUNNING] `rustc --crate-name registry [..] |
| [DIRTY] bar v0.0.0 ([..]): dependency info changed |
| [COMPILING] bar [..] |
| [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[..] |
| [FINISHED] [..] |
| [RUNNING] [..] |
| [RUNNING] [..] |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| // This is currently broken on windows-gnu, see https://github.com/rust-lang/rust/issues/109797 |
| #[cfg_attr( |
| all(target_os = "windows", target_env = "gnu"), |
| ignore = "windows-gnu not working" |
| )] |
| 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") |
| // unordered because the two `foo` builds start in parallel |
| .with_stderr_unordered("\ |
| [UPDATING] [..] |
| [DOWNLOADING] [..] |
| [DOWNLOADED] [..] |
| [COMPILING] bar v0.0.1 |
| [RUNNING] `rustc --crate-name bar [..]crate-type lib[..] |
| [COMPILING] foo [..] |
| [RUNNING] `rustc --crate-name foo [..]--crate-type lib --emit=dep-info,metadata,link -C linker-plugin-lto[..] |
| [RUNNING] `rustc --crate-name foo [..]--emit=dep-info,link -C lto=thin [..]--test[..] |
| [FINISHED] [..] |
| [RUNNING] [..] |
| [DOCTEST] foo |
| [RUNNING] `rustdoc [..] |
| ") |
| .run(); |
| } |
| |
| #[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") |
| .with_stderr_contains("[..]`rustc --crate-name bar[..]-C linker-plugin-lto[..]") |
| .with_stderr_contains("[..]`rustc --crate-name foo[..]-C linker-plugin-lto[..]") |
| // embed-bitcode should be harmless here |
| .with_stderr_contains("[..]`rustdoc [..]-C lto[..]") |
| .run(); |
| |
| // Try with bench profile. |
| p.cargo("test --doc --release -v") |
| .env("CARGO_PROFILE_BENCH_LTO", "true") |
| .with_stderr_unordered( |
| "\ |
| [FRESH] bar v0.1.0 [..] |
| [FRESH] foo v0.1.0 [..] |
| [FINISHED] release [..] |
| [DOCTEST] foo |
| [RUNNING] `rustdoc [..]-C lto[..] |
| ", |
| ) |
| .run(); |
| } |
| |
| #[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!\"); }") |
| .file("src/bin/ferret.rs", "fn main() { foo::foo(); }") |
| .build(); |
| |
| let output = p.cargo("build --release -v").exec_with_output().unwrap(); |
| verify_lto( |
| &output, |
| "foo", |
| "--crate-type dylib --crate-type rlib", |
| Lto::ObjectAndBitcode, |
| ); |
| verify_lto(&output, "ferret", "--crate-type bin", Lto::Run(None)); |
| } |
| |
| #[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( |
| "\ |
| [FRESH] bar v1.0.0 |
| [COMPILING] foo v0.1.0 [..] |
| [RUNNING] `rustc --crate-name foo src/lib.rs [..]-C lto[..]--test[..] |
| [FINISHED] [..] |
| [RUNNING] `[..]/foo[..]` |
| [DOCTEST] foo |
| [RUNNING] `rustdoc [..]-C lto[..] |
| ", |
| ) |
| .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] [..] |
| [EXECUTABLE] `[..]/target/release/deps/foo-[..][EXE]` |
| ", |
| ) |
| .run(); |
| } |