|  | |
| linux內核中Makefile的使用 | |
| linux內核中Makefile 的作(zuo)用是(shi)根據(ju)配置(zhi)的情況(kuang),構造(zao)出需(xu)要編(bian)譯(yi)(yi)的源(yuan)文件列表,然后分別(bie)編(bian)譯(yi)(yi),并(bing)把目標代碼鏈接到一起,終形成 Linux 內核二進制(zhi)文件。 由于 Linux 內核源代碼(ma)是按照(zhao)樹形結(jie)構組(zu)織的(de)(de),所以 Makefile 也被(bei)分(fen)布在目錄樹中。Linux 內核中的(de)(de) Makefile 以及(ji)與(yu) Makefile 直接相(xiang)關(guan)的(de)(de)文件有(you):     1.	Makefile:頂層 Makefile,是整個內核配置、編譯的總體控制文件。 用戶通過 make config 配置(zhi)后(hou),產(chan)(chan)生了(le)(le)(le) .config。頂層 Makefile 讀入 .config 中(zhong)的(de)配置(zhi)選擇。頂層 Makefile 有兩個(ge)主要的(de)任務(wu):產(chan)(chan)生 vmlinux 文件(jian)和內(nei)核(he)模塊(module)。為了(le)(le)(le)達到(dao)(dao)(dao)此(ci)目(mu)的(de),頂層 Makefile 遞歸的(de)進入到(dao)(dao)(dao)內(nei)核(he)的(de)各個(ge)子(zi)(zi)目(mu)錄中(zhong),分別調(diao)用位于(yu)這(zhe)些子(zi)(zi)目(mu)錄中(zhong)的(de) Makefile。至于(yu)到(dao)(dao)(dao)底進入哪些子(zi)(zi)目(mu)錄,取(qu)決于(yu)內(nei)核(he)的(de)配置(zhi)。在(zai)頂層 Makefile 中(zhong),有一句(ju):include arch/$(ARCH)/Makefile,包(bao)含了(le)(le)(le)特定 CPU 體系結構下的(de) Makefile,這(zhe)個(ge) Makefile 中(zhong)包(bao)含了(le)(le)(le)平臺(tai)相關的(de)信息。 位于各個子目錄(lu)下的(de)(de) Makefile 同樣(yang)也根據(ju) .config 給出的(de)(de)配置信息,構造出當前配置下需要的(de)(de)源文(wen)(wen)件列表,并在文(wen)(wen)件的(de)(de)后有 include $(TOPDIR)/Rules.make。   Rules.make 文件起著(zhu)非常重(zhong)要(yao)的(de)作用,它(ta)定義了所(suo)有 Makefile 共用的(de)編(bian)譯規(gui)(gui)則(ze)。比如,如果(guo)需(xu)(xu)要(yao)將本目錄(lu)下所(suo)有的(de) c 程序編(bian)譯成匯編(bian)代碼,需(xu)(xu)要(yao)在 Makefile 中(zhong)有以下的(de)編(bian)譯規(gui)(gui)則(ze):     %.s: %.c 有(you)很多子(zi)(zi)目(mu)錄下都有(you)同樣(yang)的(de)要求,就需要在各(ge)自的(de) Makefile 中(zhong)(zhong)包含此(ci)編譯規則(ze)(ze),這會比(bi)較麻(ma)煩(fan)。而 Linux 內核中(zhong)(zhong)則(ze)(ze)把(ba)此(ci)類的(de)編譯規則(ze)(ze)統一放(fang)置到 Rules.make 中(zhong)(zhong),并在各(ge)自的(de) Makefile 中(zhong)(zhong)包含進了 Rules.make(include Rules.make),這樣(yang)就避免了在多個 Makefile 中(zhong)(zhong)重復同樣(yang)的(de)規則(ze)(ze)。對于上面(mian)的(de)例子(zi)(zi),在 Rules.make 中(zhong)(zhong)對應的(de)規則(ze)(ze)為:     %.s: %.c Makefile 中的變量 頂層 Makefile 定義并向環境中(zhong)輸出了許多變量,為各(ge)個子目錄下(xia)的 Makefile 傳遞一(yi)些(xie)信息。有(you)些(xie)變量,比如 SUBDIRS,不僅在頂層 Makefile 中(zhong)定義并且(qie)賦(fu)初(chu)值,而且(qie)在 arch/*/Makefile 還作了擴充(chong)。 常用(yong)的變量有以下幾類:     1) 版本信息      2) CPU 體系結構:ARCH      3) 路徑信息:TOPDIR, SUBDIRS    SUBDIRS 定義了(le)(le)一個目錄(lu)列表,在編(bian)譯內核(he)或模(mo)塊時,頂層 Makefile 就是根(gen)據(ju) SUBDIRS 來決(jue)定進入哪些(xie)子(zi)目錄(lu)。SUBDIRS 的值(zhi)取決(jue)于內核(he)的配置(zhi),在頂層 Makefile 中(zhong) SUBDIRS 賦值(zhi)為(wei) kernel drivers mm fs net ipc lib;根(gen)據(ju)內核(he)的配置(zhi)情況(kuang),在 arch/*/Makefile 中(zhong)擴充了(le)(le) SUBDIRS 的值(zhi),參見4)中(zhong)的例子(zi)。     4) 內核組成信息:HEAD, CORE_FILES, NETWORKS, DRIVERS, LIBS      vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs 可以(yi)看出(chu),vmlinux 是由 HEAD、main.o、version.o、CORE_FILES、DRIVERS、NETWORKS 和 LIBS 組(zu)成的(de)。這些變量(liang)(如 HEAD)都是用(yong)(yong)來定義(yi)連接生(sheng)成 vmlinux 的(de)目(mu)標(biao)文(wen)件和庫文(wen)件列(lie)表(biao)(biao)。其(qi)中,HEAD在arch/*/Makefile 中定義(yi),用(yong)(yong)來確定被先鏈(lian)接進 vmlinux 的(de)文(wen)件列(lie)表(biao)(biao)。比如,對于 ARM 系列(lie)的(de) CPU,HEAD 定義(yi)為:     HEAD := arch/arm/kernel/head-$(PROCESSOR).o \   表(biao)明 head-$(PROCESSOR).o 和(he) init_task.o 需(xu)要先(xian)被(bei)鏈接到 vmlinux 中。PROCESSOR 為 armv 或(huo) armo,取決于目標 CPU。 CORE_FILES,NETWORK,DRIVERS 和(he) LIBS 在頂層 Makefile 中定義,并且由 arch/*/Makefile 根(gen)據(ju)需(xu)要進行擴(kuo)充(chong)。 CORE_FILES 對應著內核(he)的核(he)心文(wen)(wen)件,有 kernel/kernel.o,mm/mm.o,fs/fs.o,ipc/ipc.o,可以看出,這些是組成(cheng)內核(he)為重要的文(wen)(wen)件。同時,arch/arm/Makefile 對 CORE_FILES 進行了擴(kuo)充(chong):     # arch/arm/Makefile     5) 編譯信息:CPP, CC, AS, LD, AR,CFLAGS,LINKFLAGS      CROSS_COMPILE   = arm-linux- CROSS_COMPILE 定義了交(jiao)叉(cha)編(bian)譯(yi)器(qi)前綴(zhui) arm-linux-,表明所有的(de)交(jiao)叉(cha)編(bian)譯(yi)工具都是以 arm-linux- 開頭的(de),所以在(zai)各個交(jiao)叉(cha)編(bian)譯(yi)器(qi)工具之(zhi)前,都加入了 $(CROSS_COMPILE),以組成(cheng)一個完整的(de)交(jiao)叉(cha)編(bian)譯(yi)工具文件名,比如 arm-linux-gcc。   CFLAGS 定義(yi)了傳遞(di)給 C 編譯器的參數。   LINKFLAGS 是鏈(lian)接生成 vmlinux 時(shi),由鏈(lian)接器使(shi)用的參數。LINKFLAGS 在 arm/*/Makefile 中定義,比如:     # arch/arm/Makefile     6) 配置變量CONFIG_*  Rules.make 變量 前面(mian)講(jiang)過,Rules.make 是(shi)編譯(yi)規則文(wen)件,所有的 Makefile 中(zhong)都會包括(kuo) Rules.make。Rules.make 文(wen)件定義(yi)了(le)許多變量,為重(zhong)要(yao)是(shi)那些編譯(yi)、鏈(lian)接列表(biao)變量。 O_OBJS,L_OBJS,OX_OBJS,LX_OBJS:本目(mu)(mu)錄下(xia)需(xu)要編譯(yi)進 Linux 內核(he) vmlinux 的目(mu)(mu)標文件(jian)列表(biao),其中 OX_OBJS 和 LX_OBJS 中的 "X" 表(biao)明(ming)目(mu)(mu)標文件(jian)使用了(le) EXPORT_SYMBOL 輸出符號。 M_OBJS,MX_OBJS:本目(mu)錄下需要(yao)被編(bian)譯(yi)成(cheng)可(ke)裝載(zai)模塊的目(mu)標文(wen)件(jian)列(lie)表(biao)。同樣,MX_OBJS 中的 "X" 表(biao)明目(mu)標文(wen)件(jian)使用(yong)了 EXPORT_SYMBOL 輸出符號。   O_TARGET,L_TARGET:每個(ge)子目(mu)錄下都有一個(ge) O_TARGET 或 L_TARGET,Rules.make 首先從源代(dai)碼編譯生(sheng)成 O_OBJS 和 OX_OBJS 中所有的目(mu)標文(wen)件(jian),然后使(shi)用 $(LD) -r 把它們鏈接成一個(ge) O_TARGET 或 L_TARGET。O_TARGET 以 .o 結尾,而 L_TARGET 以 .a 結尾。 子目錄 Makefile 子目錄(lu) Makefile 用來控制本級目錄(lu)以下源代碼的(de)編譯規則。我們通過(guo)一個例子來講解(jie)子目錄(lu) Makefile 的(de)組成:     # a) 注釋   對 Makefile 的說明(ming)和解釋,由#開(kai)始。 b) 編(bian)譯目標(biao)定(ding)義(yi) 類似于 obj-$(CONFIG_TC) += tc.o 的(de)語句(ju)是用來定義編譯(yi)的(de)目標(biao)(biao),是子目錄 Makefile 中(zhong)重要(yao)的(de)部分。編譯(yi)目標(biao)(biao)定義那些在本(ben)子目錄下,需要(yao)編譯(yi)到(dao) Linux 內核中(zhong)的(de)目標(biao)(biao)文件列(lie)表。為了只在用戶(hu)選(xuan)擇了此功能后才編譯(yi),所有的(de)目標(biao)(biao)定義都融合了對(dui)配置(zhi)變(bian)量的(de)判(pan)斷(duan)。 前面說過(guo),每個配置變量取值范圍是(shi):y,n,m 和空,obj-$(CONFIG_TC) 分(fen)別(bie)對應著(zhu) obj-y,obj-n,obj-m,obj-。如果(guo) CONFIG_TC 配置為 y,那(nei)么 tc.o 就(jiu)進入了 obj-y 列(lie)表(biao)。obj-y 為包含到(dao) Linux 內核(he) vmlinux 中的(de)目(mu)標文(wen)件列(lie)表(biao);obj-m 為編譯(yi)成模塊(kuai)的(de)目(mu)標文(wen)件列(lie)表(biao);obj-n 和 obj- 中的(de)文(wen)件列(lie)表(biao)被忽略。配置系統就(jiu)根據這些列(lie)表(biao)的(de)屬性進行編譯(yi)和鏈(lian)接。 export-objs 中的目標文(wen)件都(dou)使用了(le)(le) EXPORT_SYMBOL() 定義(yi)了(le)(le)公(gong)共的符號,以便可裝(zhuang)載(zai)模塊(kuai)使用。在 tc.c 文(wen)件的后部(bu)分,有 "EXPORT_SYMBOL(search_tc_card);",表明 tc.o 有符號輸出。 這里(li)需(xu)要指出(chu)的是(shi),對于(yu)編譯目標的定(ding)義(yi),存在著兩種格式,分(fen)別是(shi)老式定(ding)義(yi)和(he)新式定(ding)義(yi)。老式定(ding)義(yi)就是(shi)前面 Rules.make 使(shi)用的那些變量,新式定(ding)義(yi)就是(shi) obj-y,obj-m,obj-n 和(he) obj-。Linux 內核(he)推薦使(shi)用新式定(ding)義(yi),不過(guo)由于(yu) Rules.make 不理解(jie)新式定(ding)義(yi),需(xu)要在 Makefile 中的適配段將其(qi)轉換成老式定(ding)義(yi)。 c) 適(shi)配(pei)段 適配(pei)段的(de)作用是將新式(shi)定義(yi)轉(zhuan)(zhuan)換成老式(shi)定義(yi)。在上面的(de)例子中,適配(pei)段就是將 obj-y 和 obj-m 轉(zhuan)(zhuan)換成 Rules.make 能夠理解的(de) L_TARGET,L_OBJS,LX_OBJS,M_OBJS,MX_OBJS。 L_OBJS := $(sort $(filter-out $(export-objs), $(obj-y))) 定義(yi)了 L_OBJS 的(de)生成(cheng)方式:在 obj-y 的(de)列表(biao)中過濾掉 export-objs(tc.o),然后排序并去(qu)除(chu)重復的(de)文件(jian)名。這里使(shi)用到了 GNU Make 的(de)一些特殊功能,具體的(de)含義(yi)可參考 Make 的(de)文檔(info make)。   d) include $(TOPDIR)/Rules.make 熱點鏈接:   
         1、嵌入式linux內核的五個子系統 |