I would like to run a command before and after each target in a makefile.
so something like this
pre:
@echo pre
@echo running | mailx -s "Start {target}" user@foo.com
post:
@echo post
@echo post | mailx -s "Finish {target}" user@foo.com
j:
long_running_command && echo $@ > $@
k: j
long_running_command2 && echo $@ > $@
I would like to run pre and post for j and k. Ideally, I would like to get an email for each task that starts and stops.
One way to do it is to modify all the recipes in your makefile to invoke some command. You can put it into a variable so it doesn't look too gross:
START = mailto --subject 'Started target $@' me@my.host
END = mailto --subject 'Finished target $@' me@my.host
j:
$(START)
long_running_command && echo $@ > $@
$(END)
k: j
$(START)
long_running_command2 && echo $@ > $@
$(END)
The nice thing about this is you can pick and choose which targets you want it for; maybe some of them don't need it. The disadvantage is if the command fails you won't get any "end" email at all.
If you really want to do it for every single target, then you can write a shell script that mimics the shell's behavior but also sends mail, while running the command.
$ cat mailshell
#!/bin/sh
# get rid of the -c flag
shift
mailto --subject "started $*" me@my.host
/bin/sh -c "$@"
r=$?
mailto --subject "ended $* with exit code $r" me@my.host
exit $r
(note this is totally untested but you get the idea I hope). Then in your makefile, set SHELL
to that shell:
SHELL := mailshell
j:
long_running_command && echo $@ > $@
k: j
long_running_command2 && echo $@ > $@
I guess you could still pick and choose by setting SHELL
as a target-specific variable only for those targets you wanted to use the shell.
One downside of this is that if you have recipes that have multiple lines you'll get an email for each line individually. You can work around this by enabling .ONESHELL:
to force the entire recipe to be passed to a single shell. However, I believe that this may require your mailshell
tool to be more sophisticated.
If you only have one command per recipe, you can do this by changing the configuration for the shell the commands are run in.
Have the config file run the pre
commands directly and trap EXIT
to run the after commands in.
For example:
$ cat Makefile
SHELL := BASH_ENV=/dev/fd/3 3<<<'echo before; trap "echo after" EXIT' /bin/bash
default:
echo default
other:
echo first
echo second
$ make default
echo default
before
default
after
However this may not be what you want if a recipe runs several commands, as the before and after code will run each time.
$ make other
echo first
before
first
after
echo second
before
second
after
And I don't know of a way (outside of recursive Makefiles) to have different recipes use different shells, so this won't work if you only want to set before/after for several recipes.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.