使用Makefile編譯帶原始碼路徑的工程

2021-10-04 08:17:30 字數 3506 閱讀 6018

昨天編譯乙個工程,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,你會發現,有些複雜的東西其實是基於很簡單的原理。...