Говоря "make" игнорировать зависимости при создании главной цели
Я запускаю следующий вид конвейера:
digestA: hugefileB hugefileC
cat $^ > [email protected]
rm $^
hugefileB:
touch [email protected]
hugefileC:
touch [email protected]
Цели Огромный файл и Огромный файл очень большой и требуют много времени для вычисления (и для этого требуется сила Make). Но как только digestA был создан, нет необходимости сохранять свои зависимости: он удаляет эти зависимости, чтобы освободить место на диске.
Теперь, если я снова вызову "make", будет восстановлен огромный файл и огромный файл, тогда как digestA уже нормально.
Есть ли способ сказать "make", чтобы избежать перекомпиляции зависимостей?
ПРИМЕЧАНИЕ. Я не хочу создавать две зависимости внутри правил для "digestA".
Ответы
Ответ 1
Использовать "промежуточных файлов" функцию GNU Make:
Промежуточные файлы переделываются с использованием их правил, как и все другие файлы. Но промежуточные файлы обрабатываются по-разному двумя способами.
Первое отличие состоит в том, что происходит, если промежуточный файл не существует. Если обычный файл b не существует и make считает цель, которая зависит от b, она неизменно создает b, а затем обновляет цель из b. Но если b - промежуточный файл, тогда make может оставить достаточно достаточно одного. Он не будет беспокоить обновление b или конечную цель, если только некоторые предпосылки b не являются более новыми, чем эта цель, или есть какая-то другая причина для обновления этой цели.
Второе отличие состоит в том, что если make создает b для того, чтобы обновлять что-то еще, он удаляет b позже, после того как он больше не нужен. Следовательно, промежуточный файл, который не существовал до make, также не существует после make. делает отсылку удаления вам, печатая команду rm -f
, показывающую, какой файл он удаляет.
Обычно файл не может быть промежуточным, если он упоминается в make файле как цель или предварительное условие. Однако вы можете явно помечать файл как промежуточный, указав его как предварительное условие специальной цели .INTERMEDIATE
.. Это вступает в силу, даже если файл упоминается явно каким-то другим способом.
Вы можете предотвратить автоматическое удаление промежуточного файла, пометив его как дополнительный файл. Чтобы сделать это, перечислите его как необходимое условие для целевой цели .SECONDARY
. Когда файл является вторичным, make не будет создавать файл только потому, что он еще не существует, но make не автоматически удаляет файл. Маркировка файла как вторичного также обозначает его как промежуточное.
Итак, добавление следующей строки в Makefile должно быть достаточно:
.INTERMEDIATE : hugefileB hugefileC
Вызов make в первый раз:
$ make
touch hugefileB
touch hugefileC
cat hugefileB hugefileC > digestA
rm hugefileB hugefileC
И в следующий раз:
$ make
make: `digestA' is up to date.
Ответ 2
Если вы отметите hugefileB
и hugefileC
как промежуточные файлы, вы получите нужное поведение:
digestA: hugefileB hugefileC
cat $^ > [email protected]
hugefileB:
touch [email protected]
hugefileC:
touch [email protected]
.INTERMEDIATE: hugefileB hugefileC
Например:
$ gmake
touch hugefileB
touch hugefileC
cat hugefileB hugefileC > digestA
rm hugefileB hugefileC
$ gmake
gmake: `digestA' is up to date.
$ rm -f digestA
$ gmake
touch hugefileB
touch hugefileC
cat hugefileB hugefileC > digestA
rm hugefileB hugefileC
Обратите внимание, что вам больше не нужна явная команда rm $^
- gmake автоматически удаляет промежуточные файлы в конце сборки.
Ответ 3
Я бы рекомендовал вам создавать файлы псевдо кеша, созданные целевыми объектами hugefileB
и hugeFileC
.
Затем digestA
зависит от этих файлов кеша, потому что вы знаете, что они не изменятся снова, пока вы вручную не вызовете дорогостоящие цели.
Ответ 4
Правильный способ состоит в том, чтобы не удалять файлы, поскольку это удаляет информацию, которую использует make
, чтобы определить, следует ли пересобирать файлы.
Воссоздание их как пустых не помогает, потому что make
будет предполагать, что пустые файлы полностью построены.
Если есть способ объединить дайджесты, вы можете создать один из каждого из огромных файлов, который затем сохраняется, и огромный файл автоматически удаляется, поскольку он является промежуточным.