Clearer display of build script errors in Cargo?

I've seen many examples of users stuck unable to compile crates, because they fail to notice error messages printed by build scripts. That is, the build script prints what user needs to do to fix the issue, but that text is lost in the noise of all other build error information, so user never notices the message, and it makes Rust look like it's failing for an unknown reason.

Most recent example where build script needed git installed, but user didn't notice it, and basically needed someone on the forum to read the message and say back to them what the message said. I'm not picking on this user in particular — it's a pattern, and IMHO Cargo is here to blame.

When a build script panics, Cargo dumps an overwhelming amount of information around the message:

error: yada yada yada yada yada yada yada `fltk-sys v0.15.7`

yada yada:
  yada yada yada yada yada yada: `yada yada yada yada yada yada` (yada yada: yada)
  --- yada yada
  yada:yada yada yada=yada yada/yada 
  yada:yada yada=yada
  yada:yada yada=yada yada 
  yada:yada yada yada=yada yada/yada yada 
  yada:yada yada yada=yada yada/yada yada 
  yada:yada yada yada=yada yada/yada yada 
  yada:yada yada yada=yada yada/yada yada 
  yada:yada yada yada=yada yada/yada yada 
  yada:yada yada yada=yada yada/yada yada 
  (…and 30 more lines like that…)

  --- yada
  yada 'yada' yada yada 'Git is needed to retrieve the fltk source files!: Os { code: 2, kind: NotFound, message: "The system cannot find the file specified." }', yada:\yada\yada\yada\fltk-sys-0.15.7\build.rs:93:14
  yada: yada yada `yada=yada` yada yada yada yada yada yada
yada: yada yada, yada yada yada yada yada yada...
yada: yada yada

In this infodump it's really hard to see what's going on.

Imagine if it was:

error in fltk-sys v0.15.7: Git is needed to retrieve the fltk source files
2 Likes

I'd agree. When I'm already skimming through a ton of irrelevant lines, a line starting with "thread 'main' panicked at" initially looks like it's just more noise. So it's very easy to miss the only information that matters to me at the time.

The two lines that actually start with "error: " give very limited or no information about the actual cause despite the build script's attempts to inform the user.

I wanna add that my knee-jerk reaction to any diagnostic that contains "thread ... panicked at" is "oh crap, that's an internal error, do I have time to file a bug report?" It does not suggest to me a situation that I can fix myself.

1 Like

Is this actually Cargo's fault though? Cargo dumps whatever build.rs prints to stdout/stderr, so probably it is the build script which needs to be less spammy?

Looked at the build script in question. Looks like the fix is to swap these two groups of commands:

This particular build script could output less before failing, but you can't rely on this in general. For example, build failures in C builds may print a lot before failing.

The messy "thread 'main' panicked" text is technically Rust's/std's fault, since it's the default panic message and Cargo merely pipes it. Improving this bit may need some clever integration between Rust/std/Cargo.

There's also a problem that this full verbose output is useful to sys crate developers, and might be useful to users who need to debug less obvious build failures.

How about this:

  • Cargo should continue to dump full stdout/stderr on error when the build script belongs to the current workspace. This will avoid frustrating sys crate developers.

  • When building sys crate of a dependency, it should print cargo:warning + panic message, and a suggestion to run again with --verbose to get the full output.

  • There needs to be some way of Cargo "catching" a panic with just the relevant part of the message, rather than the whole "thread 'main' panicked at". I'm not sure how could this be implemented. Some env var like RUST_MACHINE_READABLE_PANIC=1 that makes any Rust executable output panics in parseable format? Or a rustc flag similar to panic=abort, but something like panic=special-for-build-script-integration?

2 Likes

I think build scripts should use exit(1) instead of panic!() on errors.

1 Like

This seems like a good option to me, since cargo is already watching the output of the script.

It also allows the build script to add additional error info in special cases where the crate developer knows how to fix some specific error. By explicitly printing cargo:warning Here's how to fix this they would get the same "error" presentation regardless of whether the script caught the error and printed some help or panicked.

One potential complication to relying on passing a rustc flag of some sort for build scripts would be custom panic hooks, but I'm not sure how common those are in build scripts.

There's already cargo:warning= directive. It's seems natural to add cargo:error= that'd print just that error.

Possibly with a way to have span in the error for code generators. (And speaking of spans, I'd love to be able to set span in the generated code.)

5 Likes