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 > $@