Makefile始终表示生成文件目标是最新的,但会按预期生成目标

时间:2016-05-04 22:39:55

标签: shell makefile generated-code

我有一个脚本,在运行时会生成一个文件。我想创建一个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实际上已生成。

这里发生了什么?为什么我看到"是最新的"消息,我该如何摆脱它?

谢谢!

1 个答案:

答案 0 :(得分:1)

  

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

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

genfile.foo实际上已生成。

正如user657267建议:从配方正文中删除$(shell)

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

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

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

  3. $(GEN_SCRIPT)可以正常工作,但不会产生任何输出,因此$(shell $(GEN_SCRIPT))会扩展为空字符串。

  4. 看到命令为空,因此没有命令可以运行。

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