【问题标题】:Make: Auto dependency generationMake:自动依赖生成
【发布时间】:2018-12-31 07:47:56
【问题描述】:

我对使用 Make 自动生成依赖文件有一个疑问。 这里我有以下内容的makefile。

DEPSALL := $(wildcard $(patsubst %,%.d,$(basename $(TGTFILES)/*.c)))
-include $(DEPSALL)
$(TGTFILES)/%.o: $(TGTFILES)/%.c
     mkdir -p $(@D)
     $(CC64) -MT $@ -MMD -MP -MF $(patsubst %,%.d,$(basename $@)) -o $(@) -c $(CFLAGS64) $<
...
...  

我是 GNUmake 的新手,正在尝试做一些实验。我知道上面的 -M* 标志用于创建自动依赖文件“*.d”,其中包含每个 obj 文件的目标和依赖项。 在这里,在编译代码时,我只是注释掉了前两行,并且在编译代码时没有看到任何区别。不确定这些行对我的编译有何影响。

真的有必要在我的makefile中包含这两行吗?没有'include'指令(-include $(DEPSALL))它工作正常。

【问题讨论】:

  • 如果您之前运行了相同的命令并且文件已经生成,那将起作用(但最终文件将包含过时的信息)。带有减号的-include 将默默地忽略任何丢失的文件。依赖项的目的是告诉 Make 何时重新制作某些东西;如果没有依赖文件,Make 会在您更改 fnord.h 时认为 fnord.c 是最新的,即使它们有依赖关系。
  • 嗨,我之前没有运行过任何命令。我第一次运行没有这两行,依赖文件被创建并且工作正常。

标签: makefile


【解决方案1】:

假设您已经完全构建了代码,所以当您运行 make 时,什么都没有发生,因为一切都是最新的。

现在假设您的一个源文件foo.c 包含一个头文件bar.h。您编辑了头文件bar.h,但没有编辑源文件foo.c。出于本实验的目的,您可以使用touch bar.h 来模拟编辑。

现在如果你注释掉上面的前两行,当你运行make 时,它会说不需要做任何事情并且不需要重新编译任何东西,即使头文件被改变了。如果你不注释掉上面的前两行,当你运行make它会意识到头文件被改变并重新编译源文件。

就是这两行和所有-MT等选项的用途。

【讨论】:

  • 感谢您的解释.. 确实有道理。我想从上面的 make 文件中知道的一件事是,make 中的执行流程是如何发生的?我有这个疑问是因为我们首先包含依赖文件,然后我们使用 -M* 标志创建这些 .d 文件。我想知道它是如何包含这些 .d 文件的。因为第一次运行没有 .d 文件。我们创建了它们,并没有在之后(而不是我们放在之前)放置“包含”指令。你能帮我理解一下吗?
  • Make首先读取整个makefile,然后在所有makefile、包含的makefile等被解析并添加到它的内部结构之后,它才会开始更新目标。因此,几乎在所有情况下,定义哪个订单规则都无关紧要。 Makefiles 像解释语言(shell、Python 等)一样,事物在解析时运行。唯一重要的时间顺序是 (a) 选择默认目标,以及 (b) 一些非常具体、不常见的模式规则匹配形式。
  • 我们不关心第一次运行时包含的文件(当它们不存在时)的原因是我们已经知道我们必须编译源文件,因为没有对象文件。所以是否有任何过时的头文件是无关紧要的。完整的讨论见make.mad-scientist.net/papers/…
  • 感谢您帮助理解这一点:)
  • 如果您对答案感到满意,请点击对勾让其他人知道它已经回答了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-10
  • 2012-07-06
  • 1970-01-01
  • 2011-01-13
  • 1970-01-01
  • 1970-01-01
  • 2023-04-11
相关资源
最近更新 更多