嵌入式系統(tǒng)移植中的交叉編譯器詳解

交叉編譯器簡介

首先和大家分享的是嵌入式系統(tǒng)移植中交叉編譯工具集,具體如下圖:

如圖,第一個(gè)問題是為什么要有交叉編譯?

眾所周知我們的CPU它工作方式非常簡單,就是根據(jù)不同的高低電平去干不同的事情。如下圖:

如圖,比如說CPU要做加法,那么很顯然x86可以這樣認(rèn)為“add 1010”如果說看到這樣一個(gè)組合我就認(rèn)為CPU要做加法了。那么自然而然我們程序員只要寫成高低的一個(gè)標(biāo)示給CPU,CPU基本就能做加法。所以這個(gè)跟我們前面學(xué)習(xí)匯編的思想很像,但是我們現(xiàn)在不一樣了因?yàn)槲覀兊腜C一般來說是x86的,但是如果說我們現(xiàn)在的CPU換一款換成ARM同樣后面是1010,那么1010對于ARM來說因?yàn)樗莾杉也煌墓荆敲此鼘@樣的指定級的編碼和譯碼的時(shí)候是不是會(huì)有不同的結(jié)果。比如說在arm中的1010就可能不是加法了而可能是mov這一數(shù)據(jù)的搬移指令。那么大家就可以發(fā)現(xiàn)如果我們在x86上編譯的一個(gè)二進(jìn)制集合包或者是二進(jìn)制程序集合,我們不做任何的修改直接放到arm板子上運(yùn)行那么就一定會(huì)出現(xiàn)一個(gè)新的問題,就是我們的arm是不認(rèn)識這樣的集合的,也就是說跟你本身想做加法的邏輯是不一致的。

所以這樣我們就迫切想要去在x86上去編譯一個(gè)arm也能理解的邏輯。也就是這個(gè)情況就變成了如下圖:

如圖,我們x86下也就是我們的主機(jī)和目標(biāo)機(jī),就是我們原來最開始學(xué)習(xí)應(yīng)用開發(fā)的時(shí)候我們的主機(jī)就是x86,然后我們的目標(biāo)機(jī)也是x86,因?yàn)槲覀冞\(yùn)行也是在x86上運(yùn)行起來進(jìn)程或網(wǎng)絡(luò)編程的概念。但是我們現(xiàn)在嵌入式開發(fā)不一樣,我們的主機(jī)沒有變還是x86但是我們的目標(biāo)機(jī)現(xiàn)在已經(jīng)變成了ARM CPU。

所以這樣來看,我們原本正常情況下主機(jī)跟目標(biāo)機(jī)是統(tǒng)一品牌的。但是到現(xiàn)在我們就變成了主機(jī)是一個(gè)平臺目標(biāo)機(jī)是另外一個(gè)平臺,那這種情況我們就稱為交叉。

也就是說,這種情況下我們就需要一個(gè)交叉編譯器來完成從一個(gè)結(jié)構(gòu)編譯另外一個(gè)結(jié)構(gòu)的編譯器。如果目標(biāo)機(jī)跟主機(jī)是同一平臺的我們就稱為同一編譯器,比如說我們最典型的gcc,以上就是我們第一個(gè)為什么要有交叉編譯器的概念,那么在這個(gè)概念中我們要引入一個(gè)命令叫file命令,通過這個(gè)命令我們來加深一下為什么我們在以后編譯開發(fā)過程中可能遇到的新的問題,也就是我們都知道Linux系統(tǒng)中一個(gè)可執(zhí)行程序并沒有后綴名,也就是我們不會(huì)像Windows一樣寫成ese或者.xx讓大家來區(qū)分,很有可能我們最終可執(zhí)行程序都叫build,那么這種情況下就會(huì)經(jīng)常出現(xiàn)如果我不小心在實(shí)際開發(fā)中把x86下編譯的build燒寫到了arm板上,結(jié)果跑了半天都跑不出來,甚至整個(gè)程序運(yùn)行的邏輯都是混亂的。

這個(gè)原有就在于有時(shí)候我們粗心馬虎把x86的程序放在了arm板上了,那么我們應(yīng)該怎么去避免這樣一個(gè)情況了?

