1. 程式人生 > >ubuntu上製作 (arm+linux) toolchain的詳細過程(一)

ubuntu上製作 (arm+linux) toolchain的詳細過程(一)

前幾天自己親手嘗試了製作嵌入式linux開發的toolchain的過程,當然也參考了網上的一些資料,因為我自己也屬於新手行列,只是剛好公司有開發板等環境,於是就嘗試了這個所謂的嵌入式系統開發的第一步。

在進行嵌入式開發之前,首先要建立一個交叉編譯環境,這是一套編譯器、聯結器和libc庫等組成的開發環境。由於一般嵌入式開發系統儲存大小有限,通常你都要在你的強大的pc機上建立一個用於目標機的交叉編譯環境。這是一個由編譯器、聯結器和直譯器組成的綜合開發環境。交叉編譯工具主要由 binutilsgcc glibc 幾個部分組成。有時出於減小 libc 庫大小的考慮,你也可以用別的 c 庫來代替 glibc

,例如 uClibcdietlibc newlib下面我們將以建立針對arm的交叉編譯開發環境為例來解說整個過程,其他的體系結構與這個相類似,只要作一些對應的改動。我的開發環境是,宿主機 Ubuntu 7.04,目標機 arm

在開始之前想先宣告一下,之所以會選擇用ubuntu,有兩點原因,一是我自己剛好有一個ubuntu的虛擬機器是作為自己工作以外學習之用的;二是我知道初始情況下的ubuntu預裝的應用軟體比較少,這樣出錯的機會也比較大,於是呢學習到的東西也會比較多了。這點在後面的步驟中體現的比較多。由於前幾天在論壇http://forum.ubuntu.org.cn/上看到有人回帖抱怨說ubuntu不好用,很多東西都沒有預裝的,所以隨便搞個軟體都得折騰半天。其實我覺得這個事情得兩面看,首先確實,對於剛開始使用linux,或者使用了比較長時間但比較停留在表面上的應用,或者使用linux只是為了圖個新鮮而想要求linux向windows看齊的使用者來說,確實不方便;但是ubuntu的這種方式也有很好的一面,象我這次特意選的是什麼其他軟體都沒裝過的一個ubuntu系統來搭建這個交叉編譯環境,首先是為了給新手們一個真正可以全面參考了動手搭建的說明,其次由於系統中缺少了一些必要的軟體,比如flex,bison等,編譯過程中肯定會出現一些在其他系統中不會見到的錯誤,這樣可以讓我們瞭解更多東西。同時個人覺得ubuntu最方便的就是它提供了很方便的安裝源,比方說在沒安裝bison的情況下輸入bison,系統就會提示沒有安裝,並且提示了該如何安裝,於是我們只要直接複製安裝命令就OK了,多方便多人性化啊,呵呵。

另外我還想事先提供一種解決問題的方法,如果碰到奇怪的問題,也google不到,那可能是有什麼必要的軟體沒裝,其實可以檢視Makefile檔案,裡面有很多依賴關係,可以測試以下是否有必要的沒有裝,有的話裝好就OK了。

網上有很多文章都說明了,搭建開發環境的過程大致如下:

1. 下載原始檔、補丁和建立編譯的目錄 2. 建立核心標頭檔案 3. 建立二進位制工具(binutils 4. 建立初始編譯器(bootstrap gcc 5. 建立c(glibc) 6. 建立全套編譯器(full gcc  

1. 選定軟體版本號

選擇軟體版本號時,先看看glibc原始碼中的INSTALL檔案。那裡列舉了該版本的

glibc編譯時所需的binutils gcc的版本號。例如在 glibc-2.2.3/INSTALL 檔案中推薦 gcc 2.95以上,binutils 2.10.1 以上版本。

我選的各個軟體的版本是:

linux-2.4.21+rmk2
binutils-2.10.1
gcc-2.95.3
glibc-2.2.3
glibc-linuxthreads-2.2.3
這是因為這種搭配已經有人嘗試過了,是可以成功構建的,而有的組合則不一定,這時候要求我們自己修改某些軟體(如降低gcc的版本)的版本來試驗。由於我的初衷是要知道和熟悉這個過程,這樣今後要搭建其他版本的toolchain時也就比較簡單了。

2. 建立工作目錄

首先,我們建立幾個用來工作的目錄:(可根據自己喜好任意選擇建立的目錄)

我用的是/workdir/先建立一個專案目錄embedded

$pwd

/workdir

$mkdir embedded

再在這個專案目錄 embedded 下建立三個目錄 build-toolskernel tools

build-tools-用來存放你下載的 binutilsgcc glibc 的原始碼和用來編譯這些原始碼的目錄。

kernel-用來存放你的核心原始碼和核心補丁。

tools-用來存放編譯好的交叉編譯工具和庫檔案。

$cd embedded

$mkdirbuild-tools kernel tools

執行完後目錄結構如下:

$ls embedded

build-tools kernel tools

3. 輸出和環境變數

我們輸出如下的環境變數方便我們編譯。

$export PRJROOT=/workdir/embedded

$export TARGET=arm-linux

$export PREFIX=$PRJROOT/tools

$export TARGET_PREFIX=$PREFIX/$TARGET

$export PATH=$PREFIX/bin:$PATH

如果你不慣用環境變數的,你可以直接用絕對或相對路徑。我如果不用環境變數,一般都用絕對路徑,相對路徑有時會失敗。環境變數也可以定義在.bashrc檔案中,這樣當你logout或換了控制檯時,就不用老是export這些變量了。

體系結構和你的TAEGET變數的對應如下表:  

你可以在通過glibc(also in ~/gcc-2.95.3/)下的config.sub指令碼來知道,你的TARGET變數是否被支援,例如:

$./config.subarm-linux

arm-unknown-linux-gnu

4. 建立編譯目錄

為了把原始碼和編譯時生成的檔案分開,一般的編譯工作不在的原始碼目錄中,要另建一個目錄來專門用於編譯。用以下的命令來建立編譯你下載的binutilsgccglibc的原始碼的目錄。

$cd $PRJROOT/build-tools

$mkdir build-binutils build-boot-gcc build-gcc build-glibc gcc-patch

build-binutils-編譯binutils的目錄
build-boot-gcc-
編譯gcc 啟動部分的目錄
build-glibc-
編譯glibc的目錄
build-gcc-
編譯gcc 全部的目錄
gcc-patch-
gcc的補丁的目錄

gcc-2.95.3 的補丁有 gcc-2.95.3-2.patchgcc-2.95.3-no-fixinc.patch gcc-2.95.3-returntype-fix.patch,可以從下載到這些補丁,當然也可以直接google。

再將你下載的 binutils-2.10.1gcc-2.95.3glibc-2.2.3 glibc-linuxthreads-2.2.3 的原始碼放入 build-tools 目錄中

看一下你的 build-tools 目錄,有以下內容:

$ls

binutils-2.10.1.tar.bz2build-gccgcc-patch

build-binutlsbuild-glibc glibc-2.2.3.tar.gz

build-boot-gccgcc-2.95.3.tar.gzglibc-linuxthreads-2.2.3.tar.gz

 

把你從下載的核心原始碼放入 $PRJROOT /kernel 目錄

進入你的 kernel 目錄:

$cd $PRJROOT /kernel

解開核心原始碼

$tar -xzvf linux-2.4.21.tar.gz

$tar -xjvf linux-2.4.21.tar.bz2

小於 2.4.19 的核心版本解開會生成一個 linux 目錄,沒帶版本號,就將其改名。

$mv linux linux-2.4.x

Linux 核心打上你的補丁

$cd linux-2.4.21

$patch -p1 < ../patch-2.4.21-rmk2

編譯核心生成標頭檔案

$make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig

你也可以用 config xconfig 來代替 menuconfig,但這樣用可能會沒有設定某些配置檔案選項和沒有生成下面編譯所需的標頭檔案。推薦大家用 make menuconfig,這也是核心開發人員用的最多的配置方法。配置完退出並儲存,檢查一下的核心目錄中的 include/linux/version.h include/linux/autoconf.h 檔案是不是生成了,這是編譯 glibc 是要用到的,version.h autoconf.h 檔案的存在,也說明了你生成了正確的標頭檔案。

還要建立幾個正確的連結

$cd include

$ln -s asm-arm asm

$cd asm

$ln -s arch-epxa arch

$ln -s proc-armv proc

接下來Linux 核心標頭檔案拷貝過來用

$mkdir -p $TARGET_PREFIX/include

$cp -r $PRJROOT/kernel/linux-2.4.21/include/linux$TARGET_PREFIX/include

$cp -r $PRJROOT/kernel/linux-2.4.21/include/asm-arm$TARGET_PREFIX/include/asm

$cp –r include/asm-generic/ ${TARGET_PREFIX}/include