Как автоматически создать зависимость между файлами? - PullRequest
3 голосов
/ 26 марта 2012
%.d: %.c
        @set -e; rm -f $@; \
        $(CC) -MM  $< > $@.$$$$; \
        sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
        rm -f $@.$$$$

sinclude $(SOURCES:.c=.d)

выше я видел в чьем-то блоге, но он не объясняет, как работает код для создания зависимости между файлами .c и .h в make-файле.

есть кто-то, кто объяснит мне это или предоставит какие-нибудь материалы?

Буду очень признателен за вашу помощь! Спасибо!

Ответы [ 4 ]

3 голосов
/ 26 марта 2012

Из руководства по gcc :

-M
Instead of outputting the result of preprocessing, output a rule suitable for make describing the dependencies of the main source file. ...

-MM
Like -M but do not mention header files that are found in system header directories, ...

Итак, команда здесь:

$(CC) -MM  $< > $@.$$$$; \
        sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \

Создает временный файл ($ @. $$$$, т. Е. К целевому файлу с добавленным уникальным номером) с выводом gcc -MM и с использованием sed форматирует его так, что при включении в make-файл файл зависимостей будет выглядеть как target file: [gcc generated dependencies]. Затем он удаляет исходный gcc -MM вывод.

0 голосов
/ 26 марта 2012

Для всего gobbledegook с четырьмя знаками доллара в строке и т. Д. Идея довольно проста:

  1. Чтобы создать файл xyz.d из файла xyz.c, запустите показанные команды...
  2. Строка $(CC), вероятно, должна содержать $ (CFLAGS), но предполагается, что компилятор - GCC (опция -MM не является стандартной в других местах).Флаг -MM требует, чтобы компилятор генерировал выходные данные, перечисляя заголовки (или другие файлы), включенные в источник, чтобы вы получили правильную информацию о зависимости для текущей платформы.
  3. Компилятор компилирует источник и записываетзависимости от стандартного вывода, который перенаправляется во временный файл.Раскрытие $@.$$$$ в make-файле (например), xyz.$$ в оболочке, где $$ становится PID оболочки, выполняющей скрипт.
  4. Команда sed вызываетвывод от компилятора, чтобы строка, начинающаяся с xyz.o, начиналась с xyz.o xyz (поэтому объектный файл и программа, созданные из объектного файла, зависят от файлов после двоеточия) xyz.o xyz.d, поэтомуи объектный файл, и файл зависимостей должны быть обновлены, если какой-либо из исходных файлов или файлов заголовков изменяется.
  5. Вывод записывается в xyz.d.
  6. .top и bottom.
  7. Строка sinclude считывает столько файлов .d, сколько может найти.

[ Отредактировано , чтобы исправить несоответствиеуказано бета .]

0 голосов
/ 26 марта 2012

Предположим, ваш единственный новый исходный файл - foo.c, который содержит строки

#include "foo.h"
#include "bar.h"

Make определяет, что foo.d устарел (потому что он не существует или foo.c новее), поэтому он выполняет правило.

%.d: %.c
        @set -e; rm -f $@; \
        $(CC) -MM  $< > $@.$$$$; \
        sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
        rm -f $@.$$$$

sinclude $(SOURCES:.c=.d)

Make оценивает $$$$ как $$ и передает его в оболочку;оболочка интерпретирует это как значение параметра $, который представляет собой идентификатор процесса оболочки, который правило хочет использовать для создания уникального имени файла.Это останется неизменным только в пределах одной команды , поэтому правило пишется с продолжением строки ("\").Это не очень хороший способ сделать это;если есть разные процессы, пытающиеся собрать foo.d в одно и то же время, то вы, вероятно, все равно будете в безопасности.Таким образом, мы можем переписать правило:

%.d: %.c
        @set -e; rm -f $@
        $(CC) -MM  $< > $@.temp
        sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.temp > $@
        rm -f $@.temp

sinclude $(SOURCES:.c=.d)

Мы можем обойтись без первого правила, оно на самом деле не касается вопроса.

Вторая команда, $(CC) -MM $< > $@.temp, расширяется доgcc -MM foo.c > foo.d.temp (или другой компилятор).Флаг -MM указывает компилятору составить список зависимостей:

foo.o: foo.c foo.h bar.h

Следующая строка проверяет этот список с помощью sed

sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g'

, что примерно переводится как "change * 1029"* to foo.o foo.d : ":

foo.o foo.d : foo.c foo.h bar.h

(И последняя команда удаляет временный файл.)

Это не лучший способ обработки зависимостей, так как он восстановит все %.d файлы каждый раз, когда вы запускаете Make, даже те, которые не относятся к вашей цели.Более совершенный подход - Advanced Auto-Dependency Generation .

0 голосов
/ 26 марта 2012

Фактическое отслеживание #include с выполняется препроцессором (см. -M и -MM опции ).

-M

Вместо вывода результата предварительной обработки выведите правило, подходящее для make, описывающее зависимости основного исходного файла.Препроцессор выводит одно правило make, содержащее имя объектного файла для этого исходного файла, двоеточие и имена всех включенных файлов, в том числе из параметров командной строки -include или -imacros.

-MM

Как и -M, но не упоминаются файлы заголовков, которые находятся в каталогах системных заголовков, и файлы заголовков, которые прямо или косвенно включены в такой заголовок.

Также имеется довольно хороший обзор возможных способов отслеживания зависимостей такого типа здесь .

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