2008-11-18 5 views
80

У меня есть следующий make-файл, который я использую для создания программы (ядро, фактически), над которой я работаю. Это с нуля, и я изучаю процесс, поэтому он не идеален, но я думаю, что он достаточно мощный на данный момент для моего уровня опыта написания make-файлов.Как я могу заставить Makefile автоматически пересобирать исходные файлы, содержащие измененный файл заголовка? (В C/C++)

AS = nasm 
CC = gcc 
LD = ld 

TARGET  = core 
BUILD  = build 
SOURCES  = source 
INCLUDE  = include 
ASM   = assembly 

VPATH = $(SOURCES) 

CFLAGS = -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions \ 
      -nostdinc -fno-builtin -I $(INCLUDE) 
ASFLAGS = -f elf 

#CFILES  = core.c consoleio.c system.c 
CFILES  = $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 
SFILES  = assembly/start.asm 

SOBJS = $(SFILES:.asm=.o) 
COBJS = $(CFILES:.c=.o) 
OBJS = $(SOBJS) $(COBJS) 

build : $(TARGET).img 

$(TARGET).img : $(TARGET).elf 
    c:/python26/python.exe concat.py stage1 stage2 pad.bin core.elf floppy.img 

$(TARGET).elf : $(OBJS) 
    $(LD) -T link.ld -o [email protected] $^ 

$(SOBJS) : $(SFILES) 
    $(AS) $(ASFLAGS) $< -o [email protected] 

%.o: %.c 
    @echo Compiling $<... 
    $(CC) $(CFLAGS) -c -o [email protected] $< 

#Clean Script - Should clear out all .o files everywhere and all that. 
clean: 
    -del *.img 
    -del *.o 
    -del assembly\*.o 
    -del core.elf 

Моя главная проблема с этим Makefile в том, что, когда я изменить заголовок файла, что один или несколько файлов C включают в себя файлы C не перестраиваются. Я могу исправить это довольно легко, имея все мои файлы заголовков зависимостями для всех моих файлов C, но это может привести к полной перестройке проекта в любое время, когда я изменил/добавил файл заголовка, что было бы не очень изящным.

То, что я хочу, это только файлы C, которые включают файл заголовка, который я изменяю, чтобы быть перестроенным, и для того, чтобы весь проект был связан снова. Я могу сделать ссылку, заставив все файлы заголовков быть зависимыми от цели, но я не могу понять, как сделать файлы C недействительными, когда их включенные файлы заголовков более новые.

Я слышал, что у GCC есть некоторые команды, чтобы сделать это возможным (так что makefile может каким-то образом определить, какие файлы нужно перестраивать), но я не могу на всю жизнь найти реальный пример реализации, чтобы посмотреть на , Может ли кто-нибудь опубликовать решение, которое позволит это поведение в make-файле?

EDIT: Я должен уточнить, я знаком с концепцией ввода индивидуальных целей и наличия каждой цели. Это требует, чтобы я редактировал make-файл каждый раз, когда я включаю файл заголовка где-то, что немного больно. Я ищу решение, которое может самостоятельно определять зависимости заголовка файла, что я вполне уверен, что видел в других проектах.

ответ

25

Как уже отмечалась в другом месте на этом сайте, видит эту страницу: http://make.paulandlesley.org/autodep.html

Короче говоря, GCC может автоматически создавать .d файлы зависимости для вас, которые являются мини-фрагментами, содержащих Makefile зависимостей файла .c вы собрали. Каждый раз, когда вы меняете файл .c и компилируете его, файл .d будет обновлен.

Помимо добавления флага -M в gcc, вам необходимо включить файлы .d в make-файл (как описано выше Крисом). На странице есть несколько более сложных проблем, которые решаются с помощью sed, но вы можете их игнорировать и выполнять «очистить», чтобы очистить файлы .d, когда вы жалуетесь на невозможность создания файла заголовка, который больше не существует.

+2

Возможно, я ошибаюсь, но я думаю, что GCC фактически добавил функцию, чтобы попытаться обойти эту проблему. Проверьте http://gcc.gnu.org/onlinedocs/gcc-4.3.1/gcc/Preprocessor-Options.html в частности -MP. – 2013-10-21 01:44:29

6

Вам нужно будет сделать отдельные цели для каждого файла C, а затем перечислить заголовочный файл как зависимость. Вы все еще можете использовать ваши общие цели, а просто место .h зависимостей потом, вот так:

%.o: %.c 
     @echo Compiling $<... 
     $(CC) $(CFLAGS) -c -o [email protected] $< 

foo.c: bar.h 
# And so on... 
3

сверх того, что @mipadi сказал, вы можете также изучить возможность использования опции «-M», чтобы создать запись зависимостей. Вы даже можете сгенерировать их в отдельный файл (возможно, «depend.mk»), который затем включаете в make-файл. Или вы можете найти правило «make depend», которое редактирует make-файл с правильными зависимостями (термины Google: «не удалять эту строку» и зависеть).

3

