-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Description
Running cargo check --release is functionally equivalent to cargo check.
Minimal test case:
// src/main.rs
// Warn about unused stuff when in debug mode, fail compilation in release
#![cfg_attr(debug_assertions, warn(unused))]
#![cfg_attr(not(debug_assertions), deny(unused))]
fn main() {
let unused = 0;
}Results:
| Command | Expected Result | Actual Result |
|---|---|---|
cargo build |
warnings | warnings |
cargo build --release |
failure | failure |
cargo check |
warnings | warnings |
cargo check --release |
failure | warnings |
Reproduced on cargo 0.25.0 (96d8071da 2018-02-26) and cargo 1.26.0-nightly (d6c3983fe 2018-03-16).
I did a bit of digging, and I think I know why this is happening:
When running cargo check --release, the debug_assertions variable is still set to true instead of false, but when running cargo build --release, that flag is properly left disabled.
debug_assertions is defined within the Profile struct (manifest.rs), and an instance of Profile is retrieved during compilation:
cargo/src/cargo/ops/cargo_compile.rs
Lines 679 to 697 in b0a2252
| let build = if release { | |
| &profiles.release | |
| } else { | |
| &profiles.dev | |
| }; | |
| let test = if release { | |
| &profiles.bench | |
| } else { | |
| &profiles.test | |
| }; | |
| let profile = match mode { | |
| CompileMode::Test => test, | |
| CompileMode::Bench => &profiles.bench, | |
| CompileMode::Build => build, | |
| CompileMode::Check { test: false } => &profiles.check, | |
| CompileMode::Check { test: true } => &profiles.check_test, | |
| CompileMode::Doc { .. } => &profiles.doc, | |
| CompileMode::Doctest => &profiles.doctest, | |
| }; |
As you can see above, when finding the correct Profile we essentially just get the default Profile instance defined for each action (assuming we're using a default Workspace struct, which most people are) - with the notable exception of CompileMode::Build: for that mode, we either return a Profile made for release-mode or the default Profile that has debug_assertions enabled. We don't do this for CompileMode::Check. So, assuming we just retrieve the default Profile...
The default profiles are defined as such:
cargo/src/cargo/core/workspace.rs
Lines 647 to 659 in b0a2252
| let default_profiles = Profiles { | |
| release: Profile::default_release(), | |
| dev: Profile::default_dev(), | |
| test: Profile::default_test(), | |
| test_deps: Profile::default_dev(), | |
| bench: Profile::default_bench(), | |
| bench_deps: Profile::default_release(), | |
| doc: Profile::default_doc(), | |
| custom_build: Profile::default_custom_build(), | |
| check: Profile::default_check(), | |
| check_test: Profile::default_check_test(), | |
| doctest: Profile::default_doctest(), | |
| }; |
Things to note: the release Profile actually just corresponds to cargo build --release; there isn't a definition for a check_release field. The function definitions are here:
cargo/src/cargo/core/manifest.rs
Lines 708 to 799 in b0a2252
| impl Profile { | |
| pub fn default_dev() -> Profile { | |
| Profile { | |
| debuginfo: Some(2), | |
| debug_assertions: true, | |
| overflow_checks: true, | |
| incremental: true, | |
| ..Profile::default() | |
| } | |
| } | |
| pub fn default_release() -> Profile { | |
| Profile { | |
| opt_level: "3".to_string(), | |
| debuginfo: None, | |
| ..Profile::default() | |
| } | |
| } | |
| pub fn default_test() -> Profile { | |
| Profile { | |
| test: true, | |
| ..Profile::default_dev() | |
| } | |
| } | |
| pub fn default_bench() -> Profile { | |
| Profile { | |
| test: true, | |
| ..Profile::default_release() | |
| } | |
| } | |
| pub fn default_doc() -> Profile { | |
| Profile { | |
| doc: true, | |
| ..Profile::default_dev() | |
| } | |
| } | |
| pub fn default_custom_build() -> Profile { | |
| Profile { | |
| run_custom_build: true, | |
| ..Profile::default_dev() | |
| } | |
| } | |
| pub fn default_check() -> Profile { | |
| Profile { | |
| check: true, | |
| ..Profile::default_dev() | |
| } | |
| } | |
| pub fn default_check_test() -> Profile { | |
| Profile { | |
| check: true, | |
| test: true, | |
| ..Profile::default_dev() | |
| } | |
| } | |
| pub fn default_doctest() -> Profile { | |
| Profile { | |
| doc: true, | |
| test: true, | |
| ..Profile::default_dev() | |
| } | |
| } | |
| } | |
| impl Default for Profile { | |
| fn default() -> Profile { | |
| Profile { | |
| opt_level: "0".to_string(), | |
| lto: Lto::Bool(false), | |
| codegen_units: None, | |
| rustc_args: None, | |
| rustdoc_args: None, | |
| debuginfo: None, | |
| debug_assertions: false, | |
| overflow_checks: false, | |
| rpath: false, | |
| test: false, | |
| doc: false, | |
| run_custom_build: false, | |
| check: false, | |
| panic: None, | |
| incremental: false, | |
| } | |
| } | |
| } |
And as you can see, the default Profile for CompileMode::Check is equivalent to the default development Profile, with debug_assertions enabled. There is no Profile for CompileMode::Check that is also for release mode.