從源碼構建gcc交叉編譯環境

       本文使用linaro公司製作的交叉編譯gcc源代碼進行安裝,那種製作好的交叉編譯工具鏈安裝不是咱的追求,不在學習範圍。
網上有很多安裝說明都是針對現成的工具鏈安裝,而且語焉不詳,很多問題沒有講解清楚。使用源碼編譯安裝,會加深對構建系
統的理解,窺探更爲深入的部分,過程中會出現各種各樣讓人意想不到的,奇奇怪怪的沒有遇到過的問題,甚至讓人崩潰想放棄的問題。如果你淌過去了,你就進步了,學習計算機底層的技術,特別是這種開放源代碼的嵌入式技術,更是這麼一個過程,所以學習是充滿曲折的,但同時也是有趣的,促使人進步的。
       arm-linux-gnueabihf-gcc是由 Linaro 公司基於GCC推出的的ARM交叉編譯工具。可用於交叉編譯ARM系統中所有環節的代碼,包括裸機程序、u-boot、Linux kernel、filesystem和App應用程序。因手上有一塊三星S5PV210的板子,選擇了一個較爲老一點的linaro-gcc源碼進行編譯,具體對應的源代碼可到linaro公司的官網進行下載。下載地址:
https://www.linaro.org/downloads/
有用的參考網址:
https://elinux.org/images/1/15/Anatomy_of_Cross-Compilation_Toolchains.pdf
https://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/
特別是後面這個鏈接,按照它的步聚,雖然有些小問題,幾乎能完成編譯,非常的不錯,本文也按照它的步聚完成了編譯,請注意先後順序。國內的文章還是太少,也缺少相應的開發氛圍,很多小夥伴們編譯一次必定耗費幾天精力。
另外這兒貌似有個對它的編譯的,翻譯的不太清楚,可以參考一下。
https://blog.csdn.net/fickyou/article/details/51671006

1.  編譯源碼和構建環境
1.1 linaro-gcc 源代碼:
gcc-linaro-arm-linux-gnueabihf-4.9-2014.07_linux.tar.xz 
這是一個源碼包,在這個文章裏的鏈接下載的
https://blog.csdn.net/kunkliu/article/details/79695829
選擇源代碼列表裏面的
gcc-linaro-arm-linux-gnueabihf-4.9-2014.07_src.tar.bz2
解壓方法:
tar -zd gcc-linaro-arm-linux-gnueabihf-4.9-2014.07_linux.tar.xz 
會出現.bz2後綴的文件,然後解壓
tar -jxvf gcc-linaro-arm-linux-gnueabihf-4.9-2014.07_linux.tar.bz2
裏面包括編譯需要的所有部件的包,有些包可能用不着:
binutils-linaro-2.24.0-2014.07-1          expat-2.1.0                       linux-3.1.1
binutils-linaro-2.24.0-2014.07-1.tar.bz2  expat-2.1.0.tar.gz                linux-3.1.1.tar
binutils.setup.sh                         gcc-linaro-4.9-2014.07            md5sum
build-binutils                            gcc-linaro-4.9-2014.07.tar        mpc-0.9
build-eglibc                              gcc-setup.sh                      mpc-0.9.tar.gz
build-linaro-gcc                          gdb-linaro-7.6.1-2013.10          mpfr-3.1.0
build-scripts                             gdb-linaro-7.6.1-2013.10.tar.bz2  mpfr-3.1.0.tar
cloog-0.18.0                              gmp-5.0.2                         pkg-config-0.25
cloog-0.18.0.tar.gz                       gmp-5.0.2.tar.bz2                 pkg-config-0.25.tar.gz
compile-eglibc-setup.sh                   isl-0.11.1                        
eglibc-linaro-2.19-2014.07                isl-0.11.1.tar.bz2                zlib-1.2.5
eglibc-linaro-2.19-2014.07.tar.bz2        zlib-1.2.5.tar.gz
1.2 編譯主機(cent os 64)
cat /proc/version 顯示如下
Linux version 3.10.0-957.el7.x86_64 ([email protected]) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC) ) 
1.3 安裝目錄:/usr/local/arm-linux
將路徑/usr/local/arm-linux/bin 加入path中,否則後期出現各種ld找不到文件,明明文件就在那裏,這是關鍵的一步,切勿忽略。
vi /etc/profile
最後加入
export PATH=/usr/local/arm-linux/bin:$PATH
source /etc/profile

