Это будет уродливо, но оно будет работать.
Как это часто бывает с замыкающими, наша задача разбивается на эти две проблемы:
1. конструкт список целей
2. построить их
Предположим, что у нас есть пять Md файлов, отображающих в PDF файлах (имена которых мы заранее не знаем):
file1.md => file1-v1.pdf
file2.md => file2-v1.pdf
file3.md => file3-v1.pdf
file4.md => file4-v1.pdf
file5.md => file5-v1.pdf
мы не можем использовать имена файлов в режиме реального вывода в качестве целей, потому что мы заранее не знаем их, но мы видим пять входных файлов и знать, что мы должен построить один выходной файл для каждого. На данный момент, фиктивным имя будет делать:
file1-dummy.pdf: file1.md
zap file1.md
Когда Make выполняет это правило, он производит файл file1-v1.pdf
. Тот факт, что он не создает файл с именем file1-dummy.pdf
, вызывает беспокойство, но не представляет серьезной проблемы. Мы можем превратить это в шаблонное правило:
%-dummy.pdf: %.md
zap $<
Тогда все, что мы должны сделать, это включить список существующих входных файлов (file1.md
, file2.md
, ...) в список ложных целей (file1-dummy.pdf
, file2-dummy.pdf
, ...), и построить их. Все идет нормально.
Но предположим, что некоторые из выходных файлов уже существуют.Если file2-v2.pdf
уже существует - и является новее, чем file2.md
- тогда мы предпочли бы, чтобы Make не перестраивал его (пытаясь построить file2-dummy.pdf
). В этом случае мы предпочли бы, чтобы file2-v2.pdf
быть в целевом списке, с помощью правила, которые работали так:
file2-v2.pdf: file2.md
zap $<
Это не легко превратить в шаблонное правило, потому что Make не обрабатывает символы очень ну и не может справиться с несколькими подстановочными знаками в одной фразе, не без большой неуклюжести. Но есть способ написать одно правило, которое будет охватывать оба случая. Прежде всего заметим, что мы можем получить часть переменной перед дефисом с этим ляп:
$(basename $(subst -,.,$(VAR)))
вооруженных с этим, и с secondary expansion, мы можем написать шаблонное правило, которое будет работать с обоих случаях, и построить цель список, который будет использовать его:
# There are other ways to construct these two lists, but this will do.
MD := $(wildcard *.md)
PDF := $(wildcard *.pdf)
PDFROOTS := $(basename $(subst -,.,$(basename $(PDF))))
MDROOTS := $(filter-out $(PDFROOTS), $(basename $(MD)))
TARGETS:= $(addsuffix -foo.pdf, $(MDROOTS)) $(PDF)
.SECONDEXPANSION:
%.pdf: $$(basename $$(subst -,., $$*)).md
# perform actions on $<
Готовы ли вы иметь дополнительные файлы маркеров? – Beta
Меня интересовали бы решения с и без. Очевидно, что не было бы аккуратнее, но если это невозможно ... – wannymahoots