Practical Bazel: A Successful Build is a Quiet Build
Practical Bazel bazel bash
Published: 2021-09-04
Practical Bazel: A Successful Build is a Quiet Build

In Bazel, a successful build should be a quiet build. While build failures should, of course, print ample information to stderr to aide in troubleshooting, any custom Bazel code you write should not output progress information to stdout or stderr. Let Bazel be responsible for overall build progress reporting.

For genrule or bash-based targets, I’ll often implement this by capturing all output to a log file and only printing the log file if the target fails. For example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/bash
#
# This is a bash build script that may be invoked in something like
# ctx.actions.run() in a custom bazel rule

set -euo pipefail

# Perform all cleanup
cleanup() {
  # Output the build log on failures
  if [ "$1" != "0" ]; then
    if [[ -v LOG_FILE ]]; then
      if [[ -r $LOG_FILE ]]; then
        echo "Build log:" 1>&2
        cat $LOG_FILE 1>&2
      fi
    fi
  fi
  if [[ -v TMP_DIR ]]; then
    rm -rf $TMP_DIR
  fi
}
trap 'cleanup $?' EXIT

# Ensure all build steps log stdout and stderr to LOG_FILE
TMP_DIR=$(mktemp -d)
LOG_FILE=$TMP_DIR/build.log

# Perform build steps
build_step1 >> $LOG_FILE 2>&1
build_step2 >> $LOG_FILE 2>&1
...