2. 先安裝幾個必段庫:
2.1 首先編譯gmp
cd gmp-5.0.2
./configure --prefix=/usr/local/gmp-5.0.2
make 
make install
2.2 編譯mpfr,依懶gmp
cd mpfr-3.1.0
./configure --prefix=/usr/local/mpfr-3.1.0 --with-gmp=/usr/local/gmp-5.0.2
make 
make install
2.3 編譯mpc,依懶gmp,mpfr

2.4 編譯isl,依懶gmp
./configure --prefix=/usr/local/isl-0.11.1 --with-gmp=/usr/local/gmp-5.0.2
make 
make install
2.5 編譯cloog,依懶gmp.
./configure --prefix=/usr/local/cloog-0.18.0 --with-gmp=/usr/local/gmp-5.0.2
make 
make install
3. 編譯binutils,用的是主機的gcc編譯工具。
注意,爲了避免一些未知的錯誤,新建一個目錄單獨編譯:
mkdir build-binutils
假設build-binutils與binutils-linaro-2.24.0-2014.07-1源碼目錄同級
cd build-binutils,編寫一個腳本,配置腳本setup.sh如下:
#/bin/sh
../binutils-linaro-2.24.0-2014.07-1/configure --prefix=/usr/local/arm-linux \
--build=$MACHTYPE \
--target=arm-linux-gnueabihf    \
--enable-shared --disable-multilib

$MACHTYPE不能寫成$(MACHTYPE)

chmod 777 setup.sh
./setup.sh
make 
make install

編譯完成後有安裝目錄這幾個目錄:
/usr/local/arm-linux/
/usr/local/arm-linux/arm-linux-gnueabihf 
/usr/local/arm-linux/bin
/usr/local/arm-linux/share
>>arm-linux-gnueabihf:這是目標目錄,這個設置爲sysroot系統目錄,目錄下有bin和ib。
bin下有這幾個文件:ar  as  ld  ld.bfd  ld.gold  nm  objcopy  objdump  ranlib  strip
/usr/local/arm-linux/arm-linux-gnueabihf/bin/ar  
/usr/local/arm-linux/arm-linux-gnueabihf/bin/as  
/usr/local/arm-linux/arm-linux-gnueabihf/bin/ld  
/usr/local/arm-linux/arm-linux-gnueabihf/bin/ld.bfd
/usr/local/arm-linux/arm-linux-gnueabihf/bin/ld.gold  
/usr/local/arm-linux/arm-linux-gnueabihf/bin/nm  
/usr/local/arm-linux/arm-linux-gnueabihf/bin/objcopy  
/usr/local/arm-linux/arm-linux-gnueabihf/bin/objdump  
/usr/local/arm-linux/arm-linux-gnueabihf/bin/ranlib  
/usr/local/arm-linux/arm-linux-gnueabihf/bin/strip
lib下面有這個目錄:ldscripts,其下又有一推的文件。
/usr/local/arm-linux/arm-linux-gnueabihf/lib/ldscripts
>>bin下面,有一堆的交叉編譯工具(18個文件):
arm-linux-gnueabihf-addr2line  arm-linux-gnueabihf-c++filt  arm-linux-gnueabihf-gprof   arm-linux-gnueabihf-ld.gold  arm-linux-gnueabihf-objdump  arm-linux-gnueabihf-size
arm-linux-gnueabihf-ar         arm-linux-gnueabihf-dwp      arm-linux-gnueabihf-ld      arm-linux-gnueabihf-nm       arm-linux-gnueabihf-ranlib   arm-linux-gnueabihf-strings
arm-linux-gnueabihf-as         arm-linux-gnueabihf-elfedit  arm-linux-gnueabihf-ld.bfd  arm-linux-gnueabihf-objcopy  arm-linux-gnueabihf-readelf  arm-linux-gnueabihf-strip
path:/usr/local/arm-linux/bin
這是用來編譯新系統的工具。
>> share
一些幫助文檔

