简体   繁体   English

在 makefile 中的每个目标之前和之后运行

[英]run before and after each target in a makefile

I would like to run a command before and after each target in a makefile.我想在 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.我想为 j 和 k 运行 pre 和 post。 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.一种方法是修改 makefile 中的所有配方以调用某些命令。 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.如果您真的想为每个目标都这样做,那么您可以编写一个 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

(note this is totally untested but you get the idea I hope). (请注意,这完全未经测试,但您会明白我希望的想法)。 Then in your makefile, set SHELL to that shell:然后在您的 makefile 中,将SHELL设置为该 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.我想您仍然可以通过将SHELL设置为特定于目标的变量来进行选择,仅针对您想要使用 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.您可以通过启用.ONESHELL:来强制将整个配方传递给单个 shell 来解决此问题。 However, I believe that this may require your mailshell tool to be more sophisticated.但是,我相信这可能需要您的mailshell工具更加复杂。

If you only have one command per recipe, you can do this by changing the configuration for the shell the commands are run in.如果每个配方只有一个命令,则可以通过更改运行命令的 shell 的配置来实现。

Have the config file run the pre commands directly and trap EXIT to run the after commands in.让配置文件直接运行pre命令并捕获EXIT以运行 after 命令。

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.而且我不知道有什么方法(在递归 Makefile 之外)让不同的配方使用不同的外壳,所以如果你只想为几个配方设置之前/之后,这将不起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM