To do it in GNU make, you can use one of two different "metaprogramming" models supported by GNU make:
Auto-generated include files. In your main makefile, add
-include generated.mk
then write a makefile rule with the targetgenerated.mk
(probably listingMakefile
as a prerequisite), where the recipe generates the appropriate targets based on the list of targets. You have the full power of the shell to construct your target lists however you want. Every time you modify the makefile, the included file will be rebuilt then GNU make will automatically re-exec itself so you don't have to do anything extra.Use GNU make's
$(eval ...)
function, probably combined with$(call ...)
and$(foreach ...)
, to automatically evaluate rules. To do this you define a "template" for the rule usingdefine ... enddef
, with variables installed where you want to provide arguments, then use$(call ...)
to instantiate them, use$(eval ...)
on the result of thecall
, and do it in a loop for each target. Something like:$(foreach T,$(TARGETS),$(eval $(call DEFINERULE,$(T))))
Here's an example of method 1. Suppose you have this predefined content in your makefile:
TESTS := sample1_test1.png sample2_test1.png sample2_test.png
Then you can use this makefile to get something like the above:
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
Note I just wrote this off the top of my head but I think it will work.