【问题标题】:Makefile: defining rules and prerequisites in recipesMakefile:在配方中定义规则和先决条件
【发布时间】:2016-08-28 05:36:26
【问题描述】:

我有一个设置,我想用 make 处理的文件依赖于另一个程序的输出。构建程序及其所有先决条件 也是一项复杂的任务,所以我也想为此使用 make 。现在我的问题是,似乎无法在 Makefile 配方中生成规则和先决条件。考虑以下代码:

bar:
    echo target1 target2 target3 > bar

foo: bar
    $(eval BAR := $(shell cat bar))

define FUN
$(1):
    touch a$(1)
endef

ifdef BAR
$(foreach i,$BAR,$(eval $(call FUN,$(i))))
endif

blub: foo $(BAR)

我用bar 配方替换了一大组复杂的配方,这些配方最终导致生成我想要拥有的文件列表。实际上,生成bar 的内容非常复杂,应该通过一组 Makefile 配方来完成,而不能仅仅通过(如上所示)来完成:

BAR:=$(shell echo target1 target2 target3)

我想将foreach 循环放入foo 的配方中,但prerequisites cannot be defined in recipes 失败,这是有道理的,在function define in makefile 中也有解释

但似乎当我做make blub 时,当foo eval 的BAR 为不同的值时,blub 的先决条件不会重新评估。

所以我认为最终我正在寻找两件事:

  • 如何在运行时根据(并依赖于)另一个配方(在本例中为bar)输出的内容动态生成配方?

  • 如何在运行时动态更新目标的先决条件(在这种情况下为blub),基于(并依赖于)另一个配方(在这种情况下为bar)的输出?

谢谢!

编辑:解决方案

在@user657267 的帮助下,以下似乎解决了我的问题:

.PHONY: all
all: blub

-include bar.make

.PHONY: blub
blub: $(BAR)
    echo $^

bar.make: Makefile
    printf 'BAR=target1 target2 target3\n' > $@
    printf 'target1 target2 target3:\n' >>$@
    printf '\ttouch $$@' >> $@

.PHONY: clean
clean:
    rm -f target1 target2 target3 bar.make

【问题讨论】:

  • FWIW,echo 的这种使用非常不便携。您应该使用 printf (程序)打印除简单文本后跟换行符之外的任何内容。另外仅供参考,您可以使用 eval 从配方中设置变量,但不能使用它来创建新规则。这是因为在 make 读取所有 makefile 之后,在它开始运行配方之前,它会执行一个过程,将所有 makefile 数据对齐到它的内部图表中。一旦发生这种情况,您将无法通过添加新规则来更改图表。
  • @MadScientist 啊,谢谢,我认为你的评论 eval() 回答了我在回答这个问题时问你的另一个问题,即确实需要使用 include 才能工作并且不存在仅eval 的解决方案。我在这里使用echo 的哪一部分是不可移植的?
  • 并非所有回显命令都会将\t 字符序列转换为TAB 字符。
  • @MadScientist 确实根据in-ulm.de/~mascheck/various/echo+printf 我不会支持 BSD。我相应地修改了我的答案。谢谢!

标签: makefile gnu-make


【解决方案1】:

听起来你应该使用 make 的自我改造功能

-include bar.make

blub: $(BAR)
    @echo $^

bar.make:
    @echo BAR := target1 target2 target3 > $@
    @echo target1 target2 target3: ; touch $$@ >> $@

显然bar.make 的配方是人为设计的,在现实世界中,它们可能会调用某种输出有效 makefile 的脚本。

【讨论】:

  • 这是什么魔法???哇,非常感谢!您的回答帮助我找到了正确的解决方案(我还必须将其应用于我的实际问题)。我不得不对您的解决方案进行一些更改: 1. bar.make 需要依赖于 Makefile 本身,否则如果 Makefile 更改,它将不会重新生成 2. 似乎有一些缺少的转义参数touch 3. -includeblub 的顺序很重要。如果按照您的答案保留,默认目标将变为target1,这是不可取的。但是如果-include 放在blub 之后,那么$(BAR) 似乎不会评估
  • 有关更多信息,请参阅:gnu.org/software/make/manual/html_node/Remaking-Makefiles.html 这里还有一组关于执行此类操作的博客文章:make.mad-scientist.net/category/metaprogramming
  • @MadScientist 谢谢,make.mad-scientist.net 上的文章让我对这个话题的理解比官方的 make 文档在阅读了几遍后更好地理解了!不过我想知道:在make.mad-scientist.net/the-eval-function 中,eval() 函数据说是“最强大的”。这是否意味着这个问题也可以通过使用eval() 而不是这个答案中建议的基于include 的技术来解决?
  • @MadScientist 不相关,但是当我搞砸这个时,我注意到如果使用新的 file 函数代替 echo 那么 makefile 将不会被重新解析,这是故意的吗?
  • 嗯。好吧,file 发生在“运行配方”引擎的范围之外。这是扩展配方的副作用。然后配方是空的,所以 make 实际上并没有运行任何命令。让我有点吃惊的是,一个空规则不会强制重新读取 makefile。
猜你喜欢
  • 2021-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-18
  • 1970-01-01
  • 2023-03-23
相关资源
最近更新 更多