Makefile 生成多次使用变量的不同值调用另一个规则的规则
我有一个规则Makefile 生成多次使用变量的不同值调用另一个规则的规则,makefile,gnu-make,Makefile,Gnu Make,我有一个规则something,它对变量VAR起作用。我还有另一个规则something all,需要运行something,将VAR设置为vars中的每个值 vars = hello world something: echo $(VAR) something-all: $(foreach VAR,$(vars),something) 我知道这不太管用 noob@work:~/Desktop$ make something-all something something
something
,它对变量VAR
起作用。我还有另一个规则something all
,需要运行something
,将VAR
设置为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 $*
这里有一种方法:
VARS := hello world
THINGS := $(addprefix something-, $(VARS))
allthings: $(THINGS)
something-%:
echo $*
下面的代码应该可以解决您的问题 使用foreach(在sparc solaris 2.8和windows上的GNU Make 3.80上试用) 使用shell for loop(在GNU Make 3.80上试用,在sparc solaris 2.8上试用cc Make)
毫不奇怪
vars := hello world
something-all:
$(foreach VAR,$(vars),something)
尝试运行某物。这正是foreach
扩展到的内容,因为在第三个表达式中没有引用VAR
您只需引用VAR
并使用echo
等命令即可:
vars := hello world
something-all:
$(foreach VAR,$(vars),echo $(VAR);)
$ make
echo hello; echo world;
hello
world
请注意,用分号链接命令可以避免出现多个shell或--喘息--递归进行
调用。没有比这更有效的了
或者,如果命令接受几个something作为参数
vars := hello world
something-all:
echo $(foreach VAR,$(vars),$(VAR))
$ make
echo hello world
hello world
但这相当于超级简单的echo$(vars)
。因此,跳出框框,尝试改变您的需求,使这个简单的解决方案发挥作用,这可能会有回报。TL;DR:如果您想编程make,请放弃GNU make而选择BSD make。
这是我个人的推荐。虽然BSD Make似乎比GNU Make更为有限,因为它提供的编程工具更少,但它确实是,而且有一个独特的功能。这就是我提出GNU Make解决方案和BSD Make解决方案的原因:
用GNU制作
使用GNU Make,您可以定义一个目标。在Makefile中定义序列的规范方法是将序列的步骤作为依赖项添加到目标,如下所示:
vars= hello world
define something_t =
something: something-$(1)
something-$(1):
@echo $(1)
endef
$(foreach _,$(vars),$(eval $(call something_t,$_)))
建议使用此组织(而不是仅定义一个目标),因为如果中断序列,您可以使用此组织使任务易于恢复。一种生成文件,其进程完全由文件系统的状态来描述。如果每个步骤都与一个文件相关联,那么任务就很容易恢复,通常是一个编译对象,但有时也是一个空文件,它被触摸以指示重要的检查点已经通过
使用辅助宏是一种灵活的解决方案,可以适应比重复名称更复杂的任务。请注意,这确实适用于最新版本的GNU Make(4.1)。在GNU Make 3.81上,应该从宏定义中删除等号
将您的示例改编为BSD Make
如果这是您的一个选择,我建议您放弃使用GNU Make,并用BSD Make替换它,也就是说:虽然GNU Make的文档非常冗长,而且有些不清楚,但BSD Make具有复杂规则集(or)的行业优势示例,并且它有一个简单且可预测的宏语言
vars= hello world
something:
.for _var in ${vars}
echo ${_var}
.endfor
这可以演变为支持更复杂的任务,只需用适应的命令替换echo
,或使用中间步骤即可
允许用户覆盖某些任务(也在BSD Make中)
在这个稍微高级一点的变体中,我们允许用户覆盖我们自己的方法来构建目标something hello
和something world
。
对于列表中的每个项目,如果目标something-*
不存在,则会创建它,并将其添加到something
的依赖项中。定义这些目标的整个操作只有在某些内容未定义时才会发生。因此,这些宏的用户可以:
覆盖something hello
和something world
覆盖绑定到某物的完整过程
如果我们想为Make编写有用的、可重用的宏,实现这种定制的可能性是必须的。不幸的是,这类定制很难实现
你能详细说明一下“通配符规则”的方法吗?您可能正在描述我遇到的解决方案,但您可能没有。Thx@Beta我添加了这个。@Beta现在请看,谢谢您不想使用模式规则。你说的“规范”是什么意思?@Beta:我接受GNU高级用户使用的任何规范,比如automake,和/但仍然是人类可读的用&&
编码,最后加上真的
——这就是我经常使用的。问题是它否定了并行化。@Dummy00001阅读你的评论就像阅读自己的思想一样。:)在数字2中,您需要在make调用之后添加| | exit 1
,以便传播来自子make的错误。另请参见我对Jens回答的评论:在数字1中,除了最后一个错误外,您忽略所有错误。@Dummy00001谢谢。我已经更新了答案。由于OP没有要求,我没有将其包括在样本中;但OP可能忽略了这一点。。。。你刚才剽窃了一个问题并把它作为你自己的答案吗?OP已经有了,他问是否有更好的解决方案。不,我很确定这就是我说的我不想要的解决方案。IIRC从语法中删除=也会使它在GNU make的旧版本上工作。@hkBst我只是尝试了一下。你确实是对的!还有一点需要注意:如果使用利基软件不是问题,omake是最先进的make实用程序之一。如果我没有弄错的话,在基于Debian的系统上,BSD make作为bmake
(以前是pmake
)提供
vars= hello world
define something_t =
something: something-$(1)
something-$(1):
@echo $(1)
endef
$(foreach _,$(vars),$(eval $(call something_t,$_)))
vars= hello world
something:
.for _var in ${vars}
echo ${_var}
.endfor
vars = hello world
.if!target(depend)
.for _var in ${vars}
.if!target(something-${_var})
something-${_var}:
echo ${_var}
.endif
something: something-${_var}
.endfor
.endif