要点:
我在类似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
运行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
要重现:
将makefile保存在一个空目录中,然后运行" make build; make build; make clean"。
研究
处理目标的先决条件的顺序是independent of the order in which they appear in the list after the colon,因此如果要定义它们被处理的顺序,则必须引入明确的先决条件之间的依赖关系。
但是,我不认为我可以再删除依赖关系; build
取决于test
,test
对应于一个不存在且由其配方生成的文件。我推测它将在处理build
的配方时出现。
根据我对make如何解析makefile的了解,配方中的通配符函数在处理之前不应该展开。 但是,我清楚地看到内置make功能的输出和通过shell访问的常见实用程序的输出之间存在差异,所以这个假设可能是错误的,但我还没有遇到任何关于什么& #39;应该发生在这里,甚至不在GNU make手册中。
N.B。这个问题的目的只是为了理解与这个问题相关的通配符功能的运作;有一个实际的用例我从中提取了这个淡化版本,但我对这种情况更感兴趣。
答案 0 :(得分:4)
GNU make在执行任何之前,为目标扩展所有命令。在此上下文中,“expand”表示“用其值(递归地)替换所有变量引用,并评估任何函数引用。”当然,$(wildcard)
是一个函数引用。由于扩展发生在任何命令执行之前,当然无法找到文件test
- 它尚未创建。第二次运行构建时,test
已经存在,因此$(wildcard)
可以找到它。
关于您处理先决条件的顺序的声明:技术上 GNU make不保证订单,但实际上说明先决条件是从左到右处理的尽管纯粹主义者试图改变这一点(仅仅为了与那些没有完全指定依赖关系的人搞砸),GNU make实际上改变实现细节的可能性很小。 然而您只能依赖 serial 版本中的订购。如果你并行运行构建,那么事情会变得有点棘手:GNU make 仍然按照从左到右的顺序处理先决条件,但它不再等待一个完成后再开始下一个,所以实际上它们可能看起来是随机或“任意”的顺序处理,受到inter-prereq依赖性的影响,这就是为什么指定这些依赖项的好习惯。