【问题标题】:Makefile variable expansion with wildcard when rule creates new file规则创建新文件时使用通配符扩展 Makefile 变量
【发布时间】:2017-01-04 18:20:02
【问题描述】:

当规则创建一个应该修改通配符扩展行为的文件时,我无法理解 Makefile 如何处理变量扩展。

例如,我有以下 Makefile:

TEXT_FILES = $(wildcard *.txt)

all: create test

create:
    @touch hello.txt

test:
    @printf "The files are $(TEXT_FILES)\n"

我在运行make 时期望得到的是

文件是 hello.txt

因为TEXT_FILES 应该在调用时进行评估,而不是在定义时进行评估。但是,我实际上得到了(运行两次)

文件是(第一次执行时变量为空)

文件是hello.txt(下次找到)

如何获得所需的行为?

【问题讨论】:

  • 在这里stackoverflow.com/questions/22630996/… 找到了这个可能相关的问题,仍然没有解决方案。
  • 您的确切用例是什么?也许这是一个 XY 问题。
  • 我有一个文件夹,其中包含 C 代码中的模板,这些模板被转换为 1 - 1 到其他东西(也在 C 中),但在此过程中可能会生成其他文件发现这个:stackoverflow.com/questions/9744865/… 显然是通配符扩展在评估规则之前很久就发生了,所以没有办法实现我想要的行为
  • 你想用“附加文件”做什么?你知道他们的名字吗:你能从你的模板中“提取”吗?还是这些生成的文件的名字是随机的?

标签: makefile


【解决方案1】:

此行为是 make 内部缓存的结果。出于性能原因,make 将缓存它认为是真的文件系统的状态,基于它之前的状态以及它知道已经做出的更改(因为已经调用了规则)。

wildcard 等函数将查询内部缓存(如果可用)。

但是,在您的情况下,您并没有描述要制定的规则的实际行为:您没有告诉 make 这条规则会生成额外的文件。结果 make 不会更新它的缓存,wildcard 函数永远不会找到这个秘密文件。

你没有准确地说出你想要做什么,但你为什么不直接使用 shell 的通配符功能而不是 make 的 wildcard 函数呢? shell 显然不知道 make 的内部缓存:

TEXT_FILES = *.txt

all: create test

create:
        @touch hello.txt

test:
        @echo The files are $(TEXT_FILES)

【讨论】:

  • 我应该指出,这个 makefile 不是并行安全的:你不能使用 make 的 -j 选项并让它可靠地工作。您需要将 create 作为 test 的先决条件才能使其正常工作。
  • 成功了!谢谢。因此,似乎在解析 make 时评估了 make 的 wildcard 函数,而 shell 的通配符 * 仅在之后扩展 TEXT_FILES 变量时才扩展。对吗?
  • 并非如此。 Make 的函数(包括通配符)会根据它们在 makefile 中出现的位置进行扩展,请参阅gnu.org/software/make/manual/html_node/Reading-Makefiles.html 了解规则。由于您的示例中的 wildcard 出现在配方中,因此在 make 即将运行该特定配方之前(而不是在解析 makefile 时)它不会扩展。但是,由于如上所述 make 的缓存行为,通配符函数仅匹配 make 启动或 make know 被创建时存在的文件。这是特定于通配符函数的。
  • 不使用通配符函数 make 根本不会尝试扩展*;这只是另一个要制作的角色,例如a 或其他。 Make 只关心可能是变量的东西(前面是$)。所以make将字符串echo The files are *.txt传递给shell,shell负责处理文件通配。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多