Как мне использовать Make для генерации произвольной иерархии, которая повторяет другую?

Вопрос или проблема

У меня есть каталог с именем 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 не учитывают подкаталоги в целевых именах, если они не разделены символом /.

Решение

Чтобы справиться с этой проблемой, можно использовать статические шаблонные правила или прописать правила с учетом глубины вложенности. Вот пример, как это можно реализовать:

  1. Актуализируйте список HTML-файлов:
SOURCES = $(shell find ./markdown -name "*.md")
HTML = $(patsubst ./markdown/%.md, ./%.html, $(SOURCES))
  1. Определите правила генерации:

Вы можете использовать статические шаблоны с явным указанием всех целевых 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 и учитывающий вложенность директорий, позволяет избежать частей кода, дублирующих логику, что обеспечивает простоту поддержки и масштабируемость.

Оцените материал
Добавить комментарий

Капча загружается...