提问者:小点点

GNU make:清除目标依赖于includes


我使用gmake和gcc-MM跟踪头依赖关系,遵循手册。该机制依赖于makefileinclude指令来导入计算出的依赖项。

因为.d文件包含在makefile中,所以对于要生成的任何目标(包括clean),它们都必须存在。因此,在clean能够做正确的事情之前,必须生成依赖项,如果构建失败,那么clean就会造成更多的混乱。

除了clean之外,它还希望在构建任何目标之前创建所有依赖项。

此外,如果任何文件被更改为包含一个不存在的文件,那么依赖关系解析就会中断,任何东西都不会生成。

如果一个头被删除,那么包含的现有依赖文件仍然将其命名为目标,并且在删除有问题的依赖文件之前,任何东西都不会生成…这是用clean无法完成的。

用通配符替换include的替换模式以包括所有先前存在的依赖项文件可以解决一些问题,但它仍然不能清除已损坏的依赖项,而且陈旧的依赖项文件永远不会被删除。有没有更好的解决办法?手册的例子真的是为了真正的使用吗?


共3个答案

匿名用户

只是不要提供生成.d文件的规则。GNU Make的维护者Paul Smith的“Advanced Auto-Dependency Generation”中有一个很好的解释(包括您的案例)。

简而言之,以下模式在所有情况下都适用:

CPPFLAGS += -MMD -MP

%.o: %.c
    $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $<

-include $(OBJS:.o=.d)

也见我之前的相关回答:

  • GNU make。为什么使用这种复杂的语法来生成依赖项?
  • Makefile改进,依赖项生成不起作用

匿名用户

解决方案是使用条件语法:

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