2009-06-10 22 views
8

我想知道是否有一種方法可以在GNU make中實現trap,與BASH中內置的類似?如何在GNU make中捕獲錯誤和中斷?

如果用戶按CTRL-C,或者make本身失敗(非零退出),我想調用一個特定的目標或宏。

+0

+1的有趣的問題,即使你在做什麼聽起來像一個壞主意。 – finnw 2009-06-10 07:32:13

回答

2

不可以。GNU make的信號處理已經有很多不足之處了。從它的信號處理程序中,它調用如printf這樣的函數,這些函數在信號處理函數中不安全。我已經看到這個原因問題,例如.DELETE_ON_ERROR規則並不總是運行,如果stderr重定向到stdout

例如,在一個CentOS 7.4框:

  1. 創建以下Makefile

    .DELETE_ON_ERROR: 
    
    foo: 
         touch [email protected] 
         sleep 10 
    
  2. 打開它在vim並運行:make

  3. 雖然正在睡覺,擊中Ctrl - C

VIM /打印照片

Press ENTER or type command to continue 
touch foo 
sleep 10 
^C 
shell returned 130 

Interrupt: Press ENTER or type command to continue 

製作發送一箇中斷信號,但foo仍然存在。

+0

你有一些`.DELETE_ON_ERROR`不起作用的例子嗎?這是執行中的錯誤嗎? – 2017-10-03 06:33:12

+0

@HakanBaba添加「詳細信息」。 – andrewdotn 2017-10-03 19:59:47

1

不,據我所知,沒有這樣的功能。

1

make會產生返回碼。據我現在可以記住,它成功返回0,失敗2(請檢查文檔)。因此,例如,是否將make包裝在shell腳本中就足夠了?

+1

我可以做到這一點,但如果可能的話,儘量避免它,它是獨立的,我試圖*保持這種方式。 – Cyrus 2009-06-10 11:07:35

2

Make不支持它,但使用BASH技巧可以完成類似的操作。

default: complete 

complete: do_mount 
     echo "Do something here..." 

do_mount: 
     mkdir -p "$(MOUNTPOINT)" 
     (while ps -p $$PPID >/dev/null ; do \ 
       sleep 1 ; \ 
     done ; \ 
     unmount "$(MOUNTPOINT)" \ 
     ) & 
     mount "$(MOUNTSOURCE)" "$(MOUNTPOINT)" -o bind 

「unmount」將在「make」完成後運行。如果您試圖清理構建過程中可能發生的操作,但在「make」退出時沒有正常清理,通常這是一個令人滿意的解決方案。

5

在這個時候,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" 

這捕獲中斷,終止和任何非零退出代碼。

注意$(MAKE)所以cmdline覆蓋並使選項傳遞給submake。

在陷阱:

  • 明確的陷阱處理程序(使用 - )
  • 做清理
  • 退出非零退出狀態,因此,建立自動化工具報告構建失敗。

DELETE_ON_ERROR不爲目錄工作的,所以這是mktemp -d後清理鍵,例如

與有效的CMD更換<DO CLEANUP HERE>

+0

除了回聲中的嵌套引用,這當然是非法的,這似乎不起作用,至少對於我想要完成的。人們應該如何使用它?假設我的makefile只有一個具有睡眠和觸摸的目標,如@andrewdotn示例(忽略.DELETE_ON_ERROR),那麼如何修改它以使用此解決方法? – Davide 2017-10-06 18:44:16

3

@ kevinf的答案的簡化版本,這似乎不夠好基本情況:

run: 
    bash -c "trap 'docker-compose down' EXIT; docker-compose up --build" 

(這個例子是有原因的:docker-compose up不說

當 命令退出時,所有容器被停止。

但它不會rm停止的contai如docker run --rm會,所以你仍然可以看到他們與docker ps -a。)