[英]Makefile should bail out if a target fails
我有以下格式的文件-
all: target_1 target_2 target_3
target_1:
TASK_A1 | tee ta.log
TASK_A2 | tee -a ta.log
target_2:
TASK_B | tee tb.log
target_3:
TASK_C | tee tc.log
TASK_A以這種格式生成日志記錄輸出-
<some lines of output>
Errors: 0, Warnings: 12
<some more lines of output>
Errors: 5, Warnings: 10
當我完成全部操作時 ,理想情況下,如果target_1失敗,則makefile應該可以退出,但它繼續到達target_2。
我能想到的一種可能的解決方案是從每個目標的日志文件中grep“ Errors:0”,然后檢查grep的返回值(如果grep返回非零值,則退出)。 我發現這並不是一個非常有效的解決方案,因為我需要針對每個目標執行上述步驟。
有什么更有效,更智能的方法可以解決此問題?
除了對單個任務一無所知,除了處理“錯誤:0”的輸出外,您無能為力。 但是,您可以采用以下DRY原理:
runtask = $(1) | tee -a $(2) | awk '{ print; if (/Errors: 0/) y=1; } END { if (y) { exit 0 } else { exit 1 } }'
all: target_1 target_2 target_3
target_1:
@$(call runtask, TASK_A1, ta.log)
@$(call runtask, TASK_A2, ta.log)
target_2:
@$(call runtask, TASK_B, tb.log)
target_3:
@$(call runtask, TASK_C, tc.log)
至少這樣,如果您需要修改搜索模式,則不必遍歷每一行。
因此,首先,如果target_2
依賴於target_1
,則應在makefile中明確指定:
target_2: target_1
否則,如果有人使用-j
構建,則無論target_1
是否成功, target_2
都可能會運行。
接下來,如果目標之一失敗,則希望make失敗。 如果配方行的返回為假(非零),則Make將終止。 我假設TASK_A1
和朋友如果生成錯誤,則返回false(否則,本篇文章的其余部分將TASK_A1
)。
不幸的是,您有一個使事情復雜化的管道-即,配方的返回值將是tee
的返回值,而不是TASK_A1
。 見下文:
bash> false
bash> echo $?
1
bash> false | tee blah
bash> echo $?
0
在這種情況下, tee blah
返回true( 0
),所以$?
(返回碼)為0。幸運的是,您可以使用PIPESTATUS
從管道的第一部分獲取返回碼。
bash> false | tee blah; [ ${PIPESTATUS[0]} -eq 0 ]
bash> echo $?
1
bash> true | tee blah; [ ${PIPESTATUS[0]} -eq 0 ]
bash> echo $?
0
所以...總之,您可以執行以下操作:
all: target_3
target_1:
TASK_A1 | tee ta.log; [ $${PIPESTATUS[0]} -eq 0 ]
TASK_A2 | tee -a ta.log; [ $${PIPESTATUS[0]} -eq 0 ]
target_2: target1
TASK_B | tee tb.log; [ $${PIPESTATUS[0]} -eq 0 ]
target_3: target2
TASK_C | tee tc.log; [ $${PIPESTATUS[0]} -eq 0 ]
一旦make命中失敗的任務,它就會失敗。 請注意,在此解決方案中,如果TASK_A1
失敗,則TASK_A2
將不會運行。 我不確定這是否是您想要的。 如果您希望兩者都運行,則可以將target1
更改為:
target1:
( TASK_A1; TASK_A2 ) | tee ta.log; [ $${PIPESTATUS[0]} -eq 0 ]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.