How to get exit status of a shell command used in GNU Makefile?

Solution 1:

In the makefile-:

mycommand || (echo "mycommand failed $$?"; exit 1)

Each line in the makefile action invokes a new shell - the error must be checked in the action line where the command failed.

If mycommand fails the logic branches to the echo statement then exits.

Solution 2:

Here are a couple of other approaches:


shell & .SHELLSTATUS

some_recipe:
    @echo $(shell echo 'doing stuff'; exit 123)
    @echo 'command exited with $(.SHELLSTATUS)'
    @exit $(.SHELLSTATUS)

Output:

$ make some_recipe

doing stuff
command exited with 123      
make: *** [Makefile:4: some_recipe] Error 123

It does have the caveat that the shell command output isn't streamed, so you just end up with a dump to stdout when it finishes.


$?

some_recipe:
    @echo 'doing stuff'; sh -c 'exit 123';\
    EXIT_CODE=$$?;\
    echo "command exited with $$EXIT_CODE";\
    exit $$EXIT_CODE

Or, a bit easier to read:

.ONESHELL:

some_recipe:
    @echo 'doing stuff'; sh -c 'exit 123'
    @EXIT_CODE=$$?
    @echo "command exited with $$EXIT_CODE"
    @exit $$EXIT_CODE

Output:

$ make some_recipe

doing stuff                  
command exited with 123      
make: *** [Makefile:2: some_recipe] Error 123

It's essentially one string of commands, executed in the same shell.

Solution 3:

If all you want is for the make to be aborted iff the tool exits with a nonzero status, make will already do that by default.

Example Makefile:

a: b
    @echo making $@
b:
    @echo making $@
    @false
    @echo already failed

. This is what happens with my make:

$ make
making b
make: *** [Makefile:6: b] Error 1

Make sure partially or wholly created targets are removed in case you fail. For instance, this

a: b
    @gena $+ > $@
b:
    @genb > $@

is incorrect: if on the first try, genb fails, it will probably leave an incorrect b, which, on the second try, make will assume is correct. So you need to do something like

a: b
    @gena $+ > $@ || { rm $@; exit 1; }
b:
    @genb > $@