如圖我們還是用一個(gè)1.c用一個(gè)非常簡單的hello world做一個(gè)例子,然后我們用gcc -o build 1.c生成一個(gè)build程序,然后點(diǎn)擊ls查看會(huì)發(fā)現(xiàn)這個(gè)build一沒有后綴名二沒有其他的標(biāo)識,我怎么知道它是在x86下運(yùn)行還是在arm下運(yùn)行,或者換句話來說把這個(gè)程序放到我的板子上能不能運(yùn)行起來呢?然后我們就來看第一個(gè)命令叫做file build,然后點(diǎn)擊回車鍵大家就可以發(fā)現(xiàn)它上面有一堆東西,這一堆東西一般情況下我們不用全部關(guān)心但是我們唯一需要關(guān)心的就是“x86-64”因?yàn)槲疫@個(gè)機(jī)器是64位的,所以說你會(huì)發(fā)現(xiàn)看build真正屬性的第二個(gè)選項(xiàng)中它會(huì)告訴我們build工作的平臺是x86認(rèn)識的,這就是從file中去讀它文件頭的一個(gè)信息。

以上就是file非常重要的一個(gè)概念。

交叉編譯結(jié)果

下面我們來看如果有了交叉編譯器后,交叉編譯的結(jié)果又會(huì)變成什么樣子。在之前我們講交叉編譯器也說過一般有兩種方法:第一就是直接用編譯好的,第二就是自己手動(dòng)編譯。我們今天還是采用芯片廠商已經(jīng)編譯好的。

在Linux系統(tǒng)安裝軟件其實(shí)比較簡單,不是雙擊的形式,其實(shí)就是個(gè)解包的過程,它主要是把工具集解壓到一個(gè)目錄上然后我們直接使用它就可以。

然后我們來看看安裝交叉編譯器的方法:

安裝交叉編譯器其實(shí)非常簡單就是一個(gè)解壓縮的過程。解壓縮的過程,解壓到linux標(biāo)準(zhǔn)目錄,在安裝過程中我們就直接在Windows目錄下把交叉編譯器拷到你們的共享目錄就可以了。

如圖,安裝命令就是“tar-zxvf arm-linux-qcc-4.5.1-vfp-20120301.tgz ”注意在上面的那行命令中的tgz,它實(shí)際上是個(gè)縮寫,所以使用的就是zcvf,然后記住千萬不用把這個(gè)包解完就直接回車了,因?yàn)槲覀冎肋@個(gè)包是默認(rèn)Windows的共享目錄,所以一旦回車就可能導(dǎo)致編譯器中有些工具是用不了的,最典型的工具就是軟鏈接因?yàn)樵赪indows里是沒有軟鏈接的概念的,所以說如果這個(gè)包里面有軟鏈接的文件那很有可能就是解壓出來它就支持不了,最后就可能報(bào)錯(cuò)或者占用的數(shù)據(jù)量比較大。所以我們建議大家盡量不要安裝在Windows的共享目錄盡量安裝在Linux本身的虛擬機(jī)的硬盤目錄。所以我們在切換到另一個(gè)目錄需要“-C”一般來說交叉編譯器在制作的時(shí)候就把整個(gè)目錄都給你打包好了,所以有寫時(shí)候我們就習(xí)慣直接解壓的根(/)上,通過根就相當(dāng)于把解壓的權(quán)限直接交給交叉編譯器,然后點(diǎn)擊回車鍵:

如圖,大家會(huì)發(fā)現(xiàn)這個(gè)地方出現(xiàn)了一些問題,“文件已存在”這個(gè)原因是因?yàn)槲覄偛旁谇妹畹臅r(shí)候沒有使用超級用戶,所以我們要早命令“tar-zxvf arm-linux-qcc-4.5.1-vfp-20120301.tgz -C /”前加上一個(gè)sudo在去輸入就沒有錯(cuò)了。然后我們把它進(jìn)行解壓,在解壓過程中,一般來說是沒有太大問題的,大家可以小心點(diǎn)看它有沒有報(bào)什么錯(cuò)誤,如果沒有報(bào)錯(cuò)誤就可以了。

解壓完成后:

