I'm wondering if there's a way to implement trap
in GNU make
, similar to that built into BASH
?
If the user presses CTRL-C
, or if make
itself fails (non-zero exit), I'd like to call a particular target or macro.
To ignore errors in a recipe line, write a ' - ' at the beginning of the line's text (after the initial tab). The ' - ' is discarded before the line is passed to the shell for execution.
The variable $@ represents the name of the target and $< represents the first prerequisite required to create the output file.
GNU Make is a tool which controls the generation of executables and other non-source files of a program from the program's source files. Make gets its knowledge of how to build your program from a file called the makefile, which lists each of the non-source files and how to compute it from other files.
1 Answer. You can execute a command in the shell from the Makefile by using the $(shell command) syntax. If for instance you would want to exit status of the ls command in bash you would type: ls --qwfpgjl > /dev/null 2>&1 ; echo $?
At this point in time, GNU make doesn't have native support.
There is a reliable workaround however:
.PHONY: internal-target external-target
external-target:
bash -c "trap 'trap - SIGINT SIGTERM ERR; <DO CLEANUP HERE>; exit 1' SIGINT SIGTERM ERR; $(MAKE) internal-target"
internal-target:
echo "doing stuff here"
This catches interruptions, terminations AND any non-zero exit codes.
Note the $(MAKE)
so cmdline overrides and make options get passed to submake.
On trap:
DELETE_ON_ERROR does NOT work for directories, so this is key for cleaning up after mktemp -d
, for example
Replace <DO CLEANUP HERE>
with valid CMD.
A simplified version of @kevinf’s answer which seems good enough for basic cases:
run:
bash -c "trap 'docker-compose down' EXIT; docker-compose up --build"
(This example is for a reason: docker-compose up
does say
When the command exits, all containers are stopped.
but it does not rm
the stopped containers like docker run --rm
would, so you can still see them with docker ps -a
.)
No. GNU make’s signal handling already leaves a lot to be desired. From within its signal handler, it calls functions like printf
that are not safe to be called from within a signal handler. I have seen this cause problems, for example .DELETE_ON_ERROR
rules don’t always run if stderr
is redirected to stdout
.
For example, on a CentOS 7.4 box:
Create the following Makefile
:
.DELETE_ON_ERROR:
foo:
touch $@
sleep 10
Open it in vim
and run :make
,
Vim/make prints
Press ENTER or type command to continue
touch foo
sleep 10
^C
shell returned 130
Interrupt: Press ENTER or type command to continue
Make was sent an interrupt signal, but foo
still exists.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With