【LFS之步步爲營】【三】


【引言:進一步推進工作,開始工具鏈的製作,其間命令較多且較複雜,需謹慎細心。】


本節主要記錄如何構建一個新的不依賴於宿主系統的工具鏈(編譯器、彙編器 、 連接器、庫文件以及一些有用的軟件),並對每步操作進行相應說明,外加筆者遇到的一些問題及解決方案。


首先什麼叫工具鏈?

LFS/CLFS工具鏈是一套用於從C/C++源代碼生成可執行文件的軟件組件適當地組合在一起形成的系統。它包括4大部分,缺一不可:

1. Linux API  一套頭文件,包含了這些源代碼所需要訪問的系統接口;

2. binutils   包含一些處理二進制可執行文件所需的工具,如彙編器、連接器等;

3. gcc        包含了編譯C/C++源代碼所需的工具,並且還能自動調用相關的binutils工具來完成生成源代碼的工具;

4. glibc      包含了系統接口的具體實現。

在上面的定義中,這些軟件適當地組合形成完整的工具鏈。

本節編譯的文件將安裝在 $LFS/tools 目錄下,編譯出來的軟件包起臨時作用,後面還會繼續調整工具鏈。


注:上節已說明,所有爲輸入命令都爲藍色標識,輸入文本爲灰色標識



3.1  安裝 Binutils (10分鐘)

安裝的第一個軟件包是 Binutils,它包含一個鏈接器,一個彙編器和其他處理目標文件的工具。

cd $LFS/sources                              進入工作目錄;

tar xvf /lfs-sources/binutils-2.17.tar.bz2   解壓binutils壓縮包到當前目錄;

mkdir binutils-build                         創建一個專用目錄來編譯;

cd binutils-build                            進入編譯目錄;

../binutils-2.15.94.0.2.2/configure --prefix=/tools --disable-nls

參數說明:

        --prefix=/tools        參數告訴 configure 腳本,準備把 Binutils 軟件包中的程序安裝到 /tools 目錄中;

        --disable-nls          禁止了國際化(通常簡稱i18n),因爲臨時工具不需要i18n特性;

此步操作是爲編譯做準備,在當前目錄下生成編譯需要的 Makefile。


make                                         開始編譯;

make install                                 安裝;

make -C ld clean                             表示進入ld目錄,執行ld/Makefile中的clean編譯生成的文件;

make -C ld LIB_PATH=/tools/lib               進入ld目錄進行make,將make的環境變量LIB_PATH設置爲/tools/lib;

cp -v ld/ld-new /tools/bin                   拷貝ld目錄下的ld-new文件到/tools/bin;

cd ..                                        回到上層目錄$LFS/sources。

注意:這裏暫時不要刪除binutils-build目錄,因爲後面需要這個編譯過的binutils-build



3.2  安裝 GCC-4.1.2 (30分鐘)

tar xvf /lfs-sources/gcc-4.1.2.tar.bz2       解壓壓縮包到當前目錄下;

mkdir gcc-build                              同上,創建一個單獨的目錄來編譯;

cd gcc-build                                 進入編譯目錄;

../gcc-4.1.2/configure --prefix=/tools --libexecdir=/tools/lib \

         --with-local-prefix=/tools --disable-nls \

         --enable-shared --enable-languages=c

參數說明:

        --disable-shared       該參數強制 GCC 鏈接其內部的靜態庫,這樣做是爲了避免和宿主系統產生問題;

        --enable-languages=c   此參數確保只建立 C 編譯器,因爲現在只需要這一種編譯器。

由於上面命令過長,因此用連接符"\"進行連接,在輸入時也可直接全部輸入,注意參數與參數之間的空格。


make bootstrap                               編譯GCC編譯器;

命令說明:

       該命令一般在編譯編譯器時用。bootstrap不只是編譯GCC,而要連着編譯多次,它第一次用主機的GCC進行編譯,第二次用剛編譯好的GCC編譯,

       然後再用編譯好的GCC編譯,然後會畢較第二次和第二次的結果以確保它能正確無誤的生成它自己。


make install                                 安裝GCC;

ln -vs gcc /tools/bin/cc                     第一遍編譯GCC時,創建了符號鏈接,是把/tools/bin/cc 鏈接到 /tools/bin/cc/gcc;

cd ..

rm -rf gcc-build gcc-4.1.2                   刪除gcc編譯目錄和解壓的源文件。

注意:這裏不要圖省事而不刪gcc目錄,因爲這樣可能會給後面的編譯產生一些意外的錯誤。



3.3  安裝 Linux API Headers  (5分鐘)

這裏必須得說明一下,也是筆者遇到的一個很大的困惑:

LFS6.3以前的版本是使用linux-libc-headers-2.6.11.2.tar.bz2,但此版本LiveCD沒有此文件,而是使用內核包linux-2.6.22.5.tar.bz2,通過處理Linux內核源程序tar包中的各種C頭文件而實現應用程序接口 (API)獲取,以供系統C庫(在LFS中是Glibc)使用。

tar xvf /lfs-sources/linux-2.6.22.5.tar.bz2  解壓;

