交叉編譯

平台上的可執行代碼

簡單地說,就是在一個平台上生成另一個平台上的可執行代碼。同一個體系結構可以運行不同的操作系統;同樣,同一個操作系統也可以在不同的體系結構上運行。

舉例來說,我們常說的x86 Linux平台實際上是Intel x86體系結構和Linux for x86操作系統的統稱;而x86 WinNT平台實際上是Intel x86體系結構和Windows NT for x86操作系統的簡稱。

詞義


交叉編譯
交叉編譯
一個經常會被問到的問題就是,“既然我們已經有了主機編譯器,那為什麼還要交叉編譯呢?”其實答案很簡單。有時是因為目的平台上不允許或不能夠安裝我們所需要的編譯器,而我們又需要這個編譯器的某些特徵;有時是因為目的平台上的資源貧乏,無法運行我們所需要編譯器;有時又是因為目的平台還沒有建立,連操作系統都沒有,根本談不上運行什麼編譯器。
另一個經常會被問到的問題就是:“既然可以交叉編譯,那還要主機編譯幹嗎?”其實答案也很簡單,交叉編譯是不得已而為之!與主機編譯相比,交叉編譯受的限制更多,雖然在理論上我們可以做任何形式的交叉編譯,但事實上,由於受到專利、版權、技術的限制,並不總是能夠進行交叉編譯,尤其是在業餘條件下!舉例來說,我們至今無法生成惠普公司專有的som格式的可執行文件,因此我們根本無法做目的平台為HPPA-HPUX的交叉編譯。
就我們這個項目而言,需要交叉編譯的原因有兩個:首先,在項目的起始階段,目的平台尚未建立,因此需要做交叉編譯,以生成我們所需要的bootloader(啟動引導代碼)以及操作系統核心;其次,當目的平台能啟動之後,由於目的平台上資源的限制,當我們編譯大型程序時,依然可能需要用到交叉編譯。
交叉編譯這個概念的出現和流行是和嵌入式系統的廣泛發展同步的。我們常用的計算機軟體,都需要通過編譯的方式,把使用高級計算機語言編寫的代碼(比如C代碼)編譯(compile)成計算機可以識別和執行的二進位代碼。比如,我們在Windows平台上,可使用Visual C++開發環境,編寫程序並編譯成可執行程序。這種方式下,我們使用PC平台上的Windows工具開發針對Windows本身的可執行程序,這種編譯過程稱為native compilation,中文可理解為本機編譯。然而,在進行嵌入式系統的開發時,運行程序的目標平台通常具有有限的存儲空間和運算能力,比如常見的 ARM 平台,其一般的靜態存儲空間大概是16到32MB,而CPU的主頻大概在100MHz到500MHz之間。這種情況下,在ARM平台上進行本機編譯就不太可能了,這是因為一般的編譯工具鏈(compilation tool chain)需要很大的存儲空間,並需要很強的CPU運算能力。為了解決這個問題,交叉編譯工具就應運而生了。通過交叉編譯工具,我們就可以在CPU能力很強、存儲空間足夠的主機平台上(比如PC上)編譯出針對其他平台的可執行程序。
要進行交叉編譯,我們需要在主機平台上安裝對應的交叉編譯工具鏈(cross compilation tool chain),然後用這個交叉編譯工具鏈編譯我們的源代碼,最終生成可在目標平台上運行的代碼。常見的交叉編譯例子如下:
1、在Windows PC上,利用ADS(ARM 開發環境),使用armcc編譯器,則可編譯出針對ARM CPU的可執行代碼。
2、在Linux PC上,利用arm-linux-gcc編譯器,可編譯出針對Linux ARM平台的可執行代碼。
3、在Windows PC上,利用cygwin環境,運行arm-elf-gcc編譯器,可編譯出針對ARM CPU的可執行代碼。

基礎知識


