cargo/tests/testsuite/profiles.rs

887 lines
21 KiB
Rust

//! Tests for profiles.
use cargo_test_support::project;
use cargo_test_support::registry::Package;
use std::env;
#[cargo_test]
fn profile_overrides() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "test"
version = "0.0.0"
authors = []
[profile.dev]
opt-level = 1
debug = false
rpath = true
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("build -v")
.with_stderr(
"\
[COMPILING] test v0.0.0 ([CWD])
[RUNNING] `rustc --crate-name test src/lib.rs [..]--crate-type lib \
--emit=[..]link[..]\
-C opt-level=1[..]\
-C debug-assertions=on \
-C metadata=[..] \
-C rpath \
--out-dir [..] \
-L dependency=[CWD]/target/debug/deps`
[FINISHED] dev [optimized] target(s) in [..]
",
)
.run();
}
#[cargo_test]
fn opt_level_override_0() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "test"
version = "0.0.0"
authors = []
[profile.dev]
opt-level = 0
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("build -v")
.with_stderr(
"\
[COMPILING] test v0.0.0 ([CWD])
[RUNNING] `rustc --crate-name test src/lib.rs [..]--crate-type lib \
--emit=[..]link[..]\
-C debuginfo=2 [..]\
-C metadata=[..] \
--out-dir [..] \
-L dependency=[CWD]/target/debug/deps`
[FINISHED] [..] target(s) in [..]
",
)
.run();
}
#[cargo_test]
fn debug_override_1() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "test"
version = "0.0.0"
authors = []
[profile.dev]
debug = 1
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("build -v")
.with_stderr(
"\
[COMPILING] test v0.0.0 ([CWD])
[RUNNING] `rustc --crate-name test src/lib.rs [..]--crate-type lib \
--emit=[..]link[..]\
-C debuginfo=1 [..]\
-C metadata=[..] \
--out-dir [..] \
-L dependency=[CWD]/target/debug/deps`
[FINISHED] [..] target(s) in [..]
",
)
.run();
}
fn check_opt_level_override(profile_level: &str, rustc_level: &str) {
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "test"
version = "0.0.0"
authors = []
[profile.dev]
opt-level = {level}
"#,
level = profile_level
),
)
.file("src/lib.rs", "")
.build();
p.cargo("build -v")
.with_stderr(&format!(
"\
[COMPILING] test v0.0.0 ([CWD])
[RUNNING] `rustc --crate-name test src/lib.rs [..]--crate-type lib \
--emit=[..]link \
-C opt-level={level}[..]\
-C debuginfo=2 [..]\
-C debug-assertions=on \
-C metadata=[..] \
--out-dir [..] \
-L dependency=[CWD]/target/debug/deps`
[FINISHED] [..] target(s) in [..]
",
level = rustc_level
))
.run();
}
#[cargo_test]
fn opt_level_overrides() {
for &(profile_level, rustc_level) in &[
("1", "1"),
("2", "2"),
("3", "3"),
("\"s\"", "s"),
("\"z\"", "z"),
] {
check_opt_level_override(profile_level, rustc_level)
}
}
#[cargo_test]
fn top_level_overrides_deps() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "test"
version = "0.0.0"
authors = []
[profile.release]
opt-level = 1
debug = true
[dependencies.foo]
path = "foo"
"#,
)
.file("src/lib.rs", "")
.file(
"foo/Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.0"
authors = []
[profile.release]
opt-level = 0
debug = false
[lib]
name = "foo"
crate_type = ["dylib", "rlib"]
"#,
)
.file("foo/src/lib.rs", "")
.build();
p.cargo("build -v --release")
.with_stderr(&format!(
"\
[COMPILING] foo v0.0.0 ([CWD]/foo)
[RUNNING] `rustc --crate-name foo foo/src/lib.rs [..]\
--crate-type dylib --crate-type rlib \
--emit=[..]link \
-C prefer-dynamic \
-C opt-level=1[..]\
-C debuginfo=2 [..]\
-C metadata=[..] \
--out-dir [CWD]/target/release/deps \
-L dependency=[CWD]/target/release/deps`
[COMPILING] test v0.0.0 ([CWD])
[RUNNING] `rustc --crate-name test src/lib.rs [..]--crate-type lib \
--emit=[..]link \
-C opt-level=1[..]\
-C debuginfo=2 [..]\
-C metadata=[..] \
--out-dir [..] \
-L dependency=[CWD]/target/release/deps \
--extern foo=[CWD]/target/release/deps/\
{prefix}foo[..]{suffix} \
--extern foo=[CWD]/target/release/deps/libfoo.rlib`
[FINISHED] release [optimized + debuginfo] target(s) in [..]
",
prefix = env::consts::DLL_PREFIX,
suffix = env::consts::DLL_SUFFIX
))
.run();
}
#[cargo_test]
fn profile_in_non_root_manifest_triggers_a_warning() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
authors = []
[workspace]
members = ["bar"]
[profile.dev]
debug = false
"#,
)
.file("src/main.rs", "fn main() {}")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
authors = []
workspace = ".."
[profile.dev]
opt-level = 1
"#,
)
.file("bar/src/main.rs", "fn main() {}")
.build();
p.cargo("build -v")
.cwd("bar")
.with_stderr(
"\
[WARNING] profiles for the non root package will be ignored, specify profiles at the workspace root:
package: [..]
workspace: [..]
[COMPILING] bar v0.1.0 ([..])
[RUNNING] `rustc [..]`
[FINISHED] dev [unoptimized] target(s) in [..]",
)
.run();
}
#[cargo_test]
fn profile_in_virtual_manifest_works() {
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["bar"]
[profile.dev]
opt-level = 1
debug = false
"#,
)
.file("src/main.rs", "fn main() {}")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
authors = []
workspace = ".."
"#,
)
.file("bar/src/main.rs", "fn main() {}")
.build();
p.cargo("build -v")
.cwd("bar")
.with_stderr(
"\
[COMPILING] bar v0.1.0 ([..])
[RUNNING] `rustc [..]`
[FINISHED] dev [optimized] target(s) in [..]",
)
.run();
}
#[cargo_test]
fn profile_lto_string_bool_dev() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
[profile.dev]
lto = "true"
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("build")
.with_status(101)
.with_stderr(
"\
error: failed to parse manifest at `[ROOT]/foo/Cargo.toml`
Caused by:
`lto` setting of string `\"true\"` for `dev` profile is not a valid setting, \
must be a boolean (`true`/`false`) or a string (`\"thin\"`/`\"fat\"`/`\"off\"`) or omitted.
",
)
.run();
}
#[cargo_test]
fn profile_panic_test_bench() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
[profile.test]
panic = "abort"
[profile.bench]
panic = "abort"
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("build")
.with_stderr_contains(
"\
[WARNING] `panic` setting is ignored for `bench` profile
[WARNING] `panic` setting is ignored for `test` profile
",
)
.run();
}
#[cargo_test]
fn profile_doc_deprecated() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
[profile.doc]
opt-level = 0
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("build")
.with_stderr_contains("[WARNING] profile `doc` is deprecated and has no effect")
.run();
}
#[cargo_test]
fn panic_unwind_does_not_build_twice() {
// Check for a bug where `lib` was built twice, once with panic set and
// once without. Since "unwind" is the default, they are the same and
// should only be built once.
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[profile.dev]
panic = "unwind"
"#,
)
.file("src/lib.rs", "")
.file("src/main.rs", "fn main() {}")
.file("tests/t1.rs", "")
.build();
p.cargo("test -v --tests --no-run")
.with_stderr_unordered(
"\
[COMPILING] foo [..]
[RUNNING] `rustc --crate-name foo src/lib.rs [..]--crate-type lib [..]
[RUNNING] `rustc --crate-name foo src/lib.rs [..] --test [..]
[RUNNING] `rustc --crate-name foo src/main.rs [..]--crate-type bin [..]
[RUNNING] `rustc --crate-name foo src/main.rs [..] --test [..]
[RUNNING] `rustc --crate-name t1 tests/t1.rs [..]
[FINISHED] [..]
[EXECUTABLE] `[..]/target/debug/deps/t1-[..][EXE]`
[EXECUTABLE] `[..]/target/debug/deps/foo-[..][EXE]`
[EXECUTABLE] `[..]/target/debug/deps/foo-[..][EXE]`
",
)
.run();
}
#[cargo_test]
fn debug_0_report() {
// The finished line handles 0 correctly.
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[profile.dev]
debug = 0
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("build -v")
.with_stderr(
"\
[COMPILING] foo v0.1.0 [..]
[RUNNING] `rustc --crate-name foo src/lib.rs [..]
[FINISHED] dev [unoptimized] target(s) in [..]
",
)
.with_stderr_does_not_contain("-C debuginfo")
.run();
}
#[cargo_test]
fn thin_lto_works() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "top"
version = "0.5.0"
authors = []
[profile.release]
lto = 'thin'
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("build --release -v")
.with_stderr(
"\
[COMPILING] top [..]
[RUNNING] `rustc [..] -C lto=thin [..]`
[FINISHED] [..]
",
)
.run();
}
#[cargo_test]
fn strip_works() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[profile.release]
strip = 'symbols'
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("build --release -v")
.with_stderr(
"\
[COMPILING] foo [..]
[RUNNING] `rustc [..] -C strip=symbols [..]`
[FINISHED] [..]
",
)
.run();
}
#[cargo_test]
fn strip_passes_unknown_option_to_rustc() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[profile.release]
strip = 'unknown'
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("build --release -v")
.with_status(101)
.with_stderr_contains(
"\
[COMPILING] foo [..]
[RUNNING] `rustc [..] -C strip=unknown [..]`
error: incorrect value `unknown` for [..] `strip` [..] was expected
",
)
.run();
}
#[cargo_test]
fn strip_accepts_true_to_strip_symbols() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[profile.release]
strip = true
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("build --release -v")
.with_stderr(
"\
[COMPILING] foo [..]
[RUNNING] `rustc [..] -C strip=symbols [..]`
[FINISHED] [..]
",
)
.run();
}
#[cargo_test]
fn strip_accepts_false_to_disable_strip() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[profile.release]
strip = false
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("build --release -v")
.with_stderr_does_not_contain("[RUNNING] `rustc [..] -C strip[..]`")
.run();
}
// Temporarily disabled on Windows due to https://github.com/rust-lang/rust/issues/122857
#[cargo_test]
#[cfg(not(windows))]
fn strip_debuginfo_in_release() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("build --release -v")
.with_stderr_contains("[RUNNING] `rustc [..] -C strip=debuginfo[..]`")
.run();
}
// Using -Cstrip=debuginfo in release mode by default is temporarily disabled on Windows due to
// https://github.com/rust-lang/rust/issues/122857
#[cargo_test]
#[cfg(all(target_os = "windows", target_env = "msvc"))]
fn do_not_strip_debuginfo_in_release_on_windows() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
edition = "2015"
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("build --release -v")
.with_stderr_does_not_contain("[..]strip=debuginfo[..]")
.run();
}
// Temporarily disabled on Windows due to https://github.com/rust-lang/rust/issues/122857
#[cargo_test]
#[cfg(not(windows))]
fn strip_debuginfo_without_debug() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[profile.dev]
debug = 0
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("build -v")
.with_stderr_contains("[RUNNING] `rustc [..] -C strip=debuginfo[..]`")
.run();
}
#[cargo_test]
fn do_not_strip_debuginfo_with_requested_debug() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar = { path = "bar" }
[profile.release.package.bar]
debug = 1
"#,
)
.file("src/main.rs", "fn main() {}")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
verison = "0.1.0"
"#,
)
.file("bar/src/lib.rs", "")
.build();
p.cargo("build --release -v")
.with_stderr_does_not_contain("[RUNNING] `rustc [..] -C strip=debuginfo[..]`")
.run();
}
#[cargo_test]
fn rustflags_works() {
let p = project()
.file(
"Cargo.toml",
r#"
cargo-features = ["profile-rustflags"]
[profile.dev]
rustflags = ["-C", "link-dead-code=yes"]
[package]
name = "foo"
version = "0.0.1"
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("build -v")
.masquerade_as_nightly_cargo(&["profile-rustflags"])
.with_stderr(
"\
[COMPILING] foo [..]
[RUNNING] `rustc --crate-name foo [..] -C link-dead-code=yes [..]
[FINISHED] [..]
",
)
.run();
}
#[cargo_test]
fn rustflags_works_with_env() {
let p = project()
.file(
"Cargo.toml",
r#"
cargo-features = ["profile-rustflags"]
[package]
name = "foo"
version = "0.0.1"
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("build -v")
.env("CARGO_PROFILE_DEV_RUSTFLAGS", "-C link-dead-code=yes")
.masquerade_as_nightly_cargo(&["profile-rustflags"])
.with_stderr(
"\
[COMPILING] foo [..]
[RUNNING] `rustc --crate-name foo [..] -C link-dead-code=yes [..]
[FINISHED] [..]
",
)
.run();
}
#[cargo_test]
fn rustflags_requires_cargo_feature() {
let p = project()
.file(
"Cargo.toml",
r#"
[profile.dev]
rustflags = ["-C", "link-dead-code=yes"]
[package]
name = "foo"
version = "0.0.1"
"#,
)
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("build -v")
.masquerade_as_nightly_cargo(&["profile-rustflags"])
.with_status(101)
.with_stderr(
"\
[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`
Caused by:
feature `profile-rustflags` is required
The package requires the Cargo feature called `profile-rustflags`, but that feature is \
not stabilized in this version of Cargo (1.[..]).
Consider adding `cargo-features = [\"profile-rustflags\"]` to the top of Cargo.toml \
(above the [package] table) to tell Cargo you are opting in to use this unstable feature.
See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-rustflags-option \
for more information about the status of this feature.
",
)
.run();
Package::new("bar", "1.0.0").publish();
p.change_file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
[dependencies]
bar = "1.0"
[profile.dev.package.bar]
rustflags = ["-C", "link-dead-code=yes"]
"#,
);
p.cargo("check")
.masquerade_as_nightly_cargo(&["profile-rustflags"])
.with_status(101)
.with_stderr(
"\
error: failed to parse manifest at `[ROOT]/foo/Cargo.toml`
Caused by:
feature `profile-rustflags` is required
The package requires the Cargo feature called `profile-rustflags`, but that feature is \
not stabilized in this version of Cargo (1.[..]).
Consider adding `cargo-features = [\"profile-rustflags\"]` to the top of Cargo.toml \
(above the [package] table) to tell Cargo you are opting in to use this unstable feature.
See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-rustflags-option \
for more information about the status of this feature.
",
)
.run();
}
#[cargo_test]
fn debug_options_valid() {
let build = |option| {
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
authors = []
version = "0.0.0"
[profile.dev]
debug = "{option}"
"#
),
)
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("build -v")
};
for (option, cli) in [
("line-directives-only", "line-directives-only"),
("line-tables-only", "line-tables-only"),
("limited", "1"),
("full", "2"),
] {
build(option)
.with_stderr_contains(&format!("[RUNNING] `rustc [..]-C debuginfo={cli} [..]"))
.run();
}
build("none")
.with_stderr_does_not_contain("[..]-C debuginfo[..]")
.run();
}