昨天編譯乙個工程,makefile放在工程目錄,.cpp檔案放在/source目錄下,標頭檔案.h放在/include目錄下。遇到了幾個問題,一番修改,終於改好,整理如下:
出問題的makefile如下:
inc = -i./include
cflags := -o0 -g $(inc)
source = $(wildcard ./source/*.cpp)
cppfiles = $(notdir $(source))
obj = $(patsubst %.cpp, %.o, $(cppfiles))
exe = main
$(exe):$(obj)
g++ -std=c++11 -o $@ $^
%.o:%.cpp
g++ -std=c++11 -o $@ -c $^ -i. $(cflags)
.phony:clean
clean:
-rm $(exe) *.o
編譯結果:
make: *** no rule to make target `func1.o', needed by `main'. stop.
無法生成目標檔案main.o,是因為編譯器找不到原始檔,因為編譯器預設是在當前目錄下尋找原始檔。但我們在makefile中,通過notdir函式將原始檔的目錄清除掉了。在以上makefile中「exe = main」後面加個列印:
print:
@echo "cppfiles:"
@echo $(cppfiles)
然後執行make或make print,得到結果如下圖所示,可見用於編譯的原始檔都是不帶路徑的。
既然上面一小節的錯誤是由於編譯器找不到原始碼路徑,那如果我們把原始碼路徑保留下來呢?看下面這個makefile:
inc = -i./include
cflags := -o0 -g $(inc)
source = $(wildcard ./source/*.cpp)
#cppfiles = $(notdir $(source))
#obj = $(patsubst %.cpp, %.o, $(cppfiles))
obj = $(patsubst %.cpp, %.o, $(source))
exe = main
#print:
# @echo "cppfiles:"
# @echo $(cppfiles)
$(exe):$(obj)
g++ -std=c++11 -o $@ $^
%.o:%.cpp
g++ -std=c++11 -o $@ -c $^ -i. $(cflags)
.phony:clean
clean:
-rm $(exe) *.o
執行make,結果如下:
編譯成功,各cpp檔案對應的.o檔案都放在了原始碼路徑下,最終的可執行檔案放在當前路徑。
方法1中保留了原始碼路徑,那麼如果希望編譯出來的.o檔案也放在當前路徑下怎麼辦?仍然是要去掉原始碼路徑,那麼這時候編譯器去**找原始碼呢?這時候可以考慮用vpath。vpath用於設定全域性訪問路徑。make可識別乙個特殊變數「vpath」,通過"vpath"可以指定依賴檔案的搜尋路徑。變數「vpath」的定義中,使用空格或者冒號「:」將多個目錄分開,例如 vpath = include:source。make搜尋目錄的順序為:當前目錄、vpath中定義的目錄順序。
makefile如下:
vpath = ./source
inc = -i./include
cflags := -o0 -g $(inc)
source = $(wildcard ./source/*.cpp)
cppfiles = $(notdir $(source))
obj = $(patsubst %.cpp, %.o, $(cppfiles))
#obj = $(patsubst %.cpp, %.o, $(source))
exe = main
#print:
# @echo "cppfiles:"
# @echo $(cppfiles)
$(exe):$(obj)
g++ -std=c++11 -o $@ $^
%.o:%.cpp
g++ -std=c++11 -o $@ -c $^ $(cflags)
.phony:clean
clean:
-rm $(exe) *.o
執行make,結果如下:
並且,編譯生成的.o檔案也都生成在了當前目錄下:
vpath比vpath更為靈活,它可以為不同型別的檔案指定不同的搜尋目錄。使用方法:
vpath pattern directories
為符合"pattern"的檔案指定搜尋路徑「directories」,多個路徑可以使用空格或者冒號":"分開。
如 vpath %.c src1 src2 或 vpath %.h inc1:inc2
使用vpath的makefile檔案如下:
vpath %.cpp ./source
inc = -i./include
cflags := -o0 -g $(inc)
source = $(wildcard ./source/*.cpp)
cppfiles = $(notdir $(source))
obj = $(patsubst %.cpp, %.o, $(cppfiles))
#obj = $(patsubst %.cpp, %.o, $(source))
exe = main
#print:
# @echo "cppfiles:"
# @echo $(cppfiles)
$(exe):$(obj)
g++ -std=c++11 -o $@ $^
%.o:%.cpp
g++ -std=c++11 -o $@ -c $^ $(cflags)
.phony:clean
clean:
-rm $(exe) *.o
編譯結果與vpath結果一致。
編譯 makefile使用
本文重在記錄makefile的使用方法,不介紹相關原理。注意 所有的makefile指令前面都需要兩個tab縮排 1.初步使用 建立工作目錄,工作目錄下建立如下兩個檔案 main.c include int main makefile 或 makefilemain.o main.c cc c mai...
關於crtmpserver編譯執行及原始碼修改
1 x86 linux版本編譯 x86平台有兩種編譯方式 使用 cmake 直接使用 make 一 使用cmake cd crtmpserver built cmake cmake make crtmpserver crtmpserver.lua 注意 crtmpserver.lua 中mediaf...
使用makefile編譯nodejs模組
使用過node gyp編譯nodejs的addon外掛程式的人,一定很好奇,node gyp到底幫你做了什麼事情,還有,如果我們自己做,難度到底如何。本文不作makefile檔案語法的講解,如果你不懂,沒關係,能看懂基本流程就好。拋開node gyp,你會發現,有些複雜的東西其實是基於很簡單的原理。...