GNU Make。为什么这种复杂的语法生成依赖?

时间:2012-05-22 00:37:15

标签: makefile gnu-make

我正在阅读使用GNU Make管理项目,并在第2.7章 - 自动依赖关系生成中找到了这个例子。作者从GNU手册中说出了他们:

%.d: %c
        $(CC) -M $(CPPFLAGS $< > $@.$$$$; \
              sed s',\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
              rm -f $@.$$$$

但是,我能够对此做同样的事情(注意sed):

-include $(subst .c,.d,$(SOURCES))

%.d: %.c
          @$(CC) -M $(CPPFLAGS) $<  | sed 's|:| $*.d : |'  > $@;

所有这些行都是生成依赖项,然后添加*.d名称。他们不得不改变第一行:

  foo.o: bar.h foo.h fubar.h

要       foo.o foo.d:bar.h foo.h fubar.h

我更简单,似乎工作得很好,但我认为GNU人员有sed命令的原因。另外:

  • 为什么要将文件重定向到sed?为什么不简单地将其作为公共线参数
  • 为什么不完全跳过中间文件?

我知道GNU的人们也可以想到这些,但出于某种原因,选择了更复杂的设置。我只是想了解他们的推理,所以我可以动态地做这些。

3 个答案:

答案 0 :(得分:12)

实际上连规则本身都没有必要。在Paul D. Smith撰写的Advanced Auto-Dependency Generation文章中,可以很好地概述生成Make-style依赖关系的不同方法。

毕竟,以下规则应该足够(在使用GCC的情况下):

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

-include $(SOURCES:.c=.d)

UPD。

我之前也有answered类似的问题。它包含-MMD -MP选项的解释(引用GCC手册)。

答案 1 :(得分:3)

解决问题:Why do a redirect of the file into sed?如果您这样做:

@$(CC) -M $(CPPFLAGS) $<  | sed 's|:| $*.d : |'  > $@;

并且编译失败(错误输出并且不生成输出),您将创建一个空目标文件。再次运行make时,它将看到新创建的空文件,而不是重新生成它,从而导致构建错误。使用中间文件是避免意外创建空目标的常见防御策略。

答案 2 :(得分:2)

更简单的解决方案是完全摆脱sed调用,因为gcc可以直接完成你需要的所有事情:

%.d: %.c
        $(CC) -M $(CPPFLAGS) -MF $@ $< -MT "$*.o $@"