我在gnu make中有一个"字典"。
MY_KEYS:=foo bar baz
foo_VALUE:=thing1
bar_VALUE:=thing2
baz_VALUE:=thing3
我想要将项目输出到文件的字典,以使其看起来像...
foo=thing1
bar=thing2
baz=thing3
难度:"真实"词典的大小为几个KB,并且在Windows上排气命令线限制。
我目前的,效率低下的实施最终产生了太多的sh.exe流程,最终需要将近20秒钟的时间来发出价值几个KB的数据。
#Slow implementation
define NEWLINE
endef
list.txt:
@printf '' > $@
@$(foreach key,$(MY_KEYS),
printf '$(key)=$($(key)_VALUE)n' >> $@ $(NEWLINE) )
GNU Make 3.81中都无法使用$(文件)函数,因为这将是"显而易见的"修复。
您可以将密钥列表切成适合命令行的符号列表:
slice?=2
count?=3
$(shell echo -n 'MY_KEYS:=' > a.txt)
$(shell for i in `seq $(count)` ; do echo -n foo$$i' ' >> a.txt ; done)
$(shell echo >> a.txt)
$(shell for i in `seq $(count)` ; do echo foo$${i}_VALUE:=thing$$i >> a.txt ; done)
include a.txt
slices:=$(shell seq 1 $(slice) $(words $(MY_KEYS)))
define NEWLINE
endef
list.txt:
@echo -n > $@
@$(foreach s, $(slices), $(foreach key, $(wordlist $(s), $(shell echo $$(( $(s)+$(slice)-1 )) ), $(MY_KEYS)), echo $(key)=$($(key)_VALUE) >> $@ ; ) ${NEWLINE})
例如,在我的系统上,极限在10k和100k键之间:
x@vb:/tmp$ rm -f list.txt ; time make slice=100000 count=100000 list.txt
make: execvp: /bin/sh: Argument list too long
Makefile:19: recipe for target 'list.txt' failed
make: *** [list.txt] Error 127
real 0m4.366s
user 0m1.452s
sys 0m2.772s
切成10k子列表的工作起作用,并且仍然相当快:
x@vb:/tmp$ rm -f list.txt ; time make slice=10000 count=100000 list.txt
real 0m10.034s
user 0m3.852s
sys 0m5.788s
make 通常会直接执行命令,而不涉及壳。但是,您的食谱中的那些>>
重定向会导致使配方将食谱传递给实际的外壳。首先,加快速度是避免食谱中的壳元素,减半叉子。
单个重定向的递归制作适合这里的账单。草图:
.PHONY: dump
dump:
$(foreach _,${MY_KEYS},echo $_=${$__VALUE}${NEWLINE})
list.txt:
${MAKE} -s dump >$@
这将叉数C.F.的数量减半。幼稚版本。
所有的dump
规则确实是要回声。但是 make 无论如何都可以做到这一点(实际上,我们添加了-s
标志来停止此。
我们可以利用它来发挥自己的优势,并避免 all forks。-n
标志将获得 make 进行回声,不涉及外壳。
.PHONY: dump
dump:
$(foreach _,${MY_KEYS},$_=${$__VALUE}${NEWLINE})
list.txt:
${MAKE} -s -n dump >$@
pow!
但是,是的,升级您的 make 。这是20世纪; - )