我想执行以下命令:
./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?
当前回答
这招对我很管用:
NUM=4
a-out:
for (( i=1; i<=${NUM}; i++ )) \
do \
./a.out $$i ; \
done
其他回答
使用make的主要原因是-j标志。Make -j5将同时运行5个shell命令。如果你有4个cpu,这是一个很好的makefile测试。
基本上,你想看到的是:
.PHONY: all
all: job1 job2 job3
.PHONY: job1
job1: ; ./a.out 1
.PHONY: job2
job2: ; ./a.out 2
.PHONY: job3
job3: ; ./a.out 3
这是-j友好的(一个好迹象)。你能认出那个锅炉盘吗?我们可以写成:
.PHONY: all job1 job2 job3
all: job1 job2 job3
job1 job2 job3: job%:
./a.out $*
为了达到同样的效果(是的,就make而言,这与前面的公式相同,只是更紧凑一点)。
进一步的参数化,这样你就可以在命令行上指定一个限制(因为make没有任何好的算术宏,所以我在这里作弊,使用$(shell…)))
LAST := 1000
NUMBERS := $(shell seq 1 ${LAST})
JOBS := $(addprefix job,${NUMBERS})
.PHONY: all ${JOBS}
all: ${JOBS} ; echo "$@ success"
${JOBS}: job%: ; ./a.out $*
您可以使用make -j5 LAST=550运行该命令,其中LAST默认为1000。
一个简单的、独立于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})
为了跨平台支持,让命令分隔符(用于在同一行上执行多个命令)成为可配置的。
例如,如果你在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 =;
这招对我很管用:
NUM=4
a-out:
for (( i=1; i<=${NUM}; i++ )) \
do \
./a.out $$i ; \
done
这个答案,就像@Vroomfondel的答案一样,旨在以优雅的方式规避循环问题。
我的想法是让make生成循环本身作为一个导入的makefile,就像这样:
include Loop.mk
Loop.mk:Loop.sh
Loop.sh > $@
shell脚本可以像你喜欢的那样高级,但可以是一个最小的工作示例
#!/bin/bash
LoopTargets=""
NoTargest=5
for Target in `seq $NoTargest` ; do
File="target_${Target}.dat"
echo $File:data_script.sh
echo $'\t'./data_script.ss $Target
LoopTargets="$LoopTargets $File"
done
echo;echo;echo LoopTargets:=$LoopTargets
生成文件
target_1.dat:data_script.sh
./data_script.ss 1
target_2.dat:data_script.sh
./data_script.ss 2
target_3.dat:data_script.sh
./data_script.ss 3
target_4.dat:data_script.sh
./data_script.ss 4
target_5.dat:data_script.sh
./data_script.ss 5
LoopTargets:= target_1.dat target_2.dat target_3.dat target_4.dat target_5.dat
这样做的好处是make本身可以跟踪已经生成的文件以及需要(重新)生成的文件。同样,这也允许make使用-j标志进行并行化。