Makefile GNU制造中的双%

Makefile GNU制造中的双%,makefile,gnu-make,Makefile,Gnu Make,我正在尝试编写一个Makefile,它将从单个源文件生成一组“矩形”输出文件。假设我们有一个单独的SVG文件,我们想将它编译成许多PNG文件。PNG文件的创建由两个参数(即“矩形”字)控制——分辨率(高、低)和颜色(彩色、黑白)。从SVG文件创建此类PNG文件的最简单的Makefile可以如下所示: img-highres-color.png: img.svg convert --highres --color --output img-highres-color.png img.svg

我正在尝试编写一个
Makefile
,它将从单个源文件生成一组“矩形”输出文件。假设我们有一个单独的SVG文件,我们想将它编译成许多PNG文件。PNG文件的创建由两个参数(即“矩形”字)控制——分辨率(高、低)和颜色(彩色、黑白)。从SVG文件创建此类PNG文件的最简单的
Makefile
可以如下所示:

img-highres-color.png: img.svg
    convert --highres --color --output img-highres-color.png img.svg

img-highres-bw.png: img.svg
    convert --highres --bw --output img-highres-color.png img.svg

img-lowres-color.png: img.svg
    convert --lowres --color --output img-highres-color.png img.svg

img-lowres-bw.png: img.svg
    convert --lowres --bw --output img-highres-color.png img.svg
RESOLUTIONS = highres lowres
COLORS = color bw

PNG_FILES = $(foreach r, $(RESOLUTIONS), $(foreach c, $(COLORS), img-$(r)-$(c).png))

$(filter img-%-%.png, $(PNG_FILES)): img-%-%.png: img.svg
    convert --$* --$* --output img-$*-$*.png img.svg
下一步是创建使用
%
的静态模式规则。我能想到这个:

RESOLUTIONS = highres lowres
COLORS = color bw

PNG_FILES = $(foreach r, $(RESOLUTIONS), $(foreach c, $(COLORS), img-$(r)-$(c).png))

$(filter img-highres-%.png, $(PNG_FILES)): img-highres-%.png: img.svg
    convert --highres --$* --output img-highres-$*.png img.svg

$(filter img-lowres-%.png, $(PNG_FILES)): img-lowres-%.png: img.svg
    convert --lowres --$* --output img-lowres-$*.png img.svg
最后,我想创建一个静态模式规则,但这需要使用双
%
,如下所示:

img-highres-color.png: img.svg
    convert --highres --color --output img-highres-color.png img.svg

img-highres-bw.png: img.svg
    convert --highres --bw --output img-highres-color.png img.svg

img-lowres-color.png: img.svg
    convert --lowres --color --output img-highres-color.png img.svg

img-lowres-bw.png: img.svg
    convert --lowres --bw --output img-highres-color.png img.svg
RESOLUTIONS = highres lowres
COLORS = color bw

PNG_FILES = $(foreach r, $(RESOLUTIONS), $(foreach c, $(COLORS), img-$(r)-$(c).png))

$(filter img-%-%.png, $(PNG_FILES)): img-%-%.png: img.svg
    convert --$* --$* --output img-$*-$*.png img.svg
这当然不行。是否可以编写一条规则来实现这一点

以上情况是我真实情况的简化描述。重要的是,
分辨率
颜色
变量的值事先不知道。另外,您能否提供一个足够通用的解决方案来处理两个以上的维度?在上面的示例中,第三维可能是文件类型-PNG、JPG、GIF等。

您可以在此处使用
$(eval)

RESOLUTIONS=highres lowres
COLORS=color bw
PNG_FILES = $(foreach r, $(RESOLUTIONS), $(foreach c, $(COLORS), img-$(r)-$(c).png))

all: $(PNG_FILES)

# Make the rules for converting the svg into each variant.

define mkrule
img-$1-$2.png: img.svg
    @convert --$1 --$2 --output $$@ $$<
endef
$(foreach color,$(COLORS),$(foreach res,$(RESOLUTIONS),$(eval $(call mkrule,$(res),$(color)))))
分辨率=高分辨率低分辨率
颜色=颜色bw
PNG_文件=$(foreach r,$(分辨率),$(foreach c,$(颜色),img-$(r)-(c.PNG))
全部:$(PNG_文件)
#制定将svg转换为每个变量的规则。
定义mkrule
img-$1-$2.png:img.svg
@转换--$1--$2--输出$$@$$<
恩德夫
$(foreach color,$(COLORS),$(foreach res,$(RESOLUTIONS),$(eval$(调用mkrule,$(res),$(color()()))

$(eval)
允许您动态构造makefile片段并将其注入正在解析的makefile中。您应该能够使用任意多个不同的维度来扩展此功能。

您可以使用单个
%
$*
的“解包”以及如下文本操作功能:

$(filter img-%.png, $(PNG_FILES)): img-%.png: img.svg
    convert $(addprefix --,$(subst -, ,$*)) --output $@ $<
$(过滤img-%.png,$(png_文件)):img-%.png:img.svg
转换$(addprefix-,$(subst-,$*)--输出$@$<
$(subst)
-
处将
$*
拆分为单词,
$(addprefix)
依次作用于每个单词。额外好处:同样的规则也适用于两个以上的维度,只要您使用的标志中没有一个包含
-
:-)