Skip to content

Less verbose logs from make#11844

Merged
nojb merged 4 commits intoocaml:trunkfrom
xavierleroy:less-verbose-make
Jan 18, 2023
Merged

Less verbose logs from make#11844
nojb merged 4 commits intoocaml:trunkfrom
xavierleroy:less-verbose-make

Conversation

@xavierleroy
Copy link
Copy Markdown
Contributor

@xavierleroy xavierleroy commented Dec 30, 2022

It's still time to make small wishes for 2022. One of mine is less verbose build logs.

The output of make looks almost decent when each command fits on one line, as Stuart Feldman envisioned it, and looks like complete gobbledygook otherwise. Unfortunately, OCaml, like all serious projects, has very long build commands, what with all these -I and -w options.

But there's a trick! The Makefile can run commands silently after printing a short meaningful summary:

    @echo "Linking foo"
    @gcc bla bla bla bla bla -o foo

I think the Linux kernel build does this (or did it 25 years ago when I last built my own kernels). I learned this trick from Coq, and use it with pleasure in CompCert.

This draft PR applies this trick to (parts of most of) the Makefiles of OCaml. For example, it prints
OCAMLC lambda/switch.ml
instead of
./boot/ocamlrun ./boot/ocamlc -nostdlib -I ./boot -use-prims runtime/primitives -g -strict-sequence -principal -absname -w +a-4-9-40-41-42-44-45-48 -warn-error +a -bin-annot -strict-formats -I lambda -I utils -I parsing -I typing -I bytecomp -I file_formats -I lambda -I middle_end -I middle_end/closure -I middle_end/flambda -I middle_end/flambda/base_types -I asmcomp -I driver -I toplevel -I tools -c lambda/switch.ml
and
CC runtime/addrmap.c -> runtime/addrmap.b.o
instead of
gcc -c -O2 -fno-strict-aliasing -fwrapv -pthread -g -Wall -Werror -fno-common -fexcess-precision=standard -fno-tree-vrp -ffunction-sections -I./runtime -D_FILE_OFFSET_BITS=64 -DCAMLDLLIMPORT= -DIN_CAML_RUNTIME -o runtime/addrmap.b.o runtime/addrmap.c

The general format is COMMAND inputfile if there's no ambiguity about the output file, or COMMAND inputfile -> outputfile otherwise. The format is open to discussions; my only demand is that every output fits on a single line.

I attach a full build log for reference: log4.gz

Currently, only the generic compile rules are modified; other rules such as linking steps still print in full. And some Makefiles remain to be adjusted. Yet, the log file is already 3 times shorter (340 k instead of 1M).

As usual, I'll now switch to Q&A mode to speed up discussions.

Q: But if a command fails, I may need to see it in full!

A: Most of the time, we look at the error messages from the compiler, not at the command itself. But in the rare case where you need to see the command in full, there's a simple trick. After the failure, just do make -n | head. With the -n option, commands are printed in full even when preceded by @. If you're in a sequential build, the command that failed is the first command to re-execute, so it should be the first line of the make -n output. If you're in a parallel build, you can reproduce the failure with make, then see the command with make -n | head.

It would also possible to have a make variable that controls whether to abbreviate commands or leave them printed in full. But I don't know how to do this without some duplication and extra if...else...endif in the Makefiles.

Q: Why do you care? Do you really read the build logs?

A: I too often have to search through build logs from CI, yes. Smaller logs will be a relief for all our CI systems. Apart from this, the fast scrolling of huge build commands in a terminal or Emacs buffer does make me uncomfortable, indeed.

@xavierleroy
Copy link
Copy Markdown
Contributor Author

@shindere needs to know about this proposal.

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Dec 30, 2022 via email

@gasche
Copy link
Copy Markdown
Member

gasche commented Dec 30, 2022

Two questions:

  1. The "how to see the full command for reproducing a failure?" question is important. You answer in this PR, but could you put the answer in HACKING.adoc as well to make it easy to find again in the future?
  2. This approach doubles the number of "commands" run in each build, is there a noticeable slowdown on Windows? (This is probably a question for @nojb or @dra27.)

@nojb
Copy link
Copy Markdown
Contributor

nojb commented Dec 31, 2022

I am generally in favor, this makes the logs much more readable.

The format is open to discussions; my only demand is that every output fits on a single line.

At the moment, OCAMLC is used as a prefix both for ocamlc and ocamlc.opt (and similarly for ocamlopt). I think that showing OCAMLC.OPT for the second one would be slightly better. Is this doable without complicating things too much?

is there a noticeable slowdown on Windows?

I did a quick benchmark of make -j10, starting from a clean tree, with the mingw64 port, which shows a slowdown of ~7%. This is unfortunate, but I think it is still tolerable.

trunk

real    5m45.928s
user    8m46.635s
sys     5m49.594s

This PR

real    6m11.228s
user    9m23.653s
sys     7m9.884s

