i.MX6ULL開發板原始碼自制交叉編譯器

武漢永珍奧科發表於2021-12-27
前言
文章基於HD-IMX6ULL-MB  系列開發板測試驗證,該開發板由武漢芯路遙科技有限公司與武漢永珍奧科電子有限公司合作推出。此開發板基於 NXP iMX6ULL 系列 Cortex-A7 高效能處理器設計,適用於快速開發一系列具有創新性的產品如人機介面工業 4.0 掃描器、車載終端以及行動式醫療裝置。
i.MX6ULL開發板原始碼自制交叉編譯器

自己製作交叉編譯器


早期(2009年以前)我們在做嵌入式系統開發時,第一件事就是自己製作交叉編譯器。當時做交叉編譯器   需要自己下載gcc、glibc、binutils等相關工具的原始碼,然後一個一個原始碼編譯安裝。製作交叉編譯器的  過程中最痛苦的莫過於各個軟體之間的版本依賴關係,如gcc 4.6.2 依賴 glibc 2.13,如果你選定 gcc 4.7 則可能編譯製作失敗,然後再嘗試一個新的版本重新編譯,直至找到一個合適的版本為止。

後來為了方便交叉編譯器的製作,有很多組織或個人開始編寫這些製作交叉編譯器的指令碼或框架,並測 試解決這些軟體版本之間的依賴關係。當時最知名的莫過於基於 glibc crosstool 和 基於 uclibc
buildroot 了。在開始講解如何製作交叉編譯器之前,我們首先來了解一下 C執行庫

1.嵌入式C執行庫


1.1glibc庫

glibc是gnu釋出的libc庫,也即c執行庫。glibc是linux   系統中最底層的api(應用程式開發介面),幾乎其它任何的執行庫都會倚賴於glibc。glibc除了封裝linux作業系統所提供的系統服務外,它本身也提供了 許多其它一些必要功能服務的實現,主要的如下:
  1. string,字串處理
  2. signal,訊號處理
  3. dlfcn,管理共享庫的動態載入
  4. direct,檔案目錄操作
  5. elf,共享庫的動態載入器,也即interpreter
  6. iconv,不同字符集的編碼轉換
  7. inet,socket介面的實現
  8. intl,國際化,也即gettext的實現
  9. io
  10. linuxthreads
  11. locale,本地化
  12. login,虛擬終端裝置的管理,及系統的安全訪問
  13. malloc,動態記憶體的分配與管理
  14. nis
  15. stdlib,其它基本功能

gcc 是編譯器,基本上 Linux 下所有的程式(包括核心)都是 gcc 編譯的,libc 當然也是。gcc 和 libc 是互相依賴的兩個軟體,它們合作的方式類似 Linux 系統的 "自舉"。先在一個可以執行的帶有老 libc 和
gcc 的系統上,用老 gcc 編譯出一個新版本的 gcc + 老 libc,再用這個新 gcc 編譯出一個新 gcc + 新
libc,再用這套新的組合編譯整個新系統。

1.2 uClibc庫

PC上常用的標準庫glibc是一個非常寵大而完整的庫,但早期對於嵌入式系統來說,由於Flash和RAM的 儲存空間有線,其體積顯得過於大了一些。uClibc的出現就是為了解決這個問題,uClibc儘可能的相容
Glibc,大多數應用程式可以在很小或完全不修改的情況下就可能使用uClibc替代glibc。透過uClibc來代  替Glibc,可以在不改變應用程式功能的前提下,大大減少釋出檔案的大小,無論應用程式以靜態連結來 編譯,還是以動態連結形式編譯。

uClibc比一般用於Linux發行版的C庫GNU C Library (glibc)要小得多,glibc目標是要支援最大範圍的硬體和核心平臺的所有C標準,而uClibc專注於嵌入式Linux.很多功能可以根據空間需求進行取捨。現在uClibc更多執行於標準的以及無MMU的Linux系統上,支援i386,x86 64,ARM (big/little endian), AVR32,Blackfin,h8300,m68k,MIPS (big/little endian), PowerPC,SuperH (big/little endian),
SPARC,和v850等處理器。

由於當前嵌入式系統硬體效能的提升,用於儲存程式的Flash空間和用於執行程式的RAM空間都有了大幅 提升,為了保證程式更大的相容性,uClibc也逐步退出了歷史的舞臺了。


uClibc早期官網: uClibc最新官網:


1.3 eglibc庫


EGLIBC(Embedded GLIBC,縮寫為EGLIBC)是glibc的原創作組織FSF所新推出的glibc的一種變體, 目的在於將glibc用於嵌入式系統。它是GNU C 庫(glibc)的一個分支,也採用GNU寬通用公共許可證
(LGPL)釋出。它希望能應用於嵌入式系統,但它的原始碼與可執行檔案仍然保持與glibc一致。它的作 者宣稱它不是glibc的一個分支,而是用來容納glibc核心開發者拒絕採納的patch。

