我使用gmake和gcc-MM
跟踪头依赖关系,遵循手册。该机制依赖于makefileinclude
指令来导入计算出的依赖项。
因为.d
文件包含在makefile中,所以对于要生成的任何目标(包括clean
),它们都必须存在。因此,在clean
能够做正确的事情之前,必须生成依赖项,如果构建失败,那么clean
就会造成更多的混乱。
除了clean
之外,它还希望在构建任何目标之前创建所有依赖项。
此外,如果任何文件被更改为包含一个不存在的文件,那么依赖关系解析就会中断,任何东西都不会生成。
如果一个头被删除,那么包含的现有依赖文件仍然将其命名为目标,并且在删除有问题的依赖文件之前,任何东西都不会生成…这是用clean
无法完成的。
用通配符替换include
的替换模式以包括所有先前存在的依赖项文件可以解决一些问题,但它仍然不能清除已损坏的依赖项,而且陈旧的依赖项文件永远不会被删除。有没有更好的解决办法?手册的例子真的是为了真正的使用吗?
只是不要提供生成.d
文件的规则。GNU Make的维护者Paul Smith的“Advanced Auto-Dependency Generation”中有一个很好的解释(包括您的案例)。
简而言之,以下模式在所有情况下都适用:
CPPFLAGS += -MMD -MP
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $<
-include $(OBJS:.o=.d)
也见我之前的相关回答:
解决方案是使用条件语法:
ifneq ($(MAKECMDGOALS), clean)
-include $(notdir $(SOURCES:.cpp=.d))
endif
这使得clean目标不调用*.d
目标,因为当您运行make clean
时,*.d
文件不会包含在makefile中。
参考:https://www.gnu.org/software/make/manual/html_node/goals.html
我通常的模式是
all: target
target: .depends
## [snip build rules]
.depends:
gcc -MM $(CPPFLAGS) .... > $@
-include .depends
注意-include
而不是include
。基本包括有条件的:即是否存在文件
请参阅文档:http://www.gnu.org/software/make/manual/make.html#include