From 005e1a442a4cbdf4512ec940b7a02bf32d4d65fd Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 29 Jul 2020 06:41:35 -0700 Subject: [PATCH] Fix O0 build scripts by default without `[profile.release]` This fixes an issue where #8500 didn't quite work as expected, since it only worked if a crate had a `[profile.release]` section. --- src/cargo/core/profiles.rs | 34 ++++++++++++++++++++---------- src/doc/src/reference/profiles.md | 18 ++++++++++++++++ tests/testsuite/build.rs | 35 +++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/src/cargo/core/profiles.rs b/src/cargo/core/profiles.rs index 5b474b8ef9d..558cca53074 100644 --- a/src/cargo/core/profiles.rs +++ b/src/cargo/core/profiles.rs @@ -470,8 +470,31 @@ impl ProfileMaker { unit_for: UnitFor, ) -> Profile { let mut profile = self.default; + + // First apply profile-specific settings, things like + // `[profile.release]` if let Some(toml) = &self.toml { merge_profile(&mut profile, toml); + } + + // Next start overriding those settings. First comes build dependencies + // which default to opt-level 0... + if unit_for.is_for_host() { + // For-host units are things like procedural macros, build scripts, and + // their dependencies. For these units most projects simply want them + // to compile quickly and the runtime doesn't matter too much since + // they tend to process very little data. For this reason we default + // them to a "compile as quickly as possible" mode which for now means + // basically turning down the optimization level and avoid limiting + // codegen units. This ensures that we spend little time optimizing as + // well as enabling parallelism by not constraining codegen units. + profile.opt_level = InternedString::new("0"); + profile.codegen_units = None; + } + // ... and next comes any other sorts of overrides specified in + // profiles, such as `[profile.release.build-override]` or + // `[profile.release.package.foo]` + if let Some(toml) = &self.toml { merge_toml_overrides(pkg_id, is_member, unit_for, &mut profile, toml); } profile @@ -487,17 +510,6 @@ fn merge_toml_overrides( toml: &TomlProfile, ) { if unit_for.is_for_host() { - // For-host units are things like procedural macros, build scripts, and - // their dependencies. For these units most projects simply want them - // to compile quickly and the runtime doesn't matter too much since - // they tend to process very little data. For this reason we default - // them to a "compile as quickly as possible" mode which for now means - // basically turning down the optimization level and avoid limiting - // codegen units. This ensures that we spend little time optimizing as - // well as enabling parallelism by not constraining codegen units. - profile.opt_level = InternedString::new("0"); - profile.codegen_units = None; - if let Some(build_override) = &toml.build_override { merge_profile(profile, build_override); } diff --git a/src/doc/src/reference/profiles.md b/src/doc/src/reference/profiles.md index 2f739a03c3a..dc587e5950c 100644 --- a/src/doc/src/reference/profiles.md +++ b/src/doc/src/reference/profiles.md @@ -282,6 +282,24 @@ codegen-units = 16 rpath = false ``` +#### Build Dependencies + +All profiles, by default, do not optimize build dependencies (build scripts, +proc macros, and their dependencies). The default settings for build overrides +are: + +```toml +[profile.dev.build-override] +opt-level = 0 +codegen-units = 256 + +[profile.release.build-override] +opt-level = 0 +codegen-units = 256 +``` + +Build dependencies otherwise inherit settings from the active profile in use, as +described below. ### Profile selection diff --git a/tests/testsuite/build.rs b/tests/testsuite/build.rs index a6b628c93ad..9ee6c7e8d66 100644 --- a/tests/testsuite/build.rs +++ b/tests/testsuite/build.rs @@ -5127,3 +5127,38 @@ fn simple_terminal_width() { .with_stderr_contains("3 | ..._: () = 42;") .run(); } + +#[cargo_test] +fn build_script_o0_default() { + let p = project() + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + + p.cargo("build -v --release") + .with_stderr_does_not_contain("[..]build_script_build[..]opt-level[..]") + .run(); +} + +#[cargo_test] +fn build_script_o0_default_even_with_release() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [profile.release] + opt-level = 1 + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + + p.cargo("build -v --release") + .with_stderr_does_not_contain("[..]build_script_build[..]opt-level[..]") + .run(); +}