mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-28 11:20:36 +00:00

Stabilize profile-overrides.
This stabilizes the profile-overrides feature. This was proposed in [RFC 2282](https://github.com/rust-lang/rfcs/pull/2282) and implemented in #5384. Tracking issue is https://github.com/rust-lang/rust/issues/48683.
This is intended to land in 1.41 which will reach the stable channel on Jan 30th.
This includes a new documentation chapter on profiles. See the ["Overrides" section](9c993a92ce/src/doc/src/reference/profiles.md (overrides)
) in `profiles.md` file for details on what is being stabilized.
Note: The `config-profile` and `named-profiles` features are still unstable.
Closes #6214
**Concerns**
- There is some risk that `build-override` may be confusing with the [proposed future dedicated `build` profile](https://github.com/rust-lang/cargo/pull/6577). There is some more discussion about the differences at https://github.com/rust-lang/rust/issues/48683#issuecomment-445571286. I don't expect it to be a significant drawback. If we proceed later with a dedicated `build` profile, I think we can handle explaining the differences in the documentation. (The linked PR is designed to work with profile-overrides.)
- I don't anticipate any unexpected interactions with `config-profiles` or `named-profiles`.
- Some of the syntax like `"*"` or `build-override` may not be immediately obvious what it means without reading the documentation. Nobody suggested any alternatives, though.
- Configuring overrides for multiple packages is currently a pain, as you have to repeat the settings separately for each package. I propose that we can extend the syntax in the future to allow a comma-separated list of package names to alleviate this concern if it is deemed worthwhile.
- The user may not know which packages to override, particularly for some dependencies that are split across multiple crates. I think, since this is an advanced feature, the user will likely be comfortable with using things like `cargo tree` to understand what needs to be overridden. There is [some discussion](https://github.com/rust-lang/rust/issues/48683#issuecomment-473356415) in the tracking issue about automatically including a package's dependencies, but this is somewhat complex.
- There is some possibly confusing interaction with the test/bench profile. Because dependencies are always built with the dev/release profiles, overridding test/bench usually does not have an effect (unless specifying a workspace member that is being tested/benched). Overriding test/bench was previously prohibited, but was relaxed when named profiles were added.
- We may want to allow overriding the `panic`, `lto`, and `rpath` settings in the future. I can imagine a case where someone has a large workspace, and wants to override those settings for just one package in the workspace. They are currently not allowed because it doesn't make sense to change those settings for rlibs, and `panic` usually needs to be in sync for the whole profile.
- There are some strange interactions with `dylib` crates detailed in https://github.com/rust-lang/rust/issues/64319. A fix was attempted, but later reverted. Since `dylib` crates are rare (this mostly applied to `libstd`), and a workaround was implemented for `build-std` (it no longer builds a dylib), I'm not too worried about this.
- The interaction with `share-generics` can be quite confusing (see https://github.com/rust-lang/rust/issues/63484). I added a section in the docs that tries to address this concern. It's also possible future versions of `rustc` may handle this better.
- The new documentation duplicates some of the information in the rustc book. I think it's fine, as there are subtle differences, and it avoids needing to flip back and forth between the two books to learn what the settings do.
480 lines
11 KiB
Rust
480 lines
11 KiB
Rust
//! Tests for named profiles.
|
|
|
|
use cargo_test_support::{basic_lib_manifest, project};
|
|
|
|
#[cargo_test]
|
|
fn inherits_on_release() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
cargo-features = ["named-profiles"]
|
|
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[profile.release]
|
|
inherits = "dev"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("build")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_status(101)
|
|
.with_stderr(
|
|
"\
|
|
[ERROR] failed to parse manifest at [..]
|
|
|
|
Caused by:
|
|
An 'inherits' must not specified root profile 'release'
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn missing_inherits() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
cargo-features = ["named-profiles"]
|
|
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[profile.release-lto]
|
|
codegen-units = 7
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("build")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_status(101)
|
|
.with_stderr(
|
|
"\
|
|
[ERROR] failed to parse manifest at [..]
|
|
|
|
Caused by:
|
|
An 'inherits' directive is needed for all profiles that are not 'dev' or 'release'. Here it is missing from 'release-lto'",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn invalid_profile_name() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
cargo-features = ["named-profiles"]
|
|
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[profile.'.release-lto']
|
|
inherits = "release"
|
|
codegen-units = 7
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("build")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_status(101)
|
|
.with_stderr(
|
|
"\
|
|
[ERROR] failed to parse manifest at [..]
|
|
|
|
Caused by:
|
|
Invalid character `.` in profile name: `.release-lto`",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn invalid_dir_name() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
cargo-features = ["named-profiles"]
|
|
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[profile.'release-lto']
|
|
inherits = "release"
|
|
dir-name = ".subdir"
|
|
codegen-units = 7
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("build")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_status(101)
|
|
.with_stderr(
|
|
"\
|
|
[ERROR] failed to parse manifest at [..]
|
|
|
|
Caused by:
|
|
Invalid character `.` in dir-name: `.subdir`",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn invalid_inherits() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
cargo-features = ["named-profiles"]
|
|
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[profile.'release-lto']
|
|
inherits = ".release"
|
|
codegen-units = 7
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("build")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_status(101)
|
|
.with_stderr(
|
|
"\
|
|
[ERROR] failed to parse manifest at [..]
|
|
|
|
Caused by:
|
|
Invalid character `.` in inherits: `.release`",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn non_existent_inherits() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
cargo-features = ["named-profiles"]
|
|
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[profile.release-lto]
|
|
codegen-units = 7
|
|
inherits = "non-existent"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("build")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_status(101)
|
|
.with_stderr(
|
|
"\
|
|
[ERROR] failed to parse manifest at [..]
|
|
|
|
Caused by:
|
|
Profile 'non-existent' not found in Cargo.toml",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn self_inherits() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
cargo-features = ["named-profiles"]
|
|
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[profile.release-lto]
|
|
codegen-units = 7
|
|
inherits = "release-lto"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("build")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_status(101)
|
|
.with_stderr(
|
|
"\
|
|
[ERROR] failed to parse manifest at [..]
|
|
|
|
Caused by:
|
|
Inheritance loop of profiles cycles with profile 'release-lto'",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn inherits_loop() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
cargo-features = ["named-profiles"]
|
|
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[profile.release-lto]
|
|
codegen-units = 7
|
|
inherits = "release-lto2"
|
|
|
|
[profile.release-lto2]
|
|
codegen-units = 7
|
|
inherits = "release-lto"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("build")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_status(101)
|
|
.with_stderr(
|
|
"\
|
|
[ERROR] failed to parse manifest at [..]
|
|
|
|
Caused by:
|
|
Inheritance loop of profiles cycles with profile 'release-lto'",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn overrides_with_custom() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
cargo-features = ["named-profiles"]
|
|
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
xxx = {path = "xxx"}
|
|
yyy = {path = "yyy"}
|
|
|
|
[profile.dev]
|
|
codegen-units = 7
|
|
|
|
[profile.dev.package.xxx]
|
|
codegen-units = 5
|
|
[profile.dev.package.yyy]
|
|
codegen-units = 3
|
|
|
|
[profile.other]
|
|
inherits = "dev"
|
|
codegen-units = 2
|
|
|
|
[profile.other.package.yyy]
|
|
codegen-units = 6
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("xxx/Cargo.toml", &basic_lib_manifest("xxx"))
|
|
.file("xxx/src/lib.rs", "")
|
|
.file("yyy/Cargo.toml", &basic_lib_manifest("yyy"))
|
|
.file("yyy/src/lib.rs", "")
|
|
.build();
|
|
|
|
// profile overrides are inherited between profiles using inherits and have a
|
|
// higher priority than profile options provided by custom profiles
|
|
p.cargo("build -v")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_unordered(
|
|
"\
|
|
[COMPILING] xxx [..]
|
|
[COMPILING] yyy [..]
|
|
[COMPILING] foo [..]
|
|
[RUNNING] `rustc --crate-name xxx [..] -C codegen-units=5 [..]`
|
|
[RUNNING] `rustc --crate-name yyy [..] -C codegen-units=3 [..]`
|
|
[RUNNING] `rustc --crate-name foo [..] -C codegen-units=7 [..]`
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
// This also verifies that the custom profile names appears in the finished line.
|
|
p.cargo("build --profile=other -Z unstable-options -v")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr_unordered(
|
|
"\
|
|
[COMPILING] xxx [..]
|
|
[COMPILING] yyy [..]
|
|
[COMPILING] foo [..]
|
|
[RUNNING] `rustc --crate-name xxx [..] -C codegen-units=5 [..]`
|
|
[RUNNING] `rustc --crate-name yyy [..] -C codegen-units=6 [..]`
|
|
[RUNNING] `rustc --crate-name foo [..] -C codegen-units=2 [..]`
|
|
[FINISHED] other [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn conflicting_usage() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("build -Z unstable-options --profile=dev --release")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_status(101)
|
|
.with_stderr_unordered("error: Conflicting usage of --profile and --release")
|
|
.run();
|
|
|
|
p.cargo("install -Z unstable-options --profile=release --debug")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_status(101)
|
|
.with_stderr_unordered("error: Conflicting usage of --profile and --debug")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn clean_custom_dirname() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
cargo-features = ["named-profiles"]
|
|
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[profile.other]
|
|
inherits = "release"
|
|
"#,
|
|
)
|
|
.file("src/main.rs", "fn main() {}")
|
|
.build();
|
|
|
|
p.cargo("build --release")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stdout("")
|
|
.with_stderr(
|
|
"\
|
|
[COMPILING] foo v0.0.1 ([..])
|
|
[FINISHED] release [optimized] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
p.cargo("clean -p foo").masquerade_as_nightly_cargo().run();
|
|
|
|
p.cargo("build --release")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stdout("")
|
|
.with_stderr(
|
|
"\
|
|
[FINISHED] release [optimized] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
p.cargo("clean -p foo --release")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
|
|
p.cargo("build --release")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr(
|
|
"\
|
|
[COMPILING] foo v0.0.1 ([..])
|
|
[FINISHED] release [optimized] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
p.cargo("build")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stdout("")
|
|
.with_stderr(
|
|
"\
|
|
[COMPILING] foo v0.0.1 ([..])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
p.cargo("build -Z unstable-options --profile=other")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr(
|
|
"\
|
|
[COMPILING] foo v0.0.1 ([..])
|
|
[FINISHED] other [optimized] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
p.cargo("clean")
|
|
.arg("--release")
|
|
.masquerade_as_nightly_cargo()
|
|
.run();
|
|
|
|
// Make sure that 'other' was not cleaned
|
|
assert!(p.build_dir().is_dir());
|
|
assert!(p.build_dir().join("debug").is_dir());
|
|
assert!(p.build_dir().join("other").is_dir());
|
|
assert!(!p.build_dir().join("release").is_dir());
|
|
|
|
// This should clean 'other'
|
|
p.cargo("clean -Z unstable-options --profile=other")
|
|
.masquerade_as_nightly_cargo()
|
|
.with_stderr("")
|
|
.run();
|
|
assert!(p.build_dir().join("debug").is_dir());
|
|
assert!(!p.build_dir().join("other").is_dir());
|
|
}
|