В принципе, вам необходимо динамически создавать правила makefile для перестройки объектных файлов при изменении файлов заголовков. Если вы используете gcc и gnumake, это довольно легко; просто введите что-то наподобие:

в вашем файле makefile.

+2

Я вроде понимаю, за исключением того, что (кроме fromt он -MM и -MG флаги являются новыми) Я не понимаю, что регулярное выражение Ищет линии загадочного текста для. Это не сделает меня товарищами по команде счастливыми ...^_^Я попробую, хотя и посмотрю, есть ли у меня какие-то результаты. – 2008-11-18 01:14:15

+0

sed сокращен для «редактора потока», который может изменять поток текста без необходимости использования файла. Это стандартный инструмент Unix и меньше и быстрее, поэтому он используется чаще, чем awk или perl. – 2008-11-18 02:05:54

+0

У меня проблема: я делаю это под Windows. – 2008-11-20 18:47:50

16

Это эквивалентно Chris Dodd's answer, но использует другое соглашение об именах (и по совпадению не требует sed магии., Скопированные из a later duplicate.


Если вы используете компилятор GNU компилятор может собрать . список зависимостей для вас Makefile фрагмент:

depend: .depend 

.depend: $(SOURCES) 
     rm -f ./.depend 
     $(CC) $(CFLAGS) -MM $^>>./.depend; 

include .depend 

Существует также инструмент makedepend, но я никогда не любил его так же, как gcc -MM

-1

Я считаю, что команда mkdep - это то, что вы хотите. Он фактически сканирует файлы .c для строк #include и создает для них дерево зависимостей. Я считаю, что проекты Automake/Autoconf используют это по умолчанию.

19

Вы можете добавить «сделать зависеть» команды, как другие утверждали, но почему бы не получить GCC для создания зависимостей и компиляции в то же время:

DEPS := $(COBJS:.o=.d) 

-include $(DEPS) 

%.o: %.c 
    $(CC) -c $(CFLAGS) -MM -MF $(patsubst %.o,%.d,[email protected]) -o [email protected] $< 

параметр «-м» указывает файл для хранения зависимостей в.

Черточка в начале '-include' сообщает Make продолжить, когда файл .d не существует (например, при первой компиляции).

Заметьте, что ошибка в gcc относительно опции -o. Если вы укажете имя файла объекта obj/_file__c.o, то сгенерированный _file_.d по-прежнему будет содержать _file_.o, а не obj/_file_c.o.

0

Ни один из ответов не работал для меня. Например. Ответ Мартина Фидо предполагает, что gcc может создать файл зависимостей, но когда я попытался создать для него пустые (нулевые байты) объектные файлы без каких-либо предупреждений или ошибок. Это может быть ошибка gcc. Я на

$ Gcc --version ССАГПЗ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)

Так вот мой полный Makefile, который работает для меня; это сочетание решений + что-то, что не было упомянуто никем еще (например, «правила замены суффикса» определяется как .cc.o :):

CC = g++ 
CFLAGS = -Wall -g -std=c++0x 
INCLUDES = -I./includes/ 

# LFLAGS = -L../lib 
# LIBS = -lmylib -lm 

# List of all source files 
SRCS = main.cc cache.cc 

# Object files defined from source files 
OBJS = $(SRCS:.cc=.o) 

# # define the executable file 
MAIN = cache_test 

#List of non-file based targets: 
.PHONY: depend clean all 

## .DEFAULT_GOAL := all 

# List of dependencies defined from list of object files 
DEPS := $(OBJS:.o=.d) 

all: $(MAIN) 

-include $(DEPS) 

$(MAIN): $(OBJS) 
    $(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS) 

#suffix replacement rule for building .o's from .cc's 
#build dependency files first, second line actually compiles into .o 
.cc.o: 
    $(CC) $(CFLAGS) $(INCLUDES) -c -MM -MF $(patsubst %.o,%.d,[email protected]) $< 
    $(CC) $(CFLAGS) $(INCLUDES) -c -o [email protected] $< 

clean: 
    $(RM) *.o *~ $(MAIN) *.d 

Примечание Я .cc .. выше Makefile легко для настройки файлов .c.

Также важно отметить важность этих двух линий:

$(CC) $(CFLAGS) $(INCLUDES) -c -MM -MF $(patsubst %.o,%.d,[email protected]) $< 
$(CC) $(CFLAGS) $(INCLUDES) -c -o [email protected] $< 

так GCC вызывается один раз для создания файла зависимостей, а затем на самом деле компилирует файл .cc. И так далее для каждого исходного файла.

0

Упрощенное решение: просто используйте Makefile для того, чтобы правило компиляции .c в .o зависело от файлов заголовков и любого другого значения в вашем проекте как зависимости.

E.g.В Makefile где:

DEPENDENCIES=mydefs.h yourdefs.h Makefile GameOfThrones.S07E01.mkv 

::: (your other Makefile statements like rules 
::: for constructing executables or libraries) 

# Compile any .c to the corresponding .o file: 
%.o: %.c $(DEPENDENCIES) 
     $(CC) $(CFLAGS) -c -o [email protected] $< 

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

  • Нет связанных вопросов^_^