Добавление зависимостей меняет цель на первый файл C - PullRequest
0 голосов
/ 12 марта 2012

Рассмотрим следующий make-файл:

.SUFFIXES:

SRC:=../Src
OBJ:=../Obj

# Sources
SOURCES := $(SRC)/App/a.c $(SRC)/App/b.c $(SRC)/App/c.c
HEADERS := $(wildcard $(SRC)/App/*.h)

# Directories
INC_DIRS := $(SRC)/App
OBJ_INC_DIRS := $(INC_DIRS:$(SRC)/%=$(OBJ)/%)

# Objects
OBJECTS := $(SOURCES:$(SRC)%=$(OBJ)%.obj)

# Dependencies
DEPS := $(SOURCES:$(SRC)%.c=$(OBJ)%.d)
-include $(DEPS)

GCC_INCLUDES := $(foreach directory, $(INC_DIRS), -I$(directory))

all: target

target: $(OBJECTS)
    touch target

#Objects
$(OBJ)%.c.obj: $(SRC)%.c
    @echo Compiling $@
    @touch $@

# Dependencies 
$(OBJ)%.d: $(SRC)%.c
    @echo Checking dependencies for $<
    @gcc -MM $< $(GCC_INCLUDES) -MT '$(patsubst %.d,%.c.obj,$@)' -MT '$@' -MF '$@'
    @[ ! -s $@ ] && rm -f $@

# Creating directory tree before checking dependencies    
$(DEPS):|$(OBJ_INC_DIRS)

$(OBJ_INC_DIRS):
    @mkdir $@

clean:
    echo clean
    @rm $(OBJ_INC_DIRS)

При запуске в первый раз, я получаю:

Checking dependencies for ../Src/App/a.c
Checking dependencies for ../Src/App/b.c
Checking dependencies for ../Src/App/c.c
clean
Compiling ../Obj/App/a.c.obj
Compiling ../Obj/App/b.c.obj
Compiling ../Obj/App/c.c.obj
touch target

Все нормально, но теперь, сделайте снова (без изменения какого-либо файла):

make: `../Obj/App/a.c.obj' is up to date.

Теперь, если я изменю файл ac

Checking dependencies for ../Src/App/a.c
Compiling ../Obj/App/a.c.obj

target не переделан!

Как будто мой файл ac является целью, но это не так.t ... Может кто-нибудь объяснить мне, что здесь не так?

Если я уберу включение из DEPS, я наблюдаю ожидаемое поведение ...

Спасибо


РЕДАКТИРОВАТЬ

Поместив include в конце, как упомянуто @Beta works, но теперь я добавил чистую цель и покажу результат ...

1 Ответ

1 голос
/ 12 марта 2012

Мне придется провести несколько экспериментов, чтобы быть уверенным, но я думаю, что проблема в следующем:

-include $(DEPS)
...
all: target

Вы включаете $(DEPS) перед первой целью.Поэтому, если вы измените a.c, Make увидит, что он должен перестроить a.d, тогда, поскольку он includes, этот файл должен начинаться заново, и теперь a.c.obj является более ранней целью, чем all.

Попробуйте переместить -include $(DEPS) в конец make-файла.

РЕДАКТИРОВАТЬ:
(Две маленькие точки: ваше правило clean неверно, поскольку оно пытается rmкаталог, и я бы сделал make clean; make all вместо make all, так как я не уверен, что Make обещает строить цели в заданном порядке во всех случаях.)

Да, этот make-файл перестроит DEPS даже при работе clean.Makefile includes этих файлов и имеет правило для них, поэтому, если они отсутствуют или устарели, он должен перестроить их и перезапустить, независимо от того, что является целью .Лучший способ справиться с этим - Advanced Auto-Dependency Generation ;в основном команды, которые создают файлы зависимостей, входят в правило %.obj, так что a.d является побочным эффектом сборки a.c.obj.Это сложная техника, неочевидная, но она прекрасно работает.(Дайте нам знать, если вы попробуете это и у вас возникнут проблемы с настройкой.)

...