mirror of
https://github.com/rust-lang/cargo
synced 2024-11-05 18:50:39 +00:00
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](https://github.com/rust-lang/rust/issues/48683#issuecomment-472705245). 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.
This commit is contained in:
commit
6bdb9d3b11
4 changed files with 194 additions and 38 deletions
|
@ -328,7 +328,7 @@ fn merge_toml(
|
|||
toml: &TomlProfile,
|
||||
) {
|
||||
merge_profile(profile, toml);
|
||||
if unit_for.is_custom_build() {
|
||||
if unit_for.is_build() {
|
||||
if let Some(ref build_override) = toml.build_override {
|
||||
merge_profile(profile, build_override);
|
||||
}
|
||||
|
@ -590,9 +590,10 @@ impl fmt::Display for PanicStrategy {
|
|||
/// to ensure the target's dependencies have the correct settings.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub struct UnitFor {
|
||||
/// A target for `build.rs` or any of its dependencies. This enables
|
||||
/// `build-override` profiles for these targets.
|
||||
custom_build: bool,
|
||||
/// A target for `build.rs` or any of its dependencies, or a proc-macro or
|
||||
/// any of its dependencies. This enables `build-override` profiles for
|
||||
/// these targets.
|
||||
build: bool,
|
||||
/// This is true if it is *allowed* to set the `panic=abort` flag. Currently
|
||||
/// this is false for test/bench targets and all their dependencies, and
|
||||
/// "for_host" units such as proc macro and custom build scripts and their
|
||||
|
@ -605,7 +606,7 @@ impl UnitFor {
|
|||
/// proc macro/plugin, or test/bench).
|
||||
pub fn new_normal() -> UnitFor {
|
||||
UnitFor {
|
||||
custom_build: false,
|
||||
build: false,
|
||||
panic_abort_ok: true,
|
||||
}
|
||||
}
|
||||
|
@ -613,7 +614,7 @@ impl UnitFor {
|
|||
/// A unit for a custom build script or its dependencies.
|
||||
pub fn new_build() -> UnitFor {
|
||||
UnitFor {
|
||||
custom_build: true,
|
||||
build: true,
|
||||
panic_abort_ok: false,
|
||||
}
|
||||
}
|
||||
|
@ -621,7 +622,7 @@ impl UnitFor {
|
|||
/// A unit for a proc macro or compiler plugin or their dependencies.
|
||||
pub fn new_compiler() -> UnitFor {
|
||||
UnitFor {
|
||||
custom_build: false,
|
||||
build: false,
|
||||
panic_abort_ok: false,
|
||||
}
|
||||
}
|
||||
|
@ -629,7 +630,7 @@ impl UnitFor {
|
|||
/// A unit for a test/bench target or their dependencies.
|
||||
pub fn new_test() -> UnitFor {
|
||||
UnitFor {
|
||||
custom_build: false,
|
||||
build: false,
|
||||
panic_abort_ok: false,
|
||||
}
|
||||
}
|
||||
|
@ -640,15 +641,15 @@ impl UnitFor {
|
|||
/// that all its dependencies also have `panic_abort_ok=false`.
|
||||
pub fn with_for_host(self, for_host: bool) -> UnitFor {
|
||||
UnitFor {
|
||||
custom_build: self.custom_build,
|
||||
build: self.build || for_host,
|
||||
panic_abort_ok: self.panic_abort_ok && !for_host,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this unit is for a custom build script or one of its
|
||||
/// dependencies.
|
||||
pub fn is_custom_build(self) -> bool {
|
||||
self.custom_build
|
||||
pub fn is_build(self) -> bool {
|
||||
self.build
|
||||
}
|
||||
|
||||
/// Returns `true` if this unit is allowed to set the `panic` compiler flag.
|
||||
|
@ -660,15 +661,15 @@ impl UnitFor {
|
|||
pub fn all_values() -> &'static [UnitFor] {
|
||||
static ALL: [UnitFor; 3] = [
|
||||
UnitFor {
|
||||
custom_build: false,
|
||||
build: false,
|
||||
panic_abort_ok: true,
|
||||
},
|
||||
UnitFor {
|
||||
custom_build: true,
|
||||
build: true,
|
||||
panic_abort_ok: false,
|
||||
},
|
||||
UnitFor {
|
||||
custom_build: false,
|
||||
build: false,
|
||||
panic_abort_ok: false,
|
||||
},
|
||||
];
|
||||
|
|
|
@ -118,8 +118,9 @@ opt-level = 3
|
|||
[profile.dev.overrides."*"]
|
||||
opt-level = 2
|
||||
|
||||
# Build scripts and their dependencies will be compiled with -Copt-level=3
|
||||
# By default, build scripts use the same rules as the rest of the profile
|
||||
# Build scripts or proc-macros and their dependencies will be compiled with
|
||||
# `-Copt-level=3`. By default, they use the same rules as the rest of the
|
||||
# profile.
|
||||
[profile.dev.build-override]
|
||||
opt-level = 3
|
||||
```
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::support::registry::Package;
|
||||
use crate::support::{basic_lib_manifest, basic_manifest, project};
|
||||
|
||||
#[test]
|
||||
|
@ -439,3 +440,70 @@ fn profile_override_spec() {
|
|||
.with_stderr_contains("[RUNNING] `rustc [..]dep2/src/lib.rs [..] -C codegen-units=2 [..]")
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn override_proc_macro() {
|
||||
Package::new("shared", "1.0.0").publish();
|
||||
let p = project()
|
||||
.file(
|
||||
"Cargo.toml",
|
||||
r#"
|
||||
cargo-features = ["profile-overrides"]
|
||||
[package]
|
||||
name = "foo"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
shared = "1.0"
|
||||
pm = {path = "pm"}
|
||||
|
||||
[profile.dev.build-override]
|
||||
codegen-units = 4
|
||||
"#,
|
||||
)
|
||||
.file("src/lib.rs", r#"pm::eat!{}"#)
|
||||
.file(
|
||||
"pm/Cargo.toml",
|
||||
r#"
|
||||
[package]
|
||||
name = "pm"
|
||||
version = "0.1.0"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
shared = "1.0"
|
||||
"#,
|
||||
)
|
||||
.file(
|
||||
"pm/src/lib.rs",
|
||||
r#"
|
||||
extern crate proc_macro;
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
#[proc_macro]
|
||||
pub fn eat(_item: TokenStream) -> TokenStream {
|
||||
"".parse().unwrap()
|
||||
}
|
||||
"#,
|
||||
)
|
||||
.build();
|
||||
|
||||
p.cargo("build -v")
|
||||
.masquerade_as_nightly_cargo()
|
||||
// Shared built for the proc-macro.
|
||||
.with_stderr_contains("[RUNNING] `rustc [..]--crate-name shared [..]-C codegen-units=4[..]")
|
||||
// Shared built for the library.
|
||||
.with_stderr_line_without(
|
||||
&["[RUNNING] `rustc --crate-name shared"],
|
||||
&["-C codegen-units"],
|
||||
)
|
||||
.with_stderr_contains("[RUNNING] `rustc [..]--crate-name pm [..]-C codegen-units=4[..]")
|
||||
.with_stderr_line_without(
|
||||
&["[RUNNING] `rustc [..]--crate-name foo"],
|
||||
&["-C codegen-units"],
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
|
|
@ -579,6 +579,7 @@ pub struct Execs {
|
|||
expect_stderr_not_contains: Vec<String>,
|
||||
expect_stderr_unordered: Vec<String>,
|
||||
expect_neither_contains: Vec<String>,
|
||||
expect_stderr_with_without: Vec<(Vec<String>, Vec<String>)>,
|
||||
expect_json: Option<Vec<Value>>,
|
||||
expect_json_contains_unordered: Vec<Value>,
|
||||
stream_output: bool,
|
||||
|
@ -696,6 +697,37 @@ impl Execs {
|
|||
self
|
||||
}
|
||||
|
||||
/// Verify that a particular line appears in stderr with and without the
|
||||
/// given substrings. Exactly one line must match.
|
||||
///
|
||||
/// The substrings are matched as `contains`. Example:
|
||||
///
|
||||
/// ```no_run
|
||||
/// execs.with_stderr_line_without(
|
||||
/// &[
|
||||
/// "[RUNNING] `rustc --crate-name build_script_build",
|
||||
/// "-C opt-level=3",
|
||||
/// ],
|
||||
/// &["-C debuginfo", "-C incremental"],
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// This will check that a build line includes `-C opt-level=3` but does
|
||||
/// not contain `-C debuginfo` or `-C incremental`.
|
||||
///
|
||||
/// Be careful writing the `without` fragments, see note in
|
||||
/// `with_stderr_does_not_contain`.
|
||||
pub fn with_stderr_line_without<S: ToString>(
|
||||
&mut self,
|
||||
with: &[S],
|
||||
without: &[S],
|
||||
) -> &mut Self {
|
||||
let with = with.iter().map(|s| s.to_string()).collect();
|
||||
let without = without.iter().map(|s| s.to_string()).collect();
|
||||
self.expect_stderr_with_without.push((with, without));
|
||||
self
|
||||
}
|
||||
|
||||
/// Verifies the JSON output matches the given JSON.
|
||||
/// Typically used when testing cargo commands that emit JSON.
|
||||
/// Each separate JSON object should be separated by a blank line.
|
||||
|
@ -830,6 +862,7 @@ impl Execs {
|
|||
&& self.expect_stderr_not_contains.is_empty()
|
||||
&& self.expect_stderr_unordered.is_empty()
|
||||
&& self.expect_neither_contains.is_empty()
|
||||
&& self.expect_stderr_with_without.is_empty()
|
||||
&& self.expect_json.is_none()
|
||||
&& self.expect_json_contains_unordered.is_empty()
|
||||
{
|
||||
|
@ -1004,6 +1037,10 @@ impl Execs {
|
|||
}
|
||||
}
|
||||
|
||||
for (with, without) in self.expect_stderr_with_without.iter() {
|
||||
self.match_with_without(&actual.stderr, with, without)?;
|
||||
}
|
||||
|
||||
if let Some(ref objects) = self.expect_json {
|
||||
let stdout = str::from_utf8(&actual.stdout)
|
||||
.map_err(|_| "stdout was not utf8 encoded".to_owned())?;
|
||||
|
@ -1063,6 +1100,32 @@ impl Execs {
|
|||
)
|
||||
}
|
||||
|
||||
fn normalize_actual(&self, description: &str, actual: &[u8]) -> Result<String, String> {
|
||||
let actual = match str::from_utf8(actual) {
|
||||
Err(..) => return Err(format!("{} was not utf8 encoded", description)),
|
||||
Ok(actual) => actual,
|
||||
};
|
||||
// Let's not deal with \r\n vs \n on windows...
|
||||
let actual = actual.replace("\r", "");
|
||||
let actual = actual.replace("\t", "<tab>");
|
||||
Ok(actual)
|
||||
}
|
||||
|
||||
fn replace_expected(&self, expected: &str) -> String {
|
||||
// Do the template replacements on the expected string.
|
||||
let replaced = match self.process_builder {
|
||||
None => expected.to_string(),
|
||||
Some(ref p) => match p.get_cwd() {
|
||||
None => expected.to_string(),
|
||||
Some(cwd) => expected.replace("[CWD]", &cwd.display().to_string()),
|
||||
},
|
||||
};
|
||||
|
||||
// On Windows, we need to use a wildcard for the drive,
|
||||
// because we don't actually know what it will be.
|
||||
replaced.replace("[ROOT]", if cfg!(windows) { r#"[..]:\"# } else { "/" })
|
||||
}
|
||||
|
||||
fn match_std(
|
||||
&self,
|
||||
expected: Option<&String>,
|
||||
|
@ -1072,30 +1135,11 @@ impl Execs {
|
|||
kind: MatchKind,
|
||||
) -> MatchResult {
|
||||
let out = match expected {
|
||||
Some(out) => {
|
||||
// Do the template replacements on the expected string.
|
||||
let replaced = match self.process_builder {
|
||||
None => out.to_string(),
|
||||
Some(ref p) => match p.get_cwd() {
|
||||
None => out.to_string(),
|
||||
Some(cwd) => out.replace("[CWD]", &cwd.display().to_string()),
|
||||
},
|
||||
};
|
||||
|
||||
// On Windows, we need to use a wildcard for the drive,
|
||||
// because we don't actually know what it will be.
|
||||
replaced.replace("[ROOT]", if cfg!(windows) { r#"[..]:\"# } else { "/" })
|
||||
}
|
||||
Some(out) => self.replace_expected(out),
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let actual = match str::from_utf8(actual) {
|
||||
Err(..) => return Err(format!("{} was not utf8 encoded", description)),
|
||||
Ok(actual) => actual,
|
||||
};
|
||||
// Let's not deal with `\r\n` vs `\n` on Windows.
|
||||
let actual = actual.replace("\r", "");
|
||||
let actual = actual.replace("\t", "<tab>");
|
||||
let actual = self.normalize_actual(description, actual)?;
|
||||
|
||||
match kind {
|
||||
MatchKind::Exact => {
|
||||
|
@ -1219,6 +1263,47 @@ impl Execs {
|
|||
}
|
||||
}
|
||||
|
||||
fn match_with_without(
|
||||
&self,
|
||||
actual: &[u8],
|
||||
with: &[String],
|
||||
without: &[String],
|
||||
) -> MatchResult {
|
||||
let actual = self.normalize_actual("stderr", actual)?;
|
||||
let contains = |s, line| {
|
||||
let mut s = self.replace_expected(s);
|
||||
s.insert_str(0, "[..]");
|
||||
s.push_str("[..]");
|
||||
lines_match(&s, line)
|
||||
};
|
||||
let matches: Vec<&str> = actual
|
||||
.lines()
|
||||
.filter(|line| with.iter().all(|with| contains(with, line)))
|
||||
.filter(|line| !without.iter().any(|without| contains(without, line)))
|
||||
.collect();
|
||||
match matches.len() {
|
||||
0 => Err(format!(
|
||||
"Could not find expected line in output.\n\
|
||||
With contents: {:?}\n\
|
||||
Without contents: {:?}\n\
|
||||
Actual stderr:\n\
|
||||
{}\n",
|
||||
with, without, actual
|
||||
)),
|
||||
1 => Ok(()),
|
||||
_ => Err(format!(
|
||||
"Found multiple matching lines, but only expected one.\n\
|
||||
With contents: {:?}\n\
|
||||
Without contents: {:?}\n\
|
||||
Matching lines:\n\
|
||||
{}\n",
|
||||
with,
|
||||
without,
|
||||
matches.join("\n")
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn match_json(&self, expected: &Value, line: &str) -> MatchResult {
|
||||
let actual = match line.parse() {
|
||||
Err(e) => return Err(format!("invalid json, {}:\n`{}`", e, line)),
|
||||
|
@ -1436,6 +1521,7 @@ pub fn execs() -> Execs {
|
|||
expect_stderr_not_contains: Vec::new(),
|
||||
expect_stderr_unordered: Vec::new(),
|
||||
expect_neither_contains: Vec::new(),
|
||||
expect_stderr_with_without: Vec::new(),
|
||||
expect_json: None,
|
||||
expect_json_contains_unordered: Vec::new(),
|
||||
stream_output: false,
|
||||
|
@ -1529,7 +1615,7 @@ fn substitute_macros(input: &str) -> String {
|
|||
("[UNPACKING]", " Unpacking"),
|
||||
("[SUMMARY]", " Summary"),
|
||||
("[FIXING]", " Fixing"),
|
||||
("[EXE]", env::consts::EXE_SUFFIX),
|
||||
("[EXE]", env::consts::EXE_SUFFIX),
|
||||
];
|
||||
let mut result = input.to_owned();
|
||||
for &(pat, subst) in ¯os {
|
||||
|
|
Loading…
Reference in a new issue