我知道我可以make
隨時中斷進程,而不必再次重新編譯整個原始碼樹。據我所知,make
只有在尚未編譯的情況下才編譯目標,或者在上次編譯後修改了原始碼。
但如果我中斷make
,肯定會有一個或多個(取決於並發等級)半就緒的二進位檔案。下次我跑步時它們會做什麼make
?或者當我按Ctrl+C以避免部分編譯的二進位檔案時它是否完成當前目標?
答案1
簡單來說,您可以將其視為make
具有(可能很大)數量的步驟,其中每個步驟都採用多個文件作為輸入並創建一個文件作為輸出。
步驟可能是“編譯file.c
到”file.o
或“使用ld
連結main.o
到”。如果您使用中斷,則當前執行的步驟將終止,這將(或應該)刪除它正在處理的輸出檔案。通常不會留下任何“半就緒的二進位”。file.o
program
make
CtrlC
當您重新啟動時make
,它將查看所有輸入和輸出檔案的時間戳記並重新執行以下步驟:
- 輸入檔的時間戳比輸出檔更新
- 輸出文件不存在
這通常意味著,如果一個步驟需要很長時間才能運行(這在現代電腦上很少見,但大型程式的步驟在設計ld
時很容易花費很多分鐘),那麼停止並重新啟動將從頭開始該步驟。make
make
平均值的實際情況Makefile
比上述描述要複雜得多,但基本原理是相同的。
答案2
Ctrl+C導致 aSIGINT
被傳送到正在執行的進程。此訊號可以被進程捕獲。在 make 原始碼中,您可以在以下位置找到此訊號的陷阱commands.c
:
/* If we got a signal that means the user
wanted to kill make, remove pending targets. */
if (sig == SIGTERM || sig == SIGINT
... remove childrens ...
/* Delete any non-precious intermediate files that were made. */
remove_intermediates (1);
remove_intermediates()
是 的清理函數make
,請參閱此處的定義:
/* Remove all nonprecious intermediate files.
If SIG is nonzero, this was caused by a fatal signal,
meaning that a different message will be printed, and
the message will go to stderr rather than stdout. */
稍後在您看到的函數中,它們將被有效刪除:
status = unlink (f->name);
結論:
一般來說,不要害怕中斷編譯make
。如果它不是不可捕獲的訊號 ( SIGKILL, SIGSEGV, SIGSTOP
),它將清理中間文件。
答案3
當某些事情停止時make
(無論是 ctrl-C、關機,還是命令失敗),已經完成的工作會保留下來。重述時,make
一如既往:它找出還需要做什麼(因為文件已更改或make
永遠不需要處理它並不重要)並繼續工作。
上面的描述清楚地假設相關的Makefile
描述了正確執行的依賴關係和命令,所以所有需要(重新)製作的都是。