1

考虑这个简单的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构建它。因此,它运行echo "heyo" > file2.txt,然后cat file1.txt file2.txt > output.txt

但是,在后续运行中,如果file2.txt更改,Make 不会重建!如果file1.txt改变了,它会改变,但不是 for 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 检查所有的修改?

4

2 回答 2

1

您的 makefile既不生成也不更新 file1.txt(即:file1.txt必须在运行时存在make)。它包含file1.txtfile2.txt. 它只有一个空规则(即:没有 recipe 的规则):

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生成,它就会始终保持最新(前提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

如果您想output.txt在每次file2.txt更改时都构建,那么您需要file1.txt在每次file2.txt更改时都构建。这可以通过其配方实际更新file1.txt并具有file2.txt先决条件的规则来实现,例如:

file1.txt: file2.txt
    touch $@
于 2018-03-14T14:53:37.167 回答
1

我认为这里的问题是你的 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比它更新,它将运行与delendencyfile1.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 被更新,因此依赖链按您的预期工作。

于 2018-03-14T14:54:10.333 回答