我如何(有效地)将 GNU Make 3.81 "dictionary"输出到文件中



我在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世纪; - )

最新更新