Вопрос или проблема
У меня есть каталог с именем markdown
, который содержит файлы .md
и дополнительные подкаталоги. Я хочу сгенерировать соответствующий файл html для каждого файла md.
Этот makefile работает, но он требует отдельного каталога сборки:
SOURCES = $(shell find ./markdown -name "*.md")
HTML = $(patsubst ./markdown/%.md,./build/%.html,$(SOURCES))
all: $(HTML)
build/%.html: markdown/%.md
@echo -e "Конвертировать markdown файл [$<] в html [$@]."
Я просто хочу собирать в родительском каталоге markdown
, который является корнем проекта, так что я хочу:
./index.html
./foo/bar/hum/another.html
./markdown/index.md
./markdown/foo/bar/hum/another.md
Я ожидаю, что смогу просто удалить два вхождения “build/”, так что измененные строки будут выглядеть так:
HTML = $(patsubst ./markdown/%.md,./%.html,$(SOURCES))
и
%.html: markdown/%.md
Это работает с файлом верхнего уровня (./markdown/index.md
), но не работает с чем-либо другим (например, ./markdown/foo/bar/hum/another.md
). Почему так?
Я полагаю, ваша проблема связана с этим поведением при сопоставлении шаблонных правил:
Когда целевой шаблон не содержит косую черту (а обычно она и не содержит), имена каталогов в именах файлов удаляются из имени файла перед сравнением с целевым префиксом и суффиксом. После сравнения имени файла с целевым шаблоном имена каталогов, вместе с косой чертой, которая заканчивает их, добавляются к именам файлов-условий, сгенерированным из шаблонов условий правила шаблона и имени файла.
Вы можете либо изменить ваше шаблонное правило, чтобы цель содержала “https://stackoverflow.com/”, либо вы можете использовать статические шаблонные правила:
$(HTML) : %.html: markdown/%.md
...
Ответ или решение
Вопрос о том, как использовать Make для генерации иерархии файлов, отражающей структуру другой директории, актуален для разработчиков, работающих с автоматизациями сборки и обработки файлов в проектах. В данном случае речь идет о преобразовании файлов Markdown в HTML, с одновременным сохранением структуры директорий.
Проблема
Исходная проблема заключается в том, что вы хотите создать HTML-файлы для каждого файла .md
в директории markdown
, но разместить эти HTML-файлы в корневом каталоге проекта, сохранив при этом структуру подкаталогов. Ваш начальный Makefile работает, только если у вас есть отдельный каталог для сборки (например, build
), однако требует изменений, чтобы избежать создания вспомогательной директории.
Причины неисправности
При упрощении целевой записи в Makefile с _%.html: markdown/%.md
, вы сталкиваетесь с проблемами в файлах, находящихся на более глубоком уровне вложенности. Это связано с тем, что по умолчанию правила шаблонов в Make не учитывают подкаталоги в целевых именах, если они не разделены символом /
.
Решение
Чтобы справиться с этой проблемой, можно использовать статические шаблонные правила или прописать правила с учетом глубины вложенности. Вот пример, как это можно реализовать:
- Актуализируйте список HTML-файлов:
SOURCES = $(shell find ./markdown -name "*.md")
HTML = $(patsubst ./markdown/%.md, ./%.html, $(SOURCES))
- Определите правила генерации:
Вы можете использовать статические шаблоны с явным указанием всех целевых HTML-файлов:
all: $(HTML)
$(HTML): %.html: markdown/%.md
@echo -e "Конвертация markdown файла [$<] в html [$@]."
Пример эффективного Makefile
Вот как может выглядеть полный Makefile с учетом вышеуказанного:
SOURCES = $(shell find ./markdown -name "*.md")
HTML = $(patsubst ./markdown/%.md, ./%.html, $(SOURCES))
all: $(HTML)
# Правила для генерации HTML из Markdown
$(HTML): %.html: markdown/%.md
@echo -e "Конвертация markdown файла [$<] в html [$@]."
# Пример команды конвертации, используйте ваш инструмент
# markdown_to_html $< > $@
Заключение
С помощью указанного подхода вы сможете организовать процесс сборки в соответствии с вашими требованиями. Этот Makefile будет автоматически искать все .md
файлы внутри markdown
, и при вызове команды make
будет создавать соответствующие HTML файлы в корневом каталоге, сохраняя при этом структуру подкаталогов.
Подход, использующий паттерн правил в Make и учитывающий вложенность директорий, позволяет избежать частей кода, дублирующих логику, что обеспечивает простоту поддержки и масштабируемость.