Могу ли я упростить этот Makefile, включив файлы в подпапках? - PullRequest
0 голосов
/ 05 апреля 2020

У меня есть, например, следующий Makefile для генерации файлов PDF из файлов Markdown в подкаталогах:

FOLDERS = f1 f2 f3
.PHONY: $(FOLDERS)

f1: f1/f1.md
    cd $@ && pandoc $(notdir $^) -o $(patsubst %.md,%.pdf,$(notdir $^))

f2: f2/f2.md
    cd $@ && pandoc $(notdir $^) -o $(patsubst %.md,%.pdf,$(notdir $^))

f3: f3/f3.md
    cd $@ && pandoc $(notdir $^) -o $(patsubst %.md,%.pdf,$(notdir $^))

Ожидаемый результат состоит в том, что make f1 требует существования f1/f1.md и генерирует результирующий PDF как f1/f1.pdf. То же самое для f2 и f3. Это работает, но декларации кажутся излишне повторяющимися.

Есть ли способ объединить эти три правила в одно общее правило c? То есть без необходимости явно записывать все пути к файлам PDF или файлам Markdown, поскольку я могу динамически добавлять подпапки, и я предпочел бы просто изменить определение FOLDERS в первой строке. Я погуглил и попробовал несколько вещей, но я чувствую, что либо не могу найти правильное заклинание для использования, либо мне не хватает знания о том, как работают Makefiles. Может ли кто-нибудь указать мне правильное направление?

1 Ответ

0 голосов
/ 05 апреля 2020

Во-первых, обратите внимание, что здесь нет веских оснований использовать цели PHONY, поскольку эти правила, по-видимому, создают файлы, имена которых известны заранее. Цели, такие как f1/f1.pdf, были бы намного лучше.

К сожалению, мы не можем использовать правило шаблона, когда основа (например, f1) повторяется в предварительном условии. Но «консервированный рецепт» может сделать свое дело:

define pdf_template
$(1): $(1)/$(1).md
    cd $$@ && pandoc $$(notdir $$^) -o $$(patsubst %.md,%.pdf,$$(notdir $$^))
endef

$(eval $(call pdf_template,f1))
$(eval $(call pdf_template,f2))
$(eval $(call pdf_template,f3))

(Обратите внимание, как вы должны избегать знаков $ в шаблоне.)

Если эти $(eval...) строки выглядят слишком повторяющимися, вы можете заменить их на oop:

$(foreach folder,$(FOLDERS),$(eval $(call pdf_template,$(folder))))

РЕДАКТИРОВАТЬ: Если подумать, есть другой способ. Вы не можете создать шаблонное правило, которое использует ствол более одного раза:

$(FOLDERS): %: %/%.md
    cd $@ && ... this won't work

И вы не можете использовать automati c переменных в списке предварительных требований, потому что они еще не определены, когда они необходимы:

$(FOLDERS): $@/$@.md
    cd $@ && ... this won't work either

Но вы можете использовать их там, если вы используете Вторичное расширение , что заставляет Make расширять prereq список во второй раз:

.SECONDEXPANSION:

$(FOLDERS): $$@/$$@.md
    cd $@ && ... this works

Снова обратите внимание на экранированные символы $.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...