在做實際工作之前,我想我們應該先掌握一些關於交叉編譯的基本知識,其實說白了也就是理解一些我們經常會碰到的英文單詞:
宿主機(host) :編輯和編譯程序的平台,一般是基於X86的PC機,通常也被稱為主機。
目標機(target):用戶開發的系統,通常都是非X86平台。host編譯得到的可執行代碼在target上運行。
prefix: 交叉編譯器的安裝位置。
xxx-xxxx-xxxxx 平台描述。
我們在主機平台上開發程序,並在這個平台上運行交叉編譯器,編譯我們的程序;而由交叉編譯器生成的程序將在目的平台上運行。這裡值得說明得是平台描述,像arm-linux、i386-pc-linux2.4.3這樣的字元串我們經常會看到,其實它是用來描述平台的,它有完整格式、縮減格式和別名之分。完整格式是:CPU-製造廠商-操作系統,如sparc-sun-sunos4.1.4,說明平台所使用的CPU是sparc,製造廠商是sun,上面運行的操作系統是SunOS,版本是4.1.4。當然,我們都不願記這麼長的東西,因此可以使用短格式,短格式中有選擇地去除了製造廠商、軟體版本等信息,因此我們同樣可以用sparc-sunos或sparc-sunos-sunos4來描述這個平台。如果覺得這個還是太麻煩,那就可以使用別名,sun4m就可以很簡單地描述這個平台。需要注意的是,並不是所有的平台都有別名,也不是所有的短格式都可以正確地描述平台。

準備素材


怎麼說呢,你先得準備好主機平台,對我們這個項目來說,我們建議採用x86 Linux做主機平台,因為這樣需要的設置工作最少。當然你也可以使用你所喜歡的平台或你所能得到的平台,其中的區別在於你可能必須做更多的設置工作,當然也有這種可能,就是你所選擇的主機平台根本不能生成適用於目標平台的正確的交叉編譯器。
對於交叉編譯器,可以自己生成,也可以從網上下載。區別在於從網上下載非常簡單方便,但也許你找不到適合你所選擇的平台的。而自己生成交叉編譯器,有時會遇到很多挫折,但這的確是個有趣的值得懷念的經歷。
如果你想自己生成交叉編譯器,那你必須先準備下面這些東西:
1、磁碟空間。至少要500M左右的空間,如果想一氣呵成的話,那就要900M-1G的空間。
2、各種源代碼。你至少要準備binutils-2.11.2、gcc-2.95.3、linux-2.4.6、newlib-1.8.2或glibc-2.2.2的源代碼。
如果你所使用的主機平台不是運行的linux,那你還必須注意以下這些問題:
1、GNU bash必須是默認shell,所以你也許得把/bin/sh改成bash。
2、你要確認已經安裝了GNU bison,因為這些軟體同樣使用了bison擴展。
3、GNU gmake最好是系統默認的make,因為這些軟體都使用了gmake擴展,如果不是,在需要make時,記得使用gmake。
4、如果你想生成交叉glibc,則GNU gsed必須是默認sed,因為glibc會用到gsed的擴展。
5、如果你想生成交叉glibc,那還必須準備glibc-linuxthreads-2.2.2的源代碼。
6、確認正確的路徑搜索順序,最好讓GNU軟體首先被執行。

編譯器


我們建議使用現成的腳本來生成交叉編譯器,因為在配置交叉編譯器時,會經常使用一些難以理解的開關項。

發展趨勢


伴隨著以計算機技術、通訊技術為主的信息技術的飛速發展和網際網路的廣泛應用,3C(Computer、Communication、ConsumerElectronic)合一將成為必然趨勢。信息家電,手持設備,移動設備等嵌入式產品的迅速發展,使得嵌入式軟體開發再度成為一個研究熱點。由於嵌入式設備的性能局限,往往不能通過本機編譯得到所需軟體的可執行程序。因此,以Linux為主機操作系統,搭配一個交叉編譯系統,為嵌入式設備生成可執行程序已成為日益流行的編譯嵌入式軟體的解決方案。而開放源碼的編譯器GCC,經過多年的發展,已能支持幾乎所有知名廠商的處理器,是嵌入式軟體開發中理想的交叉編譯器。