Makefile GNU制造。为什么使用这种复杂的语法来生成依赖项?
我正在阅读使用GNU Make管理项目,并在第2.7章-自动依赖项生成中找到了这个示例。作者在GNU手册中提到了他们的观点:Makefile GNU制造。为什么使用这种复杂的语法来生成依赖项?,makefile,gnu-make,Makefile,Gnu Make,我正在阅读使用GNU Make管理项目,并在第2.7章-自动依赖项生成中找到了这个示例。作者在GNU手册中提到了他们的观点: %.d: %c $(CC) -M $(CPPFLAGS $< > $@.$$$$; \ sed s',\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ 所有这些行都是生成依赖项,然后添加*.d名称。他们不
%.d: %c
$(CC) -M $(CPPFLAGS $< > $@.$$$$; \
sed s',\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
所有这些行都是生成依赖项,然后添加*.d
名称。他们不得不将第一行更改为:
foo.o: bar.h foo.h fubar.h
到
foo.o foo.d:bar.h foo.h fubar.h
我的命令更简单,而且似乎工作得很好,但我认为GNU人员使用sed
命令是有原因的。此外:
- 为什么要将文件重定向到
?为什么不干脆把它作为一个公共行参数呢sed
- 为什么不完全跳过中间文件李>
我知道GNU的人也会想到这些,但出于某种原因,他们采用了更复杂的设置。我只想理解他们的推理,所以我可以在运行中执行这些操作。一个更简单的解决方案是完全取消sed调用,因为gcc可以直接完成您需要的所有操作:
%.d: %.c
$(CC) -M $(CPPFLAGS) -MF $@ $< -MT "$*.o $@"
%.d:%.c
$(CC)-M$(CPPFLAGS)-MF$@$<-MT“$*.o$@”
实际上,甚至规则本身都不是必需的。在Paul D.Smith撰写的文章中,对生成Make样式依赖项的不同方法有一个很好的概述
毕竟,以下规则应该足够了(在使用GCC的情况下):
%.o:%.c
$(CC)$(CPPFLAGS)$(CFLAGS)-MMD-MP-o$@-c$<
-包括$(来源:.c=.d)
UPD。
我刚才也有一个类似的问题。它包含对
-MMD-MP
选项的解释(引用GCC手册)。解决了以下问题:为什么要将文件重定向到sed?
如果:
@$(CC) -M $(CPPFLAGS) $< | sed 's|:| $*.d : |' > $@;
@$(CC)-M$(CPPFLAGS)$<|sed的|:|$*.d:|'>$;
如果编译失败(出错且不生成输出),您将创建一个空的目标文件。当再次运行
make
时,它将看到新创建的空文件,而不会重新生成它,从而导致生成错误。使用中间文件是一种常见的防御策略,以避免意外创建空目标。嘿,这对我很有用!我从来没有深入研究过gcc
的奥秘,它有大量的命令行选项。但是,这非常有效。我喜欢你的include
指令,比书中的指令要好得多。它更简单,更容易理解。不幸的是,由于某种原因,%.o%.c
规则未能为其中一个文件构建依赖关系。我将不得不深入研究gcc
命令参数的多样性。@David Hmm。。。那看起来很奇怪-MMD-MP
选项对我来说总是很神奇。@DavidW.,你能给我们一个导致规则失败的最小示例吗?@Beta Nothing“fails”,它只是不创建任何文件的依赖关系。这是奥利GNU的书。我想是第2.7章。Makefile在中。这可能与我定义链接依赖项的方式有关。我没有count\u words
依赖count\u words.o
,因为这是默认设置。我没有试图追查这个问题。-MP
是可选的,但非常有用。如果没有它,如果头文件已被删除或重命名,生成的依赖项将导致其目标失败。这就是我要寻找的解释。我的将创建空文件,即使编译失败。GNU的版本不会。
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -MMD -MP -o $@ -c $<
-include $(SOURCES:.c=.d)
@$(CC) -M $(CPPFLAGS) $< | sed 's|:| $*.d : |' > $@;