4. 第一次編譯gcc,注意gcc要分三步編譯,這一步是生成c,c++交叉編譯工具。
同樣單獨建一個目錄編譯
mkdir build-gcc 
假設build-gcc與gcc源碼gcc-linaro-4.9-2014.07同級目錄
cd build-gcc,編譯腳本setup.sh如下
#/bin/sh
../gcc-linaro-4.9-2014.07/configure --prefix=/usr/local/arm-linux \
--build=$MACHTYPE --target=arm-linux-gnueabihf --with-gmp=/usr/local/gmp-5.0.2 \
--with-mpfr=/usr/local/mpfr-3.1.0 --with-mpc=/usr/local/mpc-0.9 --with-isl=/usr/local/isl-0.11.1 \
--with-cloog=/usr/local/cloog-0.18.0 --disable-multilib \
--enable-languages=c,c++ --with-float=hard  

注意,這裏其實是c,c++都是可以選的,有些文章說不能選c++,而且列了一大堆配置項,經實踐,這樣簡單配置,c++也可以選擇。
chmod 777 setup.sh
./setup.sh
$ make -j4 all-gcc
$ make install-gcc
注意以上操作,只編譯安裝gcc部分,否則不通過。

所以編譯eglibc之前,一定要先執行第一步編譯gcc,使用的是本機的gcc工具編譯.

編譯完成後,這個目錄下多了這幾個目錄
include  lib  libexec
>> include:空目錄
>> lib:目錄結構如下:
lib/gcc
lib/gcc/arm-linux-gnueabihf
lib/gcc/arm-linux-gnueabihf/4.9.1
lib/gcc/arm-linux-gnueabihf/4.9.1/crtbegin.o
lib/gcc/arm-linux-gnueabihf/4.9.1/crtbeginS.o
lib/gcc/arm-linux-gnueabihf/4.9.1/crtbeginT.o  
lib/gcc/arm-linux-gnueabihf/4.9.1/crtend.o
lib/gcc/arm-linux-gnueabihf/4.9.1/crtendS.o
lib/gcc/arm-linux-gnueabihf/4.9.1/include
lib/gcc/arm-linux-gnueabihf/4.9.1/include-fixed
lib/gcc/arm-linux-gnueabihf/4.9.1/install-tools
lib/gcc/arm-linux-gnueabihf/4.9.1/libgcc.a
lib/gcc/arm-linux-gnueabihf/4.9.1/libgcov.a
lib/gcc/arm-linux-gnueabihf/4.9.1/plugin
>>libexec
/usr/local/arm-linux/libexec
/usr/local/arm-linux/libexec/gcc
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/cc1
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/collect2
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/install-tools  
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/liblto_plugin.la  
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/liblto_plugin.so  
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/liblto_plugin.so.0  
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/liblto_plugin.so.0.0.0  
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/lto1  
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/lto-wrapper  
/usr/local/arm-linux/libexec/gcc/arm-linux-gnueabihf/4.9.1/plugin

>>同時
/usr/local/arm-linux/bin目示下多出來幾個東西
/usr/local/arm-linux/bin/
共有如下文件
arm-linux-gnueabihf-addr2line  arm-linux-gnueabihf-cpp      arm-linux-gnueabihf-gcc-4.9.1   arm-linux-gnueabihf-gcov    arm-linux-gnueabihf-ld.gold  arm-linux-gnueabihf-ranlib   arm-linux-gnueabihf-strip
arm-linux-gnueabihf-ar         arm-linux-gnueabihf-dwp      arm-linux-gnueabihf-gcc-ar      arm-linux-gnueabihf-gprof   arm-linux-gnueabihf-nm       arm-linux-gnueabihf-readelf
arm-linux-gnueabihf-as         arm-linux-gnueabihf-elfedit  arm-linux-gnueabihf-gcc-nm      arm-linux-gnueabihf-ld      arm-linux-gnueabihf-objcopy  arm-linux-gnueabihf-size
arm-linux-gnueabihf-c++filt    arm-linux-gnueabihf-gcc      arm-linux-gnueabihf-gcc-ranlib  arm-linux-gnueabihf-ld.bfd  arm-linux-gnueabihf-objdump  arm-linux-gnueabihf-strings
和只編譯binutils相比,25個文件,多出7個文件,分別是
arm-linux-gnueabihf-gcc-4.9.1
arm-linux-gnueabihf-cpp
arm-linux-gnueabihf-gcc-ar
arm-linux-gnueabihf-gcc-nm
arm-linux-gnueabihf-gcc-ranlib
arm-linux-gnueabihf-gcov
arm-linux-gnueabihf-gcc

$ make -j4 all-gcc
$ make install-gcc

