盡管是老生常談,但是在比較之前,還是先明確一下什么叫做工具鏈。
LFS/CLFS工具鏈?zhǔn)且惶子糜趶腃/C++源代碼生成可執(zhí)行文件的軟件組件適當(dāng)?shù)亟M合在一起形成的系統(tǒng)。它包括4大部分,缺一不可:
1、一套頭文件,包含了這些源代碼所需要訪問的系統(tǒng)接口。
2、binutils,包含一些處理二進(jìn)制可執(zhí)行文件所需的工具,如匯編器、連接器等等。
3、gcc,包含了編譯C/C++源代碼所需的工具,并且還能自動(dòng)調(diào)用相關(guān)的binutils工具來完成生成源代碼的工具
4、glibc,包含了系統(tǒng)接口的具體實(shí)現(xiàn)。
在上面的定義中,請(qǐng)注意這些軟件必須適當(dāng)?shù)亟M合,才能形成完整的工具鏈。那么怎么才算適當(dāng)組合呢?當(dāng)然,這個(gè)工具鏈必須能夠發(fā)揮作用,也就是確實(shí)能夠編譯出目標(biāo)代碼,然后才能算適當(dāng)組合。
那么,一個(gè)適當(dāng)組合的工具鏈應(yīng)當(dāng)具有什么特點(diǎn)呢?一般我們把工具鏈運(yùn)行的機(jī)器稱為host,所產(chǎn)生的代碼稱為target。那么對(duì)于工具鏈的要求便是:它必須要能在host上運(yùn)行,所產(chǎn)生的代碼必須能在target上運(yùn)行。再進(jìn)一步分析:
1、頭文件:必須是針對(duì)target的,因?yàn)槭褂眠@個(gè)工具鏈編譯的源代碼需要訪問的系統(tǒng)接口是trget上的。
2、binutils:必須能在host上運(yùn)行,然而產(chǎn)生target的代碼。
3、gcc:和binutils一樣。不過這里要注意的是,gcc自身帶有一個(gè)庫,稱為libgcc,它必須是target上的代碼。
4、glibc:必須是target上的代碼。
有了這些基本認(rèn)識(shí),讓我們來看一看一些實(shí)際的工具鏈構(gòu)造過程。
LFS工具鏈構(gòu)造順序:binutils p1->gcc p1->頭文件->glibc->adjust->gcc p2->binutils p2
其中最后兩步應(yīng)該可以互換,但頭兩步不行。如果你有留意編譯過程,會(huì)發(fā)現(xiàn),當(dāng)gcc編譯的時(shí)候,一旦內(nèi)部編譯第一次gcc完成,產(chǎn)生了xgcc文件,隨后的編譯就會(huì)利用新編譯的gcc以及第一遍的binutils,而不是宿主的gcc和binutils。
正如youbest指出的,第一遍的binutils和gcc存在的意義,僅僅是為了能編譯出glibc。而glibc的編譯需要工具鏈所有其它內(nèi)容,包括binutils,gcc和頭文件。
LFS不使用交叉編譯,因此host和target永遠(yuǎn)是一樣的。在編譯參數(shù)中,我們永遠(yuǎn)看不到--host和--target的身影。但是,由于工具鏈的引用路徑需要反復(fù)變化,因此我們需要通過修改specs來更改。這點(diǎn)是LFS比較容易出錯(cuò)的地方。
CLFS顧名思義,是要采用交叉編譯的。其構(gòu)造順序如下:
頭文件->cross binutils->cross-gcc c->glibc->gcc final (c/c++)
我們首先看到頭文件被放在了開頭。這不是必須的,它完全可以放在glibc之前。cross-gcc只能編譯出C編譯器,因?yàn)檫@時(shí)候工具鏈還不全,glibc還不存在,不可能編譯出C++編譯器。然后構(gòu)建glibc。之后,我們才能編譯出C++編譯器,完成我們的工具鏈。
CLFS-SYSROOT的工具鏈稍有不同,順序如下:
頭文件->cross-binutils->glibc頭文件->cross-gcc c->gibc->gcc-final (c/c++)
我們看到這里多了一個(gè)glibc頭文件的安裝。事實(shí)上,這是由于這里編譯的gcc是要用sysroot的緣故。在gcc/configure里面有一段代
碼,大家在vi里面輸入/inhibit_libc=false就可以發(fā)現(xiàn),在交叉編譯,而沒有SYSROOT的情況下,inhibit_libc的值會(huì)
成為true,而要是sysroot了,就false了。
這個(gè)變量的作用,如同有關(guān)的注釋所述,是用來關(guān)閉gcc對(duì)glibc頭文件的依賴。因此,在sysroot下我們才會(huì)需要這樣一個(gè)安裝glibc頭文件的步驟。
我想在sysroot下消除這個(gè)步驟,之前測(cè)試過這個(gè)補(bǔ)丁可行:
使用這個(gè)sed命令打個(gè)補(bǔ)丁即可:
cp gcc/configure{,.orig}
sed -e 's/inhibit_libc=false/inhibit_libc=true/g' gcc/configure.orig > gcc/configure
不過最近發(fā)現(xiàn)有更簡(jiǎn)單的方法:在configure的時(shí)候加個(gè)參數(shù)--with-newlib即可。建議采用這個(gè)方法,因?yàn)椴恍枰蛉魏窝a(bǔ)丁。
在此再說一句,工具鏈構(gòu)建過程中,編譯腳本對(duì)于是否交叉編譯的判斷非常簡(jiǎn)單,只要host!=target,就會(huì)被認(rèn)為正在交叉編譯。這也就是為什么
CLFS中使用的$CLFS_HOST通常都是i686-cross-linux-gnu這樣的形式。原因很簡(jiǎn)單,因?yàn)橐_保$CLFS_HOST
與$CLFS_TARGET不同。這樣,你完全可以在i686上"交叉編譯"i686的代碼。
這點(diǎn)非常重要,這意味著我們不需要打任何補(bǔ)丁,即可利用CLFS和CLFS-SYSROOT代替LFS來完成系統(tǒng)。對(duì)于想做Multilib的朋友,這也是一個(gè)福音。畢竟,CLFS-SYSROOT比起CLFS和LFS來,節(jié)省了大量的編譯過程。
最后,我們來理解一下如何作CCLFS工具鏈。這意味著我們要在一個(gè)平臺(tái)上構(gòu)建在第二個(gè)平臺(tái)上運(yùn)行、生成第三個(gè)平臺(tái)上代碼的工具鏈。我們用build表示
構(gòu)建工具鏈的機(jī)器,host表示工具鏈要運(yùn)行的機(jī)器,target表示工具鏈生成的代碼所在機(jī)器。而在工具鏈組件上,host-target
binutils表示該binutils在host上運(yùn)行,要生成target的代碼。
步驟如下:
host 頭文件->build-host binutils->build-host gcc c->host
glibc->target 頭文件->build-target binutils->build-target gcc
c->target glibc->host-target binutils->host-target gcc final
(c/c++)
注意事項(xiàng)如下。首先,頭文件必須在相應(yīng)的glibc之前安裝。其次,build-target的binutils和gcc在這里的目的是生成target
glibc。而build-host binutils 還會(huì)被構(gòu)建host-target
binutils和gcc的過程使用到。最后,前兩次的gcc都可以只生成c編譯器,因?yàn)樗麄兊哪康亩贾皇巧蒰libc。只有最后一次gcc需要完整生成。
from: http://www.linuxsir.org/bbs/thread325648.html