2015-01-28 2 views
0

У меня есть make-файл с рекурсивным вызовом самому себе. Когда я впервые запускаю make, объектные файлы создаются и связаны просто отлично. Но когда я изменяю исходный файл и запускаю make снова, объекты не воссоздаются (make говорит, что цель обновлена). Мне нужно запустить make clean, а затем запустить make. Вот упрощенная версия моего Makefile, который я думаю, что включает в себя всю необходимую информацию:Рекурсивный вызов makefile не обновляет объектные файлы

PCC = mpicc 

#Locations 
OBJDIR = ./objects 

#Compiler and linker flags 
FLAGS = -g -lm 

#Object files 
SHAREDOBJS = $(addprefix $(OBJDIR)/,shared1.o shared2.o) 
SPECIFICOBJS = $(addprefix $(OBJDIR)/,specific1.o specific2.o) 

#How to compile and link 
$(OBJDIR)/%.o: %.c 
    $(PCC) -c $*.c $(EXTRA_FLAGS) -o $(OBJDIR)/$*.o 

PROGNAME: 
    $(MAKE) $(MAKEFLAGS) EXTRA_FLAGS="$(FLAGS)" PROGNAME_TARGET 

PROGNAME_TARGET: $(SHAREDOBJS) $(SPECIFICOBJS) 
    $(PCC) $(SHAREDOBJS) $(SPECIFICOBJS) $(EXTRA_FLAGS) -o PROGNAME 

Так работает make PROGNAME первый раз компилирует просто отлично. Но второй возвращает make: "PROGNAME" is up to date.

Мне кажется, что рекурсивный вызов никогда не производится. Например, если я добавлю echo прямо перед вызовом, то ничего не отображается в stdout.

Почему это происходит? Почему метки времени в исходных файлах не отмечены в рекурсивном вызове? Я не понимаю, почему рекурсия нарушает зависимость от исходных файлов.

Заранее спасибо.

+1

Реальный вопрос, почему у вас есть такая рекурсивная вызов? Почему бы просто не сделать все в одном и том же вызове? Добавление рекурсии - вот что вызывает вашу проблему. Если вы действительно хотите порекомендовать рекурсию, вам нужно пометить 'PROGNAME' как' .PHONY', чтобы рекурсия произошла каждый раз. – MadScientist

+0

@MadScientist: Я хочу, чтобы исходные файлы были скомпилированы с другим набором флагов в зависимости от цели. Таким образом, у меня есть другая цель, скажем 'PROGNAME2:' где 'EXTRA_FLAGS' установлено что-то другое. Но похоже, что использование целевых переменных может быть более чистым способом. –

ответ

3

Цель PROGNAME не имеет предварительных условий.

В первый раз, когда вы make PROGNAME, Make видит, что такого файла нет, поэтому он выполняет правило.

Во второй раз (после того, как вы изменили shared1.o), Make видит, что PROGNAME уже существует и что у цели нет предпосылок, поэтому он не видит необходимости перестраивать цель. Он не знает, что PROGNAME зависит от shared1.o, потому что вы этого не говорили.

Существует более одного способа решить эту проблему. Я предлагаю вам избавиться от рекурсии полностью и использовать target-specific variable value:

PROGNAME: EXTRA_FLAGS="$(FLAGS)" 
PROGNAME: PROGNAME_TARGET 

(Ваши целевые имена могут быть улучшены, но это может подождать.)

+0

Да, это точно проблема! Не могу поверить, что я не обратил на это внимания. Изменение исходного имени файла на что-то отличное от первого имени цели легко устраняет это. Но ваш комментарий о целевых переменных - это гораздо более чистый подход. Большое спасибо! –

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