2009年5月6日,因為與glibc核心開發者之間對程式發展方向的爭議,Debian開發者宣佈將要採用EGLIBC來取代glibc。Ubuntu自9.10後也採用了EGLIBC,Ark Linux也使用它。2014年初,官網上宣佈,eglibc已經停止開發,因為現在的目標是在glibc上直接解決問題(goals are now being addressed directly in GLIBC),Debian開發者也恢復到使用glibc了。

1.4 newlib庫


在做一些微控制器的裸機程式開發時,有時候最想要的是實現一個printf列印函式,以便及時輸出各種信     息。除去底層的裝置驅動不說,printf本身的實現就有夠麻煩,如果平時有儲存相關的程式碼還好,不然就 很浪費時間。除此之外,還有一些諸如strlen、strcpy之類的函式,我們不願意自己寫,既麻煩而且效率  不高,如果能借助已有的程式碼或庫就好了。

Newlib 就滿足了這點需求,它是一個面向嵌入式系統的C執行庫。最初是由Cygnus  Solutions收集組裝的一個原始碼集合,取名為newlib,現在由Red   Hat維護。對於與GNU相容的嵌入式C執行庫,Newlib 並不是唯一的選擇,但是從成熟度來講,newlib是最優秀的。newlib具有獨特的體系結構,具有可移植  性強,具有可重入特性、功能完備等特點,使得它能夠非常好地滿足深度嵌入式系統的要求。

Newlib 庫是一個開源的c函式庫,包括libc和libm兩部分。它支援ANSI  C庫標準,針對不同處理器架構進行最佳化,輕量級,適用於嵌入式系統。其特點如下:
  1. 支援printf和最佳化的字串操作
  2. 支援malloc和free等記憶體操作
  3. 支援函式可重入功能(不過這種支援對記憶體有壓力,總之是感覺弊大於利)
  4. 支援libm數學庫(不過一般嵌入式用不到浮點數,而且用模擬的開銷略大)
  5. newlib的函式是分檔案實現的,如果用不到,絕不加入連結,一般不會造成目標檔案猛增的情況。
  6. newlib C庫一般在製作微控制器裸機開發的交叉編譯器時,使用得比較多。


2  Crosstool-ng製作交叉編譯器


Crosstool早期是個很不錯的交叉編譯器製作工具,但是後來完善得不夠好,於是有人弄出了個更好的
—— crosstool-ng(crosstool Next Generation)。其特點如下:
支援menuconfig(類似於Linux核心配置) 支援眾多的架構
可選多種不同的C庫等模組提供示例配置
支援多種主機編譯環境:各種Linux發行版,Cygwin等。

接下來,我們學習瞭解一下如何使用 crosstool-ng 來製作一個ARM交叉編譯器。

2.1 Crosstool-NG 編譯與安裝


首先我們到 Crosstool-NG 的官方站點( )下載其軟體原始碼壓縮包,並解壓縮原始碼。

i.MX6ULL開發板原始碼自制交叉編譯器

接下來進入到原始碼路徑下,開始Linux系統下原始碼安裝的三部曲: ./configuremakemake install
。 這裡在configure 時透過 --prefix 選項指定將編譯生成的檔案安裝到當前路徑下即可。在進行
./configure 時可能會提示 help2man、 libtool 找不到,這可能是系統沒有安裝或者安裝的版本過低導致的,直接使用 sudo apt install 命令安裝相關係統命令即可。

i.MX6ULL開發板原始碼自制交叉編譯器

上面命令成功編譯安裝之後,可執行程式將會放到 install 資料夾下,接下來我們可以測試 ct-ng 命令是否能夠成功執行。接下來我們將會使用該程式來製作交叉編譯器。

i.MX6ULL開發板原始碼自制交叉編譯器

2.2 交叉編譯器配置


在Crosstool-NG的安裝路徑下,有很多參考的交叉編譯器示例配置,我們沒有必要所有的選項都自己從
0開始配置,可以在某個示例配置的基礎上來修改。

i.MX6ULL開發板原始碼自制交叉編譯器

因為i.MX6ULL是ARM  CortexA7核的處理器,但在上面的示例配置中並沒有該架構的相關配置,這樣我們在 A8的基礎上來進行修改,這兩種架構大致都差不多。我們將ARM CortexA8的示例配置複製一份並命名為 .config, 接下來的 ct-ng menuconfig 將會預設讀取該配置檔案。

i.MX6ULL開發板原始碼自制交叉編譯器

接下來使用 export 命令匯出 ct-ng 命令所在的路徑,如果是使用 SecureCRT 遠端登入到Linux伺服器上操作的話,還需要 export TERM=vt100  命令配置TERM環境變數,否則接下來的配置可能不能輸入。接下來再執行 ct-ng menuconfig 對交叉編譯器製作進行配置。

i.MX6ULL開發板原始碼自制交叉編譯器

下面是Crosstool-NG的配置介面,我們接下來需要在這裡進行修改。在配置的過程中, 上、下方向鍵 用來選擇相應選項, TAB 用來選擇底下的 <Select> <Exit>

