考虑这个制作文件
test.txt: foo.bar
$(shell grep ^hello $< >$@)
要测试它,需要创建一个包含的文件foo.bar
,例如,
hello
hello 2
make
始终打印
make: 'test.txt' is up to date.
即使文件test.txt
不存在,也会发生这种情况。在这种情况下,make 可以正确运行并创建test.txt
,但仍会打印上述消息。即使使用make -B
也会给出相同的信息。
我正在使用GNU Make 4.2.1。
为什么会有这种行为?
发生这种情况是因为它实际上是一个空配方,所以没有什么可运行的。
$(shell)
函数在 Makefile 配方解析时进行评估,其输出被视为配方内容。碰巧此语句生成一个输出文件作为副产品,但语句的输出为空,因此make
无关,并得出结论,目标是最新的。事实上,如果食谱结果是空的,它总是会这么说:
$ ls
Makefile foo.bar
$ cat Makefile
test.txt: foo.bar
$(info Making $@ from $<)
$ make
Making test.txt from foo.bar
make: 'test.txt' is up to date.
$ ls
Makefile foo.bar
请注意,上面的例子没有创建test.txt
,make
只是得出结论,它运行了(空(配方来更新它,所以现在它是最新的。
为了正确运行它,您应该完全删除$(shell)
函数。make
的配方已经在外壳中调用:
$ cat Makefile
test.txt: foo.bar
grep ^hello $< >$@
$ make
grep ^hello foo.bar >test.txt
$ make
make: 'test.txt' is up to date.
$ make -B
grep ^hello foo.bar >test.txt
$ ls
Makefile foo.bar test.txt