Skip to content

Commit fcf940e

Browse files
authored
Simplify the error output on failed Command invocation (#1397)
1 parent 328d0ff commit fcf940e

File tree

3 files changed

+39
-129
lines changed

3 files changed

+39
-129
lines changed

src/command_helpers.rs

+14-62
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,6 @@ fn write_warning(line: &[u8]) {
247247

248248
fn wait_on_child(
249249
cmd: &Command,
250-
program: &Path,
251250
child: &mut Child,
252251
cargo_output: &CargoOutput,
253252
) -> Result<(), Error> {
@@ -258,12 +257,7 @@ fn wait_on_child(
258257
Err(e) => {
259258
return Err(Error::new(
260259
ErrorKind::ToolExecError,
261-
format!(
262-
"Failed to wait on spawned child process, command {:?} with args {}: {}.",
263-
cmd,
264-
program.display(),
265-
e
266-
),
260+
format!("failed to wait on spawned child process `{cmd:?}`: {e}"),
267261
));
268262
}
269263
};
@@ -275,12 +269,7 @@ fn wait_on_child(
275269
} else {
276270
Err(Error::new(
277271
ErrorKind::ToolExecError,
278-
format!(
279-
"Command {:?} with args {} did not execute successfully (status code {}).",
280-
cmd,
281-
program.display(),
282-
status
283-
),
272+
format!("command did not execute successfully (status code {status}): {cmd:?}"),
284273
))
285274
}
286275
}
@@ -350,28 +339,16 @@ pub(crate) fn objects_from_files(files: &[Arc<Path>], dst: &Path) -> Result<Vec<
350339
Ok(objects)
351340
}
352341

353-
pub(crate) fn run(
354-
cmd: &mut Command,
355-
program: impl AsRef<Path>,
356-
cargo_output: &CargoOutput,
357-
) -> Result<(), Error> {
358-
let program = program.as_ref();
359-
360-
let mut child = spawn(cmd, program, cargo_output)?;
361-
wait_on_child(cmd, program, &mut child, cargo_output)
342+
pub(crate) fn run(cmd: &mut Command, cargo_output: &CargoOutput) -> Result<(), Error> {
343+
let mut child = spawn(cmd, cargo_output)?;
344+
wait_on_child(cmd, &mut child, cargo_output)
362345
}
363346

364-
pub(crate) fn run_output(
365-
cmd: &mut Command,
366-
program: impl AsRef<Path>,
367-
cargo_output: &CargoOutput,
368-
) -> Result<Vec<u8>, Error> {
369-
let program = program.as_ref();
370-
347+
pub(crate) fn run_output(cmd: &mut Command, cargo_output: &CargoOutput) -> Result<Vec<u8>, Error> {
371348
// We specifically need the output to be captured, so override default
372349
let mut captured_cargo_output = cargo_output.clone();
373350
captured_cargo_output.output = OutputKind::Capture;
374-
let mut child = spawn(cmd, program, &captured_cargo_output)?;
351+
let mut child = spawn(cmd, &captured_cargo_output)?;
375352

376353
let mut stdout = vec![];
377354
child
@@ -382,16 +359,12 @@ pub(crate) fn run_output(
382359
.unwrap();
383360

384361
// Don't care about this output, use the normal settings
385-
wait_on_child(cmd, program, &mut child, cargo_output)?;
362+
wait_on_child(cmd, &mut child, cargo_output)?;
386363

387364
Ok(stdout)
388365
}
389366

390-
pub(crate) fn spawn(
391-
cmd: &mut Command,
392-
program: &Path,
393-
cargo_output: &CargoOutput,
394-
) -> Result<Child, Error> {
367+
pub(crate) fn spawn(cmd: &mut Command, cargo_output: &CargoOutput) -> Result<Child, Error> {
395368
struct ResetStderr<'cmd>(&'cmd mut Command);
396369

397370
impl Drop for ResetStderr<'_> {
@@ -414,28 +387,18 @@ pub(crate) fn spawn(
414387
Ok(child) => Ok(child),
415388
Err(ref e) if e.kind() == io::ErrorKind::NotFound => {
416389
let extra = if cfg!(windows) {
417-
" (see https://docs.rs/cc/latest/cc/#compile-time-requirements \
418-
for help)"
390+
" (see https://docs.rs/cc/latest/cc/#compile-time-requirements for help)"
419391
} else {
420392
""
421393
};
422394
Err(Error::new(
423395
ErrorKind::ToolNotFound,
424-
format!(
425-
"Failed to find tool. Is `{}` installed?{}",
426-
program.display(),
427-
extra
428-
),
396+
format!("failed to find tool {:?}: {e}{extra}", cmd.0.get_program()),
429397
))
430398
}
431399
Err(e) => Err(Error::new(
432400
ErrorKind::ToolExecError,
433-
format!(
434-
"Command {:?} with args {} failed to start: {:?}",
435-
cmd.0,
436-
program.display(),
437-
e
438-
),
401+
format!("command `{:?}` failed to start: {e}", cmd.0),
439402
)),
440403
}
441404
}
@@ -465,7 +428,6 @@ pub(crate) fn command_add_output_file(cmd: &mut Command, dst: &Path, args: CmdAd
465428
#[cfg(feature = "parallel")]
466429
pub(crate) fn try_wait_on_child(
467430
cmd: &Command,
468-
program: &Path,
469431
child: &mut Child,
470432
stdout: &mut dyn io::Write,
471433
stderr_forwarder: &mut StderrForwarder,
@@ -483,12 +445,7 @@ pub(crate) fn try_wait_on_child(
483445
} else {
484446
Err(Error::new(
485447
ErrorKind::ToolExecError,
486-
format!(
487-
"Command {:?} with args {} did not execute successfully (status code {}).",
488-
cmd,
489-
program.display(),
490-
status
491-
),
448+
format!("command did not execute successfully (status code {status}): {cmd:?}"),
492449
))
493450
}
494451
}
@@ -497,12 +454,7 @@ pub(crate) fn try_wait_on_child(
497454
stderr_forwarder.forward_all();
498455
Err(Error::new(
499456
ErrorKind::ToolExecError,
500-
format!(
501-
"Failed to wait on spawned child process, command {:?} with args {}: {}.",
502-
cmd,
503-
program.display(),
504-
e
505-
),
457+
format!("failed to wait on spawned child process `{cmd:?}`: {e}"),
506458
))
507459
}
508460
}

src/lib.rs

+25-63
Original file line numberDiff line numberDiff line change
@@ -1594,8 +1594,8 @@ impl Build {
15941594

15951595
if objs.len() <= 1 {
15961596
for obj in objs {
1597-
let (mut cmd, name) = self.create_compile_object_cmd(obj)?;
1598-
run(&mut cmd, &name, &self.cargo_output)?;
1597+
let mut cmd = self.create_compile_object_cmd(obj)?;
1598+
run(&mut cmd, &self.cargo_output)?;
15991599
}
16001600

16011601
return Ok(());
@@ -1623,12 +1623,8 @@ impl Build {
16231623
// acquire the appropriate tokens, Once all objects have been compiled
16241624
// we wait on all the processes and propagate the results of compilation.
16251625

1626-
let pendings = Cell::new(Vec::<(
1627-
Command,
1628-
Cow<'static, Path>,
1629-
KillOnDrop,
1630-
parallel::job_token::JobToken,
1631-
)>::new());
1626+
let pendings =
1627+
Cell::new(Vec::<(Command, KillOnDrop, parallel::job_token::JobToken)>::new());
16321628
let is_disconnected = Cell::new(false);
16331629
let has_made_progress = Cell::new(false);
16341630

@@ -1649,14 +1645,8 @@ impl Build {
16491645

16501646
cell_update(&pendings, |mut pendings| {
16511647
// Try waiting on them.
1652-
pendings.retain_mut(|(cmd, program, child, _token)| {
1653-
match try_wait_on_child(
1654-
cmd,
1655-
program,
1656-
&mut child.0,
1657-
&mut stdout,
1658-
&mut child.1,
1659-
) {
1648+
pendings.retain_mut(|(cmd, child, _token)| {
1649+
match try_wait_on_child(cmd, &mut child.0, &mut stdout, &mut child.1) {
16601650
Ok(Some(())) => {
16611651
// Task done, remove the entry
16621652
has_made_progress.set(true);
@@ -1695,14 +1685,14 @@ impl Build {
16951685
};
16961686
let spawn_future = async {
16971687
for obj in objs {
1698-
let (mut cmd, program) = self.create_compile_object_cmd(obj)?;
1688+
let mut cmd = self.create_compile_object_cmd(obj)?;
16991689
let token = tokens.acquire().await?;
1700-
let mut child = spawn(&mut cmd, &program, &self.cargo_output)?;
1690+
let mut child = spawn(&mut cmd, &self.cargo_output)?;
17011691
let mut stderr_forwarder = StderrForwarder::new(&mut child);
17021692
stderr_forwarder.set_non_blocking()?;
17031693

17041694
cell_update(&pendings, |mut pendings| {
1705-
pendings.push((cmd, program, KillOnDrop(child, stderr_forwarder), token));
1695+
pendings.push((cmd, KillOnDrop(child, stderr_forwarder), token));
17061696
pendings
17071697
});
17081698

@@ -1741,17 +1731,14 @@ impl Build {
17411731
check_disabled()?;
17421732

17431733
for obj in objs {
1744-
let (mut cmd, name) = self.create_compile_object_cmd(obj)?;
1745-
run(&mut cmd, &name, &self.cargo_output)?;
1734+
let mut cmd = self.create_compile_object_cmd(obj)?;
1735+
run(&mut cmd, &self.cargo_output)?;
17461736
}
17471737

17481738
Ok(())
17491739
}
17501740

1751-
fn create_compile_object_cmd(
1752-
&self,
1753-
obj: &Object,
1754-
) -> Result<(Command, Cow<'static, Path>), Error> {
1741+
fn create_compile_object_cmd(&self, obj: &Object) -> Result<Command, Error> {
17551742
let asm_ext = AsmFileExt::from_path(&obj.src);
17561743
let is_asm = asm_ext.is_some();
17571744
let target = self.get_target()?;
@@ -1761,23 +1748,14 @@ impl Build {
17611748
let gnu = compiler.family == ToolFamily::Gnu;
17621749

17631750
let is_assembler_msvc = msvc && asm_ext == Some(AsmFileExt::DotAsm);
1764-
let (mut cmd, name) = if is_assembler_msvc {
1765-
let (cmd, name) = self.msvc_macro_assembler()?;
1766-
(cmd, Cow::Borrowed(Path::new(name)))
1751+
let mut cmd = if is_assembler_msvc {
1752+
self.msvc_macro_assembler()?
17671753
} else {
17681754
let mut cmd = compiler.to_command();
17691755
for (a, b) in self.env.iter() {
17701756
cmd.env(a, b);
17711757
}
1772-
(
1773-
cmd,
1774-
compiler
1775-
.path
1776-
.file_name()
1777-
.ok_or_else(|| Error::new(ErrorKind::IOError, "Failed to get compiler path."))
1778-
.map(PathBuf::from)
1779-
.map(Cow::Owned)?,
1780-
)
1758+
cmd
17811759
};
17821760
let is_arm = matches!(target.arch, "aarch64" | "arm");
17831761
command_add_output_file(
@@ -1817,7 +1795,7 @@ impl Build {
18171795
self.fix_env_for_apple_os(&mut cmd)?;
18181796
}
18191797

1820-
Ok((cmd, name))
1798+
Ok(cmd)
18211799
}
18221800

18231801
/// This will return a result instead of panicking; see [`Self::expand()`] for
@@ -1852,12 +1830,7 @@ impl Build {
18521830

18531831
cmd.args(self.files.iter().map(std::ops::Deref::deref));
18541832

1855-
let name = compiler
1856-
.path
1857-
.file_name()
1858-
.ok_or_else(|| Error::new(ErrorKind::IOError, "Failed to get compiler path."))?;
1859-
1860-
run_output(&mut cmd, name, &self.cargo_output)
1833+
run_output(&mut cmd, &self.cargo_output)
18611834
}
18621835

18631836
/// Run the compiler, returning the macro-expanded version of the input files.
@@ -2476,7 +2449,7 @@ impl Build {
24762449
flags_env_var_value.is_ok()
24772450
}
24782451

2479-
fn msvc_macro_assembler(&self) -> Result<(Command, &'static str), Error> {
2452+
fn msvc_macro_assembler(&self) -> Result<Command, Error> {
24802453
let target = self.get_target()?;
24812454
let tool = if target.arch == "x86_64" {
24822455
"ml64.exe"
@@ -2531,7 +2504,7 @@ impl Build {
25312504
cmd.arg("-safeseh");
25322505
}
25332506

2534-
Ok((cmd, tool))
2507+
Ok(cmd)
25352508
}
25362509

25372510
fn assemble(&self, lib_name: &str, dst: &Path, objs: &[Object]) -> Result<(), Error> {
@@ -2559,7 +2532,7 @@ impl Build {
25592532
let dlink = out_dir.join(lib_name.to_owned() + "_dlink.o");
25602533
let mut nvcc = self.get_compiler().to_command();
25612534
nvcc.arg("--device-link").arg("-o").arg(&dlink).arg(dst);
2562-
run(&mut nvcc, "nvcc", &self.cargo_output)?;
2535+
run(&mut nvcc, &self.cargo_output)?;
25632536
self.assemble_progressive(dst, &[dlink.as_path()])?;
25642537
}
25652538

@@ -2587,12 +2560,12 @@ impl Build {
25872560
// Non-msvc targets (those using `ar`) need a separate step to add
25882561
// the symbol table to archives since our construction command of
25892562
// `cq` doesn't add it for us.
2590-
let (mut ar, cmd, _any_flags) = self.get_ar()?;
2563+
let mut ar = self.try_get_archiver()?;
25912564

25922565
// NOTE: We add `s` even if flags were passed using $ARFLAGS/ar_flag, because `s`
25932566
// here represents a _mode_, not an arbitrary flag. Further discussion of this choice
25942567
// can be seen in https://github.com/rust-lang/cc-rs/pull/763.
2595-
run(ar.arg("s").arg(dst), &cmd, &self.cargo_output)?;
2568+
run(ar.arg("s").arg(dst), &self.cargo_output)?;
25962569
}
25972570

25982571
Ok(())
@@ -2601,7 +2574,7 @@ impl Build {
26012574
fn assemble_progressive(&self, dst: &Path, objs: &[&Path]) -> Result<(), Error> {
26022575
let target = self.get_target()?;
26032576

2604-
let (mut cmd, program, any_flags) = self.get_ar()?;
2577+
let (mut cmd, program, any_flags) = self.try_get_archiver_and_flags()?;
26052578
if target.env == "msvc" && !program.to_string_lossy().contains("llvm-ar") {
26062579
// NOTE: -out: here is an I/O flag, and so must be included even if $ARFLAGS/ar_flag is
26072580
// in use. -nologo on the other hand is just a regular flag, and one that we'll skip if
@@ -2619,7 +2592,7 @@ impl Build {
26192592
cmd.arg(dst);
26202593
}
26212594
cmd.args(objs);
2622-
run(&mut cmd, &program, &self.cargo_output)?;
2595+
run(&mut cmd, &self.cargo_output)?;
26232596
} else {
26242597
// Set an environment variable to tell the OSX archiver to ensure
26252598
// that all dates listed in the archive are zero, improving
@@ -2648,11 +2621,7 @@ impl Build {
26482621
// NOTE: We add cq here regardless of whether $ARFLAGS/ar_flag have been used because
26492622
// it dictates the _mode_ ar runs in, which the setter of $ARFLAGS/ar_flag can't
26502623
// dictate. See https://github.com/rust-lang/cc-rs/pull/763 for further discussion.
2651-
run(
2652-
cmd.arg("cq").arg(dst).args(objs),
2653-
&program,
2654-
&self.cargo_output,
2655-
)?;
2624+
run(cmd.arg("cq").arg(dst).args(objs), &self.cargo_output)?;
26562625
}
26572626

26582627
Ok(())
@@ -3114,10 +3083,6 @@ impl Build {
31143083
}
31153084
}
31163085

3117-
fn get_ar(&self) -> Result<(Command, PathBuf, bool), Error> {
3118-
self.try_get_archiver_and_flags()
3119-
}
3120-
31213086
/// Get the archiver (ar) that's in use for this configuration.
31223087
///
31233088
/// You can use [`Command::get_program`] to get just the path to the command.
@@ -3764,7 +3729,6 @@ impl Build {
37643729
.arg("--show-sdk-path")
37653730
.arg("--sdk")
37663731
.arg(sdk),
3767-
"xcrun",
37683732
&self.cargo_output,
37693733
)?;
37703734

@@ -3821,7 +3785,6 @@ impl Build {
38213785
.arg("--show-sdk-version")
38223786
.arg("--sdk")
38233787
.arg(sdk),
3824-
"xcrun",
38253788
&self.cargo_output,
38263789
)
38273790
.ok()?;
@@ -3992,7 +3955,6 @@ impl Build {
39923955
) -> Option<PathBuf> {
39933956
let search_dirs = run_output(
39943957
cc.arg("-print-search-dirs"),
3995-
"cc",
39963958
// this doesn't concern the compilation so we always want to show warnings.
39973959
cargo_output,
39983960
)

0 commit comments

Comments
 (0)