我想执行以下命令:
./a.out 1
./a.out 2
./a.out 3
./a.out 4
.
.
. and so on
如何写这个东西作为一个循环在Makefile?
我想执行以下命令:
./a.out 1
./a.out 2
./a.out 3
./a.out 4
.
.
. and so on
如何写这个东西作为一个循环在Makefile?
当前回答
您可以使用set -e作为for循环的前缀。例子:
all:
set -e; for a in 1 2 3; do /bin/false; echo $$a; done
Make将立即退出,退出代码<> 0。
其他回答
这招对我很管用:
NUM=4
a-out:
for (( i=1; i<=${NUM}; i++ )) \
do \
./a.out $$i ; \
done
为了跨平台支持,让命令分隔符(用于在同一行上执行多个命令)成为可配置的。
例如,如果你在Windows平台上使用MinGW,命令分隔符是&:
NUMBERS = 1 2 3 4
CMDSEP = &
doit:
$(foreach number,$(NUMBERS),./a.out $(number) $(CMDSEP))
这将在一行中执行连接的命令:
./a.out 1 & ./a.out 2 & ./a.out 3 & ./a.out 4 &
正如前面提到的,在*nix平台上使用CMDSEP =;
尽管GNUmake表工具包有一个真正的while循环(不管这在GNUmake编程中意味着什么,它有两个或三个执行阶段),如果需要的是一个迭代列表,有一个简单的解决方案,即interval。为了好玩,我们把数字也转换成十六进制:
include gmtt/gmtt.mk
# generate a list of 20 numbers, starting at 3 with an increment of 5
NUMBER_LIST := $(call interval,3,20,5)
# convert the numbers in hexadecimal (0x0 as first operand forces arithmetic result to hex) and strip '0x'
NUMBER_LIST_IN_HEX := $(foreach n,$(NUMBER_LIST),$(call lstrip,$(call add,0x0,$(n)),0x))
# finally create the filenames with a simple patsubst
FILE_LIST := $(patsubst %,./a%.out,$(NUMBER_LIST_IN_HEX))
$(info $(FILE_LIST))
输出:
./a3.out ./a8.out ./ad.out ./a12.out ./a17.out ./a1c.out ./a21.out ./a26.out ./a2b.out ./a30.out ./a35.out ./a3a.out ./a3f.out ./a44.out ./a49.out ./a4e.out ./a53.out ./a58.out ./a5d.out ./a62.out
一个简单的、独立于shell/平台的纯宏解决方案是…
# GNU make (`gmake`) compatible; ref: <https://www.gnu.org/software/make/manual>
define EOL
$()
endef
%sequence = $(if $(word ${1},${2}),$(wordlist 1,${1},${2}),$(call %sequence,${1},${2} $(words _ ${2})))
.PHONY: target
target:
$(foreach i,$(call %sequence,10),./a.out ${i}${EOL})
在循环中动态地分配变量
1 2 3 4中for数的问题;做…-solution是,在循环中没有变量可以赋值。$(eval VAR=…)只能在目标执行开始时已知赋值内容的情况下使用。如果赋值依赖于循环变量,VAR将为空。
为了避免这个问题,可以使用目标功能对循环建模。下面的例子从SRC / OBJ获取第n个文件,并将它们一起处理。使用这种结构,您甚至可以使用$(eval…)来处理循环变量,如VAR3所示。
makefile
SRC = f1.c f2.cpp f3.cpp
OBJ = f1.o f2.o f3.o
SRC2 = $(addsuffix _,$(SRC))
JOIN = $(join $(SRC2),$(OBJ))
PHONY: all
all : info loop
loop : $(JOIN)
$(JOIN) :
@# LOOP - CONTENT
@echo "TARGET: $@"
$(eval VAR1=$(word 1,$(subst _, ,$@)))
@echo "VAR1: "$(VAR1)
$(eval VAR2=$(word 2,$(subst _, ,$@)))
@echo "VAR2: "$(VAR2)
$(eval VAR3=$(subst .o,.x,$(VAR2)))
@echo "You can even substitute you loop variable VAR3: "$(VAR3)
#g++ -o $(VAR2) $(VAR1)
@echo
PHONY: info
info:
@printf "\n"
@echo "JOIN: "$(JOIN)
@printf "\n"
输出
$ make
JOIN: f1.c_f1.o f2.cpp_f2.o f3.cpp_f3.o
TARGET: f1.c_f1.o
VAR1: f1.c
VAR2: f1.o
You can even substitute you loop variable VAR3: f1.x
#g++ -o f1.o f1.c
TARGET: f2.cpp_f2.o
VAR1: f2.cpp
VAR2: f2.o
You can even substitute you loop variable VAR3: f2.x
#g++ -o f2.o f2.cpp
TARGET: f3.cpp_f3.o
VAR1: f3.cpp
VAR2: f3.o
You can even substitute you loop variable VAR3: f3.x
#g++ -o f3.o f3.cpp