GNU make通配符函数找不到运行时生成的文件

Fra*_*cis 12 gnu makefile function wildcard is-empty

简介:
我在类似unix的系统上使用GNU Make(3.81)而且我遇到了一个问题,即$(wildcard, pattern)函数无法找到由(可能/显然?)先前执行的配方生成的文件,而其他程序(例如ls)能够验证其存在.我想知道为什么通配符函数没有返回任何东西,当它被扩展(到空字符串),以及我如何获得它来查找生成的文件.

测试用例:
以下测试用例说明了问题.
Makefile内容:

.PHONY: build clean

test:
    @echo "Creating test file 'test'."
    @echo "this is a test file" > test

build: test
    @echo "Directory contents:"
    @ls
    @echo "Test file contents:"
    @cat test
    @echo "Wildcard output:"
    @echo $(wildcard test)

clean:
    @rm -f test
Run Code Online (Sandbox Code Playgroud)

运行makefile两次(然后清理)显示只有在第二次运行时它才会检测到创建的文件.
输出:

Creating test file 'test'.
Directory contents:
makefile  test
Test file contents:
this is a test file
Wildcard output:

Directory contents:
makefile  test
Test file contents:
this is a test file
Wildcard output:
test
Run Code Online (Sandbox Code Playgroud)

要重现:
将makefile保存在一个空目录中,然后运行"make build; make build; make clean".

研究:
处理目标的先决条件的顺序与它们在冒号后出现在列表中的顺序无关,因此如果要定义它们的顺序,则必须引入显式的先决条件之间的依赖关系.处理.

但是,我认为我不能再删除依赖项; build依赖于test,并且test对应于不存在且由其配方生成的文件.我推测它将build在处理配方时存在.

根据我对make如何解析makefile的了解,配方中的通配符函数在处理之前不应该展开.但是,我清楚地看到内置make功能的输出和通过shell访问的常见实用程序的输出之间的区别,所以这个假设可能是错误的,但我没有遇到任何关于应该是什么的好解释发生在这里,甚至在GNU make手册中都没有.

注意:这个问题的目的只是为了理解与这个问题相关的通配符功能的运作; 有一个实际的用例我从中提取了这个淡化版本,但我对这种情况更感兴趣.

Eri*_*ski 5

GNU make在执行任何一个目标之前扩展所有命令。在这种情况下,“扩展”意味着“用它们的值(递归地)替换所有变量引用,并评估任何函数引用。” 当然是函数引用。由于扩展发生在任何命令执行之前,当然无法找到该文件——它还没有被创建。第二次运行构建时,已经存在,所以可以找到它。$(wildcard)testtest$(wildcard)

关于您关于处理先决条件的顺序的声明:从技术上讲, GNU make 不保证顺序,但实际上,先决条件是 从左到右处理的,尽管纯粹主义者试图改变它(唯一的目的是搞砸对于尚未完全指定依赖项的人),GNU make 实际更改实现细节的可能性微乎其微。 但是,您只能真正依赖串行构建中的顺序。如果您并行运行构建,那么事情会变得有点棘手:GNU make确实如此 仍然按从左到右的顺序处理先决条件,但在开始下一个之前不再等待一个完成,因此实际上它们可能看起来以随机或“任何”顺序处理,受制于内部先决条件依赖关系,这就是为什么指定这些依赖项是一个很好的做法。