Make не должен перестраивать глубокие зависимости - PullRequest
0 голосов
/ 19 декабря 2018

У меня есть процедура сборки, примерно описанная в следующем примере Makefile:

a: b
    @echo "Build a, just using b.  Don't care about c."
    touch a

b: c
    @echo "Constructing b from c is cheap..."
    touch b
    @echo "Once accomplished, I no longer need c."

c:
    @echo "Constructing c is very expensive..."
    @echo "Work work work..."
    touch c

clean:
    $(RM) a b c

example: clean
    make a
    $(RM)   c
    make a

Дело в том, что мне нужно c, чтобы собрать b, но как только у меня будет b, я никогда не будуснова нужно c.Когда я make example, make делает c, b и a (как и ожидалось), удаляет c, а затем, в последнем вызове make a, просто переделывает c (и НЕ переделывает b и a, хотя я бы подумал, что они устарели).Но, поскольку моя цель - a, а b не изменилась, я не хочу переделывать c.Забудь об этом!Какая разница!a следует считать актуальным.

Другая особенность заключается в том, что когда я

make a
rm c
make a

(а не make example), во втором вызове makeперестраивает все (в то время как в make example второй вызов просто перестраивает c).

Как мне помешать make построить c, когда его цель a и все a 'Непосредственные предпосылки существуют и более свежи, чем они (a не устарела по сравнению с b), даже если предпосылки предварительных условий нет?

Редактировать: Я думаю, что я могу хотетьдолжен обрабатывать каждый файл как старый (например, с --old-file) , если этот файл не существует .

Ответы [ 2 ]

0 голосов
/ 21 декабря 2018

Похоже, вы хотите, чтобы make рассматривал файл c как промежуточный файл, файл, который не имеет для вас никакого значения, кроме как промежуточный результат при создании другого файла или других файлов.Эта концепция объясняется в разделе 10.4 Цепи неявных правил руководства.Поскольку в вашем примере не используются какие-либо неявные правила, вы можете вручную пометить файл c как .INTERMEDIATE.

. Этот make-файл показывает c в качестве промежуточного файла.

a: b
        @echo "Build a, just using b.  Dont care about c."
        touch a

b: c
        @echo "Constructing b from c is cheap..."
        touch b
        @echo "Once accomplished, I no longer need c."

c: d
        @echo "Constructing c is very expensive..."
        @echo "Work work work..."
        touch c

.INTERMEDIATE: c
.PRECIOUS: c

Я добавил файл d на основе вашего комментария , хотя в этом примере он не нужен.

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

$ touch d
$ make
Constructing c is very expensive...
Work work work...
touch c
Constructing b from c is cheap...
touch b
Once accomplished, I no longer need c.
Build a, just using b.  Dont care about c.
touch a

Теперь удаление c не окажет никакого влияния на сборку:

$ rm c
$ make
make: `a' is up to date.

Кроме того, поведение обновления на основедля зависимостей «как обычно».

.PRECIOUS target является необязательным.Это встроенная команда, которая инструктирует make не удалять промежуточный файл с именем c.Вы можете сами убедиться, что произойдет, если вы удалите эту строку.

0 голосов
/ 20 декабря 2018

b может быть построен из c, но вы не хотите сказать Make, что b зависит от c - если b просто существует, то этого достаточно.Таким образом, вы можете написать b рецепт как

b:
    $(MAKE) c
    @echo "Constructing b from c is cheap..."
    touch b
    @echo "Once accomplished, I no longer need c."

или если c это только , используемый при создании b, вы можете просто сложить команды для создания c в рецепт для b и не подвергать существованию c для создания вообще.

Может быть, есть более элегантные способы выразить это, не вызывая подмоделей.И если у c есть какие-то предпосылки, которые приведут к его перестройке, если они будут обновлены, я думаю, их также нужно будет перечислить в качестве пререквизитов b.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...