在左侧和右侧都有多个变量的通用makefile规则

时间:2014-07-31 10:30:31

标签: makefile

在名称中生成具有不同变量元素的大量文件的最佳方法是什么?如果可能,想使用一个规则来生成所有文件。

在我的情况下,我特别希望从类型为animation_A_01.gif的PNG帧集生成许多动画GIF文件,这取决于frame_A_01_000.png,frame_A_01_005.png,frame_A_01_010.png等。

天真的解决方案看起来像这样:

SYSTEMS = A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ...

TIMEPOINTS = 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ...

ROTATIONS =  000 005 010 015 020 025 030 035 040 045 050 055 060 065 070 075 080 085 090 095 100 105 110 115 120 125 130 135 140 145 150 155 160 165 170 175 180 185 190 195 200 205 210 215 220 225 230 235 240 245 250 255 260 265 270 275 280 285 290 295 300 305 310 315 320 325 330 335 340 345 350 355

animation_%1_%2.gif: $(foreach ROT, $ROTATIONS, frame_%1_%2_$ROT.png)
    convert -delay 10 -loop 0 $^ $@

%1表示系统,%2表示时间。这将要求GNU make支持规则左侧的双变量,但据我所知,情况并非如此。

另一个选择是,如果您可以使用多个规则来定义与规则分开的依赖关系,如下所示:

我能想到的唯一方法是对每个案例都有一个明确的规则,这将是一个痛苦。或者我可以在python / bash / etc中编写自己的make脚本,但如果可能的话,我更愿意坚持使用GNU make。我想知道如何从纯粹的学术角度用Makefile解决这个问题。

2 个答案:

答案 0 :(得分:2)

Make在其本土领域是一个很好的工具,但如果它超出了它的舒适区域,它会迅速变得暴躁。 Makefiles的黄金法则是:保持简单;如果需要复杂化,请在规则中执行,而不是make语法。

以下内容生成一组完整的文件,一次使用GNU-Make魔术,一次以便携方式生成。

LL=a b c
NN=1 2 3

files.stamp:
    for f in $(foreach L, $(LL), $(foreach N, $(NN), file-$(L)-$(N))); do echo generate $$f; done

files2.stamp:
    for l in $(LL); do for n in $(NN); do echo generate file-$$l-$$n; done; done

如果需要使用通用目标,那么执行该操作的技术是使用与目标文件匹配的简单模式,然后在规则中对目标进行解构。因此:

# convert image-a-1.png to image-a-1.gif
image-%.gif: image-%.png
    echo $< | sed 's/image-\([a-z]*\)-\([0-9]*\).*/echo convert -l \1 -n \2 $</' | sh

这看起来有点疯狂,但是使用sed构建命令然后提供给sh的技术是非常强大的。

答案 1 :(得分:0)

这并不像你想象的那么复杂:

ROTATIONS =  000 005 010 015 ...

animation_%.gif: $(addsuffix .png, $(addprefix frame_%_,$(ROTATIONS)))
    convert -delay 10 -loop 0 $^ $@