[轉] 如何編譯ARM Cross Compiler ToolChain

在Embedded系統中, 通常我們會需要做cross development, 而這時則需要cross compiler, 而有時等待網路上其他編譯好的cross compiler會太慢, 或者他們編譯時所選的選項不是你想要的, 這時則必需自行編譯, 我個人的經驗則是完全自行編譯使用, 而不用其他人所編譯好的toolchain, 所以我將我個人的經驗提供給大家做參考。在編譯之前你必需準備好以下的環境及source code:
下載原始碼
1. 安裝好一個PC Linux, 你可以用virtual machine來建立, 個人不太建議使用cygwin這類的環境來做開發環境。
2. 必需在PC Linux上按裝軟體如下:
·        
x86版本的gcc compiler (必須包含g++)
·        
公共程式texi2html
·        
公共程式gawk
·        
函式庫zlib
3. 下載kernel source code (這裏我使用2.6.35當範例) 。
4. 下載gcc source code (這裏我使用4.5.0當範例) 。
5. 下載glibc source code (這裏我使用2.11.2當範例) 。
6. 下載binutil source code (這裏我使用2.20.0當範例) 。
7. 下載glibc ARM patched file
(glibc-ports-2.11.tar.bz2)。
8. 下載gmp source code (這裏我使用5.0.1當範例) 。
9. 下載mpfr source code (這裏我使用3.0.0當範例) 。
10. 下載mpc source code (這裏我使用0.8.2當範例, 在GCC 4.5.0之後必需使用mpc)。
編譯流程
以下則是整個編譯過程的主要步驟, 你必須依照以下的順序, 否則你將無法順利編譯成功:
1. 將下載下來的source code全部解壓縮至各別的目錄。
2. 先編譯binutils, 並將其按裝在你的PC Linux上 (這裏假設按裝的目錄為/usr/local/arm-linux-gnueabi), 這個原始碼是ld, as, ranlib等的程式碼。
3. 編譯gmp並將其按裝至以上binutil按裝目錄之下的tools目錄。
4. 宣告一個系統變數 export
LD_LIBRARY_PATH=/usr/local/arm-linux-gnueabi/tools/lib。
5. 編譯mpfr並將其按裝至以上binutil按裝目錄之下的tools目錄。
6. 編譯mpc並將其按裝至以上binutil按裝目錄之下的tools目錄。
7. 增加系統search變數 export
PATH=$PATH:/usr/local/arm-linux-gnueabi/bin。
8. 編譯gcc為static以及只有 c 語言的支援, 並將其按裝至PC Linux。
9. 編譯glibc為shared library並將其按裝至PC Linux, 若是要編譯多種版本library (little endian, big endian
version), 則必須要在這個步驟重覆執行, 使用不同的參數來產生不同版本的library。
10. 再編譯一次gcc, 但是將其編譯為shared library, 並有c++的支援, 至此就大功告成。
編譯gmp步驟如下:
1. 建立一個子目錄為 /usr/local/arm-linux-gnueabi/tools
2. 進入gmp的source code directory
3. 建立一個目錄為build-arm, 並進入該目錄
4. 執行命令如下:
 CPPFLAGS=-fexceptions ../configure
–prefix=/usr/local/arm-linux-gnueabi/tools –enable-cxx –with-gnu-ld
5. 執行make & make install
編譯mpfr步驟如下:
1. 進入mpfr的source code directory
2. 建立一個目錄為build-arm, 並進入該目錄
3. 執行命令如下:
 ../configure
–prefix=/usr/local/arm-linux-gnueabi/tools
–with-gmp=/usr/local/arm-linux-gnueabi/tools –with-gnu-ld
4. 執行make & make install
編譯mpc步驟如下:
1. 進入mpc的source code directory
2. 建立一個目錄為build-arm, 並進入該目錄
3. 執行命令如下:
 ../configure
–prefix=/usr/local/arm-linux-gnueabi/tools –with-gnu-ld
–with-gmp=/usr/local/arm-linux-gnueabi/tools
–with-mpfr=/usr/local/arm-linux-gnueabi/tools
4. 執行make & make install
編譯binutil的步驟如下:
1. 進入binutils的source code directory
2. 建立一個月錄build-arm, 並且進入該目錄
3. 執行命令如下:
 ../configure
–prefix=/usr/local/arm-linux-gnueabi –host=i686-pc-linux
–build=i686-pc-linux –target=arm-linux-gnueabi –enable-shared
–disable-multilib –with-gmp=/usr/local/arm-linux-gnueabi/tools
–with-mpfr=/usr/local/arm-linux-gnueabi/tools
–with-mpc=/usr/local/arm-linux-gnueabi/tools
3-1. 假如你要支援多種版本的library (little-endian & big-endian), 則所下的參數會是如下 :
../configure –prefix=/usr/local/arm-linux-gnueabi –build=i686-pc-linux
–host=i686-pc-linux –target=arm-linux-gnueabi –enable-shared
–enable-multilib
–with-lib-path=/usr/local/arm-linux-gnueabi/lib:/usr/local/arm-linux-gnueabi/lib/be:/usr/local/arm-linux-gnueabi/lib/soft-float:/usr/local/arm-linux-gnueabi/lib/be/soft-float
–with-gmp=/usr/local/arm-linux-gnueabi/tools
–with-mpfr=/usr/local/arm-linux-gnueabi/tools
–with-mpc=/usr/local/arm-linux-gnueabi/tools
主要是多一個–with-lib-path的選項。
4. 之後執行make & make install
設定環境變數
這時需要先編譯一版使用static library的gcc版本, 再使用這版compiler去編譯glibc為shared library, 之後再回頭再編譯一次gcc為使用shared library, 在編譯之前需設定幾個環境變數如下 :
1. export LD_LIBRARY_PATH=/usr/local/arm-linux-gnueabi/tools/lib
2. export PATH=$PATH:/usr/local/arm-linux-gnueabi/bin
3. 若要支援多版本的編繹器則需要修改設定檔gcc/config/arm/t-linux-eabi,增加內容如下:
MULTILIB_OPTIONS = mlittle-endian/mbig-endian
MULTILIB_DIRNAMES = le be
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
以下是編譯的流程 :
1. 進入GCC source code目錄並建立一個子目錄build-arm-static
2. 進入build-arm-static目錄, 執行以下指令
 ../configure –host=i686-pc-linux
