Избегайте восстановления файлов, которые не будут меняться - PullRequest
2 голосов
/ 03 октября 2011

У меня есть Makefile с несколькими правилами этой формы

protolist.c: $(PROTOCOLS) Makefile src/genmodtable.sh
    $(SHELL) $(srcdir)/src/genmodtable.sh \
        $@ $(filter-out %Makefile %genmodtable.sh, $^)

Как видно из названия, protolist.c содержит список всех "протоколов", определенных файлами .c в $(PROTOCOLS). Содержимое этого файла формально зависит от всего в $(PROTOCOLS), Makefile и скрипте генератора, но очень редко для файла фактически изменяется при редактировании одного из этих .c файлов. Следовательно, genmodtable.sh кодируется так, чтобы не изменять метку времени protolist.c, если он не собирается вносить какие-либо изменения в его содержимое. Это заставляет Make пропустить перестроение protolist.o и его зависимостей, когда это действительно не нужно.

Это все отлично работает; проблема заключается в том, что, поскольку protolist.c теперь, кажется, устарел по отношению к его зависимостям, Make считает, что он должен пытаться регенерировать protolist.c при каждом запуске. Это не проблема производительности - скрипт очень быстрый - но это сбивает с толку поведение. Я смутно припоминаю идиому, включающую файлы временных меток, которые можно использовать, чтобы помешать Make сделать это, но я не смог ни восстановить ее, ни найти где-либо описанным. Кто-нибудь знает, что это?

(Также, если кто-нибудь может подсказать, как избавиться от этой глупой конструкции $(filter-out ...), это было бы полезно, так как это единственный GNUmakeism в этом Makefile.)

1 Ответ

3 голосов
/ 03 октября 2011

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

То, что вы хотите, это сделать, сравните отметку времени protolist.o с отметкой времени protolist.c, которая остается «старой»и примите решение запустить рецепт для protolist.c, в зависимости от отметки времени, ну, в общем, файла отметки времени, который обновляется при каждом запуске рецепта.
Чтобы сделать эту работу, вам нужно связатьдва вместе с пустым правилом.

protolist.o: protolist.c
    [...]

protolist.c: protolist.c.time ;

protolist.c.time: $(PROTOCOLS) Makefile src/genmodtable.sh
    $(SHELL) $(srcdir)/src/genmodtable.sh \
        protolist.c $(filter-out %Makefile %genmodtable.sh, $^)
    touch protolist.c.time

В моих собственных файлах make я должен объявить файлы меток времени как предварительные условия для специальной цели .PRECIOUS, чтобы make не мог удалить их, но яиспользование шаблонных правил;Я не уверен на 100%, но я думаю, что в этом нет необходимости при использовании явных правил, как здесь.

Чтобы избежать конструкции $(filter-out ...), не можете ли вы просто заменить ее на $(PROTOCOLS)?
(Хотя лично я придерживался бы Первое правило Пола Makefile'а : не беспокойтесь о написании переносимых make-файлов, используйте вместо этого переносимое make.)

...