一個工程中的源文件可能不少,按照類型、功能、模塊分別放在若干個目錄中,爲了有效地管理軟件工程,更高效地編譯整個工程,須要用到makefile 和 make 命令工具。Linux 程序員須學會寫makefile,使用GNU make 來構建和管理本身的軟件工程,利用makefile 進行編譯,已成爲了一種在工程方面的常見編譯方法。makefile 帶來的好處是「自動化編譯」,一旦寫好,只須要一個make 命令,整個工程徹底自動編譯,極大提升軟件開發的效率。html
Target:Dependencies (tab)命令 (tab)命令
例如:前端
prinA.cpp 包含prinA.h程序員
printB.cpp 包含printB.h函數
main.cpp 包含printA.h printB.h工具
makefile:優化
main:main.o printA.o printB.o g++ -o main main.o printA.o printB.o main.o:main.cpp g++ -c main.cpp printA.o:printA.cpp g++ -c printA.cpp pritnB.o:printB.cpp g++ -c printB.cpp .PHONY : clean clean: rm *.o main
「.PHONY」表示,clean是個僞目標文件。debug
執行:makecode
g++ -c -o main.o main.cpp
g++ -c -o printA.o printA.cpp
g++ -c -o printB.o printB.cpp
g++ -o main main.o printA.o printB.ohtm
生成 main.o pritnA.o printB.o mainblog
執行:make clean
rm *.o main
刪除 全部後綴爲.o的文件 和 main 文件
GNU的make很強大,它能夠自動推導文件以及文件依賴關係後面的命令,因而咱們就不必去在每個 .o 文件後都寫上相似的命令,由於,咱們的make會自動識別,並本身推導命令。
利用make的自動推導,能夠把makefile 簡化
簡化版makefile:
main:main.o printA.o printB.o g++ -o main main.o printA.o printB.o .PHONY : clean clean: rm *.o main
只要make 看到一個.o文件,它就會自動把其依賴項.c/.cpp 加在依賴關係中,而且推導出命令:
gcc/g++ -c -o .o .c/.cpp
執行make,即可以看到推導和編譯結果:
g++ -c -o main.o main.cpp
g++ -c -o printA.o printA.cpp
g++ -c -o printB.o printB.cpp
g++ -o main main.o printA.o printB.o
要設定一個變量,只要在一行的前端寫下這個變量的名字,後面跟一個"=" 號,後面跟要是設定的這個變量的值就可.之後要引用這個變量,只寫一個"$"符號,後面是在括號裏的變量名便可.
在makefile中使用變量:
OBJS = main.o printA.o printB.o XX = g++ CC = gcc CFLAGS = -Wall -g -O TARGET = main $(TARGET):$(OBJS) $(XX) -o $(TARGET) $(CFLAGS) $(OBJS) .PHONY :clean clean: rm $(TARGET) $(OBJS)
CFLAGS = -Wall -g -O: 配置編譯器設置,並把它複製給CFLAGS變量,其中每一個部分含義爲:
- -Wall :輸出全部警告信息
- -O: 編譯時進行優化
- -g:即是編譯debug版本
亦可以使用經常使用的內部變量:
- $@:擴展成當前規則的目的文件名
- $<:擴展成依靠列表中的第一個依靠文件
- $^:擴展成整個依靠的列表
使用內部變量makefile:
OBJS = main.o printA.o printB.o XX = g++ CC = gcc CFLAGS = -Wall -g -O TARGET = main $(TARGET):$(OBJS) $(XX) -o $@ $(CFLAGS) $^ .PHONY :clean clean: rm $(TARGET) $(OBJS)
$(wildcard PATTERN...)
在makefile 中,它被展開爲已經存在的,使用空格分開的,匹配此模式的全部文件列表.若是不存在任何符合此模式的文件,函數會忽略模式字符並返回空
例子:
SOURCES = $(wildcard *.c *.cpp)
表示產生一個全部以.c .cpp 結尾的文件列表,而後存入變量SOURCES裏
(patsubst %.src , %.dst , $(dir))
表示用patsubst 把$(dir)中的變量符合後綴是 .src 所有替換成 .dst
例子:
$(patsubt %.c, %o,$(patsubt %.cpp, %.o $(SOURCES)))
這是一個嵌套使用,表示先把 $(SOURCES)中後綴符合爲.cpp 的所有替換成.o,而後再從中把後綴符合爲.c 的所有替換成 .o
總體實現把 $(SOURCES)中後綴符合爲.c 和.cpp 的所有替換成.o
字符 '%' 的意思是匹配零或若干個字符
使用函數的makefile:
XX = g++ CC = gcc CFLAGS = -Wall -g -O TARGET = main SOURCES = $(wildcard *.cpp ) OBJS = $(patsubst %.cpp,%.o, $(SOURCES)) $(TARGET):$(OBJS) $(XX) -o $@ $(CFLAGS) $^ .PHONY :clean clean: rm $(TARGET) $(OBJS)
注:以上假定全部的文件都在同一個目錄下,且沒有子目錄
在作項目時,通常文件都會分幾個目錄來存放:
include/ bin/ src/ obj/ lib/ tools/
筆者習慣建工程時,建立前面4個目錄
mkdir include bin src obj
include/ 存放頭文件
bin/ 存放可執行文件
obj/ 存放後綴爲.o 的文件
src/ 存放.c 和.cpp 的源文件
多文件目錄工程管理的makefile:
BIN = ./bin SRC = ./src OBJ = ./obj INCLUDE =./include SOURCES = $(wildcard $(SRC)/*.cpp ) #要加notdir,去掉選定源文件的目錄,不然替換會出錯 OBJS = $(patsubst %.cpp,$(OBJ)/%.o, $(notdir $(SOURCES))) TARGET = $(BIN)/main XX = g++ #-I$(INCLUDE) :$(INCLUDE)下尋找頭文件 CFLAGS = -Wall -g -I$(INCLUDE) #用全部的.o文件生成目的可執行文件 $(TARGET):$(OBJS) $(XX) -o $@ $^ #生成各個.o 文件 $(OBJ)/%.o:$(SRC)/%.cpp $(XX) -c $(CFLAGS) -o $@ $< .PHONY :clean clean: rm $(TARGET) $(OBJS)
轉載請註明原文出處:
http://www.cnblogs.com/pz-Feng/p/8289410.html
如有錯誤不當之處,望你們指正,謝謝!