Skip to content

Commit 69cacfa

Browse files
committed
Hide unfiltered stdout and stderr output behind --verbose flag
1 parent 02557c3 commit 69cacfa

File tree

2 files changed

+100
-25
lines changed

2 files changed

+100
-25
lines changed

src/cargo/core/compiler/custom_build.rs

+58-23
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ use crate::core::{profiles::ProfileRoot, PackageId, Target};
77
use crate::util::errors::CargoResult;
88
use crate::util::machine_message::{self, Message};
99
use crate::util::{internal, profile};
10-
use anyhow::{bail, Context as _};
10+
use crate::VerboseError;
11+
use anyhow::{bail, Context as _, Error};
1112
use cargo_platform::Cfg;
12-
use cargo_util::paths;
13+
use cargo_util::{paths, ProcessError};
1314
use std::collections::hash_map::{Entry, HashMap};
1415
use std::collections::{BTreeSet, HashSet};
1516
use std::path::{Path, PathBuf};
@@ -386,26 +387,24 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
386387
let timestamp = paths::set_invocation_time(&script_run_dir)?;
387388
let prefix = format!("[{} {}] ", id.name(), id.version());
388389
let mut warnings_in_case_of_panic = Vec::new();
389-
let output = cmd
390-
.exec_with_streaming(
391-
&mut |stdout| {
392-
if let Some(warning) = stdout.strip_prefix(CARGO_WARNING) {
393-
warnings_in_case_of_panic.push(warning.to_owned());
394-
}
395-
if extra_verbose {
396-
state.stdout(format!("{}{}", prefix, stdout))?;
397-
}
398-
Ok(())
399-
},
400-
&mut |stderr| {
401-
if extra_verbose {
402-
state.stderr(format!("{}{}", prefix, stderr))?;
403-
}
404-
Ok(())
405-
},
406-
true,
407-
)
408-
.with_context(|| format!("failed to run custom build command for `{}`", pkg_descr));
390+
let output = cmd.exec_with_streaming(
391+
&mut |stdout| {
392+
if let Some(warning) = stdout.strip_prefix(CARGO_WARNING) {
393+
warnings_in_case_of_panic.push(warning.to_owned());
394+
}
395+
if extra_verbose {
396+
state.stdout(format!("{}{}", prefix, stdout))?;
397+
}
398+
Ok(())
399+
},
400+
&mut |stderr| {
401+
if extra_verbose {
402+
state.stderr(format!("{}{}", prefix, stderr))?;
403+
}
404+
Ok(())
405+
},
406+
true,
407+
);
409408

410409
if let Err(error) = output {
411410
insert_warnings_in_build_outputs(
@@ -414,7 +413,7 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
414413
metadata_hash,
415414
warnings_in_case_of_panic,
416415
);
417-
return Err(error);
416+
return Err(build_error_with_context(error, &pkg_descr));
418417
}
419418

420419
let output = output.unwrap();
@@ -496,6 +495,42 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
496495
Ok(job)
497496
}
498497

498+
fn build_error_with_context(error: Error, pkg_descr: &str) -> Error {
499+
let Some(perr) = error.downcast_ref::<ProcessError>() else {
500+
return error.context(format!("failed to run custom build command for `{}`", pkg_descr));
501+
};
502+
503+
let mut msg = format!("custom build command for `{}` has failed", pkg_descr);
504+
505+
let mut parsing_stdout = false;
506+
let output = perr
507+
.stderr
508+
.as_ref()
509+
.and_then(|stderr| std::str::from_utf8(stderr).ok())
510+
.filter(|stderr| !stderr.trim_start().is_empty())
511+
.or_else(|| {
512+
parsing_stdout = true;
513+
perr.stdout
514+
.as_ref()
515+
.and_then(|stdout| std::str::from_utf8(stdout).ok())
516+
});
517+
518+
if let Some(out) = output {
519+
let mut skipping_backtrace = false;
520+
for line in out.lines() {
521+
// Cargo directives aren't part of the error message text (except cargo:warning, which is reported separately).
522+
// Some scripts print a lot of cargo:rerun-if-env-changed that obscure the root cause of the failure.
523+
if parsing_stdout && line.starts_with("cargo:") {
524+
continue;
525+
}
526+
527+
msg.push_str("\n ");
528+
msg.push_str(line);
529+
}
530+
}
531+
Error::from(VerboseError::new(error)).context(msg)
532+
}
533+
499534
fn insert_warnings_in_build_outputs(
500535
build_script_outputs: Arc<Mutex<BuildScriptOutputs>>,
501536
id: PackageId,

tests/testsuite/build_script.rs

+42-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use std::io;
1515
use std::thread;
1616

1717
#[cargo_test]
18-
fn custom_build_script_failed() {
18+
fn custom_build_script_failed_verbose() {
1919
let p = project()
2020
.file(
2121
"Cargo.toml",
@@ -38,14 +38,54 @@ fn custom_build_script_failed() {
3838
[COMPILING] foo v0.5.0 ([CWD])
3939
[RUNNING] `rustc --crate-name build_script_build build.rs [..]--crate-type bin [..]`
4040
[RUNNING] `[..]/build-script-build`
41-
[ERROR] failed to run custom build command for `foo v0.5.0 ([CWD])`
41+
[ERROR] custom build command for `foo v0.5.0 ([CWD])` has failed
4242
4343
Caused by:
4444
process didn't exit successfully: `[..]/build-script-build` (exit [..]: 101)",
4545
)
4646
.run();
4747
}
4848

49+
#[cargo_test]
50+
fn custom_build_script_failed_terse() {
51+
let p = project()
52+
.file(
53+
"Cargo.toml",
54+
r#"
55+
[package]
56+
57+
name = "foo"
58+
version = "0.5.0"
59+
authors = ["[email protected]"]
60+
build = "build.rs"
61+
"#,
62+
)
63+
.file("src/main.rs", "fn main() {}")
64+
.file(
65+
"build.rs",
66+
"fn main() { println!(\"cargo:noise=1\netc\"); panic!(\"oops\"); }",
67+
)
68+
.build();
69+
p.cargo("build")
70+
.with_status(101)
71+
.with_stderr(
72+
"\
73+
[COMPILING] foo v0.5.0 ([CWD])
74+
[ERROR] custom build command for `foo v0.5.0 ([CWD])` has failed
75+
thread 'main' panicked at 'oops', build.rs:2:8
76+
stack backtrace:
77+
0: [..]
78+
at [..]
79+
1: build_script_build::main
80+
at [..]
81+
2: [..]
82+
at [..]
83+
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
84+
[NOTE] for more details, run again with '--verbose'",
85+
)
86+
.run();
87+
}
88+
4989
#[cargo_test]
5090
fn custom_build_env_vars() {
5191
let p = project()

0 commit comments

Comments
 (0)