2015-10-27 111 views
0

我是新來的makefile的東西,我從網上的例子來編譯這個makefile來構建我的項目,它的工作原理。事實證明,當我在不更改任何源代碼的情況下再次運行它時,所有目標文件都會重新編譯。我認爲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'對''PhonyY'的處理與'.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

好吧,這意味着CXX LDFLAGS LDLIBS是與內置規則自動關聯的常規宏名稱。 –

0

我花了好幾個小時纔出來一個功能正常的Makefile ......事情是有很多關於makefile的細節,導致很難注意到的錯誤。

不容易把東西放在不同的目錄中。更好的辦法是把所有東西放在一個文件夾中,除非有很強的理由。

#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 
相關問題