1. GNU工具鏈包括
預編譯,編譯器,鏈接器,匯編器
相關的包
Binutils : 所有和二進制文件相關的工具都包括在Binutils中。主要包括:as,ld,objdump,strip,與編譯器cpp 等。
GCC : 編譯器包括在GCC中,包括C++編譯器,Ada編譯器等
Glibc : 包括 C庫,動態連接器。
除了這三個軟件包外,工具鏈還需要包括內核文件。用戶空間中的很多操作都需要借助內核來完成,C庫中很大部分是對內核服務的封裝,某種意義上,內核頭文件可以看作是內核和C庫之間的協議,因此構建C庫前,需要首先在工具鏈中安裝內核頭文件。
此外,gcc 並不是編譯器,而是驅動程序,只會 編譯過程的各個環節,如cc1負責編譯,as負責匯編,ld負責鏈
2. 構建流程
由於C庫和GCC互相依賴,
C99有兩種實現,
hosted implementation:支持完整的C標准,包括語言標准和庫標准
freestanding implementation : 完全支持C語言標准,但只要求支持部分庫標准
先編譯個 freestanding implementation 的gcc(不需要C庫支持)
再用這個gcc編譯 c庫
再用C庫編譯hosted implementation的gcc
而編譯C庫時,需要鏈接器,所以需要編譯 Binutils,Binutils幾乎沒有依賴,所以可以直接編譯 Binutils.
另外需要內核頭文件,內核頭文件相當於內核和C庫之間的協議,C庫會根據內核頭文件檢查內核提供了哪些特性,需要在C庫層面模擬哪些內核沒有提供的服務。
所以,構建交叉編譯器的步驟如下:
1.構建交叉 Binutils:包括as ld等
2.構建臨時交叉編譯器(僅支持freestanding)
3.安裝目標內核頭文件
4.構建目標系統C庫
5.構建完整的交叉編譯器(支持hosted 的 freestanding)
3. 構建
3.1 准備
創建普通用戶
groupadd vita
useradd -m -s /bin/bash -g vita vita
-m 表示創建vita從屬目錄
-s /bin/bash表示使用bash shell
-g vita 表示將vita加入vita組
給vita超級權限
在/etc/sudoers.d/中添加一個文件vita,內容為
vita ALL=(ALL) NOPASSWD: ALL
建立工作目錄
mkdir source build cross-tools cross-gcc-tmp sysroot
chown -R vita.vita /home/vita
source 存放源代碼
build 用於編譯
cross-tools保存交叉編譯工具
cross-gcc-tmp保存臨時的freestanding編譯器
sysroot 編譯好的目標機器上的文件安裝到此目錄,相對於目標系統的根目錄。
定義環境變量
unset LANG
export HOST=x86_64-redhat-linux-gnu
export BUILD=$HOST
export TARGET=x86_64-none-linux-gnu
export CROSS_TOOL=/home/vita/cross-tools
export CROSS_GCC_TMP=/home/vita/cross-gcc-tmp
export SYSROOT=/home/vita/sysroot
PATH=$CROSS_TOOL/bin:$CROSS_GCC_TMP/bin:/sbin:/usr/sbin:$PATH
設置英文環境,使用unset LANG,以避免給一些腳本工具帶來麻煩。
為使用交叉編譯工具,我們將其目錄添加到環境變量PATH中,包括臨時GCC的存儲目錄,注意臨時GCC的目錄一定要在最終正式工具鏈目錄的后面,確保安裝最終的交叉編譯器后,在編譯時優先使用最終的交叉編譯器
HOST和BUILD和TARGET的格式是 ARCH-VENDOR-OS 組合,若沒有顯示設置編譯腳本會自動探測。
HOST表示程序運行環境
TARGET表示程序輸出文件的運行環境
BUILD表示構建程序的環境
當HOST和TARGET相同,編譯腳本構建本地運行,生成本地執行文件的編譯工具
當HOST和TARGET不同,編譯腳本構建本地運行,生成其他環境執行的文件的編譯工具
由於我的平台都是x86-64所以,我修改vendor區域,以進行構造交叉編譯編譯工具。
對於本地環境可以用 echo $MACHTYPE查看
SYSROOT使最終的編譯工具構建的程序,鏈接時,連接器查找目錄為SYSROOT
2.1 構建binutils
mkdir binutils-build
cd binutils-build
../binutil/configure --prefix=$CROSS_TOOL --target=$TARGET --with-sysroot=$SYSROOT
--prefix=$CROSS_TOOL 通過--prefix參數指定安裝腳本將編譯好的二級制工具安裝到保存交叉編譯工具鏈的$CROSS_TOOL目錄下
--target=$TARGET 若沒有顯示指定--host和--build,編譯腳本會自動探測HOST和BUILD的值,這里HOST和BUILD的值相同,是本地環境。TARGET為其他環境,與HOST不同,所以編譯腳本判斷這是構建交叉編譯工具鏈,繼而指導宿主系統的工具鏈編譯 運行在本機,但最后編譯鏈接的程序、庫是運行$TARGET的交叉二進制工具。
--with-sysroot=$SYSROOT 通過參數--with-sysroot告訴連接器,目標系統的根文件系統放置在$SYSROOT目錄下,連接時到$SYSROOT目錄下尋找相關的庫。
2.2 構建gcc free standing
2.2.1 安裝 mpc mpfr gmp
將mpc mpfr gmp 安裝到 /home/vita下
並添加環境變量
export LD_LIBRARY_PATH=/home/vita/mpc/lib
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/vita/gmp/lib
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/vita/mpfr/lib
注意 LD_LIBRARY_PATH 必須 前后不能有 分號
2.2.2 構建gcc
mkdir gcc-build
cd gcc-build
../gcc-4.7.4/configure --prefix=$CROSS_GCC_TMP --target=$TARGET --with-sysroot=$SYSROOT --with-newlib --enable-languages=c --disable-threads --disable-shared --disable-decimal-float --disable-libquadmath --disable-libmudflap --disable-libgomp --disable-nls --disable-libssp --with-gmp=/home/vita/gmp --with-mpc=/home/vita/mpc --with-mpfr=/home/vita/mpfr
make && make install
--with-newlib : 按照 free-standing構建gcc,即gcc無其他依賴 如 glibc
注意:
- 若保 texinfo 錯誤,極可能是 texinfo版本太新或太舊, 也可以選擇編譯更新版本的GCC
- 不能在GCC目錄遍歷,否則會報錯:libgcc.mvars: No such file or directory
- 編譯失敗,需刪除源碼,弄份全新的
cd cross-gcc-tmp
ln -s lib/gcc/i686-none-linux-gnu/4.7.4/libgcc_eh.a
glibc需要鏈接 libgcc_eh.a,但是gcc沒有這個文件,但libgcc.a的內容和libgcc_eh.a相同,所以可以建立軟鏈接
2.3 構建glibc
准備內核頭文件,
應用程序不能直接使用內核服務,必須使用中斷,
c庫對內核服務器進行了封裝,所以應用程序可以使用C庫調用內核服務,
所以編譯glibc必須要內核頭文件。
2.3.1 安裝內核頭文件
cd linux-3.0.1
make mrproper
make ARCH=i386 headers_check
make ARCH=i386 INSTALL_HDR_PATH=$SYSROOT/usr headers_install
2.3.2 構建glibc
../glibc-2.15/configure --prefix=$SYSROOT --host=$TARGET --enable-kernel=3.7.4 --enable-add-ons --with-headers=$SYSROOT/usr/include libc_cv_forced_unwind=yes libc_cv_c_cleanup=yes libc_cv_ctors_header=yes
make && make install
2.4 構建完整 gcc
3. gcc命名 和 特點
3.1 abi
abi是二進制級別的標准,
符號abi的編譯器生成符合abi的目標文件,這種目標文件能在 任意 符合abi且相同 arch的系統上運行。
eabi 是在abi基礎上,針對嵌入式環境做了調整的標准。
3.2 gcc的命令
arch-vendor-os-abi-
如
arm-none-linux-gnueabi-
arm-none-eabi
關鍵是 arch 和 os
arch決定其目標文件的 arch。
os說明其使用的c庫,
如 arm-none-linux-gnueabi-
os為linux,使用clib庫,則在 編譯器目錄下 應該會提供相關的 c庫(C庫不應該有開發者構建,因為現有C庫再有完整版gcc)。
arm-none-eabi
os為空,使用 -newlib構建的gcc,free standing模式,所以不提供c庫。
