0

When working with make/cmake scripts you often have to use VERBOSE=1 and look at all the commands run. This is what I do a lot, and its utterly straining for someone just looking for the origin of commands.

We often have 30 lines of word wrapping args, and the command origin is obfuscated.

Is it possible to colorize commands in general so they stand out? I need them to stand out from their arguments is all.

I can use either bash or zsh or any shell which supports this. I just need to know if its possible to do this in general.

1
  • Sounds like it's the output of make or cmake or the commands they invoke to output those command lines before passing them to the shell that you want to colourise. Apr 2, 2023 at 7:05

1 Answer 1

0

I like to have the words 'warning' and 'error' colored so I do this in my shell startup file

make(){
    local subst
    subst+="s/error/\x1b[1;31m&\x1b[0m/g; "
    subst+="s/warning/\x1b[1;33m&\x1b[0m/g; "
    subst+="s/undefined reference/\x1b[1;35m&\x1b[0m/g; "
    # For debugging
    # echo "subst = '$subst'"
    (
        set -o pipefail
        CLICOLOR_FORCE=yes_please command make "$@" 2>&1 | sed --unbuffered "${subst}"
    )
}

With the right regexes instead of my error, warning, and undefined reference, you can probably get a pretty decent highlighting of your output going on.

Here are some details.

  • You have to use \x1b in sed because it doesn't understand \033.

  • & expands to the part of the line that was matched.

  • --unbuffered is necessary otherwise your output will either come out in large chunks or in a single chunk once the whole make command finishes.

  • command avoids recursively calling the make shell function.

  • "@" forwards the arguments given to the make shell function to command make. This will include VERBOSE=1 and anything else.

  • CLICOLOR_FORCE is to have the colored output from the Makefile that CMake generates which normally gets turned off if when the output is not a TTY (ex: a pipe).

  • The subshell with set -o pipefail is because with a pipe, you normally get the return code of the last command in the pipeline. Activating the option pipefail will cause the return code of the pipeline to be 0 if all commands returned 0, or the return code of the right-most command that returned a non-zero code (i.e. (exit 8) | true | (exit 9) | true would have a return code of 9). The reason for the subshell is so that the set -o pipefail won't affect the user's shell.

Have a look at https://en.wikipedia.org/wiki/ANSI_escape_code#Colors for the color codes.

Normally, the output of a Makefile generated by CMake will have color for the [ 42%] Building C object source_file.c.o and such but this can be changed in the CMakeLists.txt with set(CMAKE_COLOR_MAKEFILE [ON|OFF]).

Color also goes away if the output of make is not a tty (like make | cat. You can force the color output in that case by setting the environment variable CLICOLOR_FORCE=yes_please (or any non-empty value). However if CMAKE_COLOR_MAKEFILE is off, `CLICOLOR_FORCE will have no effect.

If the project is not yours and CMAKE_COLOR_MAKEFILE is off, then you can add some substitutions to the list to compensate.

Also note that CLICOLOR_FORCE is a variable that is inspected by other commands so putting export CLICOLOR_FORCE=yessir in your shell startup file will affect more things that you may want. I don't do it.

Reference for CMAKE_COLOR_MAKEFILE: https://cmake.org/cmake/help/latest/variable/CMAKE_COLOR_MAKEFILE.html

1
  • Note that your escape codes make assumptions that the output is connected to a terminal that recognises the ANSI escapes. You'll get some other behaviour when connected to a different kind of terminal, or something other than a terminal (a pipe, perhaps). It's generally better to use tput to find the appropriate control (if any) for the actual system in a portable manner. May 20, 2023 at 10:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .