Makefile GNU: несколько выходов из одного правила + предотвращение удаления промежуточных файлов - PullRequest
13 голосов
/ 15 июня 2010

Это своего рода продолжение вопроса от здесь .Проблема состоит в том, что существует правило, генерирующее несколько выходов из одного входа, и команда отнимает много времени, поэтому мы бы предпочли избежать повторного вычисления.Теперь есть еще одна особенность: мы хотим, чтобы файлы не удалялись как промежуточные файлы, а в правилах используются подстановочные знаки для учета параметров.


Было предложено следующее правило:

file-a.out: program file.in
    ./program file.in file-a.out file-b.out file-c.out

file-b.out: file-a.out
    @

file-c.out: file-b.out
    @

Затем вызов make file-c.out создает оба, и мы избегаем проблем с запуском make параллельно с переключателем -j.Пока все хорошо.


Проблема в следующем.Поскольку приведенное выше решение устанавливает цепочку в DAG, make считает это по-другому;файлы file-a.out и file-b.out обрабатываются как промежуточные файлы, и они по умолчанию удаляются как ненужные, как только file-c.out готов.

Способ избежать, который был упомянут где-то здесь, и состоитдобавление file-a.out и file-b.out в качестве зависимостей от цели .SECONDARY, что предотвращает их удаление.К сожалению, это не решает мой случай, потому что мои правила используют шаблоны шаблонов;в частности, мои правила выглядят так:

file-a-%.out: program file.in
    ./program $* file.in file-a-$*.out file-b-$*.out file-c-$*.out

file-b-%.out: file-a-%.out
    @

file-c-%.out: file-b-%.out
    @

, так что можно передать параметр, который включается в имя файла, например, с помощью

make file-c-12.out

Решение, которое *Документация 1030 * предлагает добавить их в список неявных правил в список зависимостей .PRECIOUS, тем самым не допуская удаления этих файлов.


Решение с .PRECIOUS работает, но также предотвращаетэти файлы не удаляются, если правило не выполняется и файлы неполные.Есть ли другой способ заставить эту работу?

Хак, чтобы решить эту проблему, это определить цель .SECONDARY без предварительных условий, то есть

.SECONDARY:

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

Ответы [ 2 ]

21 голосов
/ 25 июня 2010

The Simplest Thing

file-a-%.out file-b-%.out file-c-%.out: program file.in
    ./program $* file.in file-a-$*.out file-b-$*.out file-c-$*.out

будет делать именно то, что вы хотите.

(Шаблонные правила с несколькими целями отличаются от нормального правила с несколькими целями, о которых вы спрашивали о здесь . См. пример зубра в руководстве по изготовлению .)

2 голосов
/ 15 июня 2010

Если вместо одного файла file.in ваши выходные данные были сгенерированы из файла предварительных требований, который включает в себя ствол, то есть

file-a.out: program file-%.in
    ./program file-$*.in file-a-$*.out file-b-$*.out file-c-$*.out

затем вы можете создать список всех возможных совпадений с целью:

inputs = $(wildcard file-*.in)
secondaries = $(patsubst file-%.in,file-a-%.out,$(inputs)) \
    $(patsubst file-%.in,file-b-%.out,$(inputs))

Аналогично, если основа происходит от конечного набора:

batchnos = 17 18 19 20 
batchnos = $(shell seq 17 20)
secondaries = $(patsubst %,file-a-%.out,$(batchnos)) $(patsubst %,file-b-%.out,$(batchnos))

Затем просто добавьте их как предварительные требования к цели .SECONDARY

.SECONDARY: $(secondaries)
...