1. 程式人生 > >Buildroot構建指南——工具鏈

Buildroot構建指南——工具鏈

Linux系統的交叉編譯工具鏈用來將原始碼變成bin檔案或者庫檔案的一個軟體。一般大家預設工具鏈等於gcc或者arm-linux-gcc,但是實際上,gcc只是工具鏈的編譯器部分,不是全部,製作一個工具鏈的原材料,除了gcc,還需要linux核心,libc庫等一系列的軟體包。所謂萬事開頭難,如何在Buildroot中使用自己的交叉編譯工具鏈則是第一道難關。

Buildroot支援從零開始用原材料軟體包自動構造工具鏈,也支援直接使用第三方製作好的工具鏈。

toolchain-buildroot 從零開始自動製作工具鏈

在make menuconfig –> Toolchain –>Toolchain type中,有2個選項,選擇

buildroot toolchain則是使用buildroot預設的自動化指令碼從零開始製作交叉編譯工具鏈,如果是選擇externaltoolchain 則是使用外部製作好的工具鏈。

Figure 1  toolchain type 選項

在mini2440_defconfig的配置檔案中,我們可以看到,它並沒有toochain相關的選項,只是在cpu指令集部分選擇了ARM920T  ,這種情況它會採用buildroot-toolchain也就是buildroot預設的自動化指令碼,從零開始製作工具鏈。實際上,你只要make toolchain然後等待幾分鐘,Buildroot就會將製作好的全新工具鏈放到

output/host/目錄下了。

Figure 2 mini2440_defconfig配置部分截圖

      整個工具鏈自動化製作過程可以參考toolchain/ 目錄下的toolchain-buildroot/ 、toolchain.mk、helpers.mk、toolchain-wrapper.mk等幾個指令碼,我就不詳細說了。但是有幾個關鍵點我還是強在下面列一下。總之製作過程還是很複雜的,所以如果是初學者,用手工方法從零開始做交叉編譯工具鏈,將是多大的挑戰。

a).  從圖3中我們可以看到製作交叉工具鏈大概需要的原材料軟體包

Figure3 製作交叉工具鏈的原材料

工具鏈主要的原材料包括:gcc,、libc庫,、linux核心標頭檔案、binutils以及一系列自動構建打包工具如m4、gmp、mpc等。

另外要強調的是,從工具鏈的原材料可以知道為什麼Linux核心、驅動以及應用軟體要用同一個工具鏈編譯,為什麼核心版本要適配它的工具鏈。這是因為工具鏈本身的製作依賴於特定版本的Linux核心和libc庫。

b). 從圖1的makemenuconfig –> Toolchain這一系列選項可以看到,製作工具鏈還可以選擇libc庫(uclibc還是glibc,自己新增Android特有的Bionic libc),不同的libc效能,size,效率,穩定性以及GPL協議支援上有著一定的差異,需要使用者謹慎選擇和測試。mini2440直接採用buildroot提供的預設的uclibc,不保證其穩定性和bug。

另外,toolchain後面還有Linux核心版本以及MMUsupport以及gcc版本的選擇,可見如果需要定製特定的Linux核心(比如不帶MMU的實時版),除了移植核心之外,還需要特別為其定製工具鏈。

c). make menuconfig –> Target option 中的選項也是與交叉工具鏈密切相關的。

其中晶片的CPU的大小端,是否編譯成elf格式,指令集,ABI的型別(EABI是Embeded ABI的意思,EABIHF是採用硬浮點的ABI),以及軟硬浮點特性(軟浮點不會有編譯相容性問題,但是在支援硬浮點的高階嵌入式晶片,採用軟浮點配置,很多效能會發揮不佳,但是ARM9這種低端平臺用軟浮點應該OK)等等選項,都是應該考慮的點。

Figure4 與交叉工具鏈相關的target option選項

toolchain-external 使用第三方現成工具鏈

這節用友善的Tiny4412開發板官方提供的工具鏈為例,介紹如何將外部第三方工具鏈移植到到Buildroot的編譯環境。Tiny4412開發板用的SOC晶片的基於ARM-Cortex-A9核心的三星Exyons-4412 真四核SOC晶片,曾經是三星旗艦手機Galaxy-S3的主打SOC。

