From bc858b0499992d985a97654ef7d2391ee6ab1b83 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 17 Aug 2016 07:35:57 +0000 Subject: [PATCH] Allow using opt-level="s"/"z" in profile overrides. Fixes #2655. --- src/cargo/core/manifest.rs | 6 +- src/cargo/ops/cargo_rustc/custom_build.rs | 2 +- src/cargo/ops/cargo_rustc/job_queue.rs | 4 +- src/cargo/ops/cargo_rustc/mod.rs | 8 +-- src/cargo/util/toml.rs | 25 ++++++- tests/profiles.rs | 80 +++++++++++++++++++++++ 6 files changed, 112 insertions(+), 13 deletions(-) diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index 02e9b4527df..a0e7450574f 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -121,7 +121,7 @@ impl Encodable for TargetKind { #[derive(RustcEncodable, RustcDecodable, Clone, PartialEq, Eq, Debug, Hash)] pub struct Profile { - pub opt_level: u32, + pub opt_level: String, pub lto: bool, pub codegen_units: Option, // None = use rustc default pub rustc_args: Option>, @@ -473,7 +473,7 @@ impl Profile { pub fn default_release() -> Profile { Profile { - opt_level: 3, + opt_level: "3".to_string(), debuginfo: false, ..Profile::default() } @@ -511,7 +511,7 @@ impl Profile { impl Default for Profile { fn default() -> Profile { Profile { - opt_level: 0, + opt_level: "0".to_string(), lto: false, codegen_units: None, rustc_args: None, diff --git a/src/cargo/ops/cargo_rustc/custom_build.rs b/src/cargo/ops/cargo_rustc/custom_build.rs index e2ea4522628..ffc1aeaab8f 100644 --- a/src/cargo/ops/cargo_rustc/custom_build.rs +++ b/src/cargo/ops/cargo_rustc/custom_build.rs @@ -111,7 +111,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) Kind::Target => cx.target_triple(), }) .env("DEBUG", &profile.debuginfo.to_string()) - .env("OPT_LEVEL", &profile.opt_level.to_string()) + .env("OPT_LEVEL", &profile.opt_level) .env("PROFILE", if cx.build_config.release {"release"} else {"debug"}) .env("HOST", cx.host_triple()) .env("RUSTC", &try!(cx.config.rustc()).path) diff --git a/src/cargo/ops/cargo_rustc/job_queue.rs b/src/cargo/ops/cargo_rustc/job_queue.rs index 103e87cc4e9..92d72135a2f 100644 --- a/src/cargo/ops/cargo_rustc/job_queue.rs +++ b/src/cargo/ops/cargo_rustc/job_queue.rs @@ -200,8 +200,8 @@ impl<'a> JobQueue<'a> { let build_type = if self.is_release { "release" } else { "debug" }; let profile = cx.lib_profile(cx.resolve.root()); - let mut opt_type = String::from(if profile.opt_level > 0 { "optimized" } - else { "unoptimized" }); + let mut opt_type = String::from(if profile.opt_level == "0" { "unoptimized" } + else { "optimized" }); if profile.debuginfo { opt_type = opt_type + " + debuginfo"; } diff --git a/src/cargo/ops/cargo_rustc/mod.rs b/src/cargo/ops/cargo_rustc/mod.rs index 27719613905..f0811e03c00 100644 --- a/src/cargo/ops/cargo_rustc/mod.rs +++ b/src/cargo/ops/cargo_rustc/mod.rs @@ -477,7 +477,7 @@ fn build_base_args(cx: &Context, unit: &Unit, crate_types: &[&str]) { let Profile { - opt_level, lto, codegen_units, ref rustc_args, debuginfo, + ref opt_level, lto, codegen_units, ref rustc_args, debuginfo, debug_assertions, rpath, test, doc: _doc, run_custom_build, ref panic, rustdoc_args: _, } = *unit.profile; @@ -509,7 +509,7 @@ fn build_base_args(cx: &Context, cmd.arg("-C").arg("prefer-dynamic"); } - if opt_level != 0 { + if opt_level != "0" { cmd.arg("-C").arg(&format!("opt-level={}", opt_level)); } @@ -549,9 +549,9 @@ fn build_base_args(cx: &Context, cmd.args(args); } - if debug_assertions && opt_level > 0 { + if debug_assertions && opt_level != "0" { cmd.args(&["-C", "debug-assertions=on"]); - } else if !debug_assertions && opt_level == 0 { + } else if !debug_assertions && opt_level == "0" { cmd.args(&["-C", "debug-assertions=off"]); } diff --git a/src/cargo/util/toml.rs b/src/cargo/util/toml.rs index 7b805d51b83..0c138e648bf 100644 --- a/src/cargo/util/toml.rs +++ b/src/cargo/util/toml.rs @@ -256,9 +256,28 @@ pub struct TomlProfiles { release: Option, } +#[derive(Clone)] +pub struct TomlOptLevel(String); + +impl Decodable for TomlOptLevel { + fn decode(d: &mut D) -> Result { + match d.read_u32() { + Ok(i) => Ok(TomlOptLevel(i.to_string())), + Err(_) => { + match d.read_str() { + Ok(ref s) if s == "s" || s == "z" => + Ok(TomlOptLevel(s.to_string())), + Ok(_) | Err(_) => + Err(d.error("expected an integer, a string \"z\" or a string \"s\"")) + } + } + } + } +} + #[derive(RustcDecodable, Clone, Default)] pub struct TomlProfile { - opt_level: Option, + opt_level: Option, lto: Option, codegen_units: Option, debug: Option, @@ -1188,14 +1207,14 @@ fn build_profiles(profiles: &Option) -> Profiles { fn merge(profile: Profile, toml: Option<&TomlProfile>) -> Profile { let &TomlProfile { - opt_level, lto, codegen_units, debug, debug_assertions, rpath, + ref opt_level, lto, codegen_units, debug, debug_assertions, rpath, ref panic } = match toml { Some(toml) => toml, None => return profile, }; Profile { - opt_level: opt_level.unwrap_or(profile.opt_level), + opt_level: opt_level.clone().unwrap_or(TomlOptLevel(profile.opt_level)).0, lto: lto.unwrap_or(profile.lto), codegen_units: codegen_units, rustc_args: None, diff --git a/tests/profiles.rs b/tests/profiles.rs index 3b86a7672b9..ab060bba265 100644 --- a/tests/profiles.rs +++ b/tests/profiles.rs @@ -4,6 +4,7 @@ extern crate hamcrest; use std::env; use std::path::MAIN_SEPARATOR as SEP; +use cargotest::is_nightly; use cargotest::support::{project, execs}; use hamcrest::assert_that; @@ -42,6 +43,85 @@ url = p.url(), ))); } +#[test] +fn opt_level_override_0() { + let mut p = project("foo"); + p = p + .file("Cargo.toml", r#" + [package] + + name = "test" + version = "0.0.0" + authors = [] + + [profile.dev] + opt-level = 0 + "#) + .file("src/lib.rs", ""); + assert_that(p.cargo_process("build").arg("-v"), + execs().with_status(0).with_stderr(&format!("\ +[COMPILING] test v0.0.0 ({url}) +[RUNNING] `rustc src{sep}lib.rs --crate-name test --crate-type lib \ + -g \ + -C metadata=[..] \ + --out-dir [..] \ + --emit=dep-info,link \ + -L dependency={dir}{sep}target{sep}debug{sep}deps` +[FINISHED] [..] target(s) in [..] +", sep = SEP, +dir = p.root().display(), +url = p.url() +))); +} + +fn check_opt_level_override(profile_level: &str, rustc_level: &str) { + let mut p = project("foo"); + p = p + .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", ""); + assert_that(p.cargo_process("build").arg("-v"), + execs().with_status(0).with_stderr(&format!("\ +[COMPILING] test v0.0.0 ({url}) +[RUNNING] `rustc src{sep}lib.rs --crate-name test --crate-type lib \ + -C opt-level={level} \ + -g \ + -C debug-assertions=on \ + -C metadata=[..] \ + --out-dir [..] \ + --emit=dep-info,link \ + -L dependency={dir}{sep}target{sep}debug{sep}deps` +[FINISHED] [..] target(s) in [..] +", sep = SEP, +dir = p.root().display(), +url = p.url(), +level = rustc_level +))); +} + +#[test] +fn opt_level_overrides() { + if !is_nightly() { return } + + for &(profile_level, rustc_level) in &[ + ("1", "1"), + ("2", "2"), + ("3", "3"), + ("\"s\"", "s"), + ("\"z\"", "z"), + ] { + check_opt_level_override(profile_level, rustc_level) + } +} + #[test] fn top_level_overrides_deps() { let mut p = project("foo");