Skip to content

Commit ba08d63

Browse files
authored
feat: add cargo_output to eliminate last vestiges of stdout pollution (#1141)
1 parent 1372bf5 commit ba08d63

File tree

3 files changed

+56
-15
lines changed

3 files changed

+56
-15
lines changed

src/command_helpers.rs

+31-4
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,28 @@ pub(crate) struct CargoOutput {
2222
pub(crate) metadata: bool,
2323
pub(crate) warnings: bool,
2424
pub(crate) debug: bool,
25+
pub(crate) output: OutputKind,
2526
checked_dbg_var: Arc<AtomicBool>,
2627
}
2728

29+
/// Different strategies for handling compiler output (to stdout)
30+
#[derive(Clone, Debug)]
31+
pub(crate) enum OutputKind {
32+
/// Forward the output to this process' stdout (Stdio::inherit)
33+
Forward,
34+
/// Discard the output (Stdio::null)
35+
Discard,
36+
/// Capture the result
37+
Capture,
38+
}
39+
2840
impl CargoOutput {
2941
pub(crate) fn new() -> Self {
3042
#[allow(clippy::disallowed_methods)]
3143
Self {
3244
metadata: true,
3345
warnings: true,
46+
output: OutputKind::Forward,
3447
debug: std::env::var_os("CC_ENABLE_DEBUG_OUTPUT").is_some(),
3548
checked_dbg_var: Arc::new(AtomicBool::new(false)),
3649
}
@@ -65,6 +78,14 @@ impl CargoOutput {
6578
Stdio::null()
6679
}
6780
}
81+
82+
fn stdio_for_output(&self) -> Stdio {
83+
match self.output {
84+
OutputKind::Capture => Stdio::piped(),
85+
OutputKind::Forward => Stdio::inherit(),
86+
OutputKind::Discard => Stdio::null(),
87+
}
88+
}
6889
}
6990

7091
pub(crate) struct StderrForwarder {
@@ -321,9 +342,10 @@ pub(crate) fn run_output(
321342
) -> Result<Vec<u8>, Error> {
322343
let program = program.as_ref();
323344

324-
cmd.stdout(Stdio::piped());
325-
326-
let mut child = spawn(cmd, program, cargo_output)?;
345+
// We specifically need the output to be captured, so override default
346+
let mut captured_cargo_output = cargo_output.clone();
347+
captured_cargo_output.output = OutputKind::Capture;
348+
let mut child = spawn(cmd, program, &captured_cargo_output)?;
327349

328350
let mut stdout = vec![];
329351
child
@@ -333,6 +355,7 @@ pub(crate) fn run_output(
333355
.read_to_end(&mut stdout)
334356
.unwrap();
335357

358+
// Don't care about this output, use the normal settings
336359
wait_on_child(cmd, program, &mut child, cargo_output)?;
337360

338361
Ok(stdout)
@@ -356,7 +379,11 @@ pub(crate) fn spawn(
356379
cargo_output.print_debug(&format_args!("running: {:?}", cmd));
357380

358381
let cmd = ResetStderr(cmd);
359-
let child = cmd.0.stderr(cargo_output.stdio_for_warnings()).spawn();
382+
let child = cmd
383+
.0
384+
.stderr(cargo_output.stdio_for_warnings())
385+
.stdout(cargo_output.stdio_for_output())
386+
.spawn();
360387
match child {
361388
Ok(child) => Ok(child),
362389
Err(ref e) if e.kind() == io::ErrorKind::NotFound => {

src/lib.rs

+14
Original file line numberDiff line numberDiff line change
@@ -1196,6 +1196,20 @@ impl Build {
11961196
self
11971197
}
11981198

1199+
/// Define whether compiler output (to stdout) should be emitted. Defaults to `true`
1200+
/// (forward compiler stdout to this process' stdout)
1201+
///
1202+
/// Some compilers emit errors to stdout, so if you *really* need stdout to be clean
1203+
/// you should also set this to `false`.
1204+
pub fn cargo_output(&mut self, cargo_output: bool) -> &mut Build {
1205+
self.cargo_output.output = if cargo_output {
1206+
OutputKind::Forward
1207+
} else {
1208+
OutputKind::Discard
1209+
};
1210+
self
1211+
}
1212+
11991213
/// Adds a native library modifier that will be added to the
12001214
/// `rustc-link-lib=static:MODIFIERS=LIBRARY_NAME` metadata line
12011215
/// emitted for cargo if `cargo_metadata` is enabled.

src/tool.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ use std::{
55
ffi::{OsStr, OsString},
66
io::Write,
77
path::{Path, PathBuf},
8-
process::{Command, Stdio},
8+
process::Command,
99
sync::RwLock,
1010
};
1111

1212
use crate::{
1313
command_helpers::{run_output, CargoOutput},
1414
run,
1515
tempfile::NamedTempfile,
16-
Error, ErrorKind,
16+
Error, ErrorKind, OutputKind,
1717
};
1818

1919
/// Configuration used to represent an invocation of a C compiler.
@@ -158,14 +158,14 @@ impl Tool {
158158
cargo_output.print_debug(&stdout);
159159

160160
// https://gitlab.kitware.com/cmake/cmake/-/blob/69a2eeb9dff5b60f2f1e5b425002a0fd45b7cadb/Modules/CMakeDetermineCompilerId.cmake#L267-271
161-
let accepts_cl_style_flags =
162-
run(Command::new(path).arg("-?").stdout(Stdio::null()), path, &{
163-
// the errors are not errors!
164-
let mut cargo_output = cargo_output.clone();
165-
cargo_output.warnings = cargo_output.debug;
166-
cargo_output
167-
})
168-
.is_ok();
161+
let accepts_cl_style_flags = run(Command::new(path).arg("-?"), path, &{
162+
// the errors are not errors!
163+
let mut cargo_output = cargo_output.clone();
164+
cargo_output.warnings = cargo_output.debug;
165+
cargo_output.output = OutputKind::Discard;
166+
cargo_output
167+
})
168+
.is_ok();
169169

170170
let clang = stdout.contains(r#""clang""#);
171171
let gcc = stdout.contains(r#""gcc""#);
@@ -283,7 +283,7 @@ impl Tool {
283283
/// Don't push optimization arg if it conflicts with existing args.
284284
pub(crate) fn push_opt_unless_duplicate(&mut self, flag: OsString) {
285285
if self.is_duplicate_opt_arg(&flag) {
286-
println!("Info: Ignoring duplicate arg {:?}", &flag);
286+
eprintln!("Info: Ignoring duplicate arg {:?}", &flag);
287287
} else {
288288
self.push_cc_arg(flag);
289289
}

0 commit comments

Comments
 (0)