一個通用的Makefile (這個應該是非常好的)


轉載於 : http://www.cnblogs.com/lidabo/p/4521123.html

一 makefile的作用 Makefile是用於自動編譯和鏈接的,一個工程有很多文件組成,每一個文件的改變都會導致工程的重新鏈接,但是不是所有的文件都需要重新編譯,Makefile中記錄有文件的信 息,在make時會決定在鏈接的時候需要重新編譯哪些文件。Makefile的宗旨就是:讓編譯器知道要編譯一個文件需要依賴其他的哪些文件。當那些依賴文件有了改變,編譯器會自動發現最終的生成文件已經過時,而應該重新編譯相應的模塊。 makefile帶來的好處就是—
"自動化編譯",一旦寫好,只需要一個make命令,整個工程完全自動編譯,極大的提高了軟件開發的效率。默認的情況下,make命令會在當前目錄下按順序找尋文件名為"GNUmakefile""makefile""Makefile"的文件,找到了解釋這個文件。當然也可以使用make -f DIR/makefile 來指定用於makefile文件 二 makefile語法簡述 2.1 makefile規則 target ... : dependencies ... command target目標文件,可以是Object File,也可以是執行文件,還可以是一個標簽 dependencies就是,要生成那個target所需要的文件或是目標。 command也就是make需要執行的命令。(任意的Shell命令,可以有若干行) 這是一個文件的依賴關系,也就是說,target這一個或多個的目標文件依賴於dependencies中的文件,其生成規則定義在command中。dependencies 中如果有一個以上的文件時間要比target文件要新的話,command所定義的命令就會被執行。這就是 Makefile的規則。也就是Makefile中最核心的內容。在Makefile中的命令,必須要以[Tab]鍵開始。 2.2 變量定義 Makefile中變量的定義一般有兩種: =和:=。 =符號定義的變量叫延時變量,只有在使用的時候才擴展開來; :=符號定義的變量為立即變量,一旦定義就擴展。 使用=定義的變量不能追加新值,使用:=定義的變量可以使用+=追加新值 2.3 文件指示 在Makefile使用include關鍵字可以把別的Makefile包含進來,這很像C語言的#include,被包含的文件會原模原樣的放在當前文件的包含位置。include的語法是:include <filename> filename可以是當前操作系統Shell的文件模式(可以保含路徑和通配符) 2.4 偽目標 偽目標並不是一個文件,只是一個標簽,由於偽目標不是文件,所以make無法生成它的依賴關系和決定 它是否要執行。我們只有通過顯示地指明這個目標才能讓其生效。當然,偽目標的取名不能和文件名重名,不然其就失去了偽目標的意義了。當然,為了避免和文件重名的這種情況,我們可以使用一個特殊的標記.PHONY來顯示地指明一個目標是偽目標,向make說明,不管是否有這個文件,這個目標就是偽目標。 2.5 自動化變量 $< 第一個依賴文件的名稱 $? 所有的依賴文件,以空格分開,這些依賴文件的修改日期比目標的創建日期晚 $@ 目標的完整名稱 $^ 所有的依賴文件,以空格分開,不包含重復的依賴文件 三 通用的makefile實例 工程必備: 頂層Makefile 頂層Makefile.build 子目錄Makefile 編譯過程: 從頂層開始遞歸進入子目錄,當進入到一個目錄的最底層時,開始使用GCC編譯,再將該層的所有.o文件打包成build-in.o,返回它的上一層目錄再遞歸進入子目錄,當編譯完所有的子目錄后,就開始編譯頂層的.c文件,最后將頂層的.o文件和頂層每個子目錄的build-in.o鏈接成我們的目標文件 頂層Makefile解析(隨工程而變): #----------------------------------------------指定編譯工具鏈--------------------------------------------------- CROSS_COMPILE = #指定編譯器種類 AS = $(CROSS_COMPILE)as # LD = $(CROSS_COMPILE)ld #鏈接工具 CC = $(CROSS_COMPILE)gcc #編譯工具 CPP = $(CC) -E # AR = $(CROSS_COMPILE)ar #打包工具 NM = $(CROSS_COMPILE)nm # STRIP = $(CROSS_COMPILE)strip #優化工具 OBJCOPY = $(CROSS_COMPILE)objcopy # OBJDUMP = $(CROSS_COMPILE)objdump # export AS LD CC CPP AR NM #將定義的變量導出,方便其他makefile使用 export STRIP OBJCOPY OBJDUMP #將定義的變量導出,方便其他makefile使用 CFLAGS := -Wall -O2 -g #編譯器參數 CFLAGS += -I $(shell pwd)/include #指定編譯器頭文件(根據實際項目手動修改) LDFLAGS := -lm -lfreetype -lvga #指定編譯器鏈接庫(根據實際項目手動修改) export CFLAGS LDFLAGS #將定義的變量導出,方便其他makefile使用 TOPDIR := $(shell pwd) #獲得當前程序的頂層目錄 export TOPDIR #輸出頂層目錄 TARGET := show_file #編譯后的程序名(根據實際項目手動修改) #-------------------------頂層要生成的.o文件以及頂層文件夾(根據實際項目手動修改)------------------ obj-y += main.o obj-y += display/ obj-y += draw/ obj-y += encoding/ obj-y += fonts/ #--------------------------------------------頂層的第一個規則(默認規則)----------------------------------------- all : make -C ./ -f $(TOPDIR)/Makefile.build #進入當前目錄,使用頂層的makefile.build進行編譯 $(CC) $(LDFLAGS) -o $(TARGET) built-in.o #將編譯好的built-in.o文件鏈接生成我們的目標文件 #------------------------------------------------頂層的清除規則------------------------------------------------------- clean: rm -f $(shell find -name "*.o") #刪除所有的.o文件 rm -f $(shell find -name "*.d") #刪除所有的.d文件 rm -f $(TARGET) #刪除目標文件 .PHONY:all clean 頂層Makefile.build解析(無需改動): PHONY := __build #定義一個PHONY變量 __build: #開頭說明__build偽目標,使其成為Makefile.build的第一個目標 obj-y := #定義當前目錄的目標變量,初始值為空 subdir-y :=  #定義當前目錄的子目錄變量,初始值為空 include Makefile     #將當前目錄的Makefile包含進來,初始化obj-y #obj-y:=a.o b.o c/ d/ __subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y))) #篩選出當前目錄的目標變量中的子目錄,並且去掉/ #$(filter %/, $(obj-y)):c/ d/ #__subdir-y:c d subdir-y += $(__subdir-y) #將開始定義的subdir-y賦值為__subdir-y #subdir-y:c d subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o) #對於subdir-y里面的每一個值(目錄),增加一個相應的目錄/built-in.o的變量值 #subdir_objs:c/built-in.o d/built-in.o cur_objs := $(filter-out %/, $(obj-y)) #得到obj-y中的.o文件 #cur_objs:a.o b.o dep_files := $(foreach f,$(cur_objs),.$(f).d) #對於所有的.o文件,定義它的依賴文件名 #dep_files: .a.d .b.d dep_files := $(wildcard $(dep_files)) ifneq ($(dep_files),) #根據依賴文件名,判斷依賴文件是否存在,存在就包含就來 include $(dep_files) endif PHONY += $(subdir-y) #將$(subdir-y)也加入到變量PHONY中 --------------------------------------------Makefile. build的第一個規則-------------------------------------------------------------- __build : $(subdir-y) built-in.o #第一個規則 $(subdir-y): #第一個規則的第一個依賴規則 make -C $@ -f $(TOPDIR)/Makefile.build #依次進入該子目錄變量里面存儲的值,使用的Makefile.build進行編譯 built-in.o : $(cur_objs) $(subdir_objs) #第一個規則的第二個依賴規則 $(LD) -r -o $@ $^ #該規則的命令:將該目錄下的.o和$(subdir_obj)打包成built-in.o文件 dep_file = .$@.d # %.o : %.c #第一個規則的第二個依賴規則的依賴規則 $(CC) $(CFLAGS) -Wp,-MD,$(dep_file) -c -o $@ $<          #用於將目錄下所有的.c文件編譯成.o文件 .PHONY : $(PHONY) #將PHONY聲明為偽目標 子目錄Makefile(隨工程而變): 子目錄的Makefile就是包含該目錄下所有的目標文件名和子目錄文件夾名。 例如任何一個子目錄可寫成: objs-y := a.o objs-y += b.o objs-y += c/ objs-y += d/ 四 示例工程 http://pan.baidu.com/share/link?shareid=145262&uk=101680913

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM