《LinuxFromScratch》第三部分:構建LFS系統第六章:安裝基本的系統軟體-6.17.GCC-4.9.2

行者武松發表於2017-11-08

             GCC 軟體包包括 GNU 編譯器集,其中有 C 和 C++ 的編譯器。

大概編譯時間:
63 SBU (包括測試)
需要磁碟空間:
2.9 GB

6.17.1. 安裝 GCC

GCC 的文件建議在原始碼目錄之外一個專用的編譯目錄中編譯 GCC:

mkdir -v ../gcc-build
cd ../gcc-build

準備編譯 GCC:

SED=sed                       
../gcc-4.9.2/configure        
     --prefix=/usr            
     --enable-languages=c,c++ 
     --disable-multilib       
     --disable-bootstrap      
     --with-system-zlib

注意,對於其它的程式語言,現在還有一些前提條件沒有準備好。可以檢視
BLFS Book
瞭解如何編譯 GCC 支援的所有語言的指令。

新配置選項的含義:

SED=sed

設定環境變數防止訪問到硬編碼的 /tools/bin/sed 路徑。

--with-system-zlib

這個選項告訴 GCC 連結系統安裝的 Zlib 庫,而不是它內部自帶的庫。

編譯軟體包:

make
[Important]

重要

本章節中 GCC 的測試套件至關重要,任何情況下都不能跳過。

GCC 測試套件中一個測試集的會耗盡堆疊空間,因此執行測試之前要增加棧大小:

ulimit -s 32768

測試編譯結果,但不要因為出現錯誤就停下來:

make -k check

要檢視測試套件結果的概要,執行:

../gcc-4.9.2/contrib/test_summary

如果只是檢視概要,可以將輸出通過管道送到 grep -A7 Summ

結果可以和 http://www.linuxfromscratch.org/lfs/build-logs/7.7-systemd/
以及 http://gcc.gnu.org/ml/gcc-testresults/ 上的相比較。

一些意料之外的錯誤總是難以避免。GCC 開發者通常意識到了這些問題,但還沒有解決。除非測試結果和上面 URL 中的相差很大,不然就可以安全繼續。

安裝軟體包:

make install

一些軟體包希望 GCC 安裝在 /lib 目錄。為了支援那些軟體包,可以建立一個符號連結:

ln -sv ../usr/bin/cpp /lib
譯者注:如果還在 gcc-build 目錄,這裡應該是 ln -sv ../../usr/bin/cpp /lib 。

很多軟體包用命令 cc 呼叫 C 編譯器。為了滿足這些軟體包,建立一個符號連結:

ln -sv gcc /usr/bin/cc

增加一個相容符號連結啟用編譯程式時進行連結時間優化(Link Time Optimization,LTO):

install -v -dm755 /usr/lib/bfd-plugins
ln -sfv ../../libexec/gcc/$(gcc -dumpmachine)/4.9.2/liblto_plugin.so /usr/lib/bfd-plugins/

現在我們最終的工具鏈已經準備就緒了,再一次確認編譯和連結都能像預期那樣正常工作很重要。我們通過做和前面章節做過的相同的完整性檢查做到這點:

echo `main(){}` > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep `: /lib`

這應該沒有錯誤,最後一個命令的輸出應該是(允許平臺相關的動態連結器名字有差異):

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

現在確認我們設定了正確的啟動檔案:

grep -o `/usr/lib.*/crt[1in].*succeeded` dummy.log

最後一個命令的輸出應該是:

/usr/lib/gcc/i686-pc-linux-gnu/4.9.2/../../../crt1.o succeeded
/usr/lib/gcc/i686-pc-linux-gnu/4.9.2/../../../crti.o succeeded
/usr/lib/gcc/i686-pc-linux-gnu/4.9.2/../../../crtn.o succeeded

取決於你機器的架構,上面的結果可能有稍微不同,差異通常是 /usr/lib/gcc 後目錄的名稱。如果你的是 64 位系統,你也許能看到後面有個 lib64 的目錄名字。這裡重要的一點是 gcc 能在 /usr/lib 目錄下找到所有的三個 crt*.o 檔案。

驗證編譯器能搜尋正確的標頭檔案:

grep -B4 `^ /usr/include` dummy.log

這個命令應該返回下面的的輸出:

#include <...> search starts here:
 /usr/lib/gcc/i686-pc-linux-gnu/4.9.2/include
 /usr/local/include
 /usr/lib/gcc/i686-pc-linux-gnu/4.9.2/include-fixed
 /usr/include

同時,注意你的目標系統三段式後面的目錄名稱可能和上面的不同,這取決於你的架構。

[Note]

注意

在版本 4.3.0 中,GCC 無條件安裝 limits.h 檔案到私有 include-fixed 目錄,要求這個目錄已經存在。

下一步,驗證新的連結器在使用正確的搜尋路徑:

grep `SEARCH.*/usr/lib` dummy.log |sed `s|; |
|g`

可以忽略指向含有 `-linux-gnu` 的路徑的引用,但最後一個命令的輸出應該是:

SEARCH_DIR("/usr/i686-pc-linux-gnu/lib32")
SEARCH_DIR("/usr/local/lib32")
SEARCH_DIR("/lib32")
SEARCH_DIR("/usr/lib32")
SEARCH_DIR("/usr/i686-pc-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib");

64 位的系統可能有一些不同的目錄。例如,下面是一臺 x86_64 機器的輸出:

SEARCH_DIR("/usr/x86_64-unknown-linux-gnu/lib64")
SEARCH_DIR("/usr/local/lib64")
SEARCH_DIR("/lib64")
SEARCH_DIR("/usr/lib64")
SEARCH_DIR("/usr/x86_64-unknown-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib");

然後確認我們使用了正確的 libc:

grep "/lib.*/libc.so.6 " dummy.log

最後一個命令的輸出(64 位主機中應該是 lib64 目錄)應該是:

attempt to open /lib/libc.so.6 succeeded

最後,確認 GCC 在使用正確的動態連結器:

grep found dummy.log

最後一個命令的輸出應該是(平臺相關的動態連結器是可以有所差異, 64 位系統中應該是 lib64 目錄):

found ld-linux.so.2 at /lib/ld-linux.so.2

如果輸出和上面的不一樣或者根本就沒有任何輸出,表明發生了很嚴重的錯誤。檢查並回溯步驟找出問題所在並糾正它。最可能的原因是配置檔案調整時出現了問題。在進入下一步之前必須解決所有的問題。

當一切都正常工作後,清理測試檔案:

rm -v dummy.c a.out dummy.log

最後,移動位置放錯的檔案:

mkdir -pv /usr/share/gdb/auto-load/usr/lib
mv -v /usr/lib/*gdb.py /usr/share/gdb/auto-load/usr/lib

6.17.2. GCC 軟體包內容

安裝的程式:
c++, cc (連結到 gcc), cpp, g++, gcc,
gcc-ar, gcc-nm, gcc-ranlib, 和 gcov
安裝的庫:
libasan.{a,so}, libatomic.{a,so},
libgcc.a, libgcc_eh.a, libgcc_s.so, libgcov.a, libgomp.{a,so},
libiberty.a, libitm.{a,so}, liblto_plugin.so,
libquadmath.{a,so}, libssp.{a,so}, libssp_nonshared.a,
libstdc++.{a,so}, libsupc++.a, 和 libtsan.{a,so}
安裝目錄:
/usr/include/c++, /usr/lib/gcc,
/usr/libexec/gcc, 和 /usr/share/gcc-4.9.2

簡要介紹

c++

C++ 編譯器

cc

C 編譯器

cpp

C 前處理器;編譯器用來擴充套件原始檔中 #include、#define 以及類似語句

g++

C++ 編譯器

gcc

C 編譯器

gcc-ar

增加外掛到命令列的 ar 的封裝。這個程式只用於新增
“連結時間優化”,在使用預設編譯選項時不起作用

gcc-nm

增加外掛到命令列的 nm 的封裝。這個程式只用於新增
“連結時間優化”,在使用預設編譯選項時不起作用

gcc-ranlib

增加外掛到命令列的 ranlib 的封裝。這個程式只用於新增
“連結時間優化”,在使用預設編譯選項時不起作用

gcov

一個覆蓋測試工具;用於分析程式以決定在哪裡進行優化有最大的效果

libasan

Address Sanitizer(譯者注:地址消毒劑,可以檢視:Wiki)執行時庫。

libgcc

包含用於 gcc 的執行時支援

libgcov

當指示 GCC 啟用分析時該庫會被連結到程式中

libgomp

用於 C/C++、Fortran 語言的多平臺共享記憶體並行程式設計的 OpenMP API 的 GNU 實現

libiberty

包含多種 GNU 程式所使用的例程,包括
getopt,
obstack,
strerror,
strtol, 和
strtoul

liblto_plugin

GCC 的連結時間優化外掛,允許 GCC 跨編譯單元進行優化

libquadmath

GCC 四精度數學庫 API

libssp

包含支援 GCC 堆疊溢位保護功能的例程

libstdc++

標準 C++ 庫

libsupc++

為 C++ 程式語言提供支援例程

libtsan

Thread Sanitizer(譯者注:資料速率檢測工具,包括一個編譯器指令模組和執行時庫) 執行時庫


相關文章