2015-10-27 3 views
0

Я новичок в makefile, я готовлю этот make-файл из онлайн-примеров для создания моего проекта, и он работает. Оказывается, что, когда я запускаю его снова без изменения исходного кода, все объектные файлы повторно скомпилируются. Я думаю, что make должен только перекомпилировать те цели, которые изменили входные файлы. Почему это происходит? =. =makefile избежать перекомпиляции, когда источник не изменился

#makefile 
ROOTDIR = $(dir $(CURDIR)) 

icc iccclean: PLAT = icc 
gcc gccclean: PLAT = gcc 
clang clangclean: PLAT = clang 

icc: CC = icpc 
gcc: CC = g++ 
clang: CC = clang-omp++ 

#these are not important and I removed the details 
LIBS = 
INC = 
FLAG = 
DEF = 

icc gcc clang: run_de 

SRCDIR = $(ROOTDIR)source #path to all .cpp .h files 
OBJDIR = $(ROOTDIR)build/$(PLAT) #path of output .o files 
TARGET = $(ROOTDIR)run_de.$(PLAT) #final executable product 

#the final product depends on object files core.o eval.o file_processing.o 

run_de: $(OBJDIR)/core.o $(OBJDIR)/eval.o $(OBJDIR)/file_processing.o 
    cd $(OBJDIR); $(CC) $(LIBS) $(FLAG) $(INC) $(DEF) -o $(TARGET) core.o eval.o file_processing.o 

#rules of making the object files 

$(OBJDIR)/core.o: $(SRCDIR)/core.cpp 
    $(CC) -c $(FLAG) $(LIBS) $(INC) $(DEF) $(SRCDIR)/core.cpp -o $(OBJDIR)/core.o 
$(OBJDIR)/eval.o: $(SRCDIR)/eval.cpp 
    $(CC) -c $(FLAG) $(LIBS) $(INC) $(DEF) $(SRCDIR)/eval.cpp -o $(OBJDIR)/eval.o 
$(OBJDIR)/file_processing.o: $(SRCDIR)/file_processing.cpp 
    $(CC) -c $(FLAG) $(LIBS) $(INC) $(DEF) $(SRCDIR)/file_processing.cpp -o $(OBJDIR)/file_processing.o 

gccclean iccclean clangclean: 
    $(RM) $(OBJDIR)/*.o $(TARGET) 

.Phony: icc gcc clang iccclean gccclean clangclean 
+0

Обратите внимание, что 'make' обрабатывает' .PHONY' совсем иначе, чем '.Phony'. –

+1

Ваше правило для 'run_de' не создает файл, поэтому команды выполняются каждый раз (создавая' run_de.icc', 'run_de.gcc' или' run_de.clang') в тщетной надежде, что он создаст ' run_de'. Это не так, поэтому в следующий раз он снова пытается. Пересмотрите правило связи. –

+0

Вы имеете в виду, что имя правила 'run_de' также должно быть именем выходного файла? @JonathanLeffler –

ответ

2

Как отмечено в комментариях, я, вероятно, не стал бы беспокоиться о подкаталоге для объектных файлов. Использование этого делает сложнее писать makefile, и я ленив и не нахожу каких-либо серьезных преимуществ для работы больше, чем это необходимо.

Обратите внимание, что CC является макросом для компилятора C; CXX обычно является макросом для компилятора C++.

У меня были бы объектные файлы и исходные файлы в текущем каталоге. Тогда я бы использовать makefile подобное:

icc iccclean: PLAT = icc 
gcc gccclean: PLAT = gcc 
clang clangclean: PLAT = clang 

icc: CXX = icpc 
gcc: CXX = g++ 
clang: CXX = clang-omp++ 

LDLIBS = 
LDFLAGS = 

SOURCE = eval.cpp core.cpp file_processing.cpp 
OBJECT = ${SOURCE:.cpp=.o} 
TARGET = run_de.${PLAT} 

icc gcc clang: ${TARGET} 

${TARGET}: ${OBJECT} 
    ${CXX} -o [email protected] ${OBJECT} ${LDFLAGS} ${LDLIBS} 

gccclean iccclean clangclean: 
    $(RM) ${OBJECT} 

.PHONY: icc gcc clang iccclean gccclean clangclean 

Когда вы получили эту работу, вы можете начать переработку его любыми способами, которые вы хотите. Вам нужно будет просмотреть, какие соответствующие флаги предназначены для компиляции источника C++ в объектные файлы. Если хотите, вы можете разместить объектные файлы в других каталогах. Вы даже можете поместить исходные файлы в другой каталог. Но научитесь ходить, прежде чем начать работать.

И используйте макросы для списков файлов и т. Д., Поэтому вам не нужно повторять себя.

+0

Отсутствует правило для создания объектных файлов? –

+0

Нет: Я предполагаю, что встроенные правила работают. –

+0

ok, это означает, что LDXLS LDXLSS CXX являются обычными именами макросов, которые автоматически связаны со встроенными правилами. –

0

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

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

#makefile 
#One lesson learnt is that the makefile scope and shell command scope are different variable workspaces. 
#Commands that are after a rule name is within shell command scope. 
#variables in makefile scope are transparenet in the shell command scope. But not vice-versa. 
#variables defined or modified in shell command scope cannot be correctly retrived in the makefile scope...... 
#This is a bloody source of bugs which is v difficult to debug. 

icc iccclean: PLAT = icc 
gcc gccclean: PLAT = gcc 
clang clangclean: PLAT = clang 

icc: CC = icpc 
gcc: CC = g++ 
clang: CC = clang-omp++ 

TARGET = ../run_de.$(MAKECOMGOALS) 
SOURCE = $(wildcard ../source/*.cpp) 

OBJECT_temp = $(subst ../source/,$(MAKECMDGOALS)/,$(SOURCE)) 
OBJECT = $(subst .cpp,.o,$(OBJECT_temp)) 

LIBS = -lgsl -lgslcblas 

gcc clang: LIBS += -lm 

INC = 
clang: LIBS += -L/usr/local/Cellar/gsl/1.16/lib 
clang: INC += -I/usr/local/Cellar/boost/1.58.0/include 
clang: INC += -I/usr/local/Cellar/gsl/1.16/include -Wall -Wno-format-extra-args 

FLAG = -std=c++11 
clang gcc: FLAG += -fopenmp 
icc: FLAG += -openmp 

DEF = 
gcc icc: DEF += -DLenovoDebian 
clang: DEF += -DyuMac 
icc gcc clang: $(TARGET) 

$(TARGET): $(OBJECT) 
    $(CC) -o $(TARGET) $(OBJECT) $(LIBS) $(INC) $(FLAG) $(DEF) 

$(MAKECMDGOALS)/%.o: ../source/%.cpp 
    $(CC) -c $< -o [email protected] $(LIBS) $(INC) $(FLAG) $(DEF) 

gccclean iccclean clangclean: 
$(RM) $(PLAT)/*.o $(TARGET) 

.PHONY: icc gcc clang iccclean gccclean clangclean 
Смежные вопросы