學習總結:工程管理與makefile
工程管理與makefile
一、為什麽需要makefile和make
一個工程中的源文件可能很多,按照類型、功能、模塊分別放在若幹個目錄中,為了有效地管理軟件工程,更高效地編譯整個工程,需要用到makefile 和 make 命令工具。Linux 程序員須學會寫makefile,使用GNU make 來構建和管理自己的軟件工程,利用makefile 進行編譯,已成為了一種在工程方面的常見編譯方法。makefile 帶來的好處是“自動化編譯”,一旦寫好,只需要一個make 命令,整個工程完全自動編譯,極大提高軟件開發的效率。
二、makefile 主要編寫規則
2.1編寫格式
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是個偽目標文件。
執行: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
生成 main.o pritnA.o printB.o main
執行:make clean
rm *.o main
刪除 所有後綴為.o的文件 和 main 文件
2.2 讓make 自動推導
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
2.3 使用變量
要設定一個變量,只要在一行的前端寫下這個變量的名字,後面跟一個"=" 號,後面跟要是設定的這個變量的值就可.以後要引用這個變量,只寫一個"$"符號,後面是在括號裏的變量名即可.
在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)
2.4 使用函數 wildcard patsubst
wildcard 用法:
$(wildcard PATTERN...)
在makefile 中,它被展開為已經存在的,使用空格分開的,匹配此模式的所有文件列表.如果不存在任何符合此模式的文件,函數會忽略模式字符並返回空
例子:
SOURCES = $(wildcard *.c *.cpp)
表示產生一個所有以.c .cpp 結尾的文件列表,然後存入變量SOURCES裏
patsubst 用法:
(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)
註:以上假定所有的文件都在同一個目錄下,且沒有子目錄
2.5 多目錄下編譯
在做項目時,一般文件都會分幾個目錄來存放:
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
若有錯誤不當之處,望大家指正,謝謝!
學習總結:工程管理與makefile