1. 程式人生 > >建立ARM交叉編譯環境 (arm-none-linux-gnueabi-gcc with EABI)

建立ARM交叉編譯環境 (arm-none-linux-gnueabi-gcc with EABI)

昨天終於把交叉編譯環境、移植核心和製作root檔案系統在arm開發板上順利跑通了。期間有的步驟很順利,但更多的是被諸多問題困擾,比如最後一個不起眼的小問題導致檔案系統無法載入,鬱悶了我一個星期,最終通過分析慢慢發現了這個bug。還有各原始碼包版本的問題,而且網上很多介紹都是基於舊版本的。我這裡全部用最新或較新的版本,當然,至於新舊版本到底哪個更好更合適,這是個智者見智的論題,不在本文討論之列。我堅信很多人也遇到過或者即將遇到我曾經歷過的錯誤和問題,因此我覺得把我過去兩週做過的相關工作,詳細地寫下來,希望對大家有所幫助!

首先是平臺和環境 ,我過去兩週都是基於vmware 中ubuntu 10.04的,但是我發現ubuntu這個很火的桌面linux發行版本並不適合進行嵌入式開發,典型的麻煩就是系統缺少很多庫、服務等等,需要自己手動安裝,增加了不少額外的工作,和我以前用的SuSe 9比麻煩不少。不過所以現在我乾脆全新裝了一個SUSE 11.2

Enterprise Server 32bit,把過去的工作重複一遍,邊編譯邊紀錄,力求不遺漏細節!

過程預覽:
1,準備工作,包括下載原始碼包、補丁、建立資料夾和設定環境變數等
2,建立核心標頭檔案
3,建立binutils
4,建立bootstrap gcc
5,建立glibc
6,建立完整版本gcc
7,測試hello world

現在就讓我們開始吧!

1 準備工作

我使用的原始碼包和補丁 如下:
linux-2.6.34.tar.bz2
binutils-2.20.tar.gz
gcc-4.3.5.tar.bz2
glibc-2.11.tar.gz
glibc-linuxthreads-2.5.tar.bz2
glibc-ports-2.11.tar.bz2
glibc-2.11.2-gcc_fix-1.patch
至於怎麼得到這些原始碼包,找google吧!

建立工作目錄
自己選一個合適的地方,建立一個總資料夾Embedded,並且在其下建立 build-tools、kernel和tools三個子資料夾、我們以後的操作就都在這裡進行了。

$ mkdir Embedded
$ cd Embedded
$ mkdir build-tools    kernel     tool
$ ls
build-tools    kernel     tool


各資料夾作用如下:

build-tools : 儲存binutils、gcc 和 glibc的原始碼和用來編譯這些原始碼的目錄。
kernel        : 儲存核心原始碼和補丁。
tools          : 儲存編譯好的交叉編譯工具和庫檔案。
然後在build-tools資料夾中建立如下子資料夾:


$ cd
build-tools
$ mkdir build-binutilsbuild-boot-gccbuild-glibcbuild-gcc


build-binutils    :編譯binutils的目錄
build-boot-gcc : 編譯gcc 啟動部分的目錄
build-glibc        :編譯glibc的目錄
build-gcc          :編譯完整gcc的目錄



設定環境變數:

這裡設定環境變數只是為了方便,因為每個工具的config都需要輸入類似的變數,不如放在環境變數裡。

在命令列下開啟vi  ~/.bashrc,在文件最後輸入下面幾行,然後登出當前使用者,重新登入

export PRJROOT=/home/jinglelong/MySoftware/Embedded
export TARGET=arm-none-linux-gnueabi
export PREFIX=$PRJROOT/tools
export TARGET_PREFIX=$PREFIX/$TARGET
export PATH=$PREFIX/bin:$PATH


各變數的具體意義如下:

PRJROOT                     : 整個工程的根目錄,這裡當然是Embeded了
TARGET                       : 目標檔案對應的體系結構,arm-linux代表編譯出來的target只能在arm體系結構中執行
PREFIX                        : 設定目標資料夾的路徑字首
TARGET_PREFIX          : 設定目標資料夾的路徑字首路徑
PATH                           : 新增可執行檔案的路徑,這裡主要是隻中間編譯工具等


2 建立核心include檔案

$ ln -s  /home/jinglelong/MySoftware/Embedded/kernel/linux-2.6.34/include/linux  $TARGET_PREFIX/include/linux
$ ln -s  /home/jinglelong/MySoftware/Embedded/kernel/linux-2.6.34/include/asm-generic/      $TARGET_PREFIX/include/asm-generic
$ ln -s  /home/jinglelong/MySoftware/Embedded/kernel/linux-2.6.34/arch/arm/include/asm/  $TARGET_PREFIX/include/asm 


編譯生成version標頭檔案

這個是編譯glibc時必須的,使用命令:make include/linux/version.h


3 建立binutils

解壓binutils原始碼到資料夾: $PRJROOT/build-tools/binutils-2.20


配置:

cd $PRJROOT/build-tools/build-binutils
$ ../binutils-2.20/configure --target=$TARGET --prefix=$PREFIX


編譯:make
出錯:
../../binutils-2.20/gas/config/tc-arm.c: In function ‘make_mapping_symbol’:
../../binutils-2.20/gas/config/tc-arm.c:2489: error: suggest braces around empty body in an ‘if’ statement
開啟檔案binutils-2.20/gas/config/tc-arm.c,把2490行的語句,用一對大括號括起來就可以了


安裝: make install
完成後檢查一下$PREFIX資料夾,是不是多了三個子資料夾,bin, lib, share? 開啟bin,發現裡面生成了14個可執行檔案:

[[email protected] bin]# ls
arm-none-linux-gnueabi-addr2line  arm-none-linux-gnueabi-as   arm-none-linux-gnueabi-gprof  arm-none-linux-gnueabi-nm       arm-none-linux-gnueabi-objdump  arm-none-linux-gnueabi-readelf  arm-none-linux-gnueabi-strings arm-none-linux-gnueabi-ar         arm-none-linux-gnueabi-c++filt  arm-none-linux-gnueabi-ld     arm-none-linux-gnueabi-objcopy  arm-none-linux-gnueabi-ranlib   arm-none-linux-gnueabi-size     arm-none-linux-gnueabi-strip


他們的功能分別是:

add2line         :將你要找的地址轉成檔案和行號,它要使用 debug 資訊。
ar                  :產生、修改和解開一個存檔檔案
as                  :gnu的彙編器
c++filt            :C++ 和 java 中有一種過載函式,所用的過載函式最後會被編譯轉化成彙編的標,c++filt 就是實現這種反向的轉化,根據標號得到函式名。
gprof              :gnu 彙編器預編譯器。
ld                   :gnu 的聯結器
nm                 :列出目標檔案的符號和對應的地址
objcopy           :將某種格式的目標檔案轉化成另外格式的目標檔案
objdump          :顯示目標檔案的資訊
ranlib              :為一個存檔檔案產生一個索引,並將這個索引存入存檔檔案中
readelf            :顯示 elf 格式的目標檔案的資訊
size                :顯示目標檔案各個節的大小和目標檔案的大小
strings            :打印出目標檔案中可以列印的字串,有個預設的長度,為4
strip                :剝掉目標檔案的所有的符號資訊



4 建立bootstrap gcc


首先,我們為什麼要建立bootstrap gcc,而不能一次性成功?原因有兩點:


一是由於平臺本身的gcc編譯器和我們要建立的gcc版本不同,第一次用平臺本身的編譯器去build目標版本的gcc編譯器的時候,新生成的目標編譯器(相當於初始編譯器編譯連結生成的可執行檔案)必然帶有初始編譯器的特徵。而當我們用新生成的編譯器再次編譯自身時,便可去掉這種差異性。


二是因為gcc編譯器依賴於glibc,而當前我們的glibc是基於本機的,所以我們首先要build基於arm體系結構的glibc,再在glibc的基礎上生成基於arm體系結構的gcc。


這一步是最容易出錯的,對每一步都必須謹慎,不要犯粗心之類的低階錯誤。


解壓原始碼
解壓gcc原始碼到build-tool資料夾下

修改原始碼:
gcc-4.3.5
CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC -Dinhibit_libc -D__gthr_posix_h

確保本機已經安裝了mpc, mpfr, gmp, 如果沒有,則在yast裡面安裝好再往後走。


配置:
../gcc-4.3.5/configure --target=$TARGET --prefix=$PREFIX --without-headers --enable-languages=c --disable-threads --with-newlib --disable-shared --disable-libmudflap --disable-libssp

編譯:make all-gcc
安裝gcc: make install
再編譯安裝libgcc,這個是後面編譯glibc必須的。
編譯:make all-target-libgcc
安裝libgcc: make install-target-libgcc

我看到網上很多文章在這一步有很多錯誤,一種是直接用make命令編譯gcc下所有內容,這個是沒有必要的,而且容易出錯。我在ubuntu和suse下都無法完成編譯,而在fedora下通過了;第二種情況是沒有編譯libgcc,這會導致後面編譯glibc無法通過。

安裝完成後,在$PREFIX/bin下又多了幾個檔案,
arm-none-linux-gnueabi-cpp         : gnu的 C 的預編譯器
arm-none-linux-gnueabi-gcc         : gnu的 C 語言編譯器
arm-none-linux-gnueabi-gcc-4.3.5 : gnu的 C 語言編譯器,其實和arm-linux-gcc是一樣的
arm-none-linux-gnueabi-gccbug    :  一個可執行指令碼,具體作用未知。
arm-none-linux-gnueabi-gcov        : gcc 的輔助測試工具,用來分析和優化程式



5 建立glibc

解壓原始碼:
把glibc原始碼解壓到build-tool下,把glibc-linuxthreads-2.5.tar.bz2解壓到glibc根目錄下,把glibc-ports-2.11.tar.bz2解壓到glibc根目錄下,並且命名為ports

進入資料夾build-glibc,建立config.cache檔案,並且在檔案中輸入以下內容

libc_cv_forced_unwind=yes
libc_cv_c_cleanup=yes
libc_cv_arm_tls=yes

配置:

BUILD_CC="gcc" CC=$TARGET-gcc ../glibc-2.11/configure --host=$TARGET --target=$TARGET --prefix=/usr --enable-add-ons --disable-profile --cache-file=config.cache --with-binutils=$PREFIX/bin/ --with-headers=$TARGET_PREFIX/include/


編譯:make
出錯:/arm-linux/bin/ld: cannot find -lgcc_eh
開啟glibc根目錄下Makeconfig檔案,去掉第541,546行中的-lgcc_eh,重新make


安裝:

make install_root=$TARGET_PREFIX prefix="" install


修改libc.so:

用vi或gedit開啟libc.so檔案,將檔案中的:
GROUP ( /lib/libc.so.6 /lib/libc_nonshared.a  AS_NEEDED ( /lib/ld-linux.so.2 ) )
更改為
GROUP ( libc.so.6 libc_nonshared.a )
儲存後退出



6 建立完整版gcc

有了前面的經驗,現在就簡單多了,進入目錄build-gcc,


配置:

../gcc-4.3.5/configure --target=$TARGET --prefix=$PREFIX --enable-languages=c,c++ --disable-libgomp


編譯:
make all

安裝:
make install

安裝完成後,在$PREFIX/bin下多了gnu的c++編譯器:
arm-none-linux-gnueabi-gcc
arm-none-linux-gnueabi-c++  

7 驗證工具鏈
建立,編譯生成一個hello world程式helloworld, 檢視elf檔案資訊:
$  arm-none-linux-gnueabi-readelf  -d helloworld
是不是看到了ARM的資訊?更直接的,就是把這個helloworld和相關依賴的動態庫拷到開發板上,看它是不是真的能helloworld!


8 總結
這次在SUSE 11.2上編譯安裝工具鏈,整個過程非常順利,其實我相信只要環境,配置等正確,常見linux發行版上都會比較順利。不過我還是建議直接下在編譯好的工具鏈,省下了不少麻煩,而且可靠性也能保證。最後,希望本教程對大家有所幫助,如果有什麼遺漏或錯誤之處,希望大家能批評指正!



參考文獻:

相關推薦

建立ARM交叉編譯環境 (arm-none-linux-gnueabi-gcc with EABI)

昨天終於把交叉編譯環境、移植核心和製作root檔案系統在arm開發板上順利跑通了。期間有的步驟很順利,但更多的是被諸多問題困擾,比如最後一個不起眼的小問題導致檔案系統無法載入,鬱悶了我一個星期,最終通過分析慢慢發現了這個bug。還有各原始碼包版本的問題,而且網上很多介紹都是基

ubuntu12.04建立交叉編譯環境,bin/.arm-none-linux-gnueabi-gcc: not found

ubuntu12.04交叉編譯器安裝,已經設定好環境變量了 ~$ echo $PATH /usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/ga

ubuntu12.04 64建立交叉編譯環境,bin/.arm-none-linux-gnueabi-gcc: not found(安裝 ia32-libs)

ubuntu12.04交叉編譯器安裝,已經設定好環境變量了 ~$ echo $PATH/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/ga

嵌入式交叉編譯環境arm-linux-gcc環境搭建

arm linux gcc 嵌入式交叉編譯環境 準備工具安裝目錄 可以去官網下載對應系統版本的arm-Linux-gcc。將壓縮包arm-linux-gcc-4.4.3.tar.gz存放在一個目錄下。 .tar.gz 和.tgz 解壓:tar zxvf FileName.tar.gz 壓縮:t

Linux下搭建arm交叉編譯環境

首先需要在網上搜索arm-linux-gcc-4.3.2.tgz 傳到Linux下,執行tar xzvf arm-linux-gcc-4.3.2.tgz -C/ 解壓到根目錄下(目錄結構/usr/local/arm/4.3.2) 這樣,編譯器就解壓到了Linux系統中 然後建立

Ubuntu14.04下嵌入式交叉編譯環境arm-linux-gcc-4.3.3搭建過程

