Make 不能识别间接依赖的变化
Make doesn't recognize changes in indirect dependencies
考虑这个简单的 makefile:
all: output.txt
# The actual build command won't be this simple.
# It'll more be like "some-compiler file1.txt",
# which includes file2.txt automatically.
output.txt: file1.txt
cat file1.txt file2.txt > output.txt
file2.txt:
echo "heyo" > file2.txt
file1.txt: file2.txt
首先 运行,Make 识别出 file2.txt
是 file1.txt
的依赖项,因此需要为要构建的 output.txt
构建它。因此,它 运行s echo "heyo" > file2.txt
然后 cat file1.txt file2.txt > output.txt
.
但是,在随后的 运行 中,如果 file2.txt
发生更改,Make 不会重建 !如果 file1.txt
改变了,它会改变,但 file2.txt
不会改变。它只是给出了可怕的 make: Nothing to be done for 'all'.
消息。
我看到人们建议的一个 hacky 解决方案是执行以下操作:
all: output.txt
output.txt: file1.txt file2.txt
cat file1.txt file2.txt > output.txt
但是,这对我来说是不可能的,因为我的次要依赖项(像 file1.txt: file2.txt
这样的行)是使用 include
.
动态生成的
当我有多级依赖关系时,如何确保 Make 检查修改一直向上? 23=]
您的 makefile 既不生成也不更新 file1.txt
(即:file1.txt
必须存在于 运行 make
).它包含 没有用于从 file2.txt
生成 file1.txt
的配方。它只有一个空规则(即:一个没有配方的规则):
file1.txt: file2.txt
因为 file1.txt
是 output.txt
的先决条件,这个空规则只是暗示 file2.txt
必须存在才能构建 output.txt
,它甚至不更新 file1.txt
当生成 file2.txt
时。
由于 file1.txt
是 output.txt
的唯一先决条件,并且 file1.txt
永远不会被 make
更新,一旦 output.txt
生成,它始终保持 up-to-date(前提是file1.txt
没有被外部更新)。
file2.txt
被更改永远不会导致 output.txt
被重建,因为:
- 它不是
output.txt
的先决条件。
- 它不会更新
file1.txt
(这是 output.txt
的唯一先决条件)。
解决方案
根据您当前的 output.txt
规则:
output.txt: file1.txt
cat file1.txt file2.txt > output.txt
如果你想在每次file2.txt
变化时构建output.txt
,那么你需要在每次file2.txt
变化时构建file1.txt
。这可以通过 recipe 实际上更新 file1.txt
并以 file2.txt
作为先决条件的规则来实现,例如:
file1.txt: file2.txt
touch $@
我认为这里的问题是您的 makefile 稍微太简单了。
让 a -> b
表示 a depends on b
。从你的 makefile 你有...
output.txt -> file1.txt -> file2.txt
当 make
尝试更新 output.txt
时,它发现 output.txt
依赖于 file1.txt
。然后它注意到 file1.txt
依赖于 file2.txt
。那时依赖链停止。如果 make 发现 file2.txt
比 file1.txt
更新,它将 运行 与 file1.txt: file2.txt
延迟关联的命令。然而,在这种情况下,没有任何命令——只有依赖项本身。这很好,但这确实意味着即使 file2.txt
更新 file1.txt
也不会。因此,当 make 在依赖链上移动到...
output.txt: file1.txt
它发现 output.txt
仍然 比 file1.txt
更新,因此不需要 运行 与该依赖项关联的任何命令。
如果添加 touch
命令...
file1.txt: file2.txt
touch $@
然后 file1.txt
将 更新,因此依赖链按您预期的方式工作。
考虑这个简单的 makefile:
all: output.txt
# The actual build command won't be this simple.
# It'll more be like "some-compiler file1.txt",
# which includes file2.txt automatically.
output.txt: file1.txt
cat file1.txt file2.txt > output.txt
file2.txt:
echo "heyo" > file2.txt
file1.txt: file2.txt
首先 运行,Make 识别出 file2.txt
是 file1.txt
的依赖项,因此需要为要构建的 output.txt
构建它。因此,它 运行s echo "heyo" > file2.txt
然后 cat file1.txt file2.txt > output.txt
.
但是,在随后的 运行 中,如果 file2.txt
发生更改,Make 不会重建 !如果 file1.txt
改变了,它会改变,但 file2.txt
不会改变。它只是给出了可怕的 make: Nothing to be done for 'all'.
消息。
我看到人们建议的一个 hacky 解决方案是执行以下操作:
all: output.txt
output.txt: file1.txt file2.txt
cat file1.txt file2.txt > output.txt
但是,这对我来说是不可能的,因为我的次要依赖项(像 file1.txt: file2.txt
这样的行)是使用 include
.
当我有多级依赖关系时,如何确保 Make 检查修改一直向上? 23=]
您的 makefile 既不生成也不更新 file1.txt
(即:file1.txt
必须存在于 运行 make
).它包含 没有用于从 file2.txt
生成 file1.txt
的配方。它只有一个空规则(即:一个没有配方的规则):
file1.txt: file2.txt
因为 file1.txt
是 output.txt
的先决条件,这个空规则只是暗示 file2.txt
必须存在才能构建 output.txt
,它甚至不更新 file1.txt
当生成 file2.txt
时。
由于 file1.txt
是 output.txt
的唯一先决条件,并且 file1.txt
永远不会被 make
更新,一旦 output.txt
生成,它始终保持 up-to-date(前提是file1.txt
没有被外部更新)。
file2.txt
被更改永远不会导致 output.txt
被重建,因为:
- 它不是
output.txt
的先决条件。 - 它不会更新
file1.txt
(这是output.txt
的唯一先决条件)。
解决方案
根据您当前的 output.txt
规则:
output.txt: file1.txt
cat file1.txt file2.txt > output.txt
如果你想在每次file2.txt
变化时构建output.txt
,那么你需要在每次file2.txt
变化时构建file1.txt
。这可以通过 recipe 实际上更新 file1.txt
并以 file2.txt
作为先决条件的规则来实现,例如:
file1.txt: file2.txt
touch $@
我认为这里的问题是您的 makefile 稍微太简单了。
让 a -> b
表示 a depends on b
。从你的 makefile 你有...
output.txt -> file1.txt -> file2.txt
当 make
尝试更新 output.txt
时,它发现 output.txt
依赖于 file1.txt
。然后它注意到 file1.txt
依赖于 file2.txt
。那时依赖链停止。如果 make 发现 file2.txt
比 file1.txt
更新,它将 运行 与 file1.txt: file2.txt
延迟关联的命令。然而,在这种情况下,没有任何命令——只有依赖项本身。这很好,但这确实意味着即使 file2.txt
更新 file1.txt
也不会。因此,当 make 在依赖链上移动到...
output.txt: file1.txt
它发现 output.txt
仍然 比 file1.txt
更新,因此不需要 运行 与该依赖项关联的任何命令。
如果添加 touch
命令...
file1.txt: file2.txt
touch $@
然后 file1.txt
将 更新,因此依赖链按您预期的方式工作。