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
.)