使用buildroot創建自己的交叉編譯工具鏈
關鍵字:buildroot 交叉編譯
Author: chad
Mail: linczone@163.com
開發環境: deepin 14.03 + mini2440 (使用原廠linux2.6.29)
曾經,很長一段時間我一直有個疑惑:為什么我用at91sam9260交叉編譯工具鏈編譯的程序只能在at91sam9260上運行,在mini2440上就不能運行?相反,用使用於mini2440的交叉編譯工具鏈編譯的程序在at91上也不能運行?mini2440與at91sam9260都是arm平台,同樣使用linux系統,為何二進制程序不能通用呢?
本文將解答這些疑惑。我們是不建議重復發明輪子的,但如果我們不自己發明一次,我們永遠不知道輪子是怎么來的。
進行嵌入式Linux開發的第一步是創建交叉編譯工具鏈,在過去很長的一段時間里,構建一套交叉編譯工具鏈對於嵌入式開發者來說簡直是一場惡夢,因為他們得手動跟蹤各種源碼包(及其更新包)之間的依賴關系。直到buildroot的出現改變了這一事實。
Buildroot是一個Makefiles和patches的命令集,它可以非常簡單的為你的目標系統產生一個交叉編譯工具鏈和根文件系統,整個創建過程就如同編譯Linux內核一般。
1、下載buildroot
直接從官網下載最新的源碼包:http://buildroot.net/downloads/
2、安裝依賴庫、軟件包
下文摘自buildroot官網操作說明:
1. Build tools: gcc (version 2.95 or any later) g++ (version 2.95 or any later) python (version 2.6 or 2.7) 2. dependencies packages: 下面的自己根據需要安裝 ncurses5 ;menuconfig 使用 qt4 ;xconfig 使用 glib2, gtk2 and glade2 ;gconfig 使用
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
3、 解壓buildroot壓縮包
4、 進入源碼目錄,make menuconfig配置
配着之前看看下s3c2440數據手冊摘錄:
接下來簡單解釋幾個比較重要的選項:
Target Architecture ---> 用於選擇目標的架構,我這里選擇ARM (little endian)(s3c2440可以運行在小端模式和大端模式,默認是小端模式) Target Architecture Variant ---> 內核類型(arm920t) Target ABI (EABI) ---> 目標使用的應用程序二進制接口,其中有兩個選擇 ①EABI(Embedded ABI) 我們選EABI. ②OABI(Old ABI) Build options ---> 主要是一些編譯時用到的選項,比如dl的路徑,下載代碼包使用的路徑,同時運行多個編譯的上限,是否使能編譯器緩沖區等等,這里按照默認就行了. Toolchain ---> 工具鏈選項 Toolchain type (Buildroottoolchain) ---> 工具鏈類型,這里我們沒使用外部Buildroot,默認 . *** Kernel Header Options *** Kernel Headers (Linux 3.18.x kernel headers) ---> C library (glibc) ---> 有uclibc/glibc等選項,此處我選擇glibc,后面會解釋原因 glibc version (2.20) ---> *** Binutils Options *** Binutils Version (binutils 2.24) ---> () Additional binutils options *** GCC Options *** GCC compiler Version (gcc 4.8.x) ---> () Additional gcc options [*] Enable C++ support [ ] Enable compiler OpenMP support [ ] Enable libmudflap support [ ] Enable graphite support [ ] Build cross gdb for the host [ ] Purge unwanted locales () Generate locale data [ ] Copy gconv libraries [*] Enable MMU support () Target Optimizations () Target linker options
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
5、保存退出,生成.config 文件
6、編譯
$make
這里不能使用make-jN,因為Buildroot不支持top-levelparallel make , 反之 , 使用BR2_JLEVEL選項來告訴Buildroot運行編譯每一個package使用make -JN.
使用make命令之后會執行下面幾個步驟:
①下載源文件(所要求的)
②配置,編譯和安裝cross-compiling toolchain(如果使用內部工具鏈),或者輸出一個toolchain(如果一個外部工具鏈使用)
③構建/安裝杯選擇的目標包
④構建內核鏡像(如果有選擇)
⑤構建啟動代碼鏡像(如果有選擇)
⑥創建根文件系統(如果有選擇)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
7、輸出文件介紹
輸出文件全部在output/目錄下:
- images/ — 存放編譯后產生的所有鏡像文件( 內核鏡像 , 加載引導鏡像 和 根文件系統鏡像)
- build/ — 存放所有的組件除了構建交叉編譯工具鏈的組件 , 在這個目錄里面每一個功能對應一個子目錄存放他們各自的組件.
- staging/ — 包含一個類似於根文件系統等級層次的層級 . 這個目錄包含了 安裝的交叉編譯工具鏈 和 所有被選擇用於目標板的所有用戶空間包.
- target/ — 包含了根文件系統,但不能用於你的開發板的
- host/ — 包含了我們需要的交叉編譯工具集
我們可以在host/usr/bin/里面看到很多我們需要的二進制文件,如下所示:# cd host/usr/bin/
8、修改環境變量
在/etc/profile文件里加入:
# vim/etc/profile 添加上: exportPATH=$PATH:/home/chad/works/binutils/buildroot-2015.02/output/host/usr/bin 保存之后,執行以下命令使其生效: # source/etc/profile
- 1
- 2
- 3
- 4
9、測試arm-linux-gcc
打印出版本號說明編譯成功:
10、hello.c測試
編寫一個hello.c程序,使用arm-linux-gcc編譯並下載到開發板進行測試。
按照上文的配置,程序運行肯定是正常的。
但是如果上面選擇的是uclibc,duang!程序運行就會出錯!
C library (uclibc) ---> 有uclibc/glibc等選項,此處如果選擇uclibc
- 1
如果我們用hexdump 查看hello的二進制文件,會發現如下信息:
#hexdump -C hello
- 1
然后我們用同樣的方法查看能正確執行的二進制程序的信息,隨便打開一個信息如下:
發現區別沒?mini2440默認調用的是glibc庫,而不是uclibc庫。
需要注意的是,buildroot編譯效率很低,一次編譯完成后,如果你想修改某些東西,則必須重新全部編譯!!也即先make clean 再 make。
如何重新編譯軟件包?
經過第一次完整編譯后,如果我們需要對源碼包重新配置,我們不能直接在buildroot上的根目錄下直接make,buildroot是不知道你已經對源碼進行重新配置,它只會將第一次編譯出來的文件,再次打包成根文件系統鏡像文件。不過,我們可以通過以下兩個方法修改源碼的配置。
- 直接刪除源碼包,例如我們要重新編譯openssh,那么可以直接刪除output/build/openssh-vesion 文件夾,那么當你make的時候,他就會自動從dl文件夾下,解壓縮源碼包,並重新安裝
- 也是以openssh為例子,如果我們不想重新編譯,只想重新配置,也就是./configure,
我們可以直接刪除 output/build/openssh-version 目錄下的 .stamp_configured
如果你只是想重新安裝可以刪除.stamp_target_install
重新make可以刪除.stamp_built
總結:
為什么針對mini2440的交叉編譯工具鏈與針對at91sam9260的交叉編譯工具鏈不通用?
看下我們前面制作交叉編譯工具鏈都指定了那些重要參數:
Target Architecture ---> 目標的架構,s3c2440 與 at9260 都是arm,這個相同 Target Architecture Variant ---> 內核類型(s3c2440[arm920t] 而 at91sam9260[arm926EJ-S],但是配置時選擇arm926t),此處不同 Target ABI (EABI) ---> 目標使用的應用程序二進制接口,此處不同 ①EABI(Embedded ABI) mini2440的選擇。 ②OABI(Old ABI) at91sam9260的選擇 Kernel Headers (Linux 3.18.x kernel headers) ---> 此處差別影響不大 C library (glibc) ---> 都選擇的是glibc glibc version (2.20) ---> 版本不一樣
至此,我想兩個平台的交叉編譯工具鏈不可通用的原因應該已經很清楚了。
—————–2015-05-21