Suppress and ignore output for Makefile?

MakefileGnu Make

Makefile Problem Overview


I know that the @ prefix suppresses output from a shell command in Makefiles, and also that the - prefix will ignore errors from a shell command. Is there a way to combine the two, i.e. a prefix that suppresses output and ignores errors? I don't think @- or -@ works.

Makefile Solutions


Solution 1 - Makefile

Actually, @- and -@ both do work, but will print a make: [target] Error 1 (ignored) warning.

Instead, you can use

@command || true

or, since : is shorthand for true in shell,

@command ||:

This often a better thing to do, because it avoid Make’s confusing warning that an error was ignored in an invisible command.

Consider the two most common cases where you might want to ignore the return value of a command:

  1. Part of the build is broken and you want to continue anyway, in which case you’ve got some learning to do. The build is broken and needs to be fixed, not bandaided in an unmaintainable way.
  2. A command returns a non-zero exit code even though it did exactly what you wanted, in which case you don’t really want Make to issue a warning.

For the second case, consider the example of grepping for warnings in the log file produced by a command. grep will return an error if it does not find a match, which is not what you want:

.PHONY: all one two three

all: at-warning at-success or-success or-warning

at-%: %.log
	@echo Making $@
	@-grep ^Warning $<

or-%: %.log
	@echo Making $@
	@grep ^Warning $< ||:

success.log:
	echo 'Success!' > $@

warning.log:
	echo 'Warning: foo' > $@

clean::
	rm -f {success,warning.log}

produces:

echo 'Warning: foo' > warning.log
Making at-warning
Warning: foo
Making at-success
make: [at-success] Error 1 (ignored)
Making or-success
Making or-warning
Warning: foo

Using @- produces a nonsensical ignored error warning when there is success, while || true handles both warnings and the absence of warnings without complaint.

Theoretically using || true is slower than using @-, but this overhead is unlikely to be a bottleneck in well-designed and -maintained build systems. The vast majority of the time should be spent building, or checking timestamps when there is nothing to build, not in running the thousands of quick commands whose return values all get ignored that would be necessary for this to have a measurable performance impact.

Solution 2 - Makefile

GNU make does allow you to combine both @ and -:

all:
        @-exit 1

Running this with gmake 3.81 produces this output:

> gmake: [all] Error 1 (ignored)

As you can see, the command is not echoed, and the error is ignored as expected.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndrew LeeView Question on Stackoverflow
Solution 1 - MakefileandrewdotnView Answer on Stackoverflow
Solution 2 - MakefileEric MelskiView Answer on Stackoverflow