我使用GNU make来构建报告(LaTeX for source,python for figures等)。对于目标,我使用广泛的模式匹配,例如:
all : sample1_test1.png sample2_test1.png sample2_test.png
sample%_test1.png : sample%.dat
python gen_figure.py $< $@ --test 1
sample%_test2.png : sample%.dat
python gen_figure.py $< $@ --test 2
现在,为了简化规则,我想使用多个模式组(如正则表达式组)并在构建规则中单独使用匹配项,例如:
all : sample1_test1.png sample2_test1.png sample2_test.png
sample(?P<Sample>[0-9]+)_test(?P<Test>[0-9]+).png : sample$(<Sample>).dat
python gen_figure.py $< $@ --test $(<Test>)
(语法是任意的,但重点是我可以定义两个名为Sample
和Test
的不同匹配组,并将它们用作我脚本的参数。)
我如何在make或其他构建系统(waf,scons等)中实现这一目标?
答案 0 :(得分:1)
要在GNU make中执行此操作,您可以使用GNU make支持的两种不同“元编程”模型之一:
自动生成的包含文件。在主makefile中,添加-include generated.mk
,然后编写一个包含目标generated.mk
的makefile规则(可能列出Makefile
作为先决条件),其中配方根据目标列表生成适当的目标。您可以使用shell的全部功能来构建您想要的目标列表。每次修改makefile时,都会重建包含的文件,然后GNU make会自动重新执行,这样你就不需要做任何额外的事情了。
使用GNU make的$(eval ...)
函数(可能与$(call ...)
和$(foreach ...)
结合使用)来自动评估规则。要执行此操作,请使用define ... enddef
为规则定义“模板”,并在要提供参数的位置安装变量,然后使用$(call ...)
实例化它们,对结果使用$(eval ...)
call
,并在每个目标的循环中执行。例如:$(foreach T,$(TARGETS),$(eval $(call DEFINERULE,$(T))))
以下是方法1的示例。假设您在makefile中有此预定义内容:
TESTS := sample1_test1.png sample2_test1.png sample2_test.png
然后你可以使用这个makefile来获得类似上面的内容:
all: $(TESTS)
-include generated.mk
generated.mk : Makefile
@rm -f '$@'
@for t in $(TESTS); do \
eval `echo "$$t" | sed 's/^sample\([0-9]*\)_test\([0-9]*\).*/sample=\1 test=\2/'`; \
echo "$$t : sample$$sample.dat ; python gen_figure.py \$$< \$$@ --test $$test" >> '$@'; \
done
注意我刚刚写下了这篇文章,但我认为它会起作用。