使用不同的变量值制作多次调用另一个规则的规则

时间:2016-01-14 00:41:08

标签: makefile gnu-make

我有一个规则something,适用于变量VAR。我还有另一条规则something-all,需要运行somethingVAR设置为vars中的每个值。

vars = hello world

something:
    echo $(VAR)

something-all:
    $(foreach VAR,$(vars),something)

这不起作用,我得到

noob@work:~/Desktop$ make something-all
something something
make: something: No such file or directory
make: *** [something-all] Error 1

它应该打印hello\nworld

我过去通过从VAR检索%来使用通配符规则执行此操作,但感觉这是错误的方法。这看起来像这样:

vars = hello world

all: $(foreach VAR,$(vars),something-$(VAR))

something-%:
    echo $*

4 个答案:

答案 0 :(得分:3)

以下内容应解决您的问题

使用foreach (在sparc-solaris 2.8和windows上尝试使用GNU Make 3.80)

vars = hello world

something:
    echo $(VAR)

something-all:
    for i in $(vars); do $(MAKE) something VAR=$$i || exit 1; done

使用shell for-loop (尝试使用GNU Make 3.80和cc make on sparc-solaris 2.8)

XMLTABLE

答案 1 :(得分:3)

TL; DR:如果你想编制make,请删除GNU Make支持BSD Make。

这是个人推荐。虽然BSD Make似乎比GNU Make更受限制,因为它提供的编程设施较少,但它是much easier to program并且有few unique killer features。这就是为什么我建议使用GNU Make和BSD Make的另一种解决方案的解决方案:

在GNU Make中执行

使用GNU Make,您可以write a macro来定义目标。在Makefile中定义序列的规范方法是将序列的步骤作为依赖项添加到目标,如下面的代码片段所示:

vars= hello world

define something_t =
something: something-$(1)
something-$(1):
    @echo $(1)
endef

$(foreach _,$(vars),$(eval $(call something_t,$_)))

建议使用此组织(而不是仅定义一个目标),因为如果中断序列,您可以使用它来使任务易于恢复。 Makefile describes a job,其进度完全由文件系统的状态描述。如果每个步骤都与一个文件相关联,那么任务就很容易恢复,通常是一个编译对象,但有时也是一个空文件,触摸它表示已经通过了重要的检查点。

使用辅助宏是一种灵活的解决方案,可以适应更复杂的任务,而不仅仅是回显名称。请注意,这适用于最新版本的GNU Make(4.1)。在GNU Make 3.81上,您应该从宏定义中删除等号。

使您的示例适应BSD Make

如果这是一个选项,我建议不要使用GNU Make并将其替换为BSD Make,即way easier to programhas a short and to the point documentation,而GNU Make的文档非常详细有点不清楚,BSD Make有复杂规则集(FreeBSD Build systemBSD Owl)的工业级实例,它有一个简单且可预测的宏语言。

vars= hello world

something:
.for _var in ${vars}
    echo ${_var}
.endfor

这可以演变为支持更复杂的任务,只需通过适应的命令替换echo或使用中间步骤。

允许用户覆盖某些任务,也在BSD Make

在这个略微更高级的变体中,我们允许用户覆盖我们自己的配方,以构建目标something-hellosomething-world。 对于列表中的每个项目,如果目标something-*尚不存在,则创建目标something,并将其添加到something的依赖项中。仅当something-hello未定义时,才会发生定义这些目标的整个操作。因此,这些宏的用户可以:

  1. 覆盖something-worldsomething
  2. 的食谱
  3. 覆盖绑定到vars = hello world .if!target(depend) .for _var in ${vars} .if!target(something-${_var}) something-${_var}: echo ${_var} .endif something: something-${_var} .endfor .endif
  4. 的完整过程

    如果我们想为Make编写有用的,可重用的宏,那么实现这样的自定义可能性是必需的。不幸的是,这种自定义是nearly impossible in GNU Make

    {{1}}

答案 2 :(得分:2)

这是一种方法:

VARS := hello world
THINGS := $(addprefix something-, $(VARS))

allthings: $(THINGS)

something-%:
    echo $*

答案 3 :(得分:1)

应该不足为奇
something something

尝试运行foreach。这正是VAR扩展为的原因,因为您未在第三个表达式中引用VAR

您需要做的只是参考echo并使用命令,例如vars := hello world something-all: $(foreach VAR,$(vars),echo $(VAR);) $ make echo hello; echo world; hello world

make

注意如何用分号链接命令避免分支多个shell或 - GASP! - 递归vars := hello world something-all: echo $(foreach VAR,$(vars),$(VAR)) $ make echo hello world hello world 调用。它没有比那更好的表现。

或者,如果你的命令接受几个东西作为参数,

echo $(vars)

但这相当于超级简单的\b([A-Za-z]{2,3}(produsero|usero)+[0-9]{1,3})\b 。因此,如果想要改变您的要求以使这个简单的解决方案发挥作用,可能会有所回报。