2015-02-06 70 views
1

目前,只有这样,我知道如何环路Makefile s是只调用shell的for循环:是否有Makefile级别的“for”循环?

BIN_TARGETS=foo bar baz 

bin: $(BIN_TARGETS) 

run: bin 
     for FILE in $(BIN_TARGETS) ; do ./$$FILE ; done 

的问题,这是make只会调用shell的for循环,呼应整个循环,然后每一个程序运行并输出其输出(如果有任何错误,他们只是在循环的末端,仅在循环中的最后一个节目报道):

$ make run 
for FILE in foo bar baz ; do ./$FILE ; done 
output of foo 
output of bar 
output of baz 

有什么Makefile -level for循环即会entially是完全等效的这个?:

run: bin 
     ./foo 
     ./bar 
     ./baz 

这将输出这样的:

$ make run 
./foo 
output of foo 
./bar 
output of bar 
./baz 
output of baz 

,并因为它发生会报告任何错误。

+0

“报告错误” 你的意思是 “中止”?因为shell循环会输出错误/ etc。当他们发生但是不会放弃他们。 – 2015-02-06 21:22:16

+0

@EtanReisner:是的,基本上。通过“报告”,我的意思是'Makefile:XX:配方'运行'失败'make:*** [run] Error 27'消息。 – Matt 2015-02-06 21:23:54

+0

你可以通过使用'./$FILE ||'来获得shell循环的失败行为。退出$?'作为我相信的循环体。 – 2015-02-06 21:25:09

回答

1

make有一个循环,但没有一个会做你想要的。

make有$(foreach)但这是一个make-level结构,它将循环使句法/等。不是shell级别的东西。

A define会让你按照你想要的方式定义配方的主体,并在你的配方中使用它,但我不能想出一种方法来从make中生成多行定义。

这将工作(根据期望的行为),但我无法得到这在创造运行期间创建。我想出了

define RECIPE 
./foo 
./bar 
./baz 
endef 

all: 
     $(RECIPE) 
+0

谢谢!我会研究'define',看看我能用它做些什么。 – Matt 2015-02-06 21:42:41

0

一种方法是使用假目标与虚构的后缀:

run: $(addsuffix .run,$(BIN_TARGETS)) 

%.run: % 
     ./$* 

然而,这时候有这样的事情foo.run多个可能的匹配变得混乱。唯一不同的是它编译并运行一个文件,然后编译并运行一个文件,而不是编译所有文件,然后运行所有文件。

1

你可以这样做:

BIN_TARGETS:=foo bar baz 

define CMD 
    $1 

endef 

bin: $(BIN_TARGETS) 

run: bin 
    $(foreach t, $(BIN_TARGETS), $(call CMD,./$(t))) 

CMD变量是必须提供的命令之间的正确分离。我还没有找到更简洁的方法。

如果foobarbaz包含:

#!/bin/bash 

echo output of $0 

然后运行make run输出:

./foo 
output of ./foo 
./bar 
output of ./bar 
./baz 
output of ./baz