-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Presentation of cargo::error encourages build scripts to exit with a successful status code on failure #15038
Comments
I see there being 3 exit conditions with
I would assume the exhaustive output would be most helpful in the case of a logic bug which would usually come in the form of a I don't see how the extra output would be relevant to help with an "error" with the For the concern for the |
I do not think that developers would print Exiting with an error status on failure is the correct thing to do, but this issue is not about beating non-compliant people with the best practices. It's the opposite: an observation that Rust users already value correctness, so they would find it objectionable to be forced to use incorrect and backwards-incompatible As much as I'd like to make pull requests to all the -sys crates to make them use the clean error presentation, I expect I'd have hard time convincing crate owners to accept a PR that uses Debug dump on fn probe_library(name: &str) -> bool {
match search_for_it(name) {
Ok(found) => {
println!("cargo::rustc-link-lib={found}");
return true;
},
Err(error) => {
println!("cargo::error={error}");
return false;
}
}
}
fn main() {
if !probe_library("dep") {
build_static().unwrap();
}
} This script prints
Build scripts very often intentionally
However, the If you think that I'm proposing to add the stdout/stderr dump on |
This is the defined behavior of the API as agreed by the Cargo team. Deviating from that would need buy-in from the Cargo team, documentation updates, and messages informing users they aren't using the feature correctly. I'm not seeing enough reason to re-litigate the discussion from #10159.
How does printing the debug dump help find the problem?
I hadn't paid attention to what code is used. Cargo happens to return this code, so not fully outside the realm of possibility but we could document it as having special behavior.
The problem is we can't distinguish intentional panics from unintentional panics.
Please do not outright dismiss others like this. You were discussing when debug information is needed. I was doing an analysis of the different cases where debug information is helpful. |
Through printf-debugging. A build script is likely to log things it's been doing (and/or its subcommands like But I'm realizing that I'm trying to report a bug for one case, and suggest a nice-to-have for another case, and discussing these two things at once just makes the discussion more complicated. So to simplify, I'm not insisting on printing the stdout/stderr raw dump for
IIRC the decision was that But there must have been some miscommunication or a mistake in the implementation, because in the shipped implementation the status is not just irrelevant, but the script must report success status to get the nicer So the status didn't just become irrelevant. It became very relevant, and I need to stress that the whole point of Printing a message in addition to the raw dump is already handled by I suspect the current behavior of If the stdout/stderr dump was meant to be consistently printed regardless of the status, then the OTOH for So the logic here looks swapped around by accident.
I'm sorry, I did not realize it's a strong phrasing. Now I see I didn't quite get your point at first. I was focused on the fact that figuring out the distinction between a panic (that I assumed to be intentional) and When a panic is unintentional and caused by a bug in the build script itself, I agree that this could be handled in a different way. |
Problem
The current implementation of
cargo::error
has a minimal, concise error presentation only when the build script exits with a successful status code (0) when it reports a build failure.If a build script fails with a non-zero status code, use of the
cargo::error
directive doesn't prevent Cargo from adding a full dump of stdout/stderr after it, which makes the output noisy and difficult to understand #10159.The current implementation incentivises build scripts to exit with the status 0 (success) to cleanly report fatal build errors. This is a non-standard behavior for reporting failures, and it's not backwards compatible with older Cargo versions that don't understand
cargo::error
.Dumping the full stdout/stderr output is a major problem that diminishes usefulness of
cargo::error
. The dump is so noisy that the errors reported viacargo::error
may be less visible and less readable than a raw text printed to stderr. The stdout dump can contain long lists ofcargo::rerun-if-(env-)changed
directives, and other potentially irrelevant logs from subcommands. A long noisy stdout/stderr dump usually causes users to stop reading the output carefully, and gloss over the entire output instead. It may even push the "error:" lines out of the view, leaving only the raw dump on screen, which ends with less helpful content. Thepkg-config
andcmake
crates have this problem, and they also happen to be the most frequent source of build script failures.pkg-config
prints 21cargo::rerun-if-env-changed
lines, which together with Cargo's boilerplate is 25 lines, the same as the default height ofcmd.exe
console on Windows. Windows users may literally not see the errors generated bycargo::error
if a build script fails with a failure status code. The long output dump can be made even noisier when the build script panics, and Cargo actively encourages users to enable even longer backtraces, which pushes the "error:" lines even further, and obscures even the last lines of stderr that may contain another copy of the error.I think the conditions for when
cargo::error=
has a clean presentation should be swapped: it should give the cleanest presentation when the build script reportscargo::error
and exits with a failure status code to match it. This is a consistent response (edit: orcargo::error
could have a clean output regardless of the status code).(edit: Optional improvement suggestion, not the main problem): when a build script prints
cargo::error
, but exits with a success code, this is a self-contradictory result. This is likely a bug in the build script. Such failures could be caused by helper functions or build-time dependencies eagerly printingcargo::error
, even when the build script manages to recover from the error and succeeds using some other way. To help catch such roguecargo::error
s that break successful build scripts, Cargo should be printing the full stdout dump, so that build script authors can check where in the log the unintended directive has appeared.In other words, this is the current behavior:
cargo::error=
but to make
cargo::error
useful to end users, and (edit: optionally) bad error reporting debuggable, it should work like this:cargo::error=
Steps
Buggy
build.rs
:happens to get a clean error output with a high signal-to-noise ratio:
A more typical script that exits with a correct status code:
gets an ugly noisy dump that makes it hard for end users to understand what's going on:
Possible Solution(s)
build scripts that report both failure and success at the same time (one via
cargo::
the other via status) should get the stdout dump to help find the source of the contradictory response.build scripts that print
cargo::error=
and correctly return failure code should get a clean error output with just the errors and warnings the script reported, without irrelevant information dumped by Cargo.Version
The text was updated successfully, but these errors were encountered: