1、 ToolChain 簡介
ToolChain包含許多部件:主要之一是GCC,它可以是本機編譯工具或交叉編譯工具,GCC由Binuitls工具支持,Binutils是二進制代碼維護工具,這些部件是編譯程序的必要工具,同時他們也需要C庫(glibc)支持。認真考慮一下:定制一套編譯工具並不是想像中的易事!如果你還想繼續看下去,必須具備如下技能:
熟悉Linux環境
熟悉Linux的必要命令和工具的使用
知道如何配置、編譯核心和應用程序
以下章節將介紹怎樣定制ARM交叉編譯工具集,但對於大多數ARM開發者來說,沒有必要親自做這件事,完全可以用現成的工具集。除非現成的工具集不滿足你的使用要求,或者你想提高開發應用的能力。總之,我們強烈建議你使用現成穩定的工具集來做應用開發!
2、 定制ToolChain
首先來看看工作的大至步驟:
決定目標的名稱
決定目標的存放位置
編譯、安裝Binutils
編譯、安裝GCC
編譯、安裝GLIBC
讓交叉編譯工具支持更多編譯語言
測試定制的交叉編譯工具
2.1、決定目標的名稱
本機編譯工具集編譯的代碼只適用本機(大多數PC是X86)運行,對於ARM開發者來說,需要一個能在本機編譯、但編譯卻生成ARM運行代碼的一套交叉編譯工具集。
因此,選擇一個與本機工具集相異的特定含義的目標名稱是非常有必要的。
arm-linux:是個比較受歡迎的名稱,支持ELF格式(ARMLinux標准)。除Acorn用戶使用老的a.out格式外。
arm-linuxaout:選擇a.out格式,ARMLinux基本不支持它了。
arm-aout、arm-coff、arm-elf、arm-thumb:其它的格式名。
你也可以在其中插入版本信息,比如:
armv2:ARMV2核,支持26bit模式。
armv3l、armv3b:ARMV3核,小字節(l)或大字節(b)模式。
armv4l、armv4b:ARMV4核,如:StrongARM、ARM7TDMI、ARM8、ARM9。同樣也支持小字節(l)或大字節(b)模式。
armv5l、armv5b:ARMV5核,如:XScale核ARM10。同樣也支持小字節(l)或大字節(b)模式。
選擇什麼名稱對定制ARM交叉編譯工具集沒太大的影響,但用大家常用的名稱會比較好些。
2.2、決定目標的存放位置
既然是定制ARM交叉編譯工具集,那麼就不能覆蓋本機的編譯工具集(否則,本機將不能再編譯本機運行代碼!),同時還要考慮本機Linux環境的多用戶、多任務特征。因此,選擇一個與本機編譯工具集不同的多用戶共享位置是必要的。
ARM交叉編譯工具集的存放位置:在本文中,我們讓它等於/usr/local/arm
(本機編譯工具集的存放位置通常在/usr或/usr/local)
ARM交叉編譯工具集的名稱:在本文中,我們讓它等於 arm-pc-linux,表示在本
地pc上編譯,生成的是ARM指令代碼(詳細規則見glibc的README文件)。
(本機編譯工具集名稱通常是: i686-pc-linux-gnu,表示在本地pc上編譯,
生成的是i686指令代碼)
ARM核心文件位置:本文中我們讓它等於 ~/armlinux 。不過,~/armlinux在這裡僅
是個聯接而已,它指向真正ARM核心源代碼位置(見2.4.1描述)。
(本機核心存放位置通常在/usr/src/linux)
2.3、編譯、安裝Binutils
它是GNU(ftp://ftp.gnu.org)工具之一,主要是二進制代碼的處理維護工具。
2.3.1、Binutils工具部件簡介
add2line:將地址轉換成文件名或行號對,以便調試程序。
ar:從體系文件中創建、修改、擴展程序代碼。
as:生成匯編程序代碼。
c++filt:建立低級語言和用戶級語言的名稱符號聯接,並保持它們的相互關系。
gasp:匯編宏處理器。
ld:目標代碼聯接,聯接各目標代碼塊,它是生成可執行代碼的最終步驟。
nm:從目標代碼文件中枚舉所有調試符號名。
objcopy:使用GNU BSD庫,把目標代碼從一文件格試拷貝成另一種格試。
objdump:顯示目標文件信息。
readelf:顯示elf文件信息。
ranlib:生成索引以加快對歸檔文件的訪問。
size:列出目標模塊或文件的代碼尺寸。
strings:打印可打印的目標代碼字符(至少4個字符),打印字符多少可以控制。對於其它格試的文件,打印字符串。
strip:放棄所有符號聯接。
2.3.2、Binutils的配置和編譯安裝
tar -jxvf binutils-2.16.1.tar.bz2 -C ~
cd ~/binutils-2.16.1
make clean
make distclean
./configure --target=arm-pc-linux --prefix=/usr/local/arm
make
make install
如果安裝成功(通常都不會有問題),進入下一步:GCC
2.4、編譯、安裝GCC
它是GNU(ftp://ftp.gnu.org)工具之一,是主要的編譯處理工具。
2.4.1 ARM核心頭文件
對於本機的編譯工具集,通常核心頭文件已經安裝在/usr/src/linux/include,或被gcc拷貝到搜尋路徑內。但對於ARM交叉編譯工具集,可能還沒有(除非在此前已經安裝過),由其是第一次定制。所以,我們需要提取ARM核心頭文件。這裡我們使用面向AT91RM9200的核心文件linux-2.4.27-vrs1.tar.bz2
(如果是通用核心,那麼你需要面向ARM的補丁文件)
tar -jxvf linux-2.4.27-vrs1.tar.bz2 -C ~
cd ~
ln -s linux-2.4.27-vrs1-ATMEL armlinux
好了,我們建立了:~/armlinux 聯接
cd ~/armlinux
vim Makefile
檢查ARCH := 的行,如果不是arm,請把它改成ARCH := arm,保存退出。
(檢查CROSS_COMPILE := /usr/local/arm/bin/arm-pc-linux-,如果不同,修改它)
make clean
make distclean
make menuconfig
配置核心(選擇ARM為AT91RM9200和其它相關配置),保存退出。
make dep
(如遇錯誤終止,看第3部份是否有解答!)
肯定有錯誤發生而終止!當然,我們並不是想現在編譯這個核心,只是理順核心文件間的關系,以便下面拷貝操作順利進行......
mkdir /usr/local/arm/arm-pc-linux/sys-include
cp -dR ~/armlinux/include/asm-arm
/usr/local/arm/arm-pc-linux/sys-include/asm
cp -dR ~/armlinux/include/linux
/usr/local/arm/arm-pc-linux/sys-include/linux
好了,我們現在有ARM交叉編譯的公用核心頭文件了。
2.4.2、gcc配置、編譯和安裝
閱讀gcc源代碼INSTALL目錄下的文件,獲得更多的配置和編譯安裝幫助。
為了使用前面編譯好的Binutils工具,添加路徑。
export PATH=$PATH:/usr/local/arm/bin
(如果/usr/local/arm/bin已經包含在PATH,此步驟省略)
tar -jxvf gcc-3.4.5.tar.bz2 -C ~
cd ~/gcc-3.4.5
2.4.3、第一次安裝ARM交叉編譯工具gcc
(閱讀gcc源代碼INSTALL目錄下的文件,獲得更多的配置、編譯和安裝幫助)
通常都會遇到問題而使整個過程不能完成,因為以下要素必須考慮:
既然是第一次安裝ARM交叉編譯工具,那麼本機的glibc支持的應該是本機的編譯工具庫,而不是ARM交叉編譯工具庫。並且支持ARM交叉編譯工具的其它支持語言(比如:C++、java)的libc庫(最終的gcc生成的二進制代碼聯接需要該庫支持)我們也沒有,所以,要增加編譯開關:
--enable-languages=c --disable-threads --disable-shared
同理,由於第一次安裝ARM交叉編譯工具,那麼支持的libc庫的頭文件也沒有!所以我們征用Dinhibit_libc來hack(這個詞只可意會,不可言傳)這個問題。操作如下:
cp ~/gcc-3.4.5/gcc/config/arm/t-linux ~/gcc-3.4.5/gcc/config/arm/t-linux.orig
vim ~/gcc-3.4.5/gcc/config/arm/t-linux
給TARGET_LIBGCC2_CFLAGS = 增加操作參數
-Dinhibit_libc -D__gthr_posix_h
保存退出。
讓我們來重新配置、編譯它......
export PATH=$PATH:/usr/local/arm/bin
(如果/usr/local/arm/bin已經包含在PATH,此步驟省略)
cd ~/gcc-3.4.5
make clean
make distclean
./configure --target=arm-pc-linux --prefix=/usr/local/arm --disable-threads --disable-shared --enable-languages=c
(由於上面我們把交叉編譯頭文件拷貝到了gcc的默認sys-include目錄,因此不需要定義--with-headers參數。實際測試中,定義--with-headers反而不能make通過,不知道是否bug)
make
(痛苦的除bug過程!)
(如遇錯誤終止,看第3部份是否有解答,並且強烈建議你從make clean開始!)
make install
如果安裝成功,我們就有了能編譯C語言的ARM交叉編譯工具gcc了。如果你只是用ARM交叉編譯工具編譯ARM核心,OK!你可以就此打住。如果想編譯用戶級代碼,繼續進入下階段......
2.5、編譯、安裝GLIBC
glibc是個C庫,幾乎所有的應用程序都需要共享它提供的功能(除了kernel、bootload、和其它完全不用C庫的功能代碼),因此glibc的存在有利益小系統或嵌入系統縮減系統總代碼尺寸與存放空間(盡管單個的glibc庫是比較大的)。所以,最後的工作就是:構造ARM交叉編譯系統的glibc庫。
2.5.1、解壓源代碼
首先解壓glibc代碼,再解壓linuxthreads代碼到glibc代碼的源碼目錄下......
tar -jxvf glibc-2.3.6.tar.bz2 -C ~
tar -jxvf glibc-linuxthreads-2.3.6.tar.bz2 -C ~/glibc-2.3.6
2.5.2、glibc配置、編譯、安裝
閱讀glibc源代碼下的文件:README、FAQ和INSTALL,獲得更多的配置、編譯和安裝幫助。
export PATH=$PATH:/usr/local/arm/bin
(如果/usr/local/arm/bin已經包含在PATH,此步驟省略)
export CC=arm-pc-linux-gcc
(定義用剛生成的ARM交叉編譯工具編譯。否則,生成的glibc庫是本地機代碼庫,而不是ARM指令集代碼庫!!!)
警告:不能在源代碼目錄下操作(為什麽?問GNU吧,我也不知道!)......
mkdir ~/temp
cd ~/temp
make clean
make distclean
~/glibc-2.3.6/configure --host=arm-pc-linux
--build=i686-pc-linux-gnu
--with-headers=/usr/local/arm/arm-pc-linux/sys-include
--enable-add-ons=linuxthreads
--enable-shared
--prefix=/usr/local/arm/arm-pc-linux
(你可能注意到glibc的--prefix值與gcc的配置不一樣!是的,你必須這樣定義,否則,後面gcc的make過程將因找不到glibc的公用頭文件或庫而錯誤終止!)
make
(痛苦的除bug過程!)
(如遇錯誤終止,看第3部份是否有解答,並且強烈建議你從make clean開始!)
make install
如果安裝成功,我們就有了能編譯C語言的ARM交叉編譯工具gcc了。如果你只是用ARM交叉編譯工具編譯arm核心,OK!你可以就此打住。如果想編譯用戶級代碼,繼續進入下階段......
2.5、編譯、安裝GLIBC
glibc是個C庫,幾乎所有的應用程序都需要共享它提供的功能(除了kernel、bootload、和其它完全不用C庫的功能代碼),因此glibc的存在有利益小系統或嵌入系統縮減系統總代碼尺寸與存放空間(盡管單個的glibc庫是比較大的)。所以,最後的工作就是:構造arm交叉編譯系統的glibc庫。
2.5.1、解壓源代碼
首先解壓glibc代碼,再解壓linuxthreads代碼到glibc代碼的源碼目錄下......
tar -jxvf glibc-2.3.6.tar.bz2 -C ~
tar -jxvf glibc-linuxthreads-2.3.6.tar.bz2 -C ~/glibc-2.3.6
2.5.2、glibc配置、編譯、安裝
閱讀glibc源代碼下的文件:README、FAQ和INSTALL,獲得更多的配置、編譯和安裝幫助。
export PATH=$PATH:/usr/local/arm/bin
(如果/usr/local/arm/bin已經包含在PATH,此步驟省略)
export CC=arm-pc-linux-gcc
(定義用剛生成的ARM交叉編譯工具編譯。否則,生成的glibc庫是本地機代碼庫,而不是arm指令集代碼庫!!!)
警告:不能在源代碼目錄下操作......
mkdir ~/temp
cd ~/temp
make clean
make distclean
~/glibc-2.3.6/configure --host=arm-pc-linux
--build=i686-pc-linux-gnu
--with-headers=/usr/local/arm/arm-pc-linux/sys-include
--enable-add-ons=linuxthreads
--enable-shared
--prefix=/usr/local/arm/arm-pc-linux
(你可能注意到glibc的--prefix值與gcc的配置不一樣!是的,你必須這樣定義,否則,後面gcc的make過程將因找不到glibc的公用頭文件或庫而錯誤終止!)
make
(如遇錯誤終止,看第3部份是否有解答,並且強烈建議你從make clean開始!)
make install