Skip to content

Console output should better reflect the build process #8889

Open
@nnethercote

Description

@nnethercote
Contributor

Describe the problem you are trying to solve

The console output can be misleading about what's happening in the build. Having lots of sequential Compiling <crate> lines makes it seem like compilation is serial, and if a slow-building crate X starts building just before a fast-building crate Y, you'll probably think that Y is the slow-building crate. (I was misled in this way about build times of different crates within rustc for a long time.)

The progress bar helps with this, because it shows which crates are currently being built... but only if you have a sufficiently wide terminal. If you have 80 chars you don't see them at all. If you have 100 chars you might see one or two or three, but any crate with a long name greatly reduces the effectiveness.

Also, linking isn't shown. This means people often blame the compiler for slowness when it's the linker's fault.

Describe the solution you'd like

  1. Instead of printing Compiling <crate> when a crate starts building, print Compiled <crate> in X.YYs. That would avoid the problem where slowness to build is blamed on the wrong crate. This is a change of tense in the message, but Cargo already mixes present and past tenses, e.g. with Downloaded <crate> and Downloaded2 3 crates (78.7 KB) in 1.03s messages.

  2. Shrink the width of the progress bar, so the crates being built can be seen even on narrow terminals.

  3. Show linking as a distinct step, including the time it took, e.g. `Linked in X.YYs".

Notes

My motivation here was comparing console output (which is moderately useful) to -Ztimings output (which is amazing), and trying to make the former a bit more like the latter.

See also

Activity

added
C-feature-requestCategory: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`
on Nov 24, 2020
nnethercote

nnethercote commented on Nov 24, 2020

@nnethercote
ContributorAuthor

2. Shrink the width of the progress bar, so the crates being built can be seen even on narrow terminals.

#8892 does this.

ehuss

ehuss commented on Nov 24, 2020

@ehuss
Contributor

I don't think it is currently possible to show link time as a separate stat, since rustc does compilation+linking together. It might be possible to have rustc spit out a JSON message when it starts linking, and Cargo could catch that to start a new timer. There might be a tiny delay, but I suspect not enough to affect the timing in a meaningful way. I think that would be useful (at least for -Ztimings). Would need to ask the compiler team what they think about adding instrumentation like that.

nnethercote

nnethercote commented on Nov 24, 2020

@nnethercote
ContributorAuthor

Maybe Cargo could output "Compiling and linking" (or "Compiled and linked") instead? Less precise, but still clearer than the current output.

alexcrichton

alexcrichton commented on Nov 24, 2020

@alexcrichton
Member

The intention of the current progress bar was to give an indicator as to what's currently compiling so we don't have to just read the last line and blame that (ideally), but it's true that we never got back to updating the console output otherwise. I'd be a bit wary of indicating the compile time of each crate individually because that could add up to a lot of noise in the current output scheme.

All that being said though, I think it's high time we completely revamp Cargo's output. Even one-short-line-per-package feels unnecessarily verbose today. I'd sort of prefer if we could have the progress bar we currently have but have maybe at most 4-5 other lines indicating "these were the slowest crates to compile" or something like that. Then when Cargo finishes it could erase the output or leave it all there. (or something like that).

Basically I think the current output has gotten us this far but it could benefit from a complete overhaul in addition to smaller tweaks.

joshtriplett

joshtriplett commented on Nov 24, 2020

@joshtriplett
Member

@ehuss We've talked about, for other reasons, separating compilation and linking: rust-lang/rust#64191

If we do that in rustc, cargo should use that, and could then reflect that in its output.

dtolnay

dtolnay commented on Feb 18, 2021

@dtolnay
Member

I think it's high time we completely revamp Cargo's output. Even one-short-line-per-package feels unnecessarily verbose today.

Sharing two recordings for possible inspiration. Both of these build systems' outputs are designed around accurately surfacing where the most time is getting spent in builds with (extremely) high parallelism. The currently running longest running jobs are always at the top.


Peek 2021-02-17 21-01

Peek 2021-02-17 21-02

ehuss

ehuss commented on Feb 18, 2021

@ehuss
Contributor

Thanks @dtolnay for sharing those. I'm not too familiar with what kind of terminal detection and support is necessary to be able to create multi-line progress indicators like that, especially across a myriad of platforms. Cargo's current progress bar is extremely primitive, which makes it a little easier to maintain, but is much more limiting.

