Всегда обрабатывайте самое внешнее расширение файла (и удаляйте расширения по пути) - PullRequest
1 голос
/ 08 апреля 2019

У меня есть куча разных исходных файлов в моем статическом HTML-блоге. Внешние расширения объясняют формат, который будет обрабатываться следующим.

Пример: Исходный файл article.html.md.gz (с целью article.html) должен обрабатываться gunzip, а затем моим процессором уценки.

Более подробная информация:

  • Порядок продлений может варьироваться
  • Иногда расширение не используется (article.html.gz)
  • Я знаю, как обрабатывать все различные расширения
  • Я знаю, что окончательная форма всегда article.html

В идеале я хотел бы написать следующие правила:

...

all-articles: $(ALL_HTML_FILES)

%: %.gz
    gunzip ...

%: %.md
    markdown ...

%: %.zip
    unzip ...

И пусть make определит путь для выбора на основе последовательности расширений.

Однако из документации я понимаю, что существуют ограничения на правила соответствия всем, и вышеупомянутое невозможно.

Какой лучший путь вперед? Может ли make справиться с этой ситуацией вообще?

Расширения составляют примеры. Мои настоящие исходные файлы имеют больше смысла: -)

1 Ответ

2 голосов
/ 08 апреля 2019

Я в отпуске, поэтому я буду кусаться.

Я не фанат шаблонных правил, они слишком ограничены и в то же время слишком произвольны для моих вкусов. В чистом виде вы можете добиться того, чего хотите, в чистом виде:

.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-процессорной рабочей станции. Современная жизнь, а?

...