需要做嵌入式的開發,照著板子的教程安裝arm-linux-gcc-4.3.3交叉編譯工具,安裝完驗證時發現安裝失敗 (報錯,錯誤與下面參考文章1中第6步一樣,照他說的那條命令去裝32位的庫,但是安裝失

64位Ubuntu 16.04搭建嵌入式交叉編譯環境arm-linux-gcc過程圖解

64位Ubuntu 16.04搭建嵌入式交叉編譯環境arm-linux-gcc過程圖解,開發裸機環境之前需要先搭建其開發環境,畢竟工欲善其事必先利其器嘛。  安裝步驟 1、準備工具安裝目錄 將壓縮包arm-Linux-gcc-4.4.3.tar.gz存放在

Ubuntu 12.04嵌入式交叉編譯環境arm-linux-gcc搭建過程圖解

安裝前的絮叨 首先簡單介紹一下,所謂的搭建交叉編譯環境,即安裝、配置交叉編譯工具鏈。在該環境下編譯出嵌入式Linux系統所需的作業系統、應用程式等,然後再上傳到目標機上。 交叉編譯工具鏈是為了編譯、連結、處理和除錯跨平臺體系結構的程式程式碼。對於交叉開發的工具鏈來說,在檔名稱上加了一個字首,用來區別本地的

配置64位UBUNTU 編譯環境出現的arm-none-linux-gnueabi-gcc: not found

在網上查詢資料後發現原因為該命令需要32庫進行支援。 需要sudo apt-get ia32-libs 但是又有資料提到ia32-libs已經廢棄。 ia32-libs已經被廢棄,那麼應該有取代的方式。 於是按照以下步驟 $ sudo apt-get install li

Linux學習】Ubuntu下嵌入式交叉編譯環境arm-linux-gcc搭建

(1)首先選擇一個路徑用來存放arm-linux-gcc。我選用的是/home/book,並在下面建立一個資料夾arm-linux-gcc。 (2)利用cp EABI-4.3.3_Emdedsky_20100610.tar.bz2 arm-linux-gcc,將壓縮包EA

visual studio 2013上搭建arm交叉編譯環境(三)Visual studio2013中Cygwin工程的建立

        前兩篇文章已經介紹了在vs上搭建arm環境的準備工作。 http://blog.csdn.net/water1209/article/details/50926869 http://blog.csdn.net/water1209/article/detail

ubuntu14.01 搭建交叉編譯環境arm-linux-gcc 4.3.2

安裝步驟 0. 安裝標準的C開發環境,由於Ubuntu 9.04 Linux安裝預設是不安裝的,所以需要先安裝一下(如果已經安裝好的話,就可以免去這一步了):$ sudo apt-get install gcc g++ libgcc1 libg++ make gdb如果

Ubuntu 14.04 LTS嵌入式交叉編譯環境arm-linux-gcc搭建過程圖解

1、將壓縮包arm-linux-gcc-3.4.5-glibc-2.3.6.tar.bz2存放在一個目錄下,這個目錄就是你等會解壓縮的目錄,以後這個目錄就不能隨便刪掉了,我的存放路徑是/home/g

Ubuntu160403安裝交叉編譯工具鏈後,出錯: ./arm-none-linux-gnueabi-gcc -v bash: ./arm-none-linux-gn

cd /etc/apt1在修改前先對 sources.list檔案進行備份sudo cp sources.list sources.list.bak1修改sources.list檔案sudo vi sources.list1刪除掉sources.list的其他內容,選擇任意源貼上複製進去,這裡以阿里云為例ub

安裝交叉編譯工具arm-none-linux-gnueabi-gcc——Linux編譯在android上執行的c程式

# vim /etc/bash.bashrc 在最後新增 PATH=$PATH:/usr/local/arm-2014.05/bin source /etc/bash.bashrc 使其立刻生效 開啟另一個終端 執行 arm-none-linux-gnueabi-gcc -v,顯示版本即說明安裝成功 方法二

在Ubentu環境下創建arm交叉編譯環境

老師 build 目錄 更新 hello 分享 date win 例程 學校:華中科技大學機械學院 作業任務:在Ubentu環境下創建arm交叉編譯環境並且在虛擬機中編譯例程 首先,利用U盤安裝windows10+Ubuntu16.04雙系統,系統剛開始安裝,需要執行以下兩

ubuntu14.04搭建Android-arm交叉編譯環境

前面我們搭建了NDK開發環境 下面開始搭建arm交叉編譯環境 1.下載交叉編譯工具 進入到NDK根目錄:cd /home/wjt/AndroidWorkSpace/NDK_Tools/android-ndk-r10b 下載到指定路徑指令:./build/tools/make-st

docker搭建ros-indigo-arm交叉編譯環境

ROS執行環境:ARM ubuntu14.04 + ROS indigo 在arm環境下編譯ros應用程式,速度極慢,無法忍受,嘗試在x86機器上搭建docker+ros交叉編譯環境。 交叉編譯環境的搭建主要參考: 1 ARM ubuntu環境上安裝arm-indigo

一套完整的ARM交叉編譯環境的搭建過程——不使用現成的工具鏈

Glibc是交叉編譯環境的執行庫。首先將glibc-2.13.tar解壓至build-tools,然後將glibc-linuxthreads-2.3.6.tar解壓至glibc原始碼所在目錄,將glibc-ports-2.13.tar.gz解壓至glibc原始碼所在目錄,並重命名為ports。進入

arm-none-linux-gnueabi-gcc【實驗環境】 1、 Ubuntu 10.10發行版 2、 FS2410平臺 【實驗步驟】

Configuredwith:/home/linux/s3c2410-2.6.35/toolchain/toolchain-build/targets/src/gcc-4.3.2/configure--build=i686-build_pc-linux-gnu --host=i686-build_pc-lin