【问题标题】:Variable depending on target因目标而异
【发布时间】:2018-10-16 14:54:48
【问题描述】:

有没有办法强制目标规则运行作为在变量中设置内容的一部分?

例如,假设我们有一个目标和规则:

all_mp3s:
    find / -name "*.mp3" > all_mp3s

然后是一个变量:

MP3S := $(file < all_mp3s)

有没有办法确保在评估 MP3S 变量之前创建了 all_mp3s 文件?

【问题讨论】:

  • 你的问题对我来说并不完全清楚。您在寻找shell function 吗?你可以做类似MP3S := $(shell find / -name "*.mp3")
  • 您的实际目标是什么?

标签: makefile


【解决方案1】:

没有简单直接的方法可以强制在分配变量之前对规则进行评估。还有更复杂的方法。以下是 GNU make 的。

我们首先假设您只想在文件all_mp3s 不存在时运行(慢)find 命令,否则使用其内容。您可以使用 GNU make 条件:

ifeq ($(wildcard all_mp3s),all_mp3s)

MP3S := $(shell cat all_mp3s)

else

MP3S := $(shell $(MAKE) all_mp3s ; cat all_mp3s)

endif

all_mp3s:
    find / -name "*.mp3" > $@

但是我如果你的 Makefile 比这个复杂,多次使用MP3S,而你真正想要的是:

  • 避免多次运行超慢的find
  • 仅在需要时运行它(并且只运行一次),
  • 在文件 (all_mp3s) 和 make 变量 (MP3S) 中获取结果,

MadScientist 有一个wonderful GNU make trick,可以在这里使用:

MP3S = $(eval MP3S := $$(shell find / -name "*.mp3"))$(MP3S)

all_mp3s:
    printf '%s\n' '$(MP3S)' > all_mp3s

.PHONY: help clean

help:
    printf 'MP3 finder\n'

clean:
    rm -f all_mp3s

如果 MP3S recursively expanded make variable 被扩展是因为你的 Makefile 的某些部分被评估并需要它的值(例如,如果你运行 make all_mp3sall_mp3s 不存在),则将运行 find 命令,它的结果存储在变量中......并且变量将被转换为simply expanded make variable,如果有的话,进一步的扩展将重用相同的,已经计算的值。

否则,如果您的 make 调用(例如 make cleanmake help)不需要 MP3S 值,则 find 命令甚至不会运行。

all_mp3s 文件是根据 MP3S 的值生成的(而不是在其他解决方案中相反)。

但是,还有另一件重要的事情需要决定:您是否要将all_mp3s 声明为虚假目标:

.PHONY: all_mp3s

还是不行?

  • 如果您将其声明为虚假,则每次调用 make all_mp3s(或依赖于 all_mp3s 的另一个目标)时,find 命令将运行一次且仅运行一次。但是依赖于all_mp3s 的目标也总是会被重建,这不一定是你想要的。

  • 1234563 all_mp3s的内容不会更新,不一定是你想要的。

由于您没有在问题中提供足够的信息来决定,这取决于您。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-14
    • 1970-01-01
    • 2020-08-11
    • 2021-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多