I think it would be great to improve the output, I just hope it doesn't require pulling in large dependencies, or require heroic efforts to get it to work across terminals. Cygwin/msys on Windows has been particularly hard to support, since Cargo doesn't live in the Cygwin universe, it is limited on what it can do.

I'm also curious how warnings and errors get displayed. One problem I struggled with in the current progress bar implementation is that it has to clear the progress bar in order to display a message (and scroll the output up), and then redisplay the progress bar. This causes severe flickering on some terminals (particularly on Windows). I'm curious how buck and bazel and other tools handle that.

camsteffen

camsteffen commented on May 5, 2021

@camsteffen

Minor suggestion. The list of crates in the Building line should match the order that they are printed in the Compiling lines. That is, the one that has been running the longest should be first, IIUC.

arcuru

arcuru commented on Jul 20, 2022

@arcuru

I am interested in working on this, and have already created a hacky prototype build using crossterm that is heavily influenced by buck/bazel. See the recording below.

@alexcrichton @ehuss @dtolnay Since this is pretty old, could you confirm if you'd actually want to take this change? It's a decent chunk of work to do it properly so I don't want to spend too much time on it if you're no longer interested.

asciicast

29 remaining items

epage

epage commented on Mar 7, 2025

@epage
Contributor

As an update, we now have config settings for

  • unicode
  • hyperlinks

And soon, system progress reporting.

Those have been setting the pattern that the use of terminal capabilities is done on a terminal-by-terminal allow-list with an explicit control via config for when the allow list does not meet a users needs. We can then extend that to richer terminal rendering than we have today.

epage

epage commented on Mar 7, 2025

@epage
Contributor

I realize I've never fully summarized my proposal for this on this issue.

My idea is that we designate output as "sticky" or "non-sticky":

  • Sticky output, like warnings an errors, persists
  • Non-sticky output (most status messages) will be cleared when their parent operation is done

I did say "most status messages", not "all". My ideal "first step" would be for each command to have a "summary" status message that is sticky. Due to how we compose things, this might initially be a "summary per step" (cargo test showing compile and test summaries) rather than a single "command summary" (test summary). Cargo scripts would have no run summary (maybe a compile summary if something was built).

We would also show multi-line progress indicators. We'd want to survey how other multi-line progress indicators handle

  • Very fast entries (flashing of output, order instability)
  • More entries than can be shown (e.g. large builds on 64-core machines)
  • How we can help people identify slow operations
  • Can the progress bar report the phase of compilation (frontend, backend, link)?

Where supported, we should probably use the terminal sync control codes for nicer refreshes.

The way I picture this happening internally is that a status message can be parented under another status message. One way of handling sticky items is to declare it independent of any parent status. Maybe one way to handle "last status is sticky" is we just bake that assumption in? Should we have implicit parenting of status messages by having a status stack in GlobalContext?

We should probably refactor the existing code to something more like a status system (e.g. instead of making direct calls to "clear line") and then work to allow support for a new status implementation underneath that.

RalfJung

RalfJung commented on Mar 20, 2025

@RalfJung
Member

For ui_test, @oli-obk built some pretty fancy multi-line status presentation, showing which tests are currently being run, and logging the ones that are completed above. I have no idea how it works but maybe the underlying tech could be useful for cargo, too.

oli-obk

oli-obk commented on Jun 3, 2025

@oli-obk
Contributor

I'm mostly just forwarding to indicatif, though with some buffering so that I don't add and remove items that get processed faster than a human can observe them.

One thing that is nicely possible in my setup is trees of builds and dependencies. So we could display what is essentially cargo tree where leaves get removed after they finish compilation. Though that can quickly get too large, so maybe just a list is actually better for cargo.

Nemo157

Nemo157 commented on Jun 3, 2025

@Nemo157
Member

So we could display what is essentially cargo tree where leaves get removed after they finish compilation. Though that can quickly get too large, so maybe just a list is actually better for cargo.

I prototyped something like this years ago; no idea if the code still works, but the asciinema should still be viewable: https://github.com/nemo157/cargo-build-tree. And you're right, it is way too large to be usable in most real projects—at least with what I show there, but relooking at it now I think there are some simplifications of the tree that could be done which might make it closer to usable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-console-outputArea: Terminal output, colors, progress bar, etc.C-feature-requestCategory: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`E-hardExperience: HardS-needs-designStatus: Needs someone to work further on the design for the feature or fix. NOT YET accepted.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @ehuss@epage@Byron@alexcrichton@Nemo157

        Issue actions

          Console output should better reflect the build process · Issue #8889 · rust-lang/cargo