–build=i686-pc-linux –target=arm-linux-gnueabi
–prefix=/usr/local/arm-linux-gnueabi
–with-gmp=/usr/local/arm-linux-gnueabi/tools
–with-mpfr=/usr/local/arm-linux-gnueabi/tools –with-gnu-ld –without-newlib
–enable-long-long –disable-libada –without-cvs –disable-libgomp
–disable-libmudflap –disable-libssp –disable-threads –enable-__cxa_atexit
–disable-shared –enable-languages=c –with-system-zlib
–with-mpc=/usr/local/arm-linux-gnueabi/tools –disable-multilib
2-1.若是要支援多版library則設定如下:
./configure –host=i686-pc-linux –build=i686-pc-linux
–target=arm-linux-gnueabi –prefix=/usr/local/arm-linux-gnueabi
–with-gmp=/usr/local/arm-linux-gnueabi/tools –with-mpfr=/usr/local/arm-linux-gnueabi/tools
–with-gnu-ld –without-newlib –enable-long-long –disable-libada
–without-cvs –disable-libgomp –disable-libmudflap –disable-libssp
–disable-threads –enable-__cxa_atexit –disable-shared –enable-languages=c
–with-system-zlib –with-mpc=/usr/local/arm-linux-gnueabi/tools
–enable-multilib
3. 執行make & make install
編譯glibc
接下來是要編譯glibc是較麻煩的一件事, 在編譯glibc之前, 你必須使用kernel來產生一些header files因為在編譯glibc時需要用到, 以下是產生kernel header file的步驟:
1. 進入kernel source code目錄, 修改Makefile中的ARCH及CROSS_COMPILE變數如下 :
ARCH := arm
CROSS_COMPILE := arm-linux-gnueabi
INSTALL_MOD_PATH := `pwd`/installed_modules
1-1. 你若要產生多種版本的library (little endian & big endian), 那你必須更改兩個檔案 (glibc-source-code/Makeconfig &
glibc-source-code/config.make.in), 以便在編譯完要按裝時可以得到適當的按裝, 其修改內容如下:
·        
glibc-source-code/Makefconfig 第193行加入以下內容:
slibdir = $(libdir)
·        
glibc-source-code/config.make.in mark掉第13行 #slibdir = @[email protected], 加入一行如下:
slibdir = @[email protected]
1-2. 在新版的glibc中gcc_eh並未準備好,所以無法使用,必須修Makeconfig檔以防止在編譯glibc時會連結gcc_eh, 你必須將該檔中的-lgcc_eh移除即。
2. 執行make menuconfig並選擇一種ARM平台, 之後將設定存下
3. 執行make headers_install以取得編譯glibc時要使用的kernel header files, 這時這些的include files將會被產生在kernel source code的目錄之下的usr/include目錄
4. 進入glibc的source code根目錄, 並建立一個目錄為build-arm-le, 並將glibc-ports-2.11.tar.bz2解壓縮的內容拷貝至glibc的目錄並設為ports的目錄
5. 進入build-arm-le的目錄, 並執行以下指令 :
CC=arm-linux-gnueabi-gcc CXX=arm-linux-gnueabi-g++
CPP=”arm-linux-gnueabi-gcc -E” LD=arm-linux-gnueabi-ld
STRIP=arm-linx-gnueabi-strip AR=arm-linux-gnueabi-ar NM=arm-linux-gnueabi-nm
AS=arm-linux-gnueabi-as RANLIB=arm-linux-gnueabi-ranlib ARCH=arm ../configure
–prefix=/usr/local/arm-linux-gnueabi –target=arm-linux-gnueabi
–host=arm-linux-gnueabi –build=i686-pc-linux –disable-profile
–enable-add-ons –with-__thread –enable-threads=posix –enable-multilib
–without-cvs –enable-shared –without-gd
–with-headers=/home/work/kernel/linux-2.6.35/usr/include
–libdir=/usr/local/arm-linux-gnueabi/lib libc_cv_forced_unwind=yes
libc_cv_c_cleanup=yes
5-1.進入build-arm-be的目錄, 並執行以下指令:
CC=”arm-linux-gnueabi-gcc -mbig-endian”
CXX=”arm-linux-gnueabi-g++ -mbig-endian”
CPP=”arm-linux-gnueabi-gcc -E -mbig-endian”
LD=”arm-linux-gnueabi-ld -EB” STRIP=arm-linx-gnueabi-strip
AR=arm-linux-gnueabi-ar NM=arm-linux-gnueabi-nm AS=”arm-linux-gnueabi-as
-EB” RANLIB=arm-linux-gnueabi-ranlib ARCH=arm ../configure
–prefix=/usr/local/arm-linux-gnueabi –target=arm-linux-gnueabi
–host=arm-linux-gnueabi –build=i686-pc-linux –disable-profile –enable-add-ons
–with-__thread –enable-threads=posix –enable-multilib –without-cvs
–enable-shared –without-gd
–with-headers=/home/work/kernel/linux-2.6.35/usr/include
–libdir=/usr/local/arm-linux-gnueabi/lib/be libc_cv_forced_unwind=yes
libc_cv_c_cleanup=yes
6. 執行make & make install, 至此即可完成glibc的建立, 你將可以在/usr/local/arm-linux-gnueabi目錄下, 可以發現include & lib的目錄內容已包含glibc的內容
7.  將kernel/usr/include目錄之下的所有檔案拷貝至/usr/local/arm-linux-gnueabi/include目錄之下
編譯gcc for shared library
最後的動作則是要再重新編譯一次gcc使它支援shared library, 在重新編譯之前, 有幾個動作必須要完成, 以下是這些動作的內容:
1. 進入/usr/local/arm-linux-gnueabi/arm-linux-gnueabi的目錄, 特別注意是有兩層的arm-linux-gnueabi, 不可弄錯
2. 執行指令如下:
> mv lib lib.bak
> ln -s ../lib lib
> ln -s ../include include
> cp -a lib.bak/* ../lib
這時可以正式開始來重新編譯gcc, 其步驟如下:
1. 進入gcc source code目錄, 並建立一個目錄為build-arm-shared, 之後進入build-arm-shared目錄
2. 執行以下指令 :
../configure –host=i686-pc-linux –build=i686-pc-linux
–target=arm-linux-gnueabi –prefix=/usr/local/arm-linux-gnueabi
–with-arch=armv6 –with-gmp=/usr/local/arm-linux-gnueabi/tools
–with-mpfr=/usr/local/arm-linux-gnueabi/tools –with-gnu-ld –without-newlib
–enable-long-long –disable-libada –without-cvs –disable-libgomp
–disable-libmudflap –disable-libssp –enable-threads –enable-__cxa_atexit
–enable-shared –enable-languages=c,c++ –with-system-zlib
–with-mpc=/usr/local/arm-linux-gnueabi/tools –disable-multilib
2-1.若要支援多版library執行指令如下:
../configure –host=i686-pc-linux –build=i686-pc-linux
–target=arm-linux-gnueabi –prefix=/usr/local/arm-linux-gnueabi –with-arch=armv6
–with-gmp=/usr/local/arm-linux-gnueabi/tools
–with-mpfr=/usr/local/arm-linux-gnueabi/tools –with-gnu-ld –without-newlib
–enable-long-long –disable-libada –without-cvs –disable-libgomp
–disable-libmudflap –disable-libssp –enable-threads –enable-__cxa_atexit
–enable-shared –enable-languages=c,c++ –with-system-zlib
–with-mpc=/usr/local/arm-linux-gnueabi/tools –enable-multilib
3. 執行make ; make install
至此就大功告成, 你可以寫一個簡單的hello程式來試試, 記得這是default share library的cross compiler, 所以你執行ap時也要記得將shared library也拷貝至embedded computer
最後有一個公共程式很好用,那就是 ldd 它可將應用程式及 library 所用到的 library 例出來,default 的 ldd 有點問題無法執行,這邊可以自行寫一個 shell script 檔名就是 arm-linux-gnueabi-ldd 其內容如下:
#!/bin/sh
arm-linux-gnueabi-objdump -x [email protected] | grep NEEDED
並將這執行放至 /usr/local/arm-linux-gnueabi/bin 目錄之下即可。
未經允許不得轉載:GoMCU » [轉] 如何編譯ARM Cross Compiler ToolChain