52
votes

I'm wondering how I can avoid some echo in a Makefile :

clean:
    rm -fr *.o

this rule will print:

$>make clean   
rm -fr *.o

$>

How can I avoid that?

6

6 Answers

82
votes

To start with: the actual command must be on the next line (or at least that is the case with GNU Make, it might be different with other Make's - I'm not sure of that)

clean:
    rm -rf *.o

(note, you need a TAB before rm -rf *.o as in every rule)

Making it silent can be done by prefixing a @:

so your makefile becomes

clean:
    @rm -rf *.o

If there are no *.o files to delete, you might still end up with an error message. To suppress these, add the following

clean:
    -@rm -rf *.o 2>/dev/null || true
  • 2>/dev/null pipes any error message to /dev/null - so you won't see any errors
  • the - in front of the command makes sure that make ignores a non-zero return code
33
votes

In fact I was looking for something else, adding this line to the Makefile :

.SILENT:clean

while execute every step of the "clean" target silently.

Until someone point some drawback to this, I use this as my favourite solution!

27
votes

I'm responding to this ancient topic because it comes up high in search and the answers are confusing. To do just what the user wants,all that is needed is:

clean:
    @rm -f *.o

The @ means that make will not echo that command. The -f argument to rm tells rm to ignore any errors, like there being no *.o files, and to return success always.

I removed the -r from the OPs example, because it means recursive and here we are just rming .o files, nothing to recurse.

There's no need for the 2>&1 >/dev/null because with the -f there will be no errors printed.

.SILENT: clean

works in place of the @, but it isn't at the same place in the Makefile as the command that it affects, so someone maintaining the project later might be confused. That's why @ is preferred. It is better locality of reference.

10
votes

If you put an @ in front of the command, it doesn't echo onto the shell. Try changing rm to @rm. (Reference)

4
votes

From the manual: .SILENT is essentially obsolete since @ is more flexible.

Much worse is that make prints far too much information. Warning/error/private messages are buried in the output. On the other hand -s (.SILENT) suppresses just anything. Especially the "nothing to be done" and "up to date" messages can be a pain. There is no option to suppress them. You have to filter them out actively or use something like colormake. Here is a solution for grep:

make | egrep -hiv 'nothing to be done|up to date'

But the output will have line numbers. The Perl solution is therefore better, because it suppresses line numbers and flushes stdout immediately:

make | perl -ne '$|=1; print unless /nothing to be done|up to date/i'

Make's a flawed tool. "What’s Wrong With GNU make?" explains this better than I can.

0
votes

There's a great article on using .SILENT that explains how to conditionally activate it.

I have used that information to put this in my Makefile:

# Use `make V=1` to print commands.
$(V).SILENT:

# Example rule, only the @echo needs to be added to existing rules
*.o: %.c
    @echo " [CC]  $<"
    gcc ...

What this does is if you run make normally, normal output is silenced and instead the echo commands work:

$ make
 [CC]  test.c
 [CC]  test2.c

But it allows you to debug problems by passing the V=1 parameter, which still shows the [CC] messages as it helps break up the output, but the traditional Makefile output is also visible:

$ make V=1
 [CC]  test.c
gcc ...
 [CC]  test2.c
gcc ...