6

我正在阅读使用 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 的人也可以想到这些,但出于某种原因,他们选择了更复杂的设置。我只是想了解他们的推理,所以我可以在飞行中做这些。

4

3 回答 3

12

实际上,即使是规则本身也没有必要。在Paul D. Smith 撰写的Advanced Auto-Dependency Generation文章中,对生成 Make 样式依赖项的不同方法进行了很好的概述。

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

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

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

UPD。

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

于 2012-05-22T10:26:47.360 回答
3

一个更简单的解决方案是完全摆脱 sed 调用,因为 gcc 可以直接完成您需要的一切:

%.d: %.c
        $(CC) -M $(CPPFLAGS) -MF $@ $< -MT "$*.o $@"
于 2012-05-22T01:27:23.327 回答
3

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

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

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

于 2012-06-01T19:48:51.837 回答