新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > linux配置、編譯內(nèi)核實(shí)用工具

linux配置、編譯內(nèi)核實(shí)用工具

——
作者: 時(shí)間:2007-04-18 來(lái)源: 收藏

Make 

Make是一種幫助大型軟件工程的編譯工作實(shí)現(xiàn)自動(dòng)化的編程語(yǔ)言。正確地使用Make可以大大減少因編譯程序而花費(fèi)的時(shí)間,因?yàn)樗梢韵槐匾脑倬幾g。Make的基本設(shè)計(jì)思想是如果目標(biāo)文件是在最近一次對(duì)源文件的修改之后編譯的,它就是“新的”,不需要重新編譯;如果最近一次對(duì)源文件的修改之后沒(méi)有及時(shí)更新目標(biāo)文件,那么該目標(biāo)文件就是“舊的”,需要重新編譯。為了理解Make如何執(zhí)行一個(gè)任務(wù),需要了解一些術(shù)語(yǔ): 

◆目標(biāo) 需要執(zhí)行的一個(gè)任務(wù)。多數(shù)情況下它就是用戶(hù)要生成的文件的名字,但是它也可以?xún)H是個(gè)任務(wù)的名字。 

◆依賴(lài)關(guān)系 兩個(gè)目標(biāo)之間相互依存的關(guān)系。如果修改目標(biāo)B會(huì)造成目標(biāo)A的修改,那么就說(shuō)目標(biāo)A依賴(lài)于目標(biāo)B,B是A的先決條件。 

◆變量 一種存儲(chǔ)臨時(shí)信息的載體。Make中使用的變量應(yīng)該加上括號(hào),例如$(TEMP)。 

◆命令 執(zhí)行任務(wù)時(shí)使用的指令,可以是一條、多條,甚至沒(méi)有。 

◆規(guī)則 一條完整的規(guī)則具有以下格式: 

目標(biāo)(target) : 先決條件(prerequisites) 

規(guī)則(command) 

...... 

其中只有目標(biāo)必須要有,其它成分可以沒(méi)有。一條完整的規(guī)則描述了編譯一個(gè)目標(biāo)的方法和依賴(lài)關(guān)系,是Makefile中最重要的部分。 

◆Makefile文件 描述如何生成一個(gè)或多個(gè)目標(biāo)的文件。它列出目標(biāo)依賴(lài)的各個(gè)文件,并提供正確編譯這些目標(biāo)所需要的規(guī)則。 

接下來(lái)以2.4.23的kbuild為例,簡(jiǎn)要介紹一下內(nèi)核的構(gòu)建過(guò)程。首先,完整的內(nèi)核構(gòu)建過(guò)程由以下五種Makefile封裝。 

1.根目錄Makefile 

它是最重要的Makefile,定義所有與體系結(jié)構(gòu)無(wú)關(guān)的變量和目標(biāo)。它讀取.config文件,并根據(jù)其信息最終生成vmlinux和modules。Make通過(guò)向下遞歸調(diào)用子目錄中的Makefile來(lái)編譯這兩個(gè)目標(biāo)。 

2.配置文件.config 

執(zhí)行“make ”會(huì)在根目錄下生成該配置文件,其內(nèi)容記錄了具體的配置選擇,也可以將舊內(nèi)核的配置文件放在這里。 

