"How make file is read" 的示例

Examples for "How make file is read"

在 GNU-Make 手册中,make 如何读取 Makefile https://www.gnu.org/software/make/manual/make.html#Reading-Makefiles 部分说

GNU make 分两个不同的阶段进行工作。在第一阶段,它读取所有的 makefile、包含的 makefile 等,并内化所有变量及其值、隐式和显式规则,并构建所有目标及其先决条件的依赖图。在第二阶段,make 使用这些内部结构来确定需要重建哪些目标并调用必要的规则来这样做。

我无法清楚地理解 b/w 这两个阶段的区别。可能正在看一个例子将有助于理解。是否有任何链接或教程可以阐明第一阶段和第二阶段究竟发生了什么。

使用这个简单的 makefile:

var := some_other_file

some_file: $(var)
  some_command $^ $@

第一阶段后文件将如下所示

var := some_other_file

some_file: some_other_file
  some_command $^ $@

请注意 $^$@ 尚未扩展,食谱仅作为阶段 2 的一部分进行扩展和调用。

在第 2 阶段,make 将使用第 1 阶段产生的规则并确定需要重新制作哪些目标,您可以看到 "thinks" by 运行 make 和 -d 标志(警告:大量输出)。

在上述案例的第 2 阶段,在检查了 some_other_file 的所有依赖项并在必要时重新制作它之后,它会考虑 some_other_file 是否比 some_file 更新。

如果是这种情况,那么(并且只有到那时)才会扩展食谱的变量,并将每一行的内容传递给 shell,这里是 some_command some_other_file some_file

因此您不能在任何地方使用 $@ 等,除非作为配方的一部分,因为自动变量仅在阶段 2 期间设置。

foo: $@bar
  some_command $^

这将在第 1 阶段扩展为:

foo: bar
  some_command $^

第 2 阶段将导致:

foo: bar
  some_command bar

可能不是你想要的。

有些品牌有办法解决这个限制。例如 GNU make 有 .SECONDEXPANSION,下面的将按预期工作:

.SECONDEXPANSION:
foo: $$@bar
  some_command $^

.SECONDEXPANSION 之后的任何内容都将在第 1 阶段展开:

.SECONDEXPANSION:
foo: $@bar
  some_command $^

和第 2 阶段:

.SECONDEXPANSION:
foo: foobar
  some_command foobar