1. 程式人生 > 實用技巧 >使用buildroot建立自己的交叉編譯工具鏈【轉】

使用buildroot建立自己的交叉編譯工具鏈【轉】

轉自:https://blog.csdn.net/linczone/article/details/45894181?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

使用buildroot建立自己的交叉編譯工具鏈

關鍵字:buildroot 交叉編譯

Author: chad
Mail: [email protected]

開發環境: 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是不知道你已經對原始碼進行重新配置,它只會將第一次編譯出來的檔案,再次打包成根檔案系統映象檔案。不過,我們可以通過以下兩個方法修改原始碼的配置。

  1. 直接刪除原始碼包,例如我們要重新編譯openssh,那麼可以直接刪除output/build/openssh-vesion 資料夾,那麼當你make的時候,他就會自動從dl資料夾下,解壓縮原始碼包,並重新安裝
  2. 也是以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