@dra27
Copy link
Copy Markdown
Member

dra27 commented Dec 31, 2022

I’m also for this! For the slowdown, I think it may be possible to avoid the call to echo by using $(info?

@xavierleroy
Copy link
Copy Markdown
Contributor Author

I just pushed a version that uses $(info ...) instead of @echo "...", it should run faster. Thanks a lot @dra27 for the suggestion!

@shindere : glad you like the idea. My next wish is a less verbose output from ocamltest...

@nojb: the code that sets OCAMLC and OCAMLOPT could also set OCAMLC_NAME and OCAMLOPT_NAME variables (e.g. to OCAMLC or OCAMLC.OPT), which could then be used when printing the command.

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Jan 2, 2023 via email

@nojb
Copy link
Copy Markdown
Contributor

nojb commented Jan 3, 2023

I just pushed a version that uses $(info ...) instead of @echo "...", it should run faster. Thanks a lot @dra27 for the suggestion!

I played around with the PR and did what seems to me like some improvements (as well as adapting more of the build system), see xavierleroy#1.

@xavierleroy
Copy link
Copy Markdown
Contributor Author

Thanks @nojb for the nice improvements, they are now merged in this PR.

Given that the initial feedback is positive and that it's starting to look really good, I'm removing the "Draft" status to show that this PR is ready for review. We will wait for @shindere's review.

@xavierleroy xavierleroy marked this pull request as ready for review January 3, 2023 10:53
@xavierleroy
Copy link
Copy Markdown
Contributor Author

xavierleroy commented Jan 3, 2023

My next wish is a less verbose output from ocamltest...

You mean all the time, or you mean when run by the CI?

I mean when run by make -C testsuite. But I also think that the default output format for ocamltest should be a single line:

   name-of-test   (passed|skipped|failed)  [time taken]

and the current output should be explicitly requested with a -v option or something.

@avsm
Copy link
Copy Markdown
Member

avsm commented Jan 3, 2023

I don't have a development environment handy to test this at the moment, but if there are a lot of generated files then you may be able to speedup the Windows build by using the GNU Make $(file ) function to write outputs instead of indirecting the V_GEN calls through an echo/cat and shell redirect.

@dra27
Copy link
Copy Markdown
Member

dra27 commented Jan 3, 2023

There aren't too many generated files, fortunately (at least in the main build). Alas, $(file ...) is GNU make 4.0, so it's not at the moment available to us without considerable care to avoid it on macOS.

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Jan 9, 2023

Just started to review this. Many thanks for the cool work. The result
looks much better than before, obviously.

Quick question: how important is the vertical alignment of filenames
to you (poor ;-) ) sighted people? I have two reasons to ask this question.

  1. In braille it makes the text less compact than it could be, so I loose a little bit of effiency in reading.
  2. More importantly: it may be nice at some point to e.g. distinguish
    BOOT_OCAMLC from OCAMLC in the printed messages and it may then become
    harder to maintain the vertical alignment, except of course if it is made
    big enough but still, all this means that if we have vertical alignment
    we will have to maintain it. Is the visual gain really worth it?
    It's a genuine question.

Am I correct that, in its present state, the PR does not provide any way to
see the details of a command?

In the implementation I have in mind, we would have a V variable to
control the verbosity. Basically, make V=0 would be equivalent to make -s and would
let one verify that the build does not yield any unexpected message (the
output of Make V=0 should be empty), make V=1 would print the nice new
messages and make V=2 would print the commands in full details as before.

Is the idea okay and, if yes, shall I try to add it to the present PR or rather to
a separate one? If it's in a separate one then likely I'll wait until all
the makefiles have been merge because that will make the work easier. But in
workin on the makefiles it would be useful to have a way to see the
commands.

How about the mkdir command? Shoudln't it get a nice output, too?

@xavierleroy
Copy link
Copy Markdown
Contributor Author

Quick question: how important is the vertical alignment of filenames to you (poor ;-) ) sighted people?

Not important to me.

How about the mkdir command? Shoudln't it get a nice output, too?

I think there will always be "raw" commands that occur too rarely to get a special output. It's OK, especially if they fit on one line, which is the case for mkdir commands. See also ln commands for which @nojb removed the nice output recently, as it was problematic (I guess).

Am I correct that, in its present state, the PR does not provide any way to
see the details of a command?

Correct. But there's always make -n.

In the implementation I have in mind, we would have a V variable to
control the verbosity. Basically, make V=0 would be equivalent to make -s and would
let one verify that the build does not yield any unexpected message (the
output of Make V=0 should be empty), make V=1 would print the nice new
messages and make V=2 would print the commands in full details as before.

Because there will always be "raw" commands, your "V=0" mode will not suppress all output, and it's better to rely on make -s. There's something similar to your "V=1" and "V=2" in the Coq makefiles, if I remember correctly.

