Я в отпуске, поэтому я буду кусаться.
Я не фанат шаблонных правил, они слишком ограничены и в то же время слишком произвольны для моих вкусов. В чистом виде вы можете добиться того, чего хотите, в чистом виде:
.DELETE_ON_ERROR:
all: # Default target
files := a.html.md.gz b.html.gz
cmds<.gz> = gzip -d <$< >$@
cmds<.md> = mdtool $< -o $@
define rule-text # 1:suffix 2:basename
$(if $(filter undefined,$(flavor cmds<$1>)),$(error Cannot handle $1 files: [$2$1]))
$2: $2$1 ; $(value cmds<$1>)
all: $2
endef
emit-rule = $(eval $(call rule-text,$1,$2))# 1:suffix 2:basename
emit-hierachy = $(if $(suffix $2),$(call emit-rule,$1,$2)$(call emit-hierachy,$(suffix $2),$(basename $2)))# 1:suffix 2:basename
emit-rules = $(foreach _,$1,$(call emit-hierachy,$(suffix $_),$(basename $_)))# 1:list of source files
$(call emit-rules,${files})
.PHONY: all
all: ; : $@ Success
Ключом здесь является $files
для вашего списка файлов.
Этот список затем передается в emit-rules .
emit-rules передает каждый файл по одному emit-hierachy .
emit-hierachy снимает каждое расширение по очереди,
генерирует соответствующий синтаксис make , который он передает $(eval …)
.
emit-hierachy продолжается до тех пор, пока у файла не останется только одно расширение.
Таким образом a.html.md.gz
становится этим make синтаксис:
a.html.md: a.html.md.gz ; gunzip <$< >$@
a.html: a.html.md ; mdtool $< -o $@
all: a.html
Аналогично, b.html.gz
становится:
b.html: b.html.gz ; gunzip <$< >$@
all: b.html
Нейто или как?
Если вы дадите emit-rules файл с нераспознанным расширением (скажем, c.html.pp
),
Вы получаете ошибка компиляции :
1:20: *** Cannot handle .pp files: [c.html.pp]. Stop.
времени компиляции? Да, до запуска команд оболочки.
Вы можете указать make , как обрабатывать .pp
файлов, определив cmds<.pp>
: -)
Для дополнительных очков это также параллельный сейф. Таким образом, вы можете использовать -j9
на своем 8-процессорном ноутбуке и -j33
на 32-процессорной рабочей станции. Современная жизнь, а?