Compiling

僅在需要時重新製作包含 makefile

  • May 13, 2022

假設我有一個 Makefile,它有兩個“主要”目標:foo.oclean. 前者有一個創建foo.o文件的方法。後者刪除所有臨時文件。

為了消除foo.o手動指定依賴項的需要,我的目標foo.d是有效的 makefile,指定格式的依賴項foo.o foo.d : dep1 dep2 depn。此依賴文件包含在 makefile 中。

生成文件如下所示:

;; This buffer is for text that is not saved, and for Lisp evaluation.
;; To create a file, visit it with C-x C-f and enter text in its buffer.

foo.o: foo.c
   cc -c -o $@ $<

foo.d: foo.c
   sh deps.sh $< > $@

include foo.d

.PHONY: clean
clean:
   rm …

當我想製作foo.o時,一切正常:foo.d得到(重新)製作,它被包含foo.o並被製作。問題是當我想製作clean目標時,foo.d被包含,甚至被製作。

如何防止製作包括製作目標的foo.d時間clean?(或者,如何僅在foo.o製作時包含它?)

該解決方案可以使用 GNU Make 的功能。

解決方案非常簡單,但會導致 Makefile 程式碼有些不可讀。

首先,我們必須知道include指令試圖包含該文件,如果它不存在,則失敗。如果文件不存在,也有-include(或sinclude)不包含該文件。但這不是我們想要的,因為它仍然會嘗試重新製作包含的 makefile,如果可能的話。

我們可以通過兩種方式避免這種情況:要麼以 Makefile 認為它無法生成包含文件的方式更改 include 指令參數(例如相對路徑與絕對路徑等),要麼在文件不包含時省略參數存在。這可以通過多種方式完成:

-include $(wildcard foo.d*)

但這有一個問題:它也匹配其他文件。所以我們可以這樣寫:

-include $(filter foo.d,$(wildcard foo.d*))

甚至這個:

-include $(filter foo.d,$(wildcard *))

而我們又犯了一個問題:foo.d沒有得到。這可以通過將其添加為的另一個目標來解決foo.o

foo.o: foo.c foo.d

或將其添加為命令:

foo.o: foo.c
   $(MAKE) foo.d
   cc …

或直接,不呼叫make

foo.o: foo.c
   sh script.sh …
   cc …

引用自:https://unix.stackexchange.com/questions/702388