@nojb
Copy link
Copy Markdown
Contributor

nojb commented Jan 11, 2023

See also ln commands for which @nojb removed the nice output recently, as it was problematic (I guess).

It wasn't problematic, but we were doing it for ln and not for mkdir, cp, etc; we should do it either for all of them or none of them, and it wasn't clear if it was worth doing it for these commands by the reasons mentioned.

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Jan 11, 2023 via email

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Jan 11, 2023 via email

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Jan 16, 2023 via email

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Jan 16, 2023 via email

@xavierleroy
Copy link
Copy Markdown
Contributor Author

This has been implemented at the top of the less-verbose-logs branch
of shindere/ocaml: make V=1 prints the commands the new way
(default) whereas make V=2 prints the commands as they were printed
before this PR.

I'm a computer scientist: I don't know this "2" thing you're using, only "0" and "1" :-)

More seriously, according to Stackoverflow wisdom, CMake, uses make VERBOSE=1 and GNU autotools make V=1 to select verbose output. I strongly suggest we use one of these two conventions.

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Jan 16, 2023 via email

@gasche
Copy link
Copy Markdown
Member

gasche commented Jan 16, 2023

It may be interesting to hear the opinions of others.

My opinion: I haven't looked at this and don't plan to, but it looks like there is a general consensus in favor of the change as, broadly, originally proposed, and less consensus on the proposed addition of an explicit verbosity setting. My recommendation would be to first merge the change at the scope of the original proposal, and split the verbosity setting patches to a follow-up PR where you can discuss more if you want.

(Re. V versus VERBOSE: in general I'm in favor of longer options because they are nicer on the reader, and I read more than I write. This being said, I guess I'm the sort of people who does not mind seeing long commands in the build logs.)

@damiendoligez
Copy link
Copy Markdown
Member

For the flag, my vote goes to V and I see a good use for relative integers here:
make V=-1 for a completely silent build
make V=0 (default) for printing abbreviated commands
make V=1 for printing full commands

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Jan 16, 2023 via email

@dra27
Copy link
Copy Markdown
Member

dra27 commented Jan 16, 2023

Re. V versus VERBOSE: in general I'm in favor of longer options because they are nicer on the reader, and I read more than I write

There’s no major reason not to have both? I keep meaning to add that in testsuite/Makefile for KEEP_TEST_DIR_ON_SUCCESS as my usage of it always begins with grep KEEP Makefile to remind me what the full name of the variable is…

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Jan 16, 2023 via email

Print concise summaries instead of full commands for some of the most verbose
commands.  For example, print
```
OCAMLC lambda/switch.ml
```
instead of
```
./boot/ocamlrun ./boot/ocamlc -nostdlib -I ./boot -use-prims runtime/primitives -g -strict-sequence -principal -absname -w +a-4-9-40-41-42-44-45-48 -warn-error +a -bin-annot -strict-formats -I lambda -I utils -I parsing -I typing -I bytecomp -I file_formats -I lambda -I middle_end -I middle_end/closure -I middle_end/flambda -I middle_end/flambda/base_types -I asmcomp -I driver -I toplevel -I tools -c lambda/switch.ml
```
and
```
CC runtime/addrmap.c -> runtime/addrmap.b.o
```
instead of
```
gcc -c -O2 -fno-strict-aliasing -fwrapv -pthread -g -Wall -Werror -fno-common -fexcess-precision=standard -fno-tree-vrp -ffunction-sections  -I./runtime  -D_FILE_OFFSET_BITS=64  -DCAMLDLLIMPORT= -DIN_CAML_RUNTIME  -o runtime/addrmap.b.o runtime/addrmap.c
```

This is work in progress; many Makefiles haven't been touched yet.
xavierleroy and others added 2 commits January 17, 2023 23:01
This saves the cost of spawning a shell just to write a message, cost that
is significant under Cygwin.  Suggested by @dra27.

This commit changes only the `@echo` introduced by the previous commit.
The same trick is applicable to other `@echo` occurrences, however.
@nojb nojb force-pushed the less-verbose-make branch from 868c09e to 228b288 Compare January 17, 2023 22:13
@nojb
Copy link
Copy Markdown
Contributor

nojb commented Jan 17, 2023

I rebased this patch on top of trunk, and:

  • Removed the extra whitespace between the command name and the target name (asked in Less verbose logs from make #11844 (comment));
  • Added a flag V=0 (default) and V=1 to control whether to use the new shorthand or the full command lines. Other variants can be added later; and
  • Added a Changes entry.

Planning to merge tomorrow...

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Jan 17, 2023 via email

@xavierleroy
Copy link
Copy Markdown
Contributor Author

Planning to merge tomorrow...

Thanks!

@nojb nojb merged commit 60260ec into ocaml:trunk Jan 18, 2023
@xavierleroy xavierleroy deleted the less-verbose-make branch January 20, 2023 19:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants