Мне нужна помощь в обрезании зависимостей в make-файле - PullRequest
4 голосов
/ 31 октября 2011

Я создал make-файл для создания простой веб-страницы. Основная идея make-файла заключается в следующем:

  • Мы компилируем одну веб-страницу, index.html
  • index.html требует стилуса css main.sty, который должен быть скомпилирован
  • На странице используется ряд примеров.
    • Код для примера one живет в lib/examples/one
    • Каждый пример состоит из трех частей
      • Разметка (файл шаблона .jade)
      • Некоторый код (файл сценария .coffee)
      • Описание (файл уценки .md)
  • Сценарий сборки должен отображать каждый пример в один HTML-файл.
    • Jade, Pygments и Markdown используются для генерации трех html-файлов
    • Шаблон example.jade используется для объединения их в один файл примера.
      • example.jade необходимо скопировать в правильный каталог примера сборки, поскольку язык шаблонов может выполнять только относительный импорт. Таким образом, чтобы импортировать example/one/code.html, мы должны скопировать шаблон в example/one и включить в него code.html.
    • После завершения каждый пример x будет скомпилирован в tbuild/examples/x.html
  • Шаблон lib/index.jade перемещен в build (чтобы он мог включать файлы примеров)
  • Затем Jade используется для компиляции шаблона index.jade в html

Это немного упрощение, но так легче понять. Упрощение заключается в том, что на самом деле в каждом примере есть два файла разметки (left.html и right.html), и что файл кода выполняется через фрагменты и , используемые в качестве сценария поэтому и code.html, и code.coffee должны быть встроены в сборку.

Прямо сейчас, make-файл выглядит так:

LIB = lib
BUILD = build
LIBEX = $(LIB)/examples
BUILDEX = $(BUILD)/examples
EXAMPLES = $(addsuffix .html,$(addprefix $(BUILDEX)/,$(shell ls $(LIBEX) | grep -v '.jade')))

all: $(BUILD)/main.css index.html

index.html: $(BUILD)/index.jade $(EXAMPLES)
    jade < $< --path $< > $@

$(BUILD)/index.jade: $(LIB)/index.jade
    mkdir -p $(@D)
    cp $< $@

$(BUILD)/main.css: $(LIB)/main.sty
    mkdir -p $(@D)
    stylus -u nib < $< > $@

$(BUILDEX)/%.html: $(BUILDEX)/%/template.jade $(BUILDEX)/%/left.html $(BUILDEX)/%/right.html $(BUILDEX)/%/code.html $(BUILDEX)/%/code.coffee $(BUILDEX)/%/text.html
    jade < $< --path $< > $@

$(BUILDEX)/%/template.jade: $(LIBEX)/template.jade
    mkdir -p $(@D)
    cp $< $@

$(BUILDEX)/%/left.html: $(LIBEX)/%/left.jade
    jade < $< --path $< > $@

$(BUILDEX)/%/right.html: $(LIBEX)/%/right.jade
    jade < $< --path $< > $@

$(BUILDEX)/%/code.html: $(LIBEX)/%/code.coffee
    pygmentize -f html -o $@ $<

$(BUILDEX)/%/code.coffee: $(LIBEX)/%/code.coffee
    mkdir -p $(@D)
    cp $< $@

$(BUILDEX)/%/text.html: $(LIBEX)/%/text.md
    markdown < $< > $@

clean:
    rm index.html -f
    rm $(BUILD) -rf

Это работает, но проблема в том, что когда я нажимаю "lib / examples / intro / code.coffee" и перезапускаю make, я получаю следующее:

mkdir -p build/examples/intro
cp lib/examples/template.jade build/examples/intro/template.jade
jade < lib/examples/intro/left.jade --path lib/examples/intro/left.jade > build/examples/intro/left.html
jade < lib/examples/intro/right.jade --path lib/examples/intro/right.jade > build/examples/intro/right.html
pygmentize -f html -o build/examples/intro/code.html lib/examples/intro/code.coffee
mkdir -p build/examples/intro
cp lib/examples/intro/code.coffee build/examples/intro/code.coffee
markdown < lib/examples/intro/text.md > build/examples/intro/text.html
jade < build/examples/intro/template.jade --path build/examples/intro/template.jade > build/examples/intro.html
jade < build/index.jade --path build/index.jade > index.html
rm build/examples/intro/right.html build/examples/intro/code.coffee build/examples/intro/code.html build/examples/intro/left.html build/examples/intro/text.html build/examples/intro/template.jade

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

mkdir -p build/examples/intro
pygmentize -f html -o build/examples/intro/code.html lib/examples/intro/code.coffee
cp lib/examples/intro/code.coffee build/examples/intro/code.coffee
jade < build/examples/intro/template.jade --path build/examples/intro/template.jade > build/examples/intro.html
jade < build/index.jade --path build/index.jade > index.html

Другими словами, я спрашиваю:

  1. Что мне нужно сделать, чтобы make-файл не перестраивался слишком сильно, когда я изменял что-то маленькое?
    • В приведенном выше примере left.html, right.html и text.html перестраиваются, когда я касаюсь code.coffee. Как я могу предотвратить это?
  2. Почему команда make ставит команду rm в конце вывода? Похоже, что это может привести к некоторой реконструкции, где это не нужно.

Спасибо, что прочитали весь этот вопрос! Я знаю, что моего make-fu не хватает, поэтому любые советы о том, как очистить make-файл и уменьшить избыточность, приветствуются!

Ответы [ 3 ]

4 голосов
/ 31 октября 2011

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

.SECONDARY:

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

.SECONDARY: - это правило;это может пойти куда угодно в make-файле.По сути, если Make обнаруживает цепочку цепочек неявных правил, A-> B-> C, где A - это файл, который существует, а C - цель, он считает B промежуточный файл и удалит его.как только работа сделанаПравило .SECONDARY: блокирует удаление.

Вы можете комбинировать правила с одинаковыми командами.Это:

foo: bar
    do something $< $@

baz: quartz
    do something $< $@

quince: geef
    do something $< $@

можно переписать так:

foo: bar

baz: quartz

quince: geef

foo baz quince:
    do something $< $@

Это устранит большую избыточность в вашем make-файле и, возможно, прояснит ситуацию.

2 голосов
/ 31 октября 2011

Как упомянуто @Beta, у вас возникают проблемы с промежуточными файлами здесь.

Каждый файл, который явно не упоминается в Makefile, а скорее выводится через правило шаблона (правило с %), является промежуточным и удаляется сразу после запуска make.А затем переделать при следующем запуске.

В этом суть вашей "проблемы": файлы left.html и right.html удаляются сразу.Бета уже упоминала, что объявление их как .SECONDARY решает эту проблему, например , руководство по эксплуатации сообщает вам .

Объявляя цель .SECONDARY без каких-либо предварительных условий в любом месте Makefile (действительно: где угодно), вы объявляете все цели как вторичные - так, без автоматического удаления.

1 голос
/ 31 октября 2011

Вы также можете использовать PHONY для целей, которые не являются файлами, чтобы повысить производительность. Как all и clean. Смотрите здесь для получения дополнительной информации: Какова цель .PHONY в make-файле?

...