閱讀834 返回首頁    go 汽車大全


《Linux From Scratch》第二部分:準備構建 第五章:構建臨時文件係統- 5.2 工具鏈技術備注

         本節解釋總體構建方法之中的某些基本原理和技術細節。並不需要立即理解本節中的所有問題。在進行實際構建的過程中,絕大部分的信息將會變得愈加清晰。在該過程中可隨時查閱本小節的內容。

第五章的總體目標是生成一個臨時的係統,它包含一個已知的較好工具集,該工具集可與宿主係統分離。通過使用 chroot,其餘各章中的命令將被包含在此環境中,以保證目標 LFS 係統能夠潔淨且無故障地生成。該構建過程的設計就是為了使得新讀者有最少的風險,同時還能有最好的指導價值。

[Note]

注意

在繼續之前,請留意工作平台的名稱,它通常稱作目標係統三段式名稱。目標係統三段式名稱可通過運行腳本 config.guess 簡單獲得,許多軟件的源碼包都附帶有該腳本(譯者注:目標係統三段式名稱描述了代碼運行的平台,是GNU 構建係統中的一個核心概念,形如 i686-pc-gnu-linux。它包含三個字段:CPU家族/型號的名稱(如 i686)、供應商(pc)和操作係統名稱(如 gnu-linux)。更詳細的信息請參閱 https://wiki.osdev.org/Target_Triplet)。解壓 Binutils 源碼包,執行其中的腳本:./config.guess 並查看其輸出。例如,對於一個現代的 32 位英特爾處理器,其輸出很可能為 i686-pc-linux-gnu

還請留意平台的動態鏈接器的名稱,它通常被稱為動態加載器(不要與 Binutils 中的標準鏈接器 ld 混淆)。該動態鏈接器由 Glibc 提供,它尋找並加載程序所需的共享庫,為程序運行作準備,並運行它。對於 32 位英特爾的機器,動態鏈接器的名稱為 ld-linux.so.2。判斷動態鏈接器的一個可靠方法是檢查宿主係統中的任意一個二進製文件,執行:readelf -l <二進製文件名> | grep interpreter 且查看其輸出。可在 Glibc 源碼樹的根目錄下的 shlib-versions 文件中找到所有平台的權威參考。

下麵是第五章構建方法的幾個關鍵技術點:

  • 通過改變 LFS_TGT 變量的目標係統三段式中的 “供應商” 字段,從而稍微調整工作平台的名稱,以保證第一遍構建 Binutils 和 GCC 時能夠生成兼容的交叉鏈接器和交叉編譯器。此處的交叉鏈接器和交叉編譯器生成的二進製文件與當前的硬件兼容,而不是用於其它的硬件架構。

  • 臨時庫經交叉編譯獲得。由於交叉編譯原本就不應該依賴於宿主係統,因此,通過降低宿主係統的頭文件或庫進入新工具的可能性,該方法可去除目標係統的可能汙染。交叉編譯的方式,還可以在 64 位硬件平台上同時構建出 32 位和 64 位庫。

  • 謹慎操作 GCC 源碼,以告訴編譯器將使用哪個目標係統動態鏈接器。

Binutils 是首個安裝的包,這是因為執行 GCC 和 Glibc 的 configure 時都將進行有關匯編器和鏈接器的多項特性測試,以判斷允許或禁用哪些軟件特性。其重要性可能更甚於最初的意識。對 GCC 或 Glibc 的錯誤配置可能導致工具鏈出現難以捉摸的問題,可能直到整個構建過程接近尾聲時才會顯現出這些問題。通常情況下,一次測試套件失敗可在你進行太多其它工作前暴露出該錯誤。

Binutils 將其匯編器和鏈接器安裝在兩個位置,即 /tools/bin/tools/$LFS_TGT/bin。一個位置的工具是硬鏈接到另一個位置的。鏈接器的一個重要方麵是它的庫搜索順序。可給 ld 傳遞參數 --verbose 獲得詳細信息。如,ld --verbose | grep SEARCH 可得到當前的搜索路徑及其順序。通過編譯一個模擬程序並向鏈接器傳遞 --verbose 開關,可顯示 ld 都鏈接了哪些文件。例如,gcc dummy.c -Wl,--verbose 2>&1 | grep succeeded 將顯示鏈接過程中成功打開的所有文件。

下一個安裝的包是 GCC。下麵是運行 GCC 的 configure 的輸出的一個例子:

checking what assembler to use... /tools/i686-lfs-linux-gnu/bin/as
checking what linker to use... /tools/i686-lfs-linux-gnu/bin/ld

基於前述原因,這很重要。它還說明了 GCC 的配置腳本並不會搜索 PATH 目錄來尋找使用什麼工具。不過,在 gcc 自身的實際運行中,並不需要使用同樣的搜索路徑。運行:gcc -print-prog-name=ld 可獲知 gcc 使用是何種標準鏈接器(LCTT 譯注:gcc -print-prog-name 這個命令是為了顯示 gcc 使用的某些內部工具的絕對路徑,但事實上,ld 並不是 GCC 的內部工具,因此這條命令實際上沒什麼用)。

在編譯模擬程序時,向 gcc 傳遞命令行選項 -v 可獲得詳細信息。例如,gcc -v dummy.c 將顯示預處理器、編譯和匯編階段的詳細信息,包括 gcc 的 include 搜索路徑及其順序。

下一個安裝的包是經過淨化的 Linux API 頭文件。這些頭文件可使得標準 C 庫(Glibc)與 Linux 內核提供的特性進行交行交互。

下一個安裝的包是 Glibc。構建 Glibc 時,最重要的考量是編譯器、二進製工具和內核頭文件。由於 Glibc 總是使用傳遞給它的配置腳本的 --host 參數有關的編譯器,如,在我們這個場景中是 i686-lfs-linux-gnu-gcc,因此編譯器通常不是一個問題。二進製工具和內核頭文件可能會更複雜一些。因此,請謹慎行事並利用可用的配置開關以強製使用正確的選擇。configure 運行完畢,目錄 glibc-build 下的文件 config.make 包含有所有的重要細節。需要注意的是,CC="i686-lfs-gnu-gcc" 用來控製使用哪個二進製工具,-nostdinc-isystem 標誌用來控製編譯器的 include 搜索路徑。這些條目強調了 Glibc 包的一個重要方麵,即其構建機製是非常自給自足的,通常並不依賴默工具鏈的默認設置。

在第二遍編譯 Binutils 過程中,我們能夠利用配置開關 --with-lib-path 來控製 ld 的庫搜索路徑。

第二遍編譯 GCC 時,也需要修改其源代碼以告訴 GCC 使用新的動態鏈接器。如果不加修改,將會導致 GCC 自身的程序嵌入來自宿主係統目錄 /lib 的動態鏈接器名稱,這將破壞遠離宿主係統的目標。正是基於前麵的這個出發點,核心工具鏈是自包含和自托管的。第五章其它的軟件包都將在 /tools 中的新 Glibc 的基礎上進行構建。

在進入第六章中的 chroot 環境前,將安裝的首個主要的軟件包是 Glibc,這是因為它天生具有前麵提及的自給自足特點。一旦將 Glibc 安裝到 /usr 中,我們將快速改變工具鏈的默認設置,然後繼續構建目標 LFS 係統的其餘部分。


創建者:Gerard Beekmans

編輯者:Matthew Burgess 和 Armin K.

翻譯團隊:LCTT

譯者/校對:Yuking-net,wxy

原文鏈接       

最後更新:2017-11-07 14:34:39

  上一篇:go  《Linux From Scratch》第二部分:準備構建 第五章:構建臨時文件係統- 5.3. 通用編譯指南
  下一篇:go  《Linux From Scratch》第二部分:準備構建 第五章:構建臨時文件係統- 5.1 簡介