Q:

Double % in GNU Make

I'm trying to write a Makefile that will generate a "rectangular" set of output files from a single source file.  Imagine we have a single SVG file and we want to compile it to many PNG files.  The creation of the PNG files is controlled by two parameters (hence the "rectangular" word) -- resolution (high, low) and color (colorful, black-white).  The simplest Makefile that creates such PNG files out of a SVG file could look like this:
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

The next step is to create a static pattern rule that uses %.  I was able to come up with this:
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

Finally, I'd like to create a single static pattern rule, but this would require using a double %, like this:
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

This of course doesn't work.  Is it possible to write a single rule to achieve this? 
The situation above is a simplified description of my real situation.  The important thing is that the value of RESOLUTIONS and COLORS variables isn't known in advance.  Also, can you provide a solution general enough to handle more than two dimensions?  In the example above the third dimension could be the file type - PNG, JPG, GIF etc. 

A:

You can use $(eval) here:
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)))))

$(eval) allows you to dynamically construct and inject makefile fragments into the makefile being parsed.   You should be able to extend this with as many different dimensions as you like.