我想执行以下命令:
./a.out 1
./a.out 2
./a.out 3
./a.out 4
.
.
. and so on
Run Code Online (Sandbox Code Playgroud)
如何把这个东西写成一个循环Makefile
?
Ide*_*lic 255
如果你正在使用GNU make,你可以试试
NUMBERS = 1 2 3 4 doit: $(foreach var,$(NUMBERS),./a.out $(var);)
这将生成并执行
./a.out 1; ./a.out 2; ./a.out 3; ./a.out 4;
pax*_*blo 253
如果我假设您使用的./a.out
是UNIX类型的平台,那么下面将会这样做.
for number in 1 2 3 4 ; do \
./a.out $$number ; \
done
Run Code Online (Sandbox Code Playgroud)
测试如下:
target:
for number in 1 2 3 4 ; do \
echo $$number ; \
done
Run Code Online (Sandbox Code Playgroud)
生产:
1
2
3
4
Run Code Online (Sandbox Code Playgroud)
对于更大的范围,请使用:
target:
number=1 ; while [[ $$number -le 10 ]] ; do \
echo $$number ; \
((number = number + 1)) ; \
done
Run Code Online (Sandbox Code Playgroud)
输出1到10(包括1和10),只需将while
终止条件从10 更改为1000即可,如评论中所示,范围更大.
因此可以完成嵌套循环:
target:
num1=1 ; while [[ $$num1 -le 4 ]] ; do \
num2=1 ; while [[ $$num2 -le 3 ]] ; do \
echo $$num1 $$num2 ; \
((num2 = num2 + 1)) ; \
done ; \
((num1 = num1 + 1)) ; \
done
Run Code Online (Sandbox Code Playgroud)
生产:
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
4 1
4 2
4 3
Run Code Online (Sandbox Code Playgroud)
bob*_*ogo 102
的使用make恕我直言,主要原因是-j
标志.make -j5
将一次运行5个shell命令.如果您有4个CPU,并且对任何makefile进行了很好的测试,那么这很好.
基本上,你想让make看到类似的东西:
.PHONY: all
all: job1 job2 job3
.PHONY: job1
job1: ; ./a.out 1
.PHONY: job2
job2: ; ./a.out 2
.PHONY: job3
job3: ; ./a.out 3
Run Code Online (Sandbox Code Playgroud)
这很-j
友好(一个好兆头).你能发现锅炉板吗?我们可以写:
.PHONY: all job1 job2 job3
all: job1 job2 job3
job1 job2 job3: job%:
./a.out $*
Run Code Online (Sandbox Code Playgroud)
为了相同的效果(是的,就制造而言,这与先前的配方相同,只是更紧凑).
进一步参数化,以便您可以在命令行上指定限制(繁琐,因为make
没有任何好的算术宏,所以我会在这里作弊并使用$(shell ...)
)
LAST := 1000
NUMBERS := $(shell seq 1 ${LAST})
JOBS := $(addprefix job,${NUMBERS})
.PHONY: all ${JOBS}
all: ${JOBS} ; echo "$@ success"
${JOBS}: job%: ; ./a.out $*
Run Code Online (Sandbox Code Playgroud)
你运行它make -j5 LAST=550
,LAST
默认为1000.
小智 21
我意识到这个问题已有几年了,但这个帖子可能仍然对某人有用,因为它演示了一种与上述不同的方法,并且不依赖于shell操作,也不需要开发人员进行硬编码数值字符串.
$(eval ....)内置宏是你的朋友.或者至少可以.
define ITERATE
$(eval ITERATE_COUNT :=)\
$(if $(filter ${1},0),,\
$(call ITERATE_DO,${1},${2})\
)
endef
define ITERATE_DO
$(if $(word ${1}, ${ITERATE_COUNT}),,\
$(eval ITERATE_COUNT+=.)\
$(info ${2} $(words ${ITERATE_COUNT}))\
$(call ITERATE_DO,${1},${2})\
)
endef
default:
$(call ITERATE,5,somecmd)
$(call ITERATE,0,nocmd)
$(info $(call ITERATE,8,someothercmd)
Run Code Online (Sandbox Code Playgroud)
这是一个简单的例子.对于大值,它不会很好地扩展 - 它可以工作,但是每次迭代时ITERATE_COUNT字符串将增加2个字符(空格和点),当你进入数千时,计算单词的时间会越来越长.如上所述,它不处理嵌套迭代(您需要一个单独的迭代函数和计数器来执行此操作).这纯粹是gnu make,没有shell要求(虽然显然OP每次都想要运行一个程序 - 在这里,我只是在显示一条消息).ITERATE中的if用于捕获值0,因为$(word ...)否则会出错.
请注意,使用增长的字符串作为计数器是因为$(words ...)内置可以提供阿拉伯计数,但是make不支持数学运算(你不能将1 + 1分配给某个东西并获得2,除非你从shell调用一些东西来为你完成它,或者使用一个同样错综复杂的宏操作).这对于INCREMENTAL计数器非常有用,但对于DECREMENT计数器则不太好.
我自己不使用它,但是最近,我需要编写一个递归函数来评估多二进制,多库构建环境中的库依赖关系,当你包含一些库时你需要知道引入OTHER库本身有其他依赖项(其中一些依赖于构建参数而有所不同),我使用类似于上面的$(eval)和计数器方法(在我的情况下,计数器用于确保我们不会以某种方式进入无穷无尽的循环,并作为诊断报告需要多少迭代).
其他一些东西没有价值,虽然对OP的Q没有意义:$(eval ...)提供了一种方法来规避make对循环引用的内部憎恶,当变量是一个宏类型时,这是很好的和强制执行的(初始化为=),而不是立即赋值(用:=初始化).有时你希望能够在自己的赋值中使用变量,而$(eval ...)将使你能够做到这一点.这里要考虑的重要一点是,在运行eval时,变量会被解析,并且已解析的部分不再被视为宏.如果你知道自己在做什么,并且你试图在自己的任务的RHS上使用变量,那么这通常是你想要发生的事情.
SOMESTRING = foo
# will error. Comment out and re-run
SOMESTRING = pre-${SOMESTRING}
# works
$(eval SOMESTRING = pre${SOMESTRING}
default:
@echo ${SOMESTRING}
Run Code Online (Sandbox Code Playgroud)
快乐的化妆.
che*_*rno 19
对于跨平台支持,使命令分隔符(用于在同一行上执行多个命令)可配置.
例如,如果您在Windows平台上使用MinGW,则命令分隔符为&
:
NUMBERS = 1 2 3 4
CMDSEP = &
doit:
$(foreach number,$(NUMBERS),./a.out $(number) $(CMDSEP))
Run Code Online (Sandbox Code Playgroud)
这将在一行中执行连接命令:
./a.out 1 & ./a.out 2 & ./a.out 3 & ./a.out 4 &
Run Code Online (Sandbox Code Playgroud)
如其他地方所述,在*nix平台上使用CMDSEP = ;
.
这实际上并不是对问题的纯粹答案,而是解决此类问题的明智方法:
无需编写复杂的文件,只需将控制委托给一个bash脚本,例如:makefile
foo : bar.cpp baz.h
bash script.sh
Run Code Online (Sandbox Code Playgroud)
和script.sh看起来像:
for number in 1 2 3 4
do
./a.out $number
done
Run Code Online (Sandbox Code Playgroud)
小智 5
也许你可以使用:
xxx:
for i in `seq 1 4`; do ./a.out $$i; done;
Run Code Online (Sandbox Code Playgroud)