Как сделать один make-файл, который применяет одну и ту же команду к подкаталогам?

Для ясности, я запускаю это на Windows с GnuWin32 make,

У меня есть набор каталогов с файлами уценки на нескольких разных уровнях - теоретически они могут быть в узлах ветвления, но я думаю, что в настоящее время они находятся только в конечных узлах. У меня есть набор команд pandoc/LaTeX, чтобы превратить файлы уценки в PDF-файлы, и, очевидно, я хочу воссоздать PDF-файлы только в том случае, если файл уценки был обновлен, поэтому makefile кажется уместным.

То, что я хотел бы, это один makefile в корне, который перебирает все подкаталоги (на любую глубину) и применяет правило make, которое я укажу для запуска pandoc.

Из того, что я смог найти, recursive makefiles потребовать от вас иметь makefile в каждом подкаталоге (что похоже на административные издержки, которых я бы хотел избежать) и / или требовать, чтобы вы перечислили все подкаталоги в начале makefile (опять же, предпочел бы избежать этого).

Теоретическая структура папок:

root
|-make
|-Folder AB
|   |-File1.md
|   \-File2.md
|-Folder C
| \-File3.md
\-Folder D
  |-Folder E
  | \-File4.md
  |-Folder F
    \-File5.md

Как мне написать make-файл, чтобы справиться с этой ситуацией?

2 ответа

Решение

Вот небольшой набор правил Makefile, которые, надеюсь, помогут вам

%.pdf : %.md
        pandoc -o $@ --pdf-engine=xelatex $^

PDF_FILES=FolderA/File1.pdf FolderA/File2.pdf \
   FolderC/File3.pdf FolderD/FolderE/File4.pdf FolderD/FolderF/File5.pdf

all: ${PDF_FILES}

Позвольте мне объяснить, что здесь происходит. Сначала у нас есть шаблонное правило, которое сообщает make, как преобразовать файл Markdown в файл PDF. --pdf-engine=xelatex вариант здесь только для иллюстрации.

Затем мы должны сказать Make, какие файлы рассмотреть. Мы объединяем имена в одну переменную PDF_FILES, Это значение для этой переменной может быть создано с помощью отдельных сценариев, которые сканируют все подкаталоги для .md файлы.

Обратите внимание, что нужно быть особенно осторожным, если имена файлов или каталогов содержат пробелы.

Затем мы просим Make проверить, PDF_FILES должно быть обновлено.

Если у вас есть другие цели в вашем make-файле, убедитесь, что all это первая нешаблонная цель, или вызов make как make all

Обновление Makefile

Если shell функции работают для вас, а базовые утилиты, такие как sed и find, доступны, вы можете сделать свой make-файл динамическим с помощью одной строки.

%.pdf : %.md
        pandoc -o $@ --pdf-engine=xelatex $^

PDF_FILES:=$(shell find -name "*.md" | xargs echo | sed 's/\.md/\.pdf/g' )
all: ${PDF_FILES}

MadScientist предложил именно это в комментариях

В противном случае вы можете реализовать скрипт, используя инструменты, доступные в вашей операционной системе, и добавить дополнительную цель update: что бы вычислить список файлов и заменить строку, начинающуюся с PDF_FILES с обновленным списком файлов.

Окончательная версия кода, которая работала для Windows, основана на предложениях @DmitiChubarov и @MadScientist:

%.pdf: %.md
    pandoc $^ -o $@

PDF_FILES:=$(shell dir /s /b *.md | sed "s/\.md/\.pdf/g")

all: ${PDF_FILES}
Другие вопросы по тегам