Makefile 总是说生成的文件目标是最新的,但按预期生成目标

Makefile always says generated-file target is up to date, but generates target as expected

我有一个脚本,当 运行 时,它会生成一个文件。如果生成的文件不存在或脚本更改,我想创建一个 Makefile 到 运行 脚本以生成文件。

这是一个简化版本。假设我有一个这样的可执行脚本 gen_test.sh

#!/bin/sh

echo "This is a generated file" > genfile.foo

还有一个像这样的 Makefile:

#
# Test Makefile
#

GEN_SCRIPT = $(CURDIR)/gen_test.sh
GEN_FILE = $(CURDIR)/genfile.foo

$(GEN_FILE): $(GEN_SCRIPT)
        $(shell $(GEN_SCRIPT))

.PHONY: clean
clean:
        $(RM) $(GEN_FILE)

当我 运行 make 时,我看到以下输出:

make: '/workspace/sw/bhshelto/temp/makefile_test/genfile.foo' is up to date.

genfile.foo 实际上会生成。

这是怎么回事?为什么我会看到 "is up to date" 消息,我该如何摆脱它?

谢谢!

When I run make, I see the following output:

make: '/workspace/sw/bhshelto/temp/makefile_test/genfile.foo' is up to date.

but genfile.foo does in fact get generated.

正如 user657267 所建议的那样:从食谱正文中删除 $(shell)

假设 gen_test.sh 不产生任何输出(或仅在 stderr 上输出),对该行为的解释相当简单:

  1. make 检测到 $(GEN_FILE) 需要重建并调用规则。

  2. 在命令调用之前,make执行命令内部变量的扩展。由于(不必要的)$(shell)$(GEN_SCRIPT) 在此扩展期间已经被调用。

  3. $(GEN_SCRIPT) 有效,但没有输出,因此 $(shell $(GEN_SCRIPT)) 被扩展为空字符串。

  4. Make 看到命令是,因此没有命令到运行。

  5. 然后 make 再次检查文件(以防变量扩展有副作用)并查看目标是最新的。然而,由于展开的命令为空,make 打印其通用的 is up to date 消息。