3.a(chǎn)rch/*/Makefile 

這是與特定體系結(jié)構(gòu)相關(guān)的Makefile。它包含在根目錄下的Makefile中,為kbuild提供體系結(jié)構(gòu)的特定信息。 

4.子目錄Makefiles 

它們存在于每個(gè)子目錄下,大約有幾百個(gè)。它們接受來(lái)自上層Make傳遞下來(lái)的信息,并根據(jù)這些信息來(lái)構(gòu)造一個(gè)需要編譯的文件列表,并交由Rules.make處理。 

5.Rules.make 

幾乎每個(gè)子目錄Makefile都包含該Makefile。根據(jù)子目錄Makefiles構(gòu)建的文件列表,Make使用Rules.make定義的通用規(guī)則來(lái)編譯所有來(lái)自列表的源文件。 

kbuild的執(zhí)行過(guò)程是:Make從根目錄Makefile開(kāi)始執(zhí)行,從中獲得與體系結(jié)構(gòu)無(wú)關(guān)的變量和依賴(lài)關(guān)系,并同時(shí)從arch/*/Makefile中獲得體系特定的變量等信息,這些信息擴(kuò)展了根目錄Makefile提供的變量。此時(shí)kbuild已經(jīng)擁有構(gòu)建內(nèi)核需要的所有變量和目標(biāo)。然后,Make進(jìn)入子目錄,把部分變量傳遞給子目錄Makefile。子目錄Makefile根據(jù)配置信息決定編譯哪些源文件,從而構(gòu)建出一個(gè)需要編譯的文件列表。最后,Rules.make根據(jù)其定義的編譯規(guī)則決定這些文件的編譯方式。 

需要注意的是,由于Make的向下遞歸特性和無(wú)序性,其執(zhí)行過(guò)程并不完全遵守順序逐行執(zhí)行的規(guī)則,但無(wú)論Make的執(zhí)行有多復(fù)雜,也只分為兩個(gè)階段。第一個(gè)階段Make會(huì)讀取所有變量和分析所有目標(biāo)的依賴(lài)關(guān)系,并最終建立一棵依賴(lài)關(guān)系樹(shù)。同時(shí),所有的立即型變量(通過(guò)“:=”賦值)在這個(gè)過(guò)程中被擴(kuò)展,就像C變量一樣。而在這個(gè)階段的最后,所有的延遲型變量才被擴(kuò)展(通過(guò)“=”賦值)。這點(diǎn)需要格外注意。第二個(gè)階段Make會(huì)根據(jù)依賴(lài)關(guān)系樹(shù)執(zhí)行命令。 

因此,一個(gè)目標(biāo)和其先決條件的規(guī)則定義的順序是無(wú)所謂的,很可能一個(gè)目標(biāo)的先決條件的規(guī)則定義在百行以后才出現(xiàn)。Make會(huì)耐心讀完所有的Makefile后分析得出依賴(lài)關(guān)系樹(shù)。 

GCC 

GCC是GNU的免費(fèi)編譯程序,也是內(nèi)核惟一指定使用的。GCC在執(zhí)行一個(gè)完整的編譯任務(wù)時(shí)會(huì)經(jīng)過(guò)以下步驟: 

◆預(yù)處理 GCC會(huì)調(diào)用cpp程序來(lái)分析各種宏指令,如#define、#if、#include等。 

◆編譯 這一階段根據(jù)輸入文件產(chǎn)生匯編語(yǔ)言指令。由于通常情況下是立即調(diào)用匯編程序as,所以輸出一般不保存在文件中,可以使用-S選項(xiàng)強(qiáng)制輸出源程序的匯編版本。 

◆匯編 這一階段將匯編語(yǔ)言源程序作為輸入,生成.o目標(biāo)文件。 

◆鏈接 這是最后一個(gè)階段。該階段中,各個(gè).o模塊被鏈接在一起構(gòu)成可執(zhí)行文件。 

as 

用戶(hù)可以明確地要求使用as來(lái)直接處理匯編文件。as產(chǎn)生的目標(biāo)文件可以分為文本段(.text)、數(shù)據(jù)段(.data)和未初始化數(shù)據(jù)段(.bss)。 

ld 

與as相似,用戶(hù)可以明確地要求使用ld鏈接程序?qū)讉€(gè)模塊組合成一個(gè)單獨(dú)的可執(zhí)行文件。其鏈接過(guò)程通常由一個(gè)叫l(wèi)d鏈接腳本的文件來(lái)描述。該腳本使用Linker Command Language編寫(xiě)。使用“l(fā)d --verose”命令可以看到這個(gè)默認(rèn)使用的ld鏈接腳本。 

