自動萬能makefile(linux ubuntu gcc/g++),讓makefile的編寫不在煩人
阿新 • • 發佈:2018-11-22
自動萬能makefile(linux ubuntu gcc/g++),讓makefile的編寫不在煩人
keyword: wildcard notdir patsubst findstring wordlist suffix foreach
功能:
1、自動以makefile的父目錄名為Target檔名稱
2、自動搜尋原始碼檔案(含子目錄)
3、自動搜尋標頭檔案檔案(含子目錄)
4、自動搜尋搜尋庫檔案(含子目錄)
5、無需任何設定也可以編譯可執行檔案
6、可以生成.a和.so檔案
注意:本檔案不對您的程式碼編譯結果擔負任何法律和道德責任,使用時需謹慎
另一個專案管理級別的高度自動化的makefile連結地址:
https://blog.csdn.net/guestcode/article/details/81229127
本文demo下載地址:
https://download.csdn.net/download/guestcode/10451084
######################################################### # 名稱:自動萬能makefile(linux ubuntu gcc/g++) # 作者:碼客(盧益貴) # 微信qq:48092788 # 時間:2018-5-20 # 功能: # 1、自動以makefile的父目錄名為Target檔名稱 # 2、自動搜尋原始碼檔案(含子目錄) # 3、自動搜尋標頭檔案檔案(含子目錄) # 4、自動搜尋搜尋庫檔案(含子目錄) # 5、無需任何設定也可以編譯可執行檔案 # 6、可以生成.a和.so檔案 # # 注意:本檔案不對您的程式碼編譯結果擔負任何法律和道德責任,使用時需謹慎 # ######################################################### ############################################### # 工程定義項(常用項,不設定為使用預設值) ############################################### # 目錄名後面不需要“/”,正確的:“src”,錯誤的:“src/”,下同 # 輸出的目標檔名,不需路徑資訊 Target := # 原始檔目錄,預設為src目錄,如果沒有src則為當前目錄 SrcDir := # 標頭檔案目錄,預設為lib目錄,沒有lib則等於SrcDir IncDir := # 庫檔案(*.a/*.so)和其標頭檔案的目錄,預設依次為lib\3rdparty目錄,否則為當前目錄 LibDir := # 目標檔案Target的輸出目錄 OutDir := # 臨時檔案目錄,預設時,SrcDir、LibDir都不為當前目錄時為obj,否則為當前目錄 ObjDir := # 除錯選項,任意值為除錯設定 DEBUG := ############################################### # 編譯定義項(常用項,不設定為使用預設值) ############################################### # c/c++編譯器名稱,預設為自動搜尋,有cpp檔案則為g++,否則為gcc # CC := gcc CC := # 靜態庫檔案編譯器名稱,預設為ar AR := # c編譯標誌,編譯器時gcc時設定,預設為:-Wall -O -g GccFlags := # c++編譯標誌,編譯器時g++時設定,預設為:-std=c++11 GxxFlags := # 靜態庫編譯標誌,預設為:-cr ArFlags := # 連結標誌,預設為:-lpthread -lrt LdFlags := ############################################### # 工程定義項預設值,此後為非常用項,修改需謹慎 ############################################### # 如果Target沒有定義輸出的目標檔名,則預設為makefile的父目錄名 ifeq ($(Target), ) Target := $(shell pwd)/$(lastword $(MAKEFILE_LIST)) Target := $(shell dirname $(Target)) Target := $(notdir $(Target)) endif # 如果沒有設定OutDir,預設為當前目錄 ifeq ($(OutDir), ) OutDir := . endif # 如果沒有設定SrcDir,預設為src,如果沒有src目錄則為當前目錄 ifeq ($(SrcDir), ) SrcDir := $(shell if [ -d src ]; then echo ./src; else echo .; fi;) endif # 如果沒有設定IncDir,預設為inc,如果沒有inc目錄等於SrcDir ifeq ($(IncDir), ) IncDir := $(shell if [ -d inc ]; then echo ./inc; else echo $(SrcDir); fi;) endif # 如果沒有設定LibDir,預設依次為lib\3rdparty目錄,否則為當前目錄 ifeq ($(LibDir), ) LibDir := $(shell if [ -d lib ]; then echo ./lib; else echo ; fi;) endif ifeq ($(LibDir), ) LibDir := $(shell if [ -d 3rdparty ]; then echo ./3rdparty; else echo .; fi;) endif # 如果沒有設定臨時檔案目錄,預設為obj ifeq ($(ObjDir), ) ObjDir := . ifneq ($(SrcDir), .) ifneq ($(LibDir), .) ObjDir := ./obj endif endif endif ############################################### # 編譯定義項預設值 ############################################### # c/c++編譯器名稱,預設值 # 自動搜尋原始碼檔案字尾,有cpp的則自動設定編譯器是g++,反之是gcc ifeq ($(CC), ) tmpVar := $(shell find ./ -type f -iname *.cpp) ifeq ($(tmpVar), ) CC := gcc else CC := g++ endif endif # 靜態庫編譯器預設值 ifeq ($(AR), ) AR := ar endif # c編譯標誌預設值,編譯器時gcc時設定 ifeq ($(GccFlags), ) GccFlags := -Wall -O -g endif # c++編譯標誌預設值,編譯器時g++時設定 ifeq ($(GxxFlags), ) GxxFlags := -std=c++11 endif # 編譯標誌預設值,最終使用CFlags來配置編譯選項 ifeq ($(CC), gcc) CFlags := $(GccFlags) else CFlags := $(GxxFlags) endif # 靜態庫編譯標誌預設值 ifeq ($(ArFlags), ) ArFlags := -cr endif # 連結標誌預設值 ifeq ($(ArFlags), ) LdFlags := -lpthread -lrt endif # 生成動態庫時設定 ifeq ($(suffix $(Target)), .so) CFlags += -fPIC LdFlags += -shared endif ifneq ($(DEBUG), ) CFlags += -ggdb -rdynamic else CFlags += -O2 -s endif ############################################### # 自動搜尋關聯檔案,從此處開始至結束,不建議修改 ############################################### # c/cpp檔案原始碼檔案搜尋的目錄,用於編譯設定 VPATH := $(shell find $(SrcDir) -type d) # 臨時檔案(*.o)列表,每個*.c/*.cpp對應一個*.o檔案,用於連結設定 ifeq ($(CC), gcc) ObjFiles := $(shell find $(LibDir) -type f -iname *.c) #如果庫中有原始碼檔案 ifneq ($(ObjFiles), ) VPATH += $(shell find $(LibDir) -type d) endif ObjFiles += $(shell find $(SrcDir) -type f -iname *.c) else ObjFiles := $(shell find $(LibDir) -type f -iname *.c -o -iname *.cpp) #如果庫中有原始碼檔案 ifneq ($(ObjFiles), ) VPATH += $(shell find $(LibDir) -type d) endif ObjFiles += $(shell find $(SrcDir) -type f -iname *.c -o -iname *.cpp) endif ObjFiles := $(notdir $(ObjFiles)) #去掉目錄資訊 ObjFiles := $(ObjFiles:%.c=$(ObjDir)/%.o) #每個*.c對應一個*.o檔案,並設定輸出到臨時目錄ObjDir ObjFiles := $(ObjFiles:%.cpp=$(ObjDir)/%.o) #每個*.cpp對應一個*.o檔案,並設定輸出到臨時目錄ObjDir # *.a/*.so檔案列表,用於連結設定 LibFiles := $(shell find $(LibDir) -type f -iname *.a -o -iname *.so) LibFiles := $(notdir $(LibFiles)) #去掉目錄資訊 LibFiles := $(LibFiles:lib%.a=-l%) #每個*.a庫檔名前加-l引數標誌,去掉字尾.a和字首lib LibFiles := $(LibFiles:lib%.so=-l%) #每個*.so庫檔名前加-l引數標誌,去掉字尾.so和字首lib # 所有include包含的*.h檔案所在的目錄列表,用於編譯設定 IncDirs := $(shell find $(IncDir) -type d) #*.c/*.cpp檔案所在目錄,預設每個*.c/*.cpp對應一個*.h檔案 # *.a/*.so和它們的定義檔案*.h所在的目錄列表,用於連結設定 LibDirs := $(shell find $(LibDir) -type d) IncDirs += $(LibDirs) LibDirs := $(LibDirs:%=-L%) #每個目錄名前加-I引數標誌 IncDirs := $(IncDirs:%=-I%) #每個目錄名前加-I引數標誌 ############################################### # 連結成最終檔案 ############################################### all:$(Target) $(Target): $(ObjFiles) @echo "\nlinking file: "$(Target) ifneq ($(OutDir), .) $(shell if [ ! -d $(OutDir) ]; then mkdir $(OutDir); fi;) endif ifeq ($(suffix $(Target)), .a) $(AR) $(ArFlags) -o $(OutDir)/$(Target) $^ else $(CC) $(CFlags) $^ $(LibDirs) $(LibFiles) -o $(OutDir)/$(Target) $(LdFlags) endif ############################################### # 編譯成obj檔案 ############################################### # 編譯c原始碼檔案,生成.o檔案 $(ObjDir)/%.o:%.c ifneq ($(ObjDir), .) $(shell if [ ! -d $(ObjDir) ]; then mkdir $(ObjDir); fi;) endif @echo "\ncompiling file: "$< $(CC) $(CFlags) -c $< -o
[email protected] $(IncDirs) $(ObjDir)/%.o:%.cpp ifneq ($(ObjDir), .) $(shell if [ ! -d $(ObjDir) ]; then mkdir $(ObjDir); fi;) endif @echo "\ncompiling file: "$< $(CC) $(CFlags) -c $< -o [email protected] $(IncDirs) ############################################### # 清理臨時檔案 ############################################### clean: ifeq ($(ObjDir), .) @rm -f *.o else $(shell if [ -d $(ObjDir) ]; then rm -r $(ObjDir);fi;) endif ifeq ($(OutDir), .) @rm -f $(Target) else $(shell if [ -d $(OutDir) ]; then rm -r $(OutDir);fi;) endif @echo "cleaned" .PHONY: all clean