万能makefile深入浅出- 第一篇
生活随笔
收集整理的這篇文章主要介紹了
万能makefile深入浅出- 第一篇
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1. 本示例演示的是最簡單的,即只需編譯源文件,不需鏈接庫的makefile的編寫方式
2. 目的是幫助那些新接觸makefile的新手如何快速寫出可用的makefile,下載本例后完全可以稍作修改就可以滿足自己的需要
3.?本篇博客逐條語句分析了萬能makefile的實現,盡可能多的添加了注釋,也在一些地方進行了修改,以用于不同情況下makefile的編寫
4. 所有示例都在centos上親測編譯,運行通過的,附上完整示例下載鏈接:http://download.csdn.net/download/yzf279533105/9744371,下載解壓后,根目錄中有介紹文檔,請按照里面的步驟操作,保證可以運行成功
5. 如有任何疑問,可聯系本人QQ:279533105
以下是makefile的內容,如發現錯誤,歡迎拍磚
# 工程根目錄," PROJECT_ROOT = ./ "表當前目錄 PROJECT_ROOT = ./# 最終生成的目標文件(可執行程序)的名字 EXECUTABLE := hello_exe# 庫文件所在的目錄,沒有的話不寫內容即可 LIBDIR:=? # 庫文件所在目錄的擴展,不需擴展時不寫內容即可 LIBDIR+=?# 所需庫文件的名字(包括靜態庫和動態庫),沒有的話不寫內容即可 # 注意名字:比如需要鏈接 libmysql.a 時只需寫 mysql 即可 LIBS :=?# 本工程所有的頭文件所在的目錄,沒有的話不寫內容即可 INCLUDES:=? # 所有的頭文件所在目錄的擴展,不需擴展時不寫內容即可 INCLUDES +=?# 本工程所有源文件所在的目錄,沒有的話不寫內容即可,現在所有的源文件都在當前目錄下, # 下面的語句 " SRCS := $(wildcard *.cpp) $(wildcard $(addsuffix /*.cpp, $(SRCDIR))) "的前面部分指的就是當前目錄中所有的.cpp文件,所以在此處不可重復包含 SRCDIR:= # 所有的源文件所在目錄的擴展,不需擴展時不寫內容即可 SRCDIR +=# 生成的最終目標文件所在的目錄,會作為偽目標,如果該路徑不存在,則新建該目錄 EXECUTEDIR := $(PROJECT_ROOT)# 生成的最終目標文件的全名(帶全路徑的) EXECUTABLE := $(EXECUTEDIR)/$(EXECUTABLE)# 指定編譯器,編譯c++時,必須使用 g++ CC:=g++# 編譯參數,-g 表帶上調試信息,這樣可以調試程序 ?-Wall 表輸出警告信息 ?-O1表示優化級別為1級 CFLAGS := -g -Wall -O1 CPPFLAGS := $(CFLAGS)# 在所有的頭文件目錄前面加上 -I ,這是make包含頭文件目錄的語法要求 CPPFLAGS += $(addprefix -I,$(INCLUDES))# 可以自動推導生成源文件對頭文件的依賴關系 CPPFLAGS += -MMD# 刪除操作 RM-F := rm -f# 函數介紹 # 函數 wildcard :擴展通配符,比如下面的*符號在變量和函數中會失效,有了 wildcard 時,通配符就不會失效,比如可以使用 $(wildcard *.c) 來獲取當前目錄下的所有的.c文件名字列表 # 函數 addsuffix:加后綴函數,示例:$(addsuffix .c,foo bar)返回值是“foo.c bar.c” # 函數 addprefix:加前綴函數,示例:$(addprefix lib, mysql.a ACE.so)返回值是 "libmysql.a libACE.so" # 函數 patsubst :模式字符串替換函數,$(patsubst %.c,%.o,x.c.c bar.c) 把字符串“x.c.c bar.c”符合模式[%.c]的單詞替換成[%.o],返回結果是“x.c.o bar.o” # 函數 filter-out:反過濾函數,即過濾掉模式符合的文件后剩下的文件名字,示例 objects=main1.o foo.o main2.o bar.o? # :mains=main1.o main2.o? # :則$(filter-out $(mains),$(objects)) 返回值是“foo.o bar.o” # 以下內容不需修改 SRCS := $(wildcard *.cpp) $(wildcard $(addsuffix /*.cpp, $(SRCDIR))) # 表當前目錄的所有.cpp文件名字列表和SRCDIR所有目錄下的所有.cpp文件名字列表,即本工程的所有.cpp文件 OBJS := $(patsubst %.cpp,%.o,$(SRCS)) # 表上面所有.cpp編譯產生的.o文件 DEPS := $(patsubst %.o,%.d,$(OBJS)) # 表上面所有.cpp編譯產生的中間文件.d文件 MISSING_DEPS := $(filter-out $(wildcard $(DEPS)),$(DEPS)) # 不清楚,打印結果是所有的.d文件 MISSING_DEPS_SOURCES := $(wildcard $(patsubst %.d,%.cpp,$(MISSING_DEPS))) # 不清楚,打印結果是所有的.cpp文件# 所有的偽目標 .PHONY : all deps objs clean veryclean rebuild info# 最終的要生成的目標文件 all: $(EXECUTABLE)# 生成所有的.d中間文件 deps : $(DEPS)# 生成所有的.o中間文件 # 注意:所有的.o文件并沒有指明依賴于誰,也沒有指明哪條命令生成它們 # 這里是make的隱含規則,對于每個.o文件,make會自動調用: $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@,來生成.o文件 # 之所以生成.d文件,是因為$(CPPFLAGS)含有-MMD,編譯器會自動推導依賴信息,放在.d文件中 # 一個.cpp文件一定會生成一個.d文件和.o文件 objs : $(OBJS)# 一般清空操作,刪除所有的.o 和 .d文件 clean :@$(RM-F) $(OBJS)@$(RM-F) $(DEPS)# 徹底清空操作,注意其依賴于偽目標 clean,所以必定會先執行clean操作,再執行下面的命令(刪除最終的目標文件) veryclean: clean@$(RM-F) $(EXECUTABLE)# 重新生成,其依賴于偽目標veryclean 和 all ,即先執行veryclean操作,再執行all操作 rebuild: veryclean all# 若MISSING_DEPS為空,則產生一個偽目標,刪除所有的.o文件 ifneq ($(MISSING_DEPS),) $(MISSING_DEPS) :@$(RM-F) $(patsubst %.d,%.o,$@) endif# 將DEPS中的文件包含進來,"-"表示忽略文件不存在的錯誤 -include $(DEPS)# 打印出所有的源文件,.o文件,.d文件, info:@echo $(SRCS)@echo $(OBJS)@echo $(DEPS)@echo $(MISSING_DEPS)@echo $(MISSING_DEPS_SOURCES)# 下面是必定要執行的目標,依賴于所有的.o文件和偽目標EXECUTEDIR(生成存放最終目標的目錄) # 下面操作表示把所有的.o文件鏈接成可執行文件,-L指定鏈接庫的路徑,-l指定鏈接庫的名字 $(EXECUTABLE) : $(OBJS) $(EXECUTEDIR)$(CC) -o $(EXECUTABLE) $(OBJS) $(addprefix -L,$(LIBDIR)) $(addprefix -l,$(LIBS))# 偽目標,用于生成存放最終目標的文件目錄,-p 參數用于允許一次性創建多層次的目錄 $(EXECUTEDIR) :mkdir -p $(EXECUTEDIR) 超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的万能makefile深入浅出- 第一篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 万能makefile深入浅出 - 第二篇
- 下一篇: C/C++ 时间相关用法