| //! Tests for profile overrides (build-override and per-package overrides). |
| |
| use cargo_test_support::registry::Package; |
| use cargo_test_support::{basic_lib_manifest, basic_manifest, project}; |
| |
| #[cargo_test] |
| fn profile_override_basic() { |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| authors = [] |
| |
| [dependencies] |
| bar = {path = "bar"} |
| |
| [profile.dev] |
| opt-level = 1 |
| |
| [profile.dev.package.bar] |
| opt-level = 3 |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .file("bar/Cargo.toml", &basic_lib_manifest("bar")) |
| .file("bar/src/lib.rs", "") |
| .build(); |
| |
| p.cargo("check -v") |
| .with_stderr( |
| "[CHECKING] bar [..] |
| [RUNNING] `rustc --crate-name bar [..] -C opt-level=3 [..]` |
| [CHECKING] foo [..] |
| [RUNNING] `rustc --crate-name foo [..] -C opt-level=1 [..]` |
| [FINISHED] dev [optimized + debuginfo] target(s) in [..]", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn profile_override_warnings() { |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| |
| [dependencies] |
| bar = {path = "bar"} |
| |
| [profile.dev.package.bart] |
| opt-level = 3 |
| |
| [profile.dev.package.no-suggestion] |
| opt-level = 3 |
| |
| [profile.dev.package."bar:1.2.3"] |
| opt-level = 3 |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .file("bar/Cargo.toml", &basic_lib_manifest("bar")) |
| .file("bar/src/lib.rs", "") |
| .build(); |
| |
| p.cargo("build") |
| .with_stderr_contains( |
| "\ |
| [WARNING] profile package spec `bar@1.2.3` in profile `dev` \ |
| has a version or URL that does not match any of the packages: \ |
| bar v0.5.0 ([..]/foo/bar) |
| [WARNING] profile package spec `bart` in profile `dev` did not match any packages |
| |
| <tab>Did you mean `bar`? |
| [WARNING] profile package spec `no-suggestion` in profile `dev` did not match any packages |
| [COMPILING] [..] |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn profile_override_bad_settings() { |
| let bad_values = [ |
| ( |
| "panic = \"abort\"", |
| "`panic` may not be specified in a `package` profile", |
| ), |
| ( |
| "lto = true", |
| "`lto` may not be specified in a `package` profile", |
| ), |
| ( |
| "rpath = true", |
| "`rpath` may not be specified in a `package` profile", |
| ), |
| ("package = {}", "package-specific profiles cannot be nested"), |
| ]; |
| for &(snippet, expected) in bad_values.iter() { |
| let p = project() |
| .file( |
| "Cargo.toml", |
| &format!( |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| |
| [dependencies] |
| bar = {{path = "bar"}} |
| |
| [profile.dev.package.bar] |
| {} |
| "#, |
| snippet |
| ), |
| ) |
| .file("src/lib.rs", "") |
| .file("bar/Cargo.toml", &basic_lib_manifest("bar")) |
| .file("bar/src/lib.rs", "") |
| .build(); |
| |
| p.cargo("check") |
| .with_status(101) |
| .with_stderr_contains(format!("Caused by:\n {}", expected)) |
| .run(); |
| } |
| } |
| |
| #[cargo_test] |
| fn profile_override_hierarchy() { |
| // Test that the precedence rules are correct for different types. |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [workspace] |
| members = ["m1", "m2", "m3"] |
| |
| [profile.dev] |
| codegen-units = 1 |
| |
| [profile.dev.package.m2] |
| codegen-units = 2 |
| |
| [profile.dev.package."*"] |
| codegen-units = 3 |
| |
| [profile.dev.build-override] |
| codegen-units = 4 |
| "#, |
| ) |
| // m1 |
| .file( |
| "m1/Cargo.toml", |
| r#" |
| [package] |
| name = "m1" |
| version = "0.0.1" |
| |
| [dependencies] |
| m2 = { path = "../m2" } |
| dep = { path = "../../dep" } |
| "#, |
| ) |
| .file("m1/src/lib.rs", "extern crate m2; extern crate dep;") |
| .file("m1/build.rs", "fn main() {}") |
| // m2 |
| .file( |
| "m2/Cargo.toml", |
| r#" |
| [package] |
| name = "m2" |
| version = "0.0.1" |
| |
| [dependencies] |
| m3 = { path = "../m3" } |
| |
| [build-dependencies] |
| m3 = { path = "../m3" } |
| dep = { path = "../../dep" } |
| "#, |
| ) |
| .file("m2/src/lib.rs", "extern crate m3;") |
| .file( |
| "m2/build.rs", |
| "extern crate m3; extern crate dep; fn main() {}", |
| ) |
| // m3 |
| .file("m3/Cargo.toml", &basic_lib_manifest("m3")) |
| .file("m3/src/lib.rs", "") |
| .build(); |
| |
| // dep (outside of workspace) |
| let _dep = project() |
| .at("dep") |
| .file("Cargo.toml", &basic_lib_manifest("dep")) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| // Profiles should be: |
| // m3: 4 (as build.rs dependency) |
| // m3: 1 (as [profile.dev] as workspace member) |
| // dep: 3 (as [profile.dev.package."*"] as non-workspace member) |
| // m1 build.rs: 4 (as [profile.dev.build-override]) |
| // m2 build.rs: 2 (as [profile.dev.package.m2]) |
| // m2: 2 (as [profile.dev.package.m2]) |
| // m1: 1 (as [profile.dev]) |
| |
| p.cargo("build -v").with_stderr_unordered("\ |
| [COMPILING] m3 [..] |
| [COMPILING] dep [..] |
| [RUNNING] `rustc --crate-name m3 m3/src/lib.rs [..] --crate-type lib --emit=[..]link[..]-C codegen-units=4 [..] |
| [RUNNING] `rustc --crate-name dep [..]dep/src/lib.rs [..] --crate-type lib --emit=[..]link[..]-C codegen-units=3 [..] |
| [RUNNING] `rustc --crate-name m3 m3/src/lib.rs [..] --crate-type lib --emit=[..]link[..]-C codegen-units=1 [..] |
| [RUNNING] `rustc --crate-name build_script_build m1/build.rs [..] --crate-type bin --emit=[..]link[..]-C codegen-units=4 [..] |
| [COMPILING] m2 [..] |
| [RUNNING] `rustc --crate-name build_script_build m2/build.rs [..] --crate-type bin --emit=[..]link[..]-C codegen-units=2 [..] |
| [RUNNING] `[..]/m1-[..]/build-script-build` |
| [RUNNING] `[..]/m2-[..]/build-script-build` |
| [RUNNING] `rustc --crate-name m2 m2/src/lib.rs [..] --crate-type lib --emit=[..]link[..]-C codegen-units=2 [..] |
| [COMPILING] m1 [..] |
| [RUNNING] `rustc --crate-name m1 m1/src/lib.rs [..] --crate-type lib --emit=[..]link[..]-C codegen-units=1 [..] |
| [FINISHED] dev [unoptimized + debuginfo] [..] |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn profile_override_spec_multiple() { |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.0.1" |
| |
| [dependencies] |
| bar = { path = "bar" } |
| |
| [profile.dev.package.bar] |
| opt-level = 3 |
| |
| [profile.dev.package."bar:0.5.0"] |
| opt-level = 3 |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .file("bar/Cargo.toml", &basic_lib_manifest("bar")) |
| .file("bar/src/lib.rs", "") |
| .build(); |
| |
| p.cargo("check -v") |
| .with_status(101) |
| .with_stderr_contains( |
| "\ |
| [ERROR] multiple package overrides in profile `dev` match package `bar v0.5.0 ([..])` |
| found package specs: bar, bar@0.5.0", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn profile_override_spec() { |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [workspace] |
| members = ["m1", "m2"] |
| |
| [profile.dev.package."dep:1.0.0"] |
| codegen-units = 1 |
| |
| [profile.dev.package."dep:2.0.0"] |
| codegen-units = 2 |
| "#, |
| ) |
| // m1 |
| .file( |
| "m1/Cargo.toml", |
| r#" |
| [package] |
| name = "m1" |
| version = "0.0.1" |
| |
| [dependencies] |
| dep = { path = "../../dep1" } |
| "#, |
| ) |
| .file("m1/src/lib.rs", "extern crate dep;") |
| // m2 |
| .file( |
| "m2/Cargo.toml", |
| r#" |
| [package] |
| name = "m2" |
| version = "0.0.1" |
| |
| [dependencies] |
| dep = {path = "../../dep2" } |
| "#, |
| ) |
| .file("m2/src/lib.rs", "extern crate dep;") |
| .build(); |
| |
| project() |
| .at("dep1") |
| .file("Cargo.toml", &basic_manifest("dep", "1.0.0")) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| project() |
| .at("dep2") |
| .file("Cargo.toml", &basic_manifest("dep", "2.0.0")) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| p.cargo("check -v") |
| .with_stderr_contains("[RUNNING] `rustc [..]dep1/src/lib.rs [..] -C codegen-units=1 [..]") |
| .with_stderr_contains("[RUNNING] `rustc [..]dep2/src/lib.rs [..] -C codegen-units=2 [..]") |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn override_proc_macro() { |
| Package::new("shared", "1.0.0").publish(); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| edition = "2018" |
| |
| [dependencies] |
| shared = "1.0" |
| pm = {path = "pm"} |
| |
| [profile.dev.build-override] |
| codegen-units = 4 |
| "#, |
| ) |
| .file("src/lib.rs", r#"pm::eat!{}"#) |
| .file( |
| "pm/Cargo.toml", |
| r#" |
| [package] |
| name = "pm" |
| version = "0.1.0" |
| |
| [lib] |
| proc-macro = true |
| |
| [dependencies] |
| shared = "1.0" |
| "#, |
| ) |
| .file( |
| "pm/src/lib.rs", |
| r#" |
| extern crate proc_macro; |
| use proc_macro::TokenStream; |
| |
| #[proc_macro] |
| pub fn eat(_item: TokenStream) -> TokenStream { |
| "".parse().unwrap() |
| } |
| "#, |
| ) |
| .build(); |
| |
| p.cargo("check -v") |
| // Shared built for the proc-macro. |
| .with_stderr_contains("[RUNNING] `rustc [..]--crate-name shared [..]-C codegen-units=4[..]") |
| // Shared built for the library. |
| .with_stderr_line_without( |
| &["[RUNNING] `rustc --crate-name shared"], |
| &["-C codegen-units"], |
| ) |
| .with_stderr_contains("[RUNNING] `rustc [..]--crate-name pm [..]-C codegen-units=4[..]") |
| .with_stderr_line_without( |
| &["[RUNNING] `rustc [..]--crate-name foo"], |
| &["-C codegen-units"], |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn no_warning_ws() { |
| // https://github.com/rust-lang/cargo/issues/7378, avoid warnings in a workspace. |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [workspace] |
| members = ["a", "b"] |
| |
| [profile.dev.package.a] |
| codegen-units = 3 |
| "#, |
| ) |
| .file("a/Cargo.toml", &basic_manifest("a", "0.1.0")) |
| .file("a/src/lib.rs", "") |
| .file("b/Cargo.toml", &basic_manifest("b", "0.1.0")) |
| .file("b/src/lib.rs", "") |
| .build(); |
| |
| p.cargo("check -p b") |
| .with_stderr( |
| "\ |
| [CHECKING] b [..] |
| [FINISHED] [..] |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn build_override_shared() { |
| // A dependency with a build script that is shared with a build |
| // dependency, using different profile settings. That is: |
| // |
| // foo DEBUG=2 |
| // ├── common DEBUG=2 |
| // │ └── common Run build.rs DEBUG=2 |
| // │ └── common build.rs DEBUG=0 (build_override) |
| // └── foo Run build.rs DEBUG=2 |
| // └── foo build.rs DEBUG=0 (build_override) |
| // └── common DEBUG=0 (build_override) |
| // └── common Run build.rs DEBUG=0 (build_override) |
| // └── common build.rs DEBUG=0 (build_override) |
| // |
| // The key part here is that `common` RunCustomBuild is run twice, once |
| // with DEBUG=2 (as a dependency of foo) and once with DEBUG=0 (as a |
| // build-dependency of foo's build script). |
| Package::new("common", "1.0.0") |
| .file( |
| "build.rs", |
| r#" |
| fn main() { |
| if std::env::var("DEBUG").unwrap() != "false" { |
| println!("cargo:rustc-cfg=foo_debug"); |
| } else { |
| println!("cargo:rustc-cfg=foo_release"); |
| } |
| } |
| "#, |
| ) |
| .file( |
| "src/lib.rs", |
| r#" |
| pub fn foo() -> u32 { |
| if cfg!(foo_debug) { |
| assert!(cfg!(debug_assertions)); |
| 1 |
| } else if cfg!(foo_release) { |
| assert!(!cfg!(debug_assertions)); |
| 2 |
| } else { |
| panic!("not set"); |
| } |
| } |
| "#, |
| ) |
| .publish(); |
| |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| edition = "2018" |
| |
| [build-dependencies] |
| common = "1.0" |
| |
| [dependencies] |
| common = "1.0" |
| |
| [profile.dev.build-override] |
| debug = 0 |
| debug-assertions = false |
| "#, |
| ) |
| .file( |
| "build.rs", |
| r#" |
| fn main() { |
| assert_eq!(common::foo(), 2); |
| } |
| "#, |
| ) |
| .file( |
| "src/main.rs", |
| r#" |
| fn main() { |
| assert_eq!(common::foo(), 1); |
| } |
| "#, |
| ) |
| .build(); |
| |
| p.cargo("run").run(); |
| } |