13

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

测试用例:
下面的测试用例说明了这个问题。
生成文件内容:

.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

重现:
将生成文件保存在一个空目录中,然后运行“make build;make build;make clean”。

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

但是,我认为我不能再剥离依赖项了。build取决于test,并且test对应于一个不存在的文件,它是由它的配方生成的。我想它会在build处理配方时出现。

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

注意这个问题的目的只是为了了解与这个问题相关的通配符函数的工作原理;有一个实际用例,我从中提炼出这个淡化版本,但我对这个案例更感兴趣。

4

1 回答 1

5

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

关于您关于处理先决条件的顺序的声明:从 技术上讲,GNU make 不保证顺序,但实际上,先决条件是从左到右处理的,尽管纯粹主义者试图改变它(仅出于拧紧的目的对于没有完全指定依赖关系的人),GNU make 实际上会改变实现细节的可能性非常小。 但是,您只能真正依赖串行构建中的排序。如果您并行运行构建,那么事情会变得有点棘手:GNU make可以仍然以从左到右的顺序处理 prereq,但它不再等待一个完成后再开始下一个,因此实际上它们可能看起来是以随机或“任何”顺序处理的,受 prereq 间依赖关系的影响,这就是为什么最好指定这些依赖项。

于 2013-02-24T04:33:27.250 回答