從友善官方提供的交叉編譯工具鏈的包命名來看,工具鏈使用的gcc版本是4.5.1,有vfp則說明工具鏈支援應付點編譯。V6應該是指令集是ARMV6,但是ARM-V6實際上是ARM11的指令集,Cortex-A9的應該是ArmV7才對, 這裡應該是命名出錯了,算是一個小漏洞吧。

Figure5  友善官方提供的tiny4412交叉編譯工具鏈

移植步驟如下:

1.      為了不產生命名誤導,我們將工具鏈的壓縮包中4.5.1/* 目錄下的所以內容拷貝出來,放到一個叫toolchain-tiny4412重新壓縮成名字為arm-linux-gcc-4.5.1-tiny4412.tar.bz2的壓縮包,將其cp到/mnt/sdb/3rd-pkg目錄下,細心的朋友已經發現,根據前面一篇Buildroot快速入門的內容,這個資料夾是我儲存第三方軟體包的專門資料夾,待會Buildroot會用file的方法從該資料夾中把工具鏈cp到buildroot/dl/目錄下的。

Figure6 儲存在/mnt/sdb/3rd-pkg 目錄下的工具鏈壓縮包

2.      在make menuconfig –> Toolchain –>Toolchain type中選中external toolchain下面的Toolchain欄中的arm-linux-gcc-4.5.1for tiny4412選項,實際上原本是沒有的,是我自己加上去的。

Figure7 Toolchain的選擇

3.      那麼如何把自己的工具鏈加上去呢?cd buildroot/toolchain/toolchain-external/資料夾,根據前一篇文章快速上手的經驗,要加自己的工具鏈,肯定是該配置,再改mk檔案啦!

在該目錄的Config.in檔案的108行,有一個現成的第三方ARM cortex-A9 第三方交叉工具鏈的配置程式碼。

Figure8  buildroot/toolchain/toolchain-external/Config.in中的ARM Cortex-A9現成參考配置

我們可以參考模仿這段程式碼,稍微修改,在這段程式碼後面加入我們自己的配置程式碼:

注意,命名很重要,變數名一定是BR2_TOOLCHAIN_EXTERNAL_開頭,後面加上自己的工具鏈名。

Figure9 Config.in中參考修改的tiny4412工具鏈配置程式碼

在我的修改中,出來提示字串和help部分的相關注釋和提示文字,主要是把主機gcc版本的最低要求降低到4.5,再去掉了核心標頭檔案最低版本限制(這裡其實是友善官方的疏忽,友善在製作工具鏈的時候,採用的Linux核心標頭檔案版本很低,和編譯的核心版本不匹配,導致標頭檔案版本檢查會報錯,因而我去掉了最低版本的限制,這也是潛在漏洞之一吧)

4.      配置交叉工具鏈字首名。在Config.in的690行左右,為剛才新增的BR2_TOOLCHAIN_EXTERNAL_TINY4412_ARM選擇工具鏈字首名。

字首名的格式組成是這樣的:目標cpu-廠商-作業系統-庫和abi格式,我們參考之前模仿的配置,選擇arm-nonelinux-gnueabi,

實際上,友善官方給的工具鏈就是以arm-nonelinux-gnueabi作為字首命名的。

Figure10  工具鏈字首名配置

Figure11 tiny4412官方的工具鏈命名

5.      修改toolchain-external.mk 檔案,加入自己配置。在296行,仿照前面一個工具鏈的變數配置,為BR2_TOOLCHAIN_EXTERNAL_TINY4412_ARM的配置增加下載地址和壓縮包的名字,壓縮包名字在第一步已經做好。至於下載地址,直接抄過來就行了,友善提供的定製化工具鏈,網上下載不到的。

Figure12 為toolchain-external.mk 加入tiny4412工具鏈的配置

事實上,開啟那個地址,我們可以看到由sourcery官方維護的很多現成製作好的工具鏈,所以嘛直接拿來用就好了,自己從零製作工具鏈多麻煩啊!當然這些工具鏈的穩定性還是需要自己測試一番。

Figure13 sourcery網上可下載的現成工具鏈

6.      在menuconfig中設定下載的映象地址。這個和前一篇文章一樣,將本地儲存工具鏈的地址,按照格式,設定為file的映象地址。實際上,Buildroot的下載指令碼,預設的規定是優先去本地的file映象地址找軟體包,找不到之後,才會走git或者網站下載等其它方法。當然網上肯定是下載不到的,但是先從本地找到就OK,這也是第一步為什麼要儲存工具鏈壓縮包到該地址的原因。

關於Buildroot下載軟體包的順序,可以參考package/pkg-download.mk的指令碼,在214行可以看到,只有在本地file路徑找不到了,才會採用配置的(PKG)_SITE_METHOD方法去獲取軟體包。

Figure14  工具鏈的下載映象地址

Figure15 Buildroot自動下載指令碼的下載過程

7.      menuconfig中的幾項配置。修改完配置指令碼和編譯構建mk指令碼後,還得在menuconfig中把修改的東西配置進去。

在target Option的配置中,注意上一節提到的幾點。但是這裡有幾個新的選項需要注意

a). CPU架構選擇的是Cortex-A9

b) vfp友善官方給的工具鏈是支援的,所以這裡可以開啟,這樣就能支援硬浮點了

c) NEON SIMD是CPU支援的高效能多媒體引擎的功能,這是4412這種級別的多媒體處理器的殺手級功能,但是我們現在並不瞭解它的特性,也不知道友善的工具鏈在製作的有沒有把該功能加上去,因而暫時不開啟。但是專業的工程師要去了解這項功能,以便發揮SOC和CPU的潛能。

d). VFP硬浮點的版本,這一項由於友善的資料不明確,暫時選VFPv3-D16版本,根據說明,Coretex-A9對這個版本都會支援的。

e). ABI的問題,根據圖11的內容,友善的工具鏈應該只是用了EABI來做的,沒有用EABIhf。這幾項是什麼意思呢?浮點選項其實有軟浮點、硬浮點EABI(softfp)和硬浮點EABIhf三個。

軟浮點就是用軟體模擬浮點運算

硬浮點EABI就是用浮點指令,但是為了相容舊版本的軟浮點編譯出來的庫還是用整數暫存器傳遞浮點數,這樣犧牲了一些效率,但是在工具鏈中存在舊的軟浮點庫時,是可以相容並不會出現編譯錯誤的。

硬浮點EABIhf則是使用純粹的硬浮點指令和浮點暫存器來計算浮點數,這樣效率會更高,但是不再相容工具鏈中舊版的軟浮點下編譯出來的庫,如果不重新制作硬浮點EABIhf的工具鏈,可能會出現編譯問題。

EABIhf需要知道整個工具鏈的庫的相容特性,目前看起來友善官方工具鏈不支援這個選項,其工具鏈命名也是EABI,但是有支援vfp,因而我們選擇硬浮點EABI的配置。具體要如何支援EABIhf,可以搜其它相關文章,這個可能需要重新制作整個工具鏈。

以上這些選項實際上都是編譯toolchain-wrapper傳遞的,toolchain-wrapper是一箇中間層,負責編譯時,傳遞某些特定選項給工具鏈,以上這些選項確定後,都會被toolchain-wrapper以引數的時候在編譯時傳遞給交叉工具鏈的。

Figure 16 menuconfig -->target option的配置

Figure 17 menuconfig -->toolchain的配置

在加入了tiny4412的配置後,最後在toolchani中選擇自己的工具鏈,選上MMU功能,然後用pipe選項進行編譯加速。

最後,make toolchain  ,你就可以看到Buildroot系統如何構建出tiny4412的工具鏈了。

小結

整體而言,從零製作一個工具鏈,對嵌入式的知識掌握還是需要深入的掌握,另外,工具鏈對整個系統程式碼的穩定性有著極大的影響,所以直接用自動製作的工具鏈,一定要經過嚴格的壓力測試,否則容易出現各種隱患。

因而,採用第三方製作好的,有專門公司維護的工具鏈,應該是一個更為有效的開發方式。