如圖,我們進(jìn)入opt目錄后,因?yàn)閛pt中本身就有個(gè)目錄,但是我們可以一級一級的進(jìn)去。最后進(jìn)入4.5.1目錄后會(huì)發(fā)現(xiàn)這個(gè)目錄下的選項(xiàng)其實(shí)就是交叉編譯器中總括的安裝包,其中有寫目錄對我們來說是有幫助的。

比如說“bin”這個(gè)目錄就相當(dāng)于交叉編譯器中的命令集合,也就是說我們的命令基本上應(yīng)該在bin里去找。而“l(fā)ib”它有兩種形式,第一種形式就是我們交叉編譯器在運(yùn)行的時(shí)候它有一個(gè)庫。第二種就是我們最終要交叉編譯器雖然在x86中運(yùn)行但是最終要編譯成arm,所以說我們在編譯過程中就涉及到兩種庫,一種是x86的庫一種就是arm的庫。

也就是說我們交叉編譯器本身是個(gè)軟件,它在運(yùn)行需要x86的一個(gè)平臺,所以這個(gè)時(shí)候它肯定是要有一個(gè)x86的庫為它運(yùn)行時(shí)準(zhǔn)備的,但是它最終生成的目標(biāo)要依賴arm體系。所以它鏈接的時(shí)候需要arm庫的提供。

如圖,我們先進(jìn)入bin里面看一下,這個(gè)地方大家會(huì)發(fā)現(xiàn)文件比較多,當(dāng)然文件雖多大家可以發(fā)現(xiàn)都有一個(gè)統(tǒng)一的規(guī)則。當(dāng)然這個(gè)地方先來提成一個(gè)思想也就是說我們安裝的叫交叉編譯集合或者叫交叉編譯鏈一個(gè)整塊,也就是說我們不僅僅要用到它叫g(shù)cc的東西,同時(shí)還可以看到gcc的外面還有很多其他的命令,這些命令其實(shí)就是我們在后面會(huì)給大家介紹叫做工具集的功能,所以說我們實(shí)際上安裝交叉編譯器就是安裝一套工具,不光是gcc。然后輸入如圖上命令,它其實(shí)就是個(gè)l文件,l文件軟鏈接到本地目錄下的文件,所以這個(gè)命名規(guī)則跟我們之前講的交叉編譯器的規(guī)則也很像“arm-none-linux-gnueabi-gcc”也就是在Linux下新的標(biāo)準(zhǔn)接口的一個(gè)gcc工具。一般來說這個(gè)名字太長懶得去寫,我們就可以用軟鏈接的方式去把它鏈在這里,直接敲“arm-linux-gcc”就可以了,所以這就是我們比較常用的方式。

那么我們安裝的一般步驟來說第一步就是把它解壓,一般來說要把它解壓到linux標(biāo)準(zhǔn)目錄下一步就是我們的兩種使用方法。

使用

1.使用簡單方法(就是我直接在shear中敲)

#arm-linux-gcc -o build 1.c(這樣就可以直接用它了,跟我們的gcc命令一樣,只是調(diào)用命令不在調(diào)用gcc了而是“arm-linux”這個(gè)命令)

簡單方法的優(yōu)缺點(diǎn):敲很少的字符就可以工作了,但是它的缺點(diǎn)也很多,就比如說你的系統(tǒng)不僅僅開發(fā)的這一個(gè)品牌,還有其他別的品牌,那在這種情況下就很可能不知道用這種快捷方式是找的哪一個(gè),所以很有可能導(dǎo)致我們在編譯中出現(xiàn)一些稀奇古怪的問題。因?yàn)槟憔幾g器用錯(cuò)了,很有可能你新編譯器不知道或者老編譯器又不支持,所以這種方法使用起來一定要小心,也就是你系統(tǒng)里不能有多個(gè)編譯器。

2.使用絕對路徑方法(最好的辦法)

#/opt/FriendlyARM/toolschain/4.5.1/bin/arm-linux-gcc -o build 1.c

絕對路徑的優(yōu)缺點(diǎn):它的缺點(diǎn)就是跟簡單路徑相反太復(fù)雜,但是我個(gè)人還是比較喜歡用絕對路徑雖然麻煩點(diǎn)但是它不用每次都輸入,而且這種方法絕對能保證你用的編譯器是正確的。


原文鏈接:http://www.maiziedu.com/wiki/embed/cross/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容