5. 編譯內核頭,編譯eglibc需要用到內核頭,進入內核源代碼目錄,執行以下命令
cd linux-3.1.1
make ARCH=arm headers_check
make ARCH=arm INSTALL_HDR_PATH=/usr/local/arm-linux/arm-linux-gnueabihf headers_install

6. 第一次編譯eglibc庫,編譯安裝c庫標準頭文件和啓動文件
同樣,這一步新建一個目錄編譯安裝,注意配置項build與host.
mkdir build-eglibc
假設build-eglibc與eglibc源碼同級目錄
cd build-eglibc,編譯安裝腳本setup.sh如下
#/bin/sh
../eglibc-linaro-2.19-2014.07/configure \
--prefix=/usr/local/arm-linux/arm-linux-gnueabihf \
--build=$(MACHTYPE) \
--host=arm-linux-gnueabihf \
--target=arm-linux-gnueabihf \
--with-headers=/usr/local/arm-linux/arm-linux-gnueabihf/include \
libc_cv_forced_unwind=yes
注意,這裏要指定內核頭文件,即5步編譯安裝的內核頭文件。
./setup.sh
執行安裝腳本後,執行命令:
make install-bootstrap-headers=yes install-headers
make -j4 csu/subdir_lib
install csu/crt1.o csu/crti.o csu/crtn.o /usr/local/arm-linux/arm-linux-gnueabihf/lib
arm-linux-gnueabihf-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o /usr/local/arm-linux/arm-linux-gnueabihf/lib/libc.so
touch /usr/local/arm-linux/arm-linux-gnueabihf/include/gnu/stubs.h

這裏,創建了兩個虛擬文件libc.so 和 stubs.h,也是第7步編譯的需要,否則出找不到libc.so之類的錯誤,實則在第7步他們會被替換掉。

7. 第二次編譯gcc生成編譯eglibc所需要的編譯器支持庫,這一步使用的編譯工具是使用第4步編譯出來的,這一步會生成第8步編譯所需要的庫. 
cd build-gcc
make -j4 all-target-libgcc
make install-target-libgcc

8. 第二次編譯eglibc庫,生成c語言標準庫
cd build-eglibc
make -j4
make install

9. 第三次編譯gcc,生成c++語言標準
cd build-gcc
make -j4
make install

這一次,有可能會出現如下錯誤:
fatal error: sys/sdt.h: No such file or directory
在我的代碼裏面,出錯位置如下:
gcc-linaro-4.9-2014.07/libstdc++-v3/libsupc++/unwind-cxx.h:41:21: fatal error: sys/sdt.h: No such file or directory
找了許久沒有找到優雅的解決辦法,最後我的解決辦法爲:
在主機查sdt.h這個文件,發現在位置:/usr/include/sys/sdt.h
打開unwind-cxx.h這個文件,其內容有如下一句:
#include <sys/sdt.h>
爲了編譯,將其改爲絕對路徑
#include</usr/include/sys/sdt.h>

再將編譯,這一次編譯成功並安裝。

經過以上9步的操作,生成的交叉編譯器,編譯生成的程序在s5pv210的開發板上測試過通過。

10. 編譯可能會遇到的錯誤,大多與編譯參數設置不當造成的,錯誤可能千奇百性,很是讓人崩潰。下面是一些遇到的錯誤及原因:
>> 編譯eglibc庫時,一定要另建一個文件夾來編譯安裝,也要先編譯內核頭,不然出現如下類似錯誤:
configure: WARNING: using cross tools not prefixed with host triplet
../sysdeps/unix/sysv/linux/recv.S:5:20: fatal error: socket.S: No such file or directory
 #include <socket.S>
>> 編譯順序不當造成的錯誤:
checking whether -lc should be explicitly linked in... no
checking dynamic linker characteristics... configure: error: Link tests are not allowed after GCC_NO_EXECUTABLES.
make[1]: *** [configure-zlib] Error 1
>> 修改配置腳本後引起的錯誤,清空構建目錄重新執行配置腳本
configure: error: `target_alias' has changed since the previous run:
configure: former value: i686-pc-linux-gnu
configure: current value: i386-rtems
configure: error: changes in the environment can compromise the build
configure: error: run `make distclean' and/or `rm ./config.cache' and start over
>> 配置主機和構建項不當造成的錯誤:
configure: error: cannot compute suffix of object files: cannot compile
注意build,host,target項的設置。


  

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