如何在GNU make中捕获错误和中断?

Cyr*_*rus 14 signals makefile gnu-make bash-trap

我想知道是否有一种方法可以trap在GNU中实现make,类似于内置的BASH

如果用户按下CTRL-C,或者make自身失败(非零退出),我想调用特定目标或宏.

kev*_*inf 13

此时,GNU make没有本机支持.

但是有一个可靠的解决方法:

.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"
Run Code Online (Sandbox Code Playgroud)

这可以捕获中断,终止和任何非零退出代码.

请注意,$(MAKE)所以cmdline覆盖并将选项传递给submake.

关于陷阱:

  • 清除陷阱处理程序(带 - )
  • 做清理工作
  • 以非零退出状态退出,因此构建自动化工具会报告失败的构建.

DELETE_ON_ERROR不适用于目录,因此这是清理后的关键mktemp -d,例如

替换<DO CLEANUP HERE>为有效的CMD.


Jes*_*ick 11

@ kevinf答案的简化版本,对于基本案例来说似乎已经足够了:

run:
    bash -c "trap 'docker-compose down' EXIT; docker-compose up --build"
Run Code Online (Sandbox Code Playgroud)

(这个例子是有原因的:docker-compose up确实如此

命令退出时,所有容器都将停止.

但它不会rmdocker run --rm已经停止的容器一样,所以你仍然可以看到它们docker ps -a.)


and*_*otn 4

不。GNU make\xe2\x80\x99s 信号处理已经有很多不足之处。从其信号处理程序内部,它调用类似printf从信号处理程序内部调用不安全的函数。我已经看到这会导致问题,例如.DELETE_ON_ERROR规则 don\xe2\x80\x99t 如果重定向stderrstdout.

\n\n

例如,在 CentOS 7.4 机器上:

\n\n
    \n
  1. 创建以下内容Makefile

    \n\n
    .DELETE_ON_ERROR:\n\nfoo:\n        touch $@\n        sleep 10\n
    Run Code Online (Sandbox Code Playgroud)
  2. \n
  3. 打开它vim并运行:make

  4. \n
  5. 当它睡觉的时候,点击Ctrl-C
  6. \n
\n\n

Vim/制作打印

\n\n
Press ENTER or type command to continue\ntouch foo\nsleep 10\n^C\nshell returned 130\n\nInterrupt: Press ENTER or type command to continue\n
Run Code Online (Sandbox Code Playgroud)\n\n

Make被发送了一个中断信号,但foo仍然存在。

\n