2016-08-17 4 views
3

В make-файле программы необходимо написать правила, определяющие зависимости каждого объектного файла. Рассмотрим объектный файл fileA.o. Очевидно, что этот объектный файл зависит от исходного файла fileA.c. Но это также будет зависеть от всех файлов заголовков, которые включает этот исходный файл. Поэтому в make-файл должно быть добавлено следующее правило:О файлах зависимостей GNU make * .d

# This rule states that fileA.o depends on fileA.c (obviously), but also 
    # on the header files fileA.h, fileB.h and fileC.h 
    fileA.o: fileA.c fileA.h fileB.h fileC.h 

Обратите внимание, что правило не имеет рецепта. Можно было бы добавить к нему рецепт, но это, строго говоря, не обязательно, потому что GNU make может полагаться на неявное правило (с рецептом) для компиляции файла *.c в файл *.o.

В любом случае, написать такие правила вручную - это адская задача. Представьте себе, что работа по поддержанию правил makefile синхронизируется с операторами #include из исходного кода.

Руководство по GNU make описано в главе 4.14 «Автоматическое создание предварительных условий» - методология для автоматизации этой процедуры. Процедура начинается с генерации файла *.d для каждого исходного файла. Цитирую:

Для каждого исходного файла name.c есть Makefile name.d который перечисляет, какие файлы объектный файл name.o зависит.

В пособии продолжается:

Вот шаблонное правило для создания файла предпосылок (т.е. Makefile) называется name.d из исходного C-файла под названием name.c :

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

К сожалению, руководство не объясняет подробно, как на самом деле работает это правило. Да, он дает нужный файл name.d, но почему? Правило очень запутано.

При взгляде на это правило у меня возникает ощущение, что его рецепт будет работать ровно на Linux. Я прав? Есть ли способ сделать этот рецепт правильно запущен в Windows?

Любая помощь очень ценится :-)

ответ

6

Выход на все ошибки

@set -e; 

Удалить существующий файл DEP ([email protected] = цель = %.d)

rm -f [email protected]; 

Есть компилятор генерировать dep и вывод во временный файл, добавленный в оболочку pid ($< = first prerequisite = %.c, $$$$ ->$$ -> PID)

$(CC) -M $(CPPFLAGS) $< > [email protected]$$$$; 

Захват мишени соответствие $*.o ($* = матч шток = %), заменить его с целью последующей файла зависимостей самой, выход к DEP файла

sed 's,\($*\)\.o[ :]*,\1.o [email protected] : ,g' < [email protected]$$$$ > [email protected]; \ 

Удаление температуры отд

rm -f [email protected]$$$$ 

Давайте подключить foo, CC = gcc и CPPFLAGS = '', чтобы увидеть, что происходит после того, как делают закончил расширяющийся материал:

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

Оболочка сама будет расширяться $$ к ИДП, и последнее правило в DEP файл будет выглядеть как

foo.o foo.d : foo.c foo.h someheader.h 

Обратите внимание, что это довольно устаревший способ генерации зависимостей, если вы используете GCC или лязг вы можете generate them как часть самой компиляции с CPPFLAGS += -MMD -MP.

Скажем, у вас есть программа под названием foo:

objs := foo.o bar.o 
deps := $(objs:.o=.d) 

vpath %.c $(dir $(MAKEFILE_LIST)) 

CPPFLAGS += -MMD -MP 

foo: $(objs) 

.PHONY: clean 
clean: ; $(RM) foo $(objs) $(deps) 

-include $(deps) 

Это все, что вам нужно, встроенные правила будут делать все остальное. Очевидно, что вещи будут немного сложнее, если вы хотите, чтобы объектные файлы находились в другой папке или вы хотите строить за пределами исходного дерева.

Директива vpath позволяет запускать make в другом каталоге и создавать файлы, созданные там, например. make -f path/to/source/Makefile.

+0

Вау, большое вам спасибо за все объяснения. Я все еще полностью понимаю ваши объяснения. Но вы определенно дали мне большой импульс :-) –

+0

Я использую компилятор GCC. Итак, есть более элегантный способ генерации зависимостей? Не могли бы вы описать это? Я немного стесняюсь спрашивать об этом, потому что я знаю, что это, вероятно, потребует много вашего времени. Но я был бы так благодарен :-) –

+0

@ K.Mulier Добавил короткий пример. – user657267

Смежные вопросы