假设我有一个 Makefile,它有两个“主要”目标:foo.o
和clean
。前一个有创建文件的方法foo.o
。后一种删除所有临时文件。
为了消除手动指定依赖项的需要foo.o
,我的目标foo.d
是有效的 makefile,以 format 指定依赖项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
就会被包含在内,甚至被制定。
如何阻止 make 包括制定目标的foo.d
时间? clean
(或者,如何仅在foo.o
制作时包含它?)
该解决方案可以使用 GNU Make 的功能。
答案1
解决方案非常简单,但会导致 Makefile 代码有些不可读。
首先,我们必须知道该include
指令尝试包含该文件,如果它不存在,则会失败。还有-include
(或sinclude
),如果文件不存在,则根本不包含该文件。但这不是我们想要的,因为如果可能的话,它仍然会尝试重新创建包含的 makefile。
我们可以通过两种方式避免这种情况:要么通过更改 include 指令参数,使 Makefile 认为它无法生成该包含文件(例如相对路径与绝对路径等),要么在文件不包含该文件时省略该参数。存在。这可以通过多种方式完成:
-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 …