Skip to content

Commit bc858b0

Browse files
committed
Allow using opt-level="s"/"z" in profile overrides.
Fixes #2655.
1 parent 5593045 commit bc858b0

File tree

6 files changed

+112
-13
lines changed

6 files changed

+112
-13
lines changed

src/cargo/core/manifest.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ impl Encodable for TargetKind {
121121

122122
#[derive(RustcEncodable, RustcDecodable, Clone, PartialEq, Eq, Debug, Hash)]
123123
pub struct Profile {
124-
pub opt_level: u32,
124+
pub opt_level: String,
125125
pub lto: bool,
126126
pub codegen_units: Option<u32>, // None = use rustc default
127127
pub rustc_args: Option<Vec<String>>,
@@ -473,7 +473,7 @@ impl Profile {
473473

474474
pub fn default_release() -> Profile {
475475
Profile {
476-
opt_level: 3,
476+
opt_level: "3".to_string(),
477477
debuginfo: false,
478478
..Profile::default()
479479
}
@@ -511,7 +511,7 @@ impl Profile {
511511
impl Default for Profile {
512512
fn default() -> Profile {
513513
Profile {
514-
opt_level: 0,
514+
opt_level: "0".to_string(),
515515
lto: false,
516516
codegen_units: None,
517517
rustc_args: None,

src/cargo/ops/cargo_rustc/custom_build.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>)
111111
Kind::Target => cx.target_triple(),
112112
})
113113
.env("DEBUG", &profile.debuginfo.to_string())
114-
.env("OPT_LEVEL", &profile.opt_level.to_string())
114+
.env("OPT_LEVEL", &profile.opt_level)
115115
.env("PROFILE", if cx.build_config.release {"release"} else {"debug"})
116116
.env("HOST", cx.host_triple())
117117
.env("RUSTC", &try!(cx.config.rustc()).path)

src/cargo/ops/cargo_rustc/job_queue.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,8 @@ impl<'a> JobQueue<'a> {
200200

201201
let build_type = if self.is_release { "release" } else { "debug" };
202202
let profile = cx.lib_profile(cx.resolve.root());
203-
let mut opt_type = String::from(if profile.opt_level > 0 { "optimized" }
204-
else { "unoptimized" });
203+
let mut opt_type = String::from(if profile.opt_level == "0" { "unoptimized" }
204+
else { "optimized" });
205205
if profile.debuginfo {
206206
opt_type = opt_type + " + debuginfo";
207207
}

src/cargo/ops/cargo_rustc/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ fn build_base_args(cx: &Context,
477477
unit: &Unit,
478478
crate_types: &[&str]) {
479479
let Profile {
480-
opt_level, lto, codegen_units, ref rustc_args, debuginfo,
480+
ref opt_level, lto, codegen_units, ref rustc_args, debuginfo,
481481
debug_assertions, rpath, test, doc: _doc, run_custom_build,
482482
ref panic, rustdoc_args: _,
483483
} = *unit.profile;
@@ -509,7 +509,7 @@ fn build_base_args(cx: &Context,
509509
cmd.arg("-C").arg("prefer-dynamic");
510510
}
511511

512-
if opt_level != 0 {
512+
if opt_level != "0" {
513513
cmd.arg("-C").arg(&format!("opt-level={}", opt_level));
514514
}
515515

@@ -549,9 +549,9 @@ fn build_base_args(cx: &Context,
549549
cmd.args(args);
550550
}
551551

552-
if debug_assertions && opt_level > 0 {
552+
if debug_assertions && opt_level != "0" {
553553
cmd.args(&["-C", "debug-assertions=on"]);
554-
} else if !debug_assertions && opt_level == 0 {
554+
} else if !debug_assertions && opt_level == "0" {
555555
cmd.args(&["-C", "debug-assertions=off"]);
556556
}
557557

src/cargo/util/toml.rs

+22-3
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,28 @@ pub struct TomlProfiles {
256256
release: Option<TomlProfile>,
257257
}
258258

259+
#[derive(Clone)]
260+
pub struct TomlOptLevel(String);
261+
262+
impl Decodable for TomlOptLevel {
263+
fn decode<D: Decoder>(d: &mut D) -> Result<TomlOptLevel, D::Error> {
264+
match d.read_u32() {
265+
Ok(i) => Ok(TomlOptLevel(i.to_string())),
266+
Err(_) => {
267+
match d.read_str() {
268+
Ok(ref s) if s == "s" || s == "z" =>
269+
Ok(TomlOptLevel(s.to_string())),
270+
Ok(_) | Err(_) =>
271+
Err(d.error("expected an integer, a string \"z\" or a string \"s\""))
272+
}
273+
}
274+
}
275+
}
276+
}
277+
259278
#[derive(RustcDecodable, Clone, Default)]
260279
pub struct TomlProfile {
261-
opt_level: Option<u32>,
280+
opt_level: Option<TomlOptLevel>,
262281
lto: Option<bool>,
263282
codegen_units: Option<u32>,
264283
debug: Option<bool>,
@@ -1188,14 +1207,14 @@ fn build_profiles(profiles: &Option<TomlProfiles>) -> Profiles {
11881207

11891208
fn merge(profile: Profile, toml: Option<&TomlProfile>) -> Profile {
11901209
let &TomlProfile {
1191-
opt_level, lto, codegen_units, debug, debug_assertions, rpath,
1210+
ref opt_level, lto, codegen_units, debug, debug_assertions, rpath,
11921211
ref panic
11931212
} = match toml {
11941213
Some(toml) => toml,
11951214
None => return profile,
11961215
};
11971216
Profile {
1198-
opt_level: opt_level.unwrap_or(profile.opt_level),
1217+
opt_level: opt_level.clone().unwrap_or(TomlOptLevel(profile.opt_level)).0,
11991218
lto: lto.unwrap_or(profile.lto),
12001219
codegen_units: codegen_units,
12011220
rustc_args: None,

tests/profiles.rs

+80
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ extern crate hamcrest;
44
use std::env;
55
use std::path::MAIN_SEPARATOR as SEP;
66

7+
use cargotest::is_nightly;
78
use cargotest::support::{project, execs};
89
use hamcrest::assert_that;
910

@@ -42,6 +43,85 @@ url = p.url(),
4243
)));
4344
}
4445

46+
#[test]
47+
fn opt_level_override_0() {
48+
let mut p = project("foo");
49+
p = p
50+
.file("Cargo.toml", r#"
51+
[package]
52+
53+
name = "test"
54+
version = "0.0.0"
55+
authors = []
56+
57+
[profile.dev]
58+
opt-level = 0
59+
"#)
60+
.file("src/lib.rs", "");
61+
assert_that(p.cargo_process("build").arg("-v"),
62+
execs().with_status(0).with_stderr(&format!("\
63+
[COMPILING] test v0.0.0 ({url})
64+
[RUNNING] `rustc src{sep}lib.rs --crate-name test --crate-type lib \
65+
-g \
66+
-C metadata=[..] \
67+
--out-dir [..] \
68+
--emit=dep-info,link \
69+
-L dependency={dir}{sep}target{sep}debug{sep}deps`
70+
[FINISHED] [..] target(s) in [..]
71+
", sep = SEP,
72+
dir = p.root().display(),
73+
url = p.url()
74+
)));
75+
}
76+
77+
fn check_opt_level_override(profile_level: &str, rustc_level: &str) {
78+
let mut p = project("foo");
79+
p = p
80+
.file("Cargo.toml", &format!(r#"
81+
[package]
82+
83+
name = "test"
84+
version = "0.0.0"
85+
authors = []
86+
87+
[profile.dev]
88+
opt-level = {level}
89+
"#, level = profile_level))
90+
.file("src/lib.rs", "");
91+
assert_that(p.cargo_process("build").arg("-v"),
92+
execs().with_status(0).with_stderr(&format!("\
93+
[COMPILING] test v0.0.0 ({url})
94+
[RUNNING] `rustc src{sep}lib.rs --crate-name test --crate-type lib \
95+
-C opt-level={level} \
96+
-g \
97+
-C debug-assertions=on \
98+
-C metadata=[..] \
99+
--out-dir [..] \
100+
--emit=dep-info,link \
101+
-L dependency={dir}{sep}target{sep}debug{sep}deps`
102+
[FINISHED] [..] target(s) in [..]
103+
", sep = SEP,
104+
dir = p.root().display(),
105+
url = p.url(),
106+
level = rustc_level
107+
)));
108+
}
109+
110+
#[test]
111+
fn opt_level_overrides() {
112+
if !is_nightly() { return }
113+
114+
for &(profile_level, rustc_level) in &[
115+
("1", "1"),
116+
("2", "2"),
117+
("3", "3"),
118+
("\"s\"", "s"),
119+
("\"z\"", "z"),
120+
] {
121+
check_opt_level_override(profile_level, rustc_level)
122+
}
123+
}
124+
45125
#[test]
46126
fn top_level_overrides_deps() {
47127
let mut p = project("foo");

0 commit comments

Comments
 (0)