Skip to content

Commit 6bdb9d3

Browse files
committed
Auto merge of #6811 - ehuss:include-proc-macro, r=alexcrichton
Include proc-macros in `build-override`. This adds proc-macros (and their dependencies) to the `build-override` profile setting. The motivation is that these are all "build time" dependencies, and as such should probably behave the same. See the discussion on the [tracking issue](rust-lang/rust#48683 (comment)). My intent is that this paves the way for stabilizing without necessarily waiting for #6577. The only change here is the line in `with_for_host`, the rest is just renaming for clarity. This also includes some of the testsuite changes from #6577 to make it easier to check for compiler flags.
2 parents 86b8888 + 3cf913e commit 6bdb9d3

File tree

4 files changed

+194
-38
lines changed

4 files changed

+194
-38
lines changed

src/cargo/core/profiles.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ fn merge_toml(
328328
toml: &TomlProfile,
329329
) {
330330
merge_profile(profile, toml);
331-
if unit_for.is_custom_build() {
331+
if unit_for.is_build() {
332332
if let Some(ref build_override) = toml.build_override {
333333
merge_profile(profile, build_override);
334334
}
@@ -590,9 +590,10 @@ impl fmt::Display for PanicStrategy {
590590
/// to ensure the target's dependencies have the correct settings.
591591
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
592592
pub struct UnitFor {
593-
/// A target for `build.rs` or any of its dependencies. This enables
594-
/// `build-override` profiles for these targets.
595-
custom_build: bool,
593+
/// A target for `build.rs` or any of its dependencies, or a proc-macro or
594+
/// any of its dependencies. This enables `build-override` profiles for
595+
/// these targets.
596+
build: bool,
596597
/// This is true if it is *allowed* to set the `panic=abort` flag. Currently
597598
/// this is false for test/bench targets and all their dependencies, and
598599
/// "for_host" units such as proc macro and custom build scripts and their
@@ -605,31 +606,31 @@ impl UnitFor {
605606
/// proc macro/plugin, or test/bench).
606607
pub fn new_normal() -> UnitFor {
607608
UnitFor {
608-
custom_build: false,
609+
build: false,
609610
panic_abort_ok: true,
610611
}
611612
}
612613

613614
/// A unit for a custom build script or its dependencies.
614615
pub fn new_build() -> UnitFor {
615616
UnitFor {
616-
custom_build: true,
617+
build: true,
617618
panic_abort_ok: false,
618619
}
619620
}
620621

621622
/// A unit for a proc macro or compiler plugin or their dependencies.
622623
pub fn new_compiler() -> UnitFor {
623624
UnitFor {
624-
custom_build: false,
625+
build: false,
625626
panic_abort_ok: false,
626627
}
627628
}
628629

629630
/// A unit for a test/bench target or their dependencies.
630631
pub fn new_test() -> UnitFor {
631632
UnitFor {
632-
custom_build: false,
633+
build: false,
633634
panic_abort_ok: false,
634635
}
635636
}
@@ -640,15 +641,15 @@ impl UnitFor {
640641
/// that all its dependencies also have `panic_abort_ok=false`.
641642
pub fn with_for_host(self, for_host: bool) -> UnitFor {
642643
UnitFor {
643-
custom_build: self.custom_build,
644+
build: self.build || for_host,
644645
panic_abort_ok: self.panic_abort_ok && !for_host,
645646
}
646647
}
647648

648649
/// Returns `true` if this unit is for a custom build script or one of its
649650
/// dependencies.
650-
pub fn is_custom_build(self) -> bool {
651-
self.custom_build
651+
pub fn is_build(self) -> bool {
652+
self.build
652653
}
653654

654655
/// Returns `true` if this unit is allowed to set the `panic` compiler flag.
@@ -660,15 +661,15 @@ impl UnitFor {
660661
pub fn all_values() -> &'static [UnitFor] {
661662
static ALL: [UnitFor; 3] = [
662663
UnitFor {
663-
custom_build: false,
664+
build: false,
664665
panic_abort_ok: true,
665666
},
666667
UnitFor {
667-
custom_build: true,
668+
build: true,
668669
panic_abort_ok: false,
669670
},
670671
UnitFor {
671-
custom_build: false,
672+
build: false,
672673
panic_abort_ok: false,
673674
},
674675
];

src/doc/src/reference/unstable.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,9 @@ opt-level = 3
118118
[profile.dev.overrides."*"]
119119
opt-level = 2
120120

121-
# Build scripts and their dependencies will be compiled with -Copt-level=3
122-
# By default, build scripts use the same rules as the rest of the profile
121+
# Build scripts or proc-macros and their dependencies will be compiled with
122+
# `-Copt-level=3`. By default, they use the same rules as the rest of the
123+
# profile.
123124
[profile.dev.build-override]
124125
opt-level = 3
125126
```

tests/testsuite/profile_overrides.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::support::registry::Package;
12
use crate::support::{basic_lib_manifest, basic_manifest, project};
23

34
#[test]
@@ -439,3 +440,70 @@ fn profile_override_spec() {
439440
.with_stderr_contains("[RUNNING] `rustc [..]dep2/src/lib.rs [..] -C codegen-units=2 [..]")
440441
.run();
441442
}
443+
444+
#[test]
445+
fn override_proc_macro() {
446+
Package::new("shared", "1.0.0").publish();
447+
let p = project()
448+
.file(
449+
"Cargo.toml",
450+
r#"
451+
cargo-features = ["profile-overrides"]
452+
[package]
453+
name = "foo"
454+
version = "0.1.0"
455+
edition = "2018"
456+
457+
[dependencies]
458+
shared = "1.0"
459+
pm = {path = "pm"}
460+
461+
[profile.dev.build-override]
462+
codegen-units = 4
463+
"#,
464+
)
465+
.file("src/lib.rs", r#"pm::eat!{}"#)
466+
.file(
467+
"pm/Cargo.toml",
468+
r#"
469+
[package]
470+
name = "pm"
471+
version = "0.1.0"
472+
473+
[lib]
474+
proc-macro = true
475+
476+
[dependencies]
477+
shared = "1.0"
478+
"#,
479+
)
480+
.file(
481+
"pm/src/lib.rs",
482+
r#"
483+
extern crate proc_macro;
484+
use proc_macro::TokenStream;
485+
486+
#[proc_macro]
487+
pub fn eat(_item: TokenStream) -> TokenStream {
488+
"".parse().unwrap()
489+
}
490+
"#,
491+
)
492+
.build();
493+
494+
p.cargo("build -v")
495+
.masquerade_as_nightly_cargo()
496+
// Shared built for the proc-macro.
497+
.with_stderr_contains("[RUNNING] `rustc [..]--crate-name shared [..]-C codegen-units=4[..]")
498+
// Shared built for the library.
499+
.with_stderr_line_without(
500+
&["[RUNNING] `rustc --crate-name shared"],
501+
&["-C codegen-units"],
502+
)
503+
.with_stderr_contains("[RUNNING] `rustc [..]--crate-name pm [..]-C codegen-units=4[..]")
504+
.with_stderr_line_without(
505+
&["[RUNNING] `rustc [..]--crate-name foo"],
506+
&["-C codegen-units"],
507+
)
508+
.run();
509+
}

tests/testsuite/support/mod.rs

Lines changed: 108 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,7 @@ pub struct Execs {
579579
expect_stderr_not_contains: Vec<String>,
580580
expect_stderr_unordered: Vec<String>,
581581
expect_neither_contains: Vec<String>,
582+
expect_stderr_with_without: Vec<(Vec<String>, Vec<String>)>,
582583
expect_json: Option<Vec<Value>>,
583584
expect_json_contains_unordered: Vec<Value>,
584585
stream_output: bool,
@@ -696,6 +697,37 @@ impl Execs {
696697
self
697698
}
698699

700+
/// Verify that a particular line appears in stderr with and without the
701+
/// given substrings. Exactly one line must match.
702+
///
703+
/// The substrings are matched as `contains`. Example:
704+
///
705+
/// ```no_run
706+
/// execs.with_stderr_line_without(
707+
/// &[
708+
/// "[RUNNING] `rustc --crate-name build_script_build",
709+
/// "-C opt-level=3",
710+
/// ],
711+
/// &["-C debuginfo", "-C incremental"],
712+
/// )
713+
/// ```
714+
///
715+
/// This will check that a build line includes `-C opt-level=3` but does
716+
/// not contain `-C debuginfo` or `-C incremental`.
717+
///
718+
/// Be careful writing the `without` fragments, see note in
719+
/// `with_stderr_does_not_contain`.
720+
pub fn with_stderr_line_without<S: ToString>(
721+
&mut self,
722+
with: &[S],
723+
without: &[S],
724+
) -> &mut Self {
725+
let with = with.iter().map(|s| s.to_string()).collect();
726+
let without = without.iter().map(|s| s.to_string()).collect();
727+
self.expect_stderr_with_without.push((with, without));
728+
self
729+
}
730+
699731
/// Verifies the JSON output matches the given JSON.
700732
/// Typically used when testing cargo commands that emit JSON.
701733
/// Each separate JSON object should be separated by a blank line.
@@ -830,6 +862,7 @@ impl Execs {
830862
&& self.expect_stderr_not_contains.is_empty()
831863
&& self.expect_stderr_unordered.is_empty()
832864
&& self.expect_neither_contains.is_empty()
865+
&& self.expect_stderr_with_without.is_empty()
833866
&& self.expect_json.is_none()
834867
&& self.expect_json_contains_unordered.is_empty()
835868
{
@@ -1004,6 +1037,10 @@ impl Execs {
10041037
}
10051038
}
10061039

1040+
for (with, without) in self.expect_stderr_with_without.iter() {
1041+
self.match_with_without(&actual.stderr, with, without)?;
1042+
}
1043+
10071044
if let Some(ref objects) = self.expect_json {
10081045
let stdout = str::from_utf8(&actual.stdout)
10091046
.map_err(|_| "stdout was not utf8 encoded".to_owned())?;
@@ -1063,6 +1100,32 @@ impl Execs {
10631100
)
10641101
}
10651102

1103+
fn normalize_actual(&self, description: &str, actual: &[u8]) -> Result<String, String> {
1104+
let actual = match str::from_utf8(actual) {
1105+
Err(..) => return Err(format!("{} was not utf8 encoded", description)),
1106+
Ok(actual) => actual,
1107+
};
1108+
// Let's not deal with \r\n vs \n on windows...
1109+
let actual = actual.replace("\r", "");
1110+
let actual = actual.replace("\t", "<tab>");
1111+
Ok(actual)
1112+
}
1113+
1114+
fn replace_expected(&self, expected: &str) -> String {
1115+
// Do the template replacements on the expected string.
1116+
let replaced = match self.process_builder {
1117+
None => expected.to_string(),
1118+
Some(ref p) => match p.get_cwd() {
1119+
None => expected.to_string(),
1120+
Some(cwd) => expected.replace("[CWD]", &cwd.display().to_string()),
1121+
},
1122+
};
1123+
1124+
// On Windows, we need to use a wildcard for the drive,
1125+
// because we don't actually know what it will be.
1126+
replaced.replace("[ROOT]", if cfg!(windows) { r#"[..]:\"# } else { "/" })
1127+
}
1128+
10661129
fn match_std(
10671130
&self,
10681131
expected: Option<&String>,
@@ -1072,30 +1135,11 @@ impl Execs {
10721135
kind: MatchKind,
10731136
) -> MatchResult {
10741137
let out = match expected {
1075-
Some(out) => {
1076-
// Do the template replacements on the expected string.
1077-
let replaced = match self.process_builder {
1078-
None => out.to_string(),
1079-
Some(ref p) => match p.get_cwd() {
1080-
None => out.to_string(),
1081-
Some(cwd) => out.replace("[CWD]", &cwd.display().to_string()),
1082-
},
1083-
};
1084-
1085-
// On Windows, we need to use a wildcard for the drive,
1086-
// because we don't actually know what it will be.
1087-
replaced.replace("[ROOT]", if cfg!(windows) { r#"[..]:\"# } else { "/" })
1088-
}
1138+
Some(out) => self.replace_expected(out),
10891139
None => return Ok(()),
10901140
};
10911141

1092-
let actual = match str::from_utf8(actual) {
1093-
Err(..) => return Err(format!("{} was not utf8 encoded", description)),
1094-
Ok(actual) => actual,
1095-
};
1096-
// Let's not deal with `\r\n` vs `\n` on Windows.
1097-
let actual = actual.replace("\r", "");
1098-
let actual = actual.replace("\t", "<tab>");
1142+
let actual = self.normalize_actual(description, actual)?;
10991143

11001144
match kind {
11011145
MatchKind::Exact => {
@@ -1219,6 +1263,47 @@ impl Execs {
12191263
}
12201264
}
12211265

1266+
fn match_with_without(
1267+
&self,
1268+
actual: &[u8],
1269+
with: &[String],
1270+
without: &[String],
1271+
) -> MatchResult {
1272+
let actual = self.normalize_actual("stderr", actual)?;
1273+
let contains = |s, line| {
1274+
let mut s = self.replace_expected(s);
1275+
s.insert_str(0, "[..]");
1276+
s.push_str("[..]");
1277+
lines_match(&s, line)
1278+
};
1279+
let matches: Vec<&str> = actual
1280+
.lines()
1281+
.filter(|line| with.iter().all(|with| contains(with, line)))
1282+
.filter(|line| !without.iter().any(|without| contains(without, line)))
1283+
.collect();
1284+
match matches.len() {
1285+
0 => Err(format!(
1286+
"Could not find expected line in output.\n\
1287+
With contents: {:?}\n\
1288+
Without contents: {:?}\n\
1289+
Actual stderr:\n\
1290+
{}\n",
1291+
with, without, actual
1292+
)),
1293+
1 => Ok(()),
1294+
_ => Err(format!(
1295+
"Found multiple matching lines, but only expected one.\n\
1296+
With contents: {:?}\n\
1297+
Without contents: {:?}\n\
1298+
Matching lines:\n\
1299+
{}\n",
1300+
with,
1301+
without,
1302+
matches.join("\n")
1303+
)),
1304+
}
1305+
}
1306+
12221307
fn match_json(&self, expected: &Value, line: &str) -> MatchResult {
12231308
let actual = match line.parse() {
12241309
Err(e) => return Err(format!("invalid json, {}:\n`{}`", e, line)),
@@ -1436,6 +1521,7 @@ pub fn execs() -> Execs {
14361521
expect_stderr_not_contains: Vec::new(),
14371522
expect_stderr_unordered: Vec::new(),
14381523
expect_neither_contains: Vec::new(),
1524+
expect_stderr_with_without: Vec::new(),
14391525
expect_json: None,
14401526
expect_json_contains_unordered: Vec::new(),
14411527
stream_output: false,
@@ -1529,7 +1615,7 @@ fn substitute_macros(input: &str) -> String {
15291615
("[UNPACKING]", " Unpacking"),
15301616
("[SUMMARY]", " Summary"),
15311617
("[FIXING]", " Fixing"),
1532-
("[EXE]", env::consts::EXE_SUFFIX),
1618+
("[EXE]", env::consts::EXE_SUFFIX),
15331619
];
15341620
let mut result = input.to_owned();
15351621
for &(pat, subst) in &macros {

0 commit comments

Comments
 (0)