【问题标题】:Makefile secondary expansion: execution of escaped function?Makefile二次扩展:转义函数的执行?
【发布时间】:2017-05-09 09:10:42
【问题描述】:

考虑以下生成文件:

.SECONDEXPANSION:

%.result: jobs/% $$(call get-job,$$<)
    echo $^

define get-job
$(shell head -n 1 $(1))
$(shell tail -n +2 $(1))
endef

这个想法是jobs/下的每个文件都包含一个文件名列表,应该附加到先决条件列表中。

但是,如果我想从现有文件 jobs/xyz 创建 xyz.result,我会收到以下错误消息:

$ make -n xyz.result
head: cannot open 'xyz.result' for reading: No such file or directory
tail: cannot open 'xyz.result' for reading: No such file or directory
head: cannot open 'xyz.result' for reading: No such file or directory
tail: cannot open 'xyz.result' for reading: No such file or directory
make: *** No rule to make target 'xyz.result'. Stop.

我知道 $$&lt; 没有设置为我想要的,因为它反映了任何先前规则的先决条件列表。
我不明白的是:

  • 在我的理解中,$$&lt; 应该评估为空字符串(如第二个子标题下的official doc 中的示例所示)。但是,这里似乎扩展为目标的值(xyz.result)。这是为什么呢?
  • 似乎get-job 函数被调用了两次(headtail 都叫了两次)。我了解先决条件列表已扩展两次。但在第一次运行中,call 仍然被转义,所以这不是我所期望的。

(也许整个方法有缺陷,我不应该(ab)首先使用 Makefile 来完成这类任务。)

【问题讨论】:

    标签: makefile gnu-make variable-expansion


    【解决方案1】:

    我不知道为什么$$&lt; 会这样扩展。

    不过,您可以改用 $$* 来使您的配置生效:

    %.result: jobs/% $$(strip $$(call get-job,jobs/$$*))
            echo $^
    

    您需要添加strip 调用,以便call 结果中嵌入的换行符将变成空格。

    【讨论】:

    • 谢谢,它有效!不过,我不明白为什么——你知道为什么不调用strip 会导致get-job 被执行两次吗?毕竟这些换行符来自headtail...
    • 它不会被调用两次。它被调用一次。但是,嵌入在 define...endef 中的换行符被保留。所以在第一个 shell 命令的输出和第二个 shell 命令的输出之间有一个换行符。你可以这样写:get-job = $(shell head -n 1 $(1)) $(shell tail -n +2 $(1)) 不使用define,那么你就不需要strip 调用。
    • 我明白了。但是,为什么我会分别从headtail 收到两条错误消息?
    • 我不知道你为什么这样做......我无法重现。当我使用您的原始测试时,headtail 各收到一条错误消息,而不是两条。
    • 好吧,也许我不想知道:-p.
    猜你喜欢
    • 2014-06-06
    • 1970-01-01
    • 2021-09-18
    • 1970-01-01
    • 2020-03-01
    • 1970-01-01
    • 2019-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多