前言
文章基于HD-IMX6ULL-MB 系列開發(fā)板測(cè)試驗(yàn)證,該開發(fā)板由武漢芯路遙科技有限公司與武漢萬(wàn)象奧科電子有限公司合作推出。此開發(fā)板基于 NXP iMX6ULL 系列 Cortex-A7 高性能處理器設(shè)計(jì),適用于快速開發(fā)一系列具有創(chuàng)新性的產(chǎn)品如人機(jī)界面工業(yè) 4.0 掃描儀、車載終端以及便攜式醫(yī)療設(shè)備。
自己制作交叉編譯器
早期(2009年以前)我們?cè)谧?a target="_blank">嵌入式系統(tǒng)開發(fā)時(shí),第一件事就是自己制作交叉編譯器。當(dāng)時(shí)做交叉編譯器 需要自己下載gcc、glibc、binutils等相關(guān)工具的源碼,然后一個(gè)一個(gè)源碼編譯安裝。制作交叉編譯器的 過(guò)程中最痛苦的莫過(guò)于各個(gè)軟件之間的版本依賴關(guān)系,如gcc 4.6.2 依賴 glibc 2.13,如果你選定 gcc 4.7 則可能編譯制作失敗,然后再嘗試一個(gè)新的版本重新編譯,直至找到一個(gè)合適的版本為止。
后來(lái)為了方便交叉編譯器的制作,有很多組織或個(gè)人開始編寫這些制作交叉編譯器的腳本或框架,并測(cè) 試解決這些軟件版本之間的依賴關(guān)系。當(dāng)時(shí)最知名的莫過(guò)于基于 glibc 的 crosstool 和 基于 uclibc 的
buildroot 了。在開始講解如何制作交叉編譯器之前,我們首先來(lái)了解一下 C運(yùn)行庫(kù)。
1.嵌入式C運(yùn)行庫(kù)
1.1glibc庫(kù)
glibc是gnu發(fā)布的libc庫(kù),也即c運(yùn)行庫(kù)。glibc是linux 系統(tǒng)中最底層的api(應(yīng)用程序開發(fā)接口),幾乎其它任何的運(yùn)行庫(kù)都會(huì)倚賴于glibc。glibc除了封裝linux操作系統(tǒng)所提供的系統(tǒng)服務(wù)外,它本身也提供了 許多其它一些必要功能服務(wù)的實(shí)現(xiàn),主要的如下:
string,字符串處理
signal,信號(hào)處理
dlfcn,管理共享庫(kù)的動(dòng)態(tài)加載
direct,文件目錄操作
elf,共享庫(kù)的動(dòng)態(tài)加載器,也即interpreter
iconv,不同字符集的編碼轉(zhuǎn)換
inet,socket接口的實(shí)現(xiàn)
intl,國(guó)際化,也即gettext的實(shí)現(xiàn)
io
linuxthreads
locale,本地化
login,虛擬終端設(shè)備的管理,及系統(tǒng)的安全訪問
malloc,動(dòng)態(tài)內(nèi)存的分配與管理
nis
stdlib,其它基本功能
gcc 是編譯器,基本上 Linux 下所有的程序(包括內(nèi)核)都是 gcc 編譯的,libc 當(dāng)然也是。gcc 和 libc 是互相依賴的兩個(gè)軟件,它們合作的方式類似 Linux 系統(tǒng)的 "自舉"。先在一個(gè)可以運(yùn)行的帶有老 libc 和
gcc 的系統(tǒng)上,用老 gcc 編譯出一個(gè)新版本的 gcc + 老 libc,再用這個(gè)新 gcc 編譯出一個(gè)新 gcc + 新
libc,再用這套新的組合編譯整個(gè)新系統(tǒng)。
1.2 uClibc庫(kù)
PC上常用的標(biāo)準(zhǔn)庫(kù)glibc是一個(gè)非常寵大而完整的庫(kù),但早期對(duì)于嵌入式系統(tǒng)來(lái)說(shuō),由于Flash和RAM的 存儲(chǔ)空間有線,其體積顯得過(guò)于大了一些。uClibc的出現(xiàn)就是為了解決這個(gè)問題,uClibc盡可能的兼容
Glibc,大多數(shù)應(yīng)用程序可以在很小或完全不修改的情況下就可能使用uClibc替代glibc。通過(guò)uClibc來(lái)代 替Glibc,可以在不改變應(yīng)用程序功能的前提下,大大減少發(fā)布文件的大小,無(wú)論應(yīng)用程序以靜態(tài)鏈接來(lái) 編譯,還是以動(dòng)態(tài)鏈接形式編譯。
uClibc比一般用于Linux發(fā)行版的C庫(kù)GNU C Library (glibc)要小得多,glibc目標(biāo)是要支持最大范圍的硬件和內(nèi)核平臺(tái)的所有C標(biāo)準(zhǔn),而uClibc專注于嵌入式Linux.很多功能可以根據(jù)空間需求進(jìn)行取舍。現(xiàn)在uClibc更多運(yùn)行于標(biāo)準(zhǔn)的以及無(wú)MMU的Linux系統(tǒng)上,支持i386,x86 64,ARM (big/little endian), AVR32,Blackfin,h8300,m68k,MIPS (big/little endian), PowerPC,SuperH (big/little endian),
SPARC,和v850等處理器。
由于當(dāng)前嵌入式系統(tǒng)硬件性能的提升,用于存儲(chǔ)程序的Flash空間和用于運(yùn)行程序的RAM空間都有了大幅 提升,為了保證程序更大的兼容性,uClibc也逐步退出了歷史的舞臺(tái)了。
uClibc早期官網(wǎng): uClibc最新官網(wǎng):
https://www.uclibc.org/ h ttps://uclibc-ng.org/
1.3 eglibc庫(kù)
EGLIBC(Embedded GLIBC,縮寫為EGLIBC)是glibc的原創(chuàng)作組織FSF所新推出的glibc的一種變體, 目的在于將glibc用于嵌入式系統(tǒng)。它是GNU C 庫(kù)(glibc)的一個(gè)分支,也采用GNU寬通用公共許可證
(LGPL)發(fā)布。它希望能應(yīng)用于嵌入式系統(tǒng),但它的源代碼與可執(zhí)行文件仍然保持與glibc一致。它的作 者宣稱它不是glibc的一個(gè)分支,而是用來(lái)容納glibc核心開發(fā)者拒絕采納的patch。
2009年5月6日,因?yàn)榕cglibc核心開發(fā)者之間對(duì)程序發(fā)展方向的爭(zhēng)議,Debian開發(fā)者宣布將要采用EGLIBC來(lái)取代glibc。Ubuntu自9.10后也采用了EGLIBC,Ark Linux也使用它。2014年初,官網(wǎng)上宣布,eglibc已經(jīng)停止開發(fā),因?yàn)楝F(xiàn)在的目標(biāo)是在glibc上直接解決問題(goals are now being addressed directly in GLIBC),Debian開發(fā)者也恢復(fù)到使用glibc了。
1.4 newlib庫(kù)
在做一些單片機(jī)的裸機(jī)程序開發(fā)時(shí),有時(shí)候最想要的是實(shí)現(xiàn)一個(gè)printf打印函數(shù),以便及時(shí)輸出各種信 息。除去底層的設(shè)備驅(qū)動(dòng)不說(shuō),printf本身的實(shí)現(xiàn)就有夠麻煩,如果平時(shí)有保存相關(guān)的代碼還好,不然就 很浪費(fèi)時(shí)間。除此之外,還有一些諸如strlen、strcpy之類的函數(shù),我們不愿意自己寫,既麻煩而且效率 不高,如果能借助已有的代碼或庫(kù)就好了。
Newlib 就滿足了這點(diǎn)需求,它是一個(gè)面向嵌入式系統(tǒng)的C運(yùn)行庫(kù)。最初是由Cygnus Solutions收集組裝的一個(gè)源代碼集合,取名為newlib,現(xiàn)在由Red Hat維護(hù)。對(duì)于與GNU兼容的嵌入式C運(yùn)行庫(kù),Newlib 并不是唯一的選擇,但是從成熟度來(lái)講,newlib是最優(yōu)秀的。newlib具有獨(dú)特的體系結(jié)構(gòu),具有可移植 性強(qiáng),具有可重入特性、功能完備等特點(diǎn),使得它能夠非常好地滿足深度嵌入式系統(tǒng)的要求。
Newlib 庫(kù)是一個(gè)開源的c函數(shù)庫(kù),包括libc和libm兩部分。它支持ANSI C庫(kù)標(biāo)準(zhǔn),針對(duì)不同處理器架構(gòu)進(jìn)行優(yōu)化,輕量級(jí),適用于嵌入式系統(tǒng)。其特點(diǎn)如下:
支持printf和優(yōu)化的字符串操作
支持malloc和free等內(nèi)存操作
支持函數(shù)可重入功能(不過(guò)這種支持對(duì)內(nèi)存有壓力,總之是感覺弊大于利)
支持libm數(shù)學(xué)庫(kù)(不過(guò)一般嵌入式用不到浮點(diǎn)數(shù),而且用模擬的開銷略大)
newlib的函數(shù)是分文件實(shí)現(xiàn)的,如果用不到,絕不加入鏈接,一般不會(huì)造成目標(biāo)文件猛增的情況。
newlib C庫(kù)一般在制作單片機(jī)裸機(jī)開發(fā)的交叉編譯器時(shí),使用得比較多。
2 Crosstool-ng制作交叉編譯器
Crosstool早期是個(gè)很不錯(cuò)的交叉編譯器制作工具,但是后來(lái)完善得不夠好,于是有人弄出了個(gè)更好的
—— crosstool-ng(crosstool Next Generation)。其特點(diǎn)如下:
支持menuconfig(類似于Linux內(nèi)核配置) 支持眾多的架構(gòu)
可選多種不同的C庫(kù)等模塊提供示例配置
支持多種主機(jī)編譯環(huán)境:各種Linux發(fā)行版,Cygwin等。
接下來(lái),我們學(xué)習(xí)了解一下如何使用 crosstool-ng 來(lái)制作一個(gè)ARM交叉編譯器。
2.1 Crosstool-NG 編譯與安裝
首先我們到 Crosstool-NG 的官方站點(diǎn)(https://crosstool-ng.github.io/)下載其軟件源碼壓縮包,并解壓縮源碼。
接下來(lái)進(jìn)入到源碼路徑下,開始Linux系統(tǒng)下源碼安裝的三部曲: ./configure、make、 make install
。 這里在configure 時(shí)通過(guò) --prefix 選項(xiàng)指定將編譯生成的文件安裝到當(dāng)前路徑下即可。在進(jìn)行
./configure 時(shí)可能會(huì)提示 help2man、 libtool 找不到,這可能是系統(tǒng)沒有安裝或者安裝的版本過(guò)低導(dǎo)致的,直接使用 sudo apt install 命令安裝相關(guān)系統(tǒng)命令即可。
上面命令成功編譯安裝之后,可執(zhí)行程序?qū)?huì)放到 install 文件夾下,接下來(lái)我們可以測(cè)試 ct-ng 命令是否能夠成功執(zhí)行。接下來(lái)我們將會(huì)使用該程序來(lái)制作交叉編譯器。
2.2 交叉編譯器配置
在Crosstool-NG的安裝路徑下,有很多參考的交叉編譯器示例配置,我們沒有必要所有的選項(xiàng)都自己從
0開始配置,可以在某個(gè)示例配置的基礎(chǔ)上來(lái)修改。
因?yàn)閕.MX6ULL是ARM CortexA7核的處理器,但在上面的示例配置中并沒有該架構(gòu)的相關(guān)配置,這樣我們?cè)?A8的基礎(chǔ)上來(lái)進(jìn)行修改,這兩種架構(gòu)大致都差不多。我們將ARM CortexA8的示例配置拷貝一份并命名為 .config, 接下來(lái)的 ct-ng menuconfig 將會(huì)默認(rèn)讀取該配置文件。
接下來(lái)使用 export 命令導(dǎo)出 ct-ng 命令所在的路徑,如果是使用 SecureCRT 遠(yuǎn)程登錄到Linux服務(wù)器上操作的話,還需要 export TERM=vt100 命令配置TERM環(huán)境變量,否則接下來(lái)的配置可能不能輸入。接下來(lái)再執(zhí)行 ct-ng menuconfig 對(duì)交叉編譯器制作進(jìn)行配置。
下面是Crosstool-NG的配置界面,我們接下來(lái)需要在這里進(jìn)行修改。在配置的過(guò)程中,上、下方向鍵 用來(lái)選擇相應(yīng)選項(xiàng),TAB鍵 用來(lái)選擇底下的 或 :在 Paths and misc options 選項(xiàng)中,我們主要要修改如下幾個(gè)選項(xiàng),修改指定下載的軟件包存放路徑${PWD}/tarballs 和 交叉編譯器的安裝路徑 /opt/xtools/cortexA7:在 Target options 選項(xiàng)中,我們主要修改 “ Floating point” 選項(xiàng),因?yàn)?iMX6ULL處理器帶有 FPU,這里為了保持兼容性,選擇 softfp (FPU)。在 Toolchain options 選項(xiàng)中,如果想拷貝該交叉編譯器給別的機(jī)器使用,則可以選中"Build Static Toolchain",另外修改 "Tuple's vendor string" 選項(xiàng)中指定交叉編譯器名稱。在 Operating System 選項(xiàng)中,因?yàn)槲覀円浦驳腖inux內(nèi)核目標(biāo)版本為 5.10.x, 所以這里內(nèi)核的版本選擇要跟開發(fā)板上移植的版本保持一致,否則今后編譯Linux內(nèi)核時(shí)可能會(huì)出現(xiàn)兼容性問題。在這里, crosstool-NG的默認(rèn)內(nèi)核版本較低,這里需要修改配置為我們想要的版本。下面的這些選項(xiàng)配置,依賴Paths and misc options 菜單中的 [*] Try features marked as EXPERIMENTAL選項(xiàng)。"Source of linux" 選擇 (Custom location)"Custom source location" 里設(shè)置 Linux路徑為 (${PWD}/tarballs/linux-5.10.tar.xz) ,接下來(lái)我們將會(huì)手動(dòng)下載相應(yīng)的Linux內(nèi)核源碼壓縮包到這里;"Version of linux" 里選擇 (newer than anything below) ;在 C-library 選項(xiàng)中,C library 選擇 (glibc) ,其他使用默認(rèn)剩余的其它選項(xiàng),我們就不作任何修改采用默認(rèn)配置。關(guān)于 C compiler 編譯器里的相關(guān)選項(xiàng),大家也可以了解一下。配置完成后回到主菜單,使用 Tab鍵 切換到 < Exit > ,然后選擇保存退出即可。交叉編譯器配置完成之后,接下來(lái)我們就準(zhǔn)備開始交叉編譯器的編譯過(guò)程。2.3 交叉編譯器編譯在前面的配置中,我們計(jì)劃將交叉編譯器安裝到系統(tǒng)的 /opt/xtools 路徑下,這里我們首先需要使用root 權(quán)限創(chuàng)建這個(gè)文件夾,并給所有其他用戶 寫 權(quán)限。CrossTool-NG在編譯過(guò)程中,會(huì)下載制作交叉編譯器所需要的軟件源碼包,但有些軟件包的下載地址可 能已經(jīng)失效,這時(shí)我們可以自己找到相關(guān)軟件的相應(yīng)版本軟件包,然后手動(dòng)下載到指定的壓縮包存放路 徑下,如前面配置中指定的 ${PWD}/tarballs 。下面是一些已知的失效文件,我們提前手動(dòng)下載好,其它所需要的軟件包將會(huì)在開始編譯后自動(dòng)下載。接下來(lái)我們就開始交叉編譯的編譯制作過(guò)程,這個(gè)過(guò)程的時(shí)間依賴PC的性能。我的Linux服務(wù)器處理器 是Intel(R) Xeon(R) CPU E31235 @ 3.20GHz,4核8線程,所以我這里使用 ct-ng build.8 命令用8個(gè)進(jìn)程同時(shí)編譯。交叉編譯器編譯完成之后,我們可以使用下面命令查看制作好的交叉編譯器相關(guān)版本信息:2.4 交叉編譯器測(cè)試接下來(lái)我們使用制作好的交叉編譯器,交叉編譯之前寫好的 hello.c 測(cè)試程序,并放到 ARM 開發(fā)板上運(yùn)行測(cè)試。需要注意的是因?yàn)樾轮谱鞯慕徊婢幾g器跟開發(fā)板上運(yùn)行的C運(yùn)行庫(kù)版本不一致,這里必須加上 -static 進(jìn)行靜態(tài)鏈接,這樣編譯生成的程序才能在開發(fā)板上運(yùn)行。ARM 開發(fā)板上下載運(yùn)行測(cè)試:版權(quán)聲明本文檔所有內(nèi)容文字資料由凌云實(shí)驗(yàn)室郭工編著,主要用于凌云嵌入式Linux教學(xué)內(nèi)部使用,版權(quán)歸屬 作者個(gè)人所有。任何媒體、網(wǎng)站、或個(gè)人未經(jīng)本人協(xié)議授權(quán)不得轉(zhuǎn)載、鏈接、轉(zhuǎn)帖或以其他方式復(fù)制發(fā)布/發(fā)表。已經(jīng)授權(quán)的媒體、網(wǎng)站,在下載使用時(shí)必須注明來(lái)源,違者本人將依法追究責(zé)任。Copyright (C)2021 凌云物網(wǎng)智科實(shí)驗(yàn)室·郭工Author: GuoWenxue guowenxue@gmail.com
-
Linux系統(tǒng)
+關(guān)注
關(guān)注
4文章
595瀏覽量
27464 -
嵌入式開發(fā)
+關(guān)注
關(guān)注
18文章
1034瀏覽量
47644 -
開發(fā)板
+關(guān)注
關(guān)注
25文章
5110瀏覽量
97898
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論