【问题标题】:For each on target of Makefile variable对于 Makefile 变量的每个目标
【发布时间】:2018-09-11 18:57:30
【问题描述】:

我的 makefile 如下所示

apps = app1 app2 app3

all: dir app1 app2 app3 zip cleanup

现在我想在apps 变量列表上做一些循环,

类似

`loop on apps

endloop`

是否可以在makefile中循环,我需要在apps变量列表上循环

更新

假设这个变量(apps)是由我的程序在make 文件中生成的,它为每个项目提供不同的应用程序值,有时是apps= app1 app2,有时是@987654330 @ 有时可以是 20 个或更多应用程序 apps= app1 app2 appN

我如何迭代 apps 变量并做一些事情,例如在每次迭代中打印如下内容:

now im in `app1`
now im in `app2`
etc

尝试以下操作时

.PHONY: foo
all: foo
APPS = app1 app2 app3 app4
foo : $(APPS)
    for $$f in $(APPS); do echo $$f is here; done

我收到以下错误:

make: *** No rule to make targetapp1',foo'. Stop.需要

【问题讨论】:

  • 您希望在该列表中的确切内容是什么。您可以使用带有 for 循环的 shell 命令...
  • @BasileStarynkevitch - 你能举个例子吗?如何在每次迭代中迭代并打印来自应用程序的值?
  • 如果您edit 您的问题可以改进并准确说明您想在该列表中做什么,我可能会提供一个。但我不确定你想做什么......
  • 我也不明白你所说的“打印应用程序的价值”是什么意思。你的问题真的不清楚。
  • @BasileStarynkevitch - 假设这个变量(应用程序)是由我的 golang 程序在 make 文件中生成的,它为每个项目提供不同的应用程序值,有时是 apps= app1 app2,有时是 apps= app1 和有时可以是 20 个或更多应用程序 apps= app1 app2 appN

标签: linux makefile gnu-make gnu


【解决方案1】:

我看到你已经来回走了一点,所以让我发表一个可能有用也可能没有帮助的评论。

一般而言,您不会在 make 配方中编写循环,因为 make 本身提供“循环”。因此,当您编写如下规则时:

all: app1 app2 app3 app4

make 将尝试构建这些先决条件中的每一个,一次一个。因此,如果您想要一个生成文件,它为 apps 变量中的每个条目回显一行,您可以这样做:

all: $(apps)

$(apps):
        @echo $@

这告诉 make 从目标 all 开始,并尝试“构建”它的每个先决条件,即 apps 变量中的值。

然后,您定义如何构建应用程序的规则,并为每个应用程序指定规则为 echo $@,其中 $@ 是扩展至当前构建目标的 automatic variable

在make中,语法:

foo bar biz:
        some command

是写作的简写,与写作相同:

foo:
        some command
bar:
        some command
biz:
        some command

在编写 makefile 时,关键是你要考虑如何编写规则以从零个或多个必备文件创建 一个 文件(目标)。然后让您担心如何将所有这些先决条件连接在一起并正确排序。

预计到达时间 如果您想为 $(apps) 变量中保存的长列表中的一个特定目标制定特殊规则,您可以这样做:

$(filter-out bar,$(apps)):
        @echo print $@

bar:
        some other command

【讨论】:

  • 非常感谢,这正是我所需要的 :) 1+,一个问题,如果我想要 bar 运行 some other command ,我该怎么做?
  • 您可以像上一个示例一样写出所有规则,而不是为所有$(apps) 写一个规则。如果您有很多应用程序但只希望其中一个不同,则必须执行类似将$(apps): 目标更改为$(filter-out bar,$(apps)): 的操作,这样它就不会为bar 创建规则,然后创建一个bar: 的单独规则可以满足您的需求。
  • 你能把它添加到答案中吗?
【解决方案2】:

也许你想要类似的东西(我假设Makefile 的一些other部分描述了app1app2 等...应该如何使用适当的规则构建)。

foo: app1 app2 app3 app4 
     for f in $^ ; do echo $$f is here ; done

或(稍微好一点)

APPS = app1 app2 app3 app4
foo : $(APPS)
     for f in $(APPS); do echo $$f is here; done

您可能对 make 中的 foreach function 感兴趣(或者可能是它的 eval function,可能与其他东西混合在一起)

最后,您的makefile(或其中的某些部分included)可以由某些(shell,AWK,Python,...)脚本(甚至是另一个用C++,Java,Ocaml编码的程序,无论您想要)

我建议使用remake,作为remake -x,来调试你的Makefile

您还可以生成一些 submakefile 并在某些配方中运行 $(MAKE) -f submakefile

我强烈建议您至少花一小时完整阅读documentation of GNU make,然后再在Makefile 中编写代码。您可能还需要阅读documentation of bash

最后,您可能会考虑使用其他构建自动化工具,例如 ninja(其理念不同build.ninja 文件预计会生成必须为它提供一个生成器)

对于您的下一个问题,请提供一些MCVE

【讨论】:

  • 我尝试喜欢你的答案并得到错误,make: *** No rule to make target app1',foo'. Stop. 需要任何想法?
  • 在您的问题中显示minimal reproducible example
  • 谢谢,但我照原样复制你的例子,它不工作,和以前一样的错误,它对你有用吗?
  • 我不知道,因为我还是不明白你的问题。闻起来很像XY problem
  • @BasileStarynkevitch:for $$f in $^ ; do echo $$f is here ; done 可能不是你想的那样。不是for f in $^ ; do echo $$f is here ; done,而是?另一个提案中的相同错字。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-23
相关资源
最近更新 更多