cd linux-2.6.22.5                            進入剛解壓到當前目錄的內核目錄;

make mrproper                                確保上一次的活動沒有留下失效的文件和依賴;

make headers_check                           從源碼中測試內核頭文件;

make INSTALL_HDR_PATH=dest headers_install   提取過程會刪除目標目錄中的原有文件,所以把它們放在一箇中間的本地目錄中

cp -rv dest/include/* /tools/include         拷貝目標目錄中的所有原文件到/tools/include;

cd ..

rm -rf linux-2.6.22.5                        刪除解壓的內核目錄。



3.4  安裝 Glibc (30分鐘)

tar xvf /lfs-sources/glibc-2.5.1.tar.bz2     解壓;

mkdir glibc-build                            同上,創建一個單獨的目錄來編譯;

cd glibc-build                               同上;

../glibc-2.5.1/configure --prefix=/tools --disable-profile \

--enable-add-ons --enable-kernel=2.6.0 --with-binutils=/tools/bin \

--without-gd --with-headers=/tools/include --without-selinux

參數說明:

        --disable-profile                關掉了分析(profiling)信息相關的庫文件編譯;

        --enable-add-ons                 告訴 Glibc 使用附加的 NPTL 包作爲它的線程庫;

        --enable-kernel=2.6.0            告訴Glibc 編譯支持2.6.0版和更新版Linux 內核的庫;

        --with-headers=/tools/include    指示Glibc 按照前面剛剛安裝到tools 目錄中的內核頭文件編譯自己,

                                         從而準確的知道內核的特性以根據這些特性對自己進行最佳化編譯。


make                                          編譯;

mkdir /tools/etc                              創建etc目錄;

touch /tools/etc/ld.so.conf                   創建ld.so.conf文件,因爲touch創建不存在的文件,避免編譯安裝出現警告;

make install                                  安裝;

cd ..

rm -rf glibc-build glibc-2.5.1                刪除glibc編譯和解壓目錄。



3.5  調整並測試工具鏈  (10分鐘)

mv -v /tools/bin/{ld,ld-old}                               備份/tools/bin/ld文件;

mv -v /tools/$(gcc -dumpmachine)/bin/{ld,ld-old}           同樣備份ld文件;

mv -v /tools/bin/{ld-new,ld}                               更新ld文件;

ln -sv /tools/bin/ld /tools/$(gcc -dumpmachine)/bin/ld     創建新的ld連接;

以上4步操作結果如下圖:


現在已經安裝好了臨時C庫,接下來本章中要編譯的所有工具都應該連接到這些庫上。爲了達到這個目標,需要調整交叉編譯器的 specs 文件,以便指向 /tools目錄中的新的動態鏈接器。

將編譯器的 “specs” 文件轉存到一個位置,在那裏可以按默認值找到它。然後,一個簡單的sed替代工具更改GCC 將用到的動態鏈接器。這裏的原則是,在/lib 中找到所有相關的動態鏈接器文件,並調整它們,以便指向新的位置 /tools。

gcc -dumpspecs | sed 's@^/lib/ld-linux.so.2@/tools&@g' > `dirname $(gcc -print-libgcc-file-name)`/specs


GCC_INCLUDEDIR=`dirname $(gcc -print-libgcc-file-name)`/include &&

find ${GCC_INCLUDEDIR}/* -maxdepth 0 -xtype d -exec rm -rvf '{}' \; &&

rm -vf `grep -l "DO NOT EDIT THIS FILE" ${GCC_INCLUDEDIR}/*` &&

unset GCC_INCLUDEDIR

工具鏈的的調整方法有好幾種,而且不同版本GCC的specs可能會有不同,但實際上都是把specs文件中的/lib/ld-linux.so.2替換成了/tools/lib/ld-linux.so.2,也可直接用gcc -dumpspecs導出後手工直接編輯specs文件。這裏就是採用的這種方法。


確認新工具鏈的基本功能(編譯和連接)是否按預期工作,運行下面的命令做一個簡單的合理性檢查:

echo 'main(){}' > dummy.c

cc dummy.c

readelf -l a.out | grep 'tools'

查看a.out的依賴庫,輸出大致如下

[Requesting program interpreter: /tools/lib/ld-linux.so.2]

則表示調整成功,因爲所有的庫已經連接到了/tools/lib下。

rm -rf a.out dummy.c                   





下面介紹筆者在此過程中所遇到的一些問題,以供參考:

1.編譯GCC編譯器 makebootstrap 時報錯:

mkdir -p --/usr/local/lib/gcc/i686-pc-linux-gnu/3.4.3                                 

mkdir: cannot create directory`/usr/local/lib/gcc': Permission denied       

make[1]: *** [installdirs] Error 1                                                                 

make[1]: Leaving directory`/mnt/lfs/sources/gcc-build/gcc'                      

make: *** [install-gcc] Error 2                                                                     

原因出在GCC參數配置錯誤。 


2.



--------------------------------------------------------------------------------------

2013年最後一天,寫完跨年,依舊堅持細節,需更嚴謹。

2013-12-31  







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章