【问题标题】:GNU make: clean target depends on includesGNU make:干净的目标取决于包含
【发布时间】:2012-10-03 03:33:30
【问题描述】:

我正在使用 gmake 和 gcc -MM 跟踪标头依赖项,遵循 the manual。该机制依赖于 makefile include 指令来导入计算的依赖项。

因为.d 文件包含在makefile 中,所以它们必须存在才能生成任何目标,包括clean。因此,在clean 能够做正确的事情之前,必须生成依赖关系,如果构建失败,那么clean 只会变得更加混乱。

除了clean,它还想在构建任何目标之前制作所有依赖项。

此外,如果将任何文件更改为包含不存在的文件,则依赖关系解析会中断,并且不会生成任何内容。

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

用通配符替换include 的替换模式以包含所有预先存在的依赖文件可以解决一些问题,但它仍然无法清除损坏的依赖文件,并且永远不会删除过时的依赖文件。有更好的解决方案吗?手册中的示例真的是为了实际使用吗?

【问题讨论】:

    标签: makefile dependencies gnu-make


    【解决方案1】:

    只是不提供生成.d 文件的规则。 GNU Make 的维护者 Paul Smith 的"Advanced Auto-Dependency Generation" 很好地解释了为什么它不是那么好(包括你的情况)。

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

    CPPFLAGS += -MMD -MP
    
    %.o: %.c
        $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $<
    
    -include $(OBJS:.o=.d)
    

    另见我之前的相关回答:

    【讨论】:

    • @Potatoswatter,没有。在这种情况下,.d 文件的生成与实际编译相结合,GCC 在一次调用中执行这些步骤。
    • 对不起,我不应该在阅读更多内容之前发言。看起来-MP 解决了 sehe 解决后的剩余问题。但我更喜欢将对象保存在另一个目录中,并且可能希望对依赖文件进行更多处理以支持预编译的头文件。
    • @Potatoswatter,我以前从未使用过 PCH,但是为对象和源拆分目录并不是什么大问题。只需在目标和先决条件前加上路径:$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c。依赖文件将放置在目标文件附近,$(OBJ_DIR)。
    • 这个令人赞叹的方法的一个调整:如果有人删除f.d,然后编辑f.h,那么make将不会重新编译f.o(因为没有人告诉它f.o: f.h )。在这种情况下,您可以让make 删除任何没有相应.d 文件的.o 文件。将此添加到 makefile 的末尾:${OBJS:.o=.d}: ; rm ${@:.d=.o}
    • @Daniel 并行编程是您需要牢牢把握正在发生的事情的一个领域。这是无可替代的。
    【解决方案2】:

    解决方法是使用Conditional Syntax:

    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

    【讨论】:

      【解决方案3】:

      我平时的模式是这样的

      all: target
      target: .depends
      
      ## [snip build rules]
      
      .depends:
           gcc -MM $(CPPFLAGS) .... > $@
      
      -include .depends
      

      注意-include 而不是include。基本上,它有条件地包括:即 iff 文件存在

      查看文档:http://www.gnu.org/software/make/manual/make.html#Include

      【讨论】:

      • +1:添加减号解决了眼前的问题。谢谢,现在我指出了正确的方向……
      • 现在没有必要制定规则来生成依赖项。依赖关系最好作为编译的副产品生成。对于第一个编译依赖项是不必要的,因为每个源都需要构建。仅对于后续构建依赖项是必需的,并且它们是由先前构建生成的。
      • @MaximYegorushkin 我每天都在学习。好的。 (我也读过其他答案:))
      猜你喜欢
      • 2011-02-07
      • 2012-12-13
      • 2011-03-05
      • 2015-07-31
      • 2011-09-20
      • 2013-12-19
      • 1970-01-01
      • 2014-07-08
      • 1970-01-01
      相关资源
      最近更新 更多