i.MX6ULL開發板原始碼自制交叉編譯器


Paths and misc options 選項中,我們主要要修改如下幾個選項,修改指定下載的軟體包存放路徑
${PWD}/tarballs 和 交叉編譯器的安裝路徑 /opt/xtools/cortexA7


i.MX6ULL開發板原始碼自制交叉編譯器


Target options 選項中,我們主要修改 “ Floating point” 選項,因為 iMX6ULL處理器帶有 FPU,這裡為了保持相容性,選擇 softfp (FPU)


i.MX6ULL開發板原始碼自制交叉編譯器


Toolchain options 選項中,如果想複製該交叉編譯器給別的機器使用,則可以選中" Build Static Toolchain",另外修改 " Tuple's vendor string" 選項中指定交叉編譯器名稱。


i.MX6ULL開發板原始碼自制交叉編譯器


Operating System 選項中,因為我們移植的Linux核心目標版本為 5.10.x, 所以這裡核心的版本選擇要跟開發板上移植的版本保持一致,否則今後編譯Linux核心時可能會出現相容性問題。在這裡, crosstool-NG的預設核心版本較低,這裡需要修改配置為我們想要的版本。下面的這些選項配置,依賴 Paths and misc options 選單中的 [*] Try features marked as EXPERIMENTAL選項。
" Source of linux" 選擇 (Custom location)
" Custom source location" 裡設定 Linux路徑為 (${PWD}/tarballs/linux-5.10.tar.xz) ,接下來我們將會手動下載相應的Linux核心原始碼壓縮包到這裡;
" Version of linux" 裡選擇 (newer than anything below)


i.MX6ULL開發板原始碼自制交叉編譯器



i.MX6ULL開發板原始碼自制交叉編譯器
C-library 選項中, C library 選擇 (glibc) ,其他使用預設

剩餘的其它選項,我們就不作任何修改採用預設配置。關於 C compiler  編譯器裡的相關選項,大家也可以瞭解一下。

i.MX6ULL開發板原始碼自制交叉編譯器

配置完成後回到主選單,使用 Tab 切換到 < Exit > ,然後選擇儲存退出即可。交叉編譯器配置完成之後,接下來我們就準備開始交叉編譯器的編譯過程。


i.MX6ULL開發板原始碼自制交叉編譯器


2.3 交叉編譯器編譯


在前面的配置中,我們計劃將交叉編譯器安裝到系統的 /opt/xtools 路徑下,這裡我們首先需要使用
root 許可權建立這個資料夾,並給所有其他使用者 許可權。


i.MX6ULL開發板原始碼自制交叉編譯器


CrossTool-NG在編譯過程中,會下載製作交叉編譯器所需要的軟體原始碼包,但有些軟體包的下載地址可 能已經失效,這時我們可以自己找到相關軟體的相應版本軟體包,然後手動下載到指定的壓縮包存放路   徑下,如前面配置中指定的   ${PWD}/tarballs  。下面是一些已知的失效檔案,我們提前手動下載好,其它所需要的軟體包將會在開始編譯後自動下載。

i.MX6ULL開發板原始碼自制交叉編譯器

接下來我們就開始交叉編譯的編譯製作過程,這個過程的時間依賴PC的效能。我的Linux伺服器處理器   是Intel(R) Xeon(R) CPU E31235 @ 3.20GHz,4核8執行緒,所以我這裡使用 ct-ng build.8 命令用8個程式同時編譯。

i.MX6ULL開發板原始碼自制交叉編譯器

交叉編譯器編譯完成之後,我們可以使用下面命令檢視製作好的交叉編譯器相關版本資訊:

i.MX6ULL開發板原始碼自制交叉編譯器

2.4 交叉編譯器測試


接下來我們使用製作好的交叉編譯器,交叉編譯之前寫好的 hello.c 測試程式,並放到 ARM 開發板上執行測試。需要注意的是因為新制作的交叉編譯器跟開發板上執行的C執行庫版本不一致,這裡必須加上 -
static 進行靜態連結,這樣編譯生成的程式才能在開發板上執行。

i.MX6ULL開發板原始碼自制交叉編譯器

ARM 開發板上下載執行測試:

i.MX6ULL開發板原始碼自制交叉編譯器

版權宣告                                            

本文件所有內容文字資料由凌雲實驗室郭工編著,主要用於凌雲嵌入式Linux教學內部使用,版權歸屬 作者個人所有。任何媒體、網站、或個人未經本人協議授權不得轉載、連結、轉帖或以其他方式複製釋出/發表。已經授權的媒體、網站,在下載使用時必須註明來源,違者本人將依法追究責任。
Copyright (C)2021 凌雲物網智科實驗室·郭工
Author: GuoWenxue guowenxue@gmail.com


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70009145/viewspace-2849529/,如需轉載,請註明出處,否則將追究法律責任。

相關文章