From 590c803ff19b66146c971a427f1f29d06cda265b Mon Sep 17 00:00:00 2001 From: Alex Tokarev Date: Wed, 18 Mar 2020 20:48:19 +0300 Subject: [PATCH] Print colored warnings when build script panics Fixes #3672 --- src/cargo/core/compiler/custom_build.rs | 38 +++++++++++++++++++++++-- tests/testsuite/build_script.rs | 33 +++++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index 2bc320e56d8..6853bd3a758 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -11,7 +11,9 @@ use std::collections::hash_map::{Entry, HashMap}; use std::collections::{BTreeSet, HashSet}; use std::path::{Path, PathBuf}; use std::str; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; + +const CARGO_WARNING: &str = "cargo:warning="; /// Contains the parsed output of a custom build script. #[derive(Clone, Debug, Hash, Default)] @@ -343,9 +345,13 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes state.running(&cmd); let timestamp = paths::set_invocation_time(&script_run_dir)?; let prefix = format!("[{} {}] ", id.name(), id.version()); + let mut warnings_in_case_of_panic = Vec::new(); let output = cmd .exec_with_streaming( &mut |stdout| { + if stdout.starts_with(CARGO_WARNING) { + warnings_in_case_of_panic.push(stdout[CARGO_WARNING.len()..].to_owned()); + } if extra_verbose { state.stdout(format!("{}{}", prefix, stdout)); } @@ -359,7 +365,19 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes }, true, ) - .chain_err(|| format!("failed to run custom build command for `{}`", pkg_name))?; + .chain_err(|| format!("failed to run custom build command for `{}`", pkg_name)); + + if let Err(error) = output { + insert_warnings_in_build_outputs( + build_script_outputs, + id, + metadata_hash, + warnings_in_case_of_panic, + ); + return Err(error); + } + + let output = output.unwrap(); // After the build command has finished running, we need to be sure to // remember all of its output so we can later discover precisely what it @@ -429,6 +447,22 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes Ok(job) } +fn insert_warnings_in_build_outputs( + build_script_outputs: Arc>, + id: PackageId, + metadata_hash: Metadata, + warnings: Vec, +) { + let build_output_with_only_warnings = BuildOutput { + warnings, + ..BuildOutput::default() + }; + build_script_outputs + .lock() + .unwrap() + .insert(id, metadata_hash, build_output_with_only_warnings); +} + impl BuildOutput { pub fn parse_file( path: &Path, diff --git a/tests/testsuite/build_script.rs b/tests/testsuite/build_script.rs index b9b2f427cc5..0ae555d3aba 100644 --- a/tests/testsuite/build_script.rs +++ b/tests/testsuite/build_script.rs @@ -2980,6 +2980,39 @@ warning: bar .run(); } +#[cargo_test] +fn warnings_emitted_when_build_script_panics() { + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "foo" + version = "0.5.0" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo:warning=foo"); + println!("cargo:warning=bar"); + panic!(); + } + "#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stdout("") + .with_stderr_contains("warning: foo\nwarning: bar") + .run(); +} + #[cargo_test] fn warnings_hidden_for_upstream() { Package::new("bar", "0.1.0")