ar 

ar是GNU的二進(jìn)制文件處理程序,用于創(chuàng)建、修改及從歸檔文件中抽取文件。由它生成的.a歸檔文件實(shí)際上是一個(gè)包含許多可執(zhí)行二進(jìn)制代碼子程序集合的庫(kù)文件。 

RPMBuild 

使用“make rpm”可以把內(nèi)核源代碼制作成RPM包。在此之前,kbuild會(huì)執(zhí)行“make spec”生成rpmbuild程序用到的spec文件,詳見(jiàn)“man rpmbuild”。 

中間件 

根目錄scripts下的各種腳本和C源文件都可以稱(chēng)作中間件。它們并不是內(nèi)核組件的一部分,只是在kbuild執(zhí)行過(guò)程中的輔助程序。以split-include為例,講述配置文件的運(yùn)作機(jī)理。 

.config由關(guān)鍵字/值對(duì)組成,其內(nèi)容類(lèi)似于: 




CONFIG_MPENTIUMIII=y 
# CONFIG_MPENTIUM4 is not set 
CONFIG_REISERFS_FS=m 
  




這些信息在執(zhí)行“make ”時(shí)自動(dòng)生成。同時(shí)include/linux/autoconf.h依照.config的內(nèi)容生成。它的格式類(lèi)似于: 




#define CONFIG_MPENTIUMIII 1 
#undef CONFIG_MPENTIUM4 
#undefCONFIG_REISERFS_FS 
#define CONFIG_REISERFS_FS_MODULE 1 
  




對(duì)比一下不難發(fā)現(xiàn),include/linux/autoconf.h明確地洞悉了.config的意圖:哪些組件不編譯,哪些需要編譯進(jìn)內(nèi)核,而哪些又要作為模塊來(lái)編譯?split-include根據(jù)include/linux/autoconf.h在include/config/下建立相關(guān)的目錄和.h文件。每個(gè).h文件只包括include/linux/autoconf.h中的某一行,比如在配置內(nèi)核選項(xiàng)時(shí)支持NTFS文件系統(tǒng),并把它編譯進(jìn)內(nèi)核,在.config中就會(huì)生成“CONFIG_NTFS_FS=y”,相應(yīng)地在include/linux/autoconf.h中會(huì)生成“#define CONFIG_NTFS_FS 1”一項(xiàng)。這樣,所有與NTFS文件系統(tǒng)相關(guān)的C源文件都會(huì)包含include/config/ntfs/fs.h頭文件。 

如果以前編譯過(guò)內(nèi)核,并且沒(méi)有使用過(guò)“make mrproper”,.config、include/linux/autoconf.h和include/linux/config/就不會(huì)被刪除。這里涉及到新舊內(nèi)核的配置問(wèn)題。一個(gè)全新的內(nèi)核代碼是未經(jīng)配置的。如果只在原內(nèi)核的功能基礎(chǔ)上增加對(duì)NTFS的支持,那么從頭開(kāi)始配置無(wú)疑是浪費(fèi)時(shí)間??梢岳^續(xù)使用原內(nèi)核的.config文件,而所有的配置信息不會(huì)有任何更改,并且可以直接在原配置的基礎(chǔ)上增加新功能。 

在復(fù)雜的情況下,保留的舊內(nèi)核配置信息還要與新的配置信息進(jìn)行比較:哪些舊信息需要覆蓋,哪些需要保留?下面來(lái)看一下幾種可能的情況: 

  

舊值保存在include/config/下的.h文件中,新值保存在新生成的include/linux/autoconf.h文件中。split-include的代碼不僅描述了如何處理這五種情況,還描述了include/config/下文件和子目錄的生成過(guò)程。 



評(píng)論


相關(guān)推薦

技術(shù)專(zhuān)區(qū)

關(guān)閉