Makefile: порядок оценки зависимостей

Предположим, цель foo.tar, это зависит от списка файлов foo.filesнапример,

FOO_FILES := $(shell cat foo.files)

foo.tar: foo.files $(FOO_FILES)
    tar -cf foo $(FOO_FILES)

Теперь предположим, что необходимо сгенерировать foo.files, например:

foo.files: foo.files.template
    sed -e "s/@{VERSION}/$(VERSION)/" < $< > $@

Ясно, что foo.files зависит от foo.files.template, но как можно убедиться, что FOO_FILES оценивается после генерации foo.files?

3 ответа

Решение

Ваши оригинальные правила верны. Поскольку обновление foo.files приводит к устареванию значения FOO_FILES, вам просто нужно убедиться, что ваш Makefile повторно оценен gnu make, когда foo.files был обновлен, так как ваш Makefile зависит от foo.files:

Makefile : foo.files

Итак, я нашел ответ на тему Advanced Generation Dependency Generation на сайте mad-scientist.net. По сути, можно переоценить make-файл с помощью функции GNU/Make. Когда есть правило для генерации включенного make-файла, весь make-файл будет перечитан после генерации включенного файла. Таким образом -

# -*- mode: make -*-
VERSION := 1.2.3

foo.tar: foo.files $(FOO_FILES)
    tar cf $@ $(FOO_FILES)

clean:
    rm -f foo.files foo_files.mk foo.tar

foo.files: foo.files.template
    sed -e "s/@{VERSION}/$(VERSION)/" < $< > $@

# -- voodoo start here --
# This will ensure that FOO_FILES will be evaluated only
# *after* foo.files is generated.
foo_files.mk: foo.files
    echo "FOO_FILES := `xargs < $<`" > $@

include foo_files.mk
# -- voodoo ends here --

.PHONY: clean

- кажется, поступает правильно.


... и просто для полноты:

foo.files.template является:

a-$(VERSION)
b-$(VERSION)

и предполагать наличие a-1.2.3 а также b-1.2.3,

Это не может быть сделано за один проход; Make определяет, какие цели должны быть перестроены, прежде чем оно фактически выполнит какое-либо правило, и в этом случае полный список целей не существует, пока не будет выполнено одно из правил.

Это должно сделать это:

FOO_FILES := $(shell cat foo.files)

foo.tar: foo.files
    $(MAKE) foo-tarball

.PHONY: foo-tarball
foo-tarball: $(FOO_FILES)
    tar -cf foo $^

РЕДАКТИРОВАТЬ:
Как указывает ОП, это не будет работать так, как написано; Я оставил обязательное условие:

foo.tar: foo.files $(FOO_FILES)
    ...

Обратите внимание, что это будет повторяться, даже если foo.files не изменился, что не является строго необходимым; это можно исправить, но не элегантно. (Для сравнения, выбранное решение, которое, я признаю, чище моего, повторяется, даже если цель не имеет ничего общего с foo.tar.)

Другие вопросы по тегам