我想在makefile中的每个目标之前和之后运行一个命令。
这样的事情
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 $@ > $@
我想为j和k运行pre和post。理想情况下,我希望收到每个启动和停止任务的电子邮件。
答案 0 :(得分:2)
一种方法是修改makefile中的所有配方以调用某些命令。您可以将其放入变量中,因此它看起来不太粗糙:
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)
关于这一点的好处是你可以选择你想要的目标;也许他们中的一些人不需要它。缺点是如果命令失败,你就不会得到任何结果"电子邮件。
如果您真的想为每个目标执行此操作,那么您可以编写一个shell脚本来模拟shell的行为,同时还可以在运行命令时发送邮件。
$ 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
(注意这完全没有经过考验,但你得到了我希望的想法)。然后在您的makefile中,将SHELL
设置为该shell:
SHELL := mailshell
j:
long_running_command && echo $@ > $@
k: j
long_running_command2 && echo $@ > $@
我想你仍然可以通过将SHELL
设置为特定于目标的变量来进行选择,只针对那些你想要使用shell的目标。
这样做的一个缺点是,如果您有多行的食谱,您将分别收到每行的电子邮件。您可以通过启用.ONESHELL:
强制将整个配方传递到单个shell来解决此问题。但是,我认为这可能需要您的mailshell
工具更加复杂。
答案 1 :(得分:1)
如果每个配方只有一个命令,则可以通过更改运行命令的外壳的配置来实现。
让配置文件直接运行pre
命令并捕获EXIT
以便在其中运行after命令。
例如:
$ 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
但是,如果配方运行多个命令,这可能不是您想要的,因为每次运行之前和之后的代码。
$ make other
echo first
before
first
after
echo second
before
second
after
而且我不知道有一种方法(除了递归Makefile之外),可以使不同的配方使用不同的外壳程序,因此,如果您只想为多个配方设置之前/之后,这将不起作用。