對於沒有作過嵌入式編程的人,可能不太理解交叉編譯的概念,那麼什麼是交叉編譯?它有什麼做用?html
在解釋什麼是交叉編譯以前,先要明白什麼是本地編譯。linux
本地編譯c++
本地編譯能夠理解爲,在當前編譯平臺下,編譯出來的程序只能放到當前平臺下運行。平時咱們常見的軟件開發,都是屬於本地編譯:git
好比,咱們在 x86 平臺上,編寫程序並編譯成可執行程序。這種方式下,咱們使用 x86 平臺上的工具,開發針對 x86 平臺自己的可執行程序,這個編譯過程稱爲本地編譯。github
交叉編譯編程
交叉編譯能夠理解爲,在當前編譯平臺下,編譯出來的程序能運行在體系結構不一樣的另外一種目標平臺上,可是編譯平臺自己卻不能運行該程序:api
好比,咱們在 x86 平臺上,編寫程序並編譯成能運行在 ARM 平臺的程序,編譯獲得的程序在 x86 平臺上是不能運行的,必須放到 ARM 平臺上才能運行。架構
之因此要有交叉編譯,主要緣由是:函數
Speed: 目標平臺的運行速度每每比主機慢得多,許多專用的嵌入式硬件被設計爲低成本和低功耗,沒有過高的性能工具
Capability: 整個編譯過程是很是消耗資源的,嵌入式系統每每沒有足夠的內存或磁盤空間
Availability: 即便目標平臺資源很充足,能夠本地編譯,可是第一個在目標平臺上運行的本地編譯器總須要經過交叉編譯得到
Flexibility: 一個完整的Linux編譯環境須要不少支持包,交叉編譯使咱們不須要花時間將各類支持包移植到目標板上
交叉編譯的困難點在於兩個方面:
不一樣的體系架構擁有不一樣的機器特性
Word size: 是64位仍是32位系統
Endianness: 是大端仍是小端系統
Alignment: 是否必修按照4字節對齊方式進行訪問
Default signedness: 默認數據類型是有符號仍是無符號
NOMMU: 是否支持MMU
交叉編譯時的主機環境與目標環境不一樣
Configuration issues:
HOSTCC vs TARGETCC:
Toolchain Leaks:
Libraries:
Testing:
詳細的對比能夠參看這篇文章,已經寫的很詳細了,在這就不細說了:Introduction to cross-compiling for Linux
明白了什麼是交叉編譯,那咱們來看看什麼是交叉編譯鏈。
首先編譯過程是按照不一樣的子功能,依照前後順序組成的一個複雜的流程,以下圖:
編譯流程
那麼編譯過程包括了預處理、編譯、彙編、連接等功能。既然有不一樣的子功能,那每一個子功能都是一個單獨的工具來實現,它們合在一塊兒造成了一個完整的工具集。
同時編譯過程又是一個有前後順序的流程,它必然牽涉到工具的使用順序,每一個工具按照前後關係串聯在一塊兒,這就造成了一個鏈式結構。
所以,交叉編譯鏈就是爲了編譯跨平臺體系結構的程序代碼而造成的由多個子工具構成的一套完整的工具集。同時,它隱藏了預處理、編譯、彙編、連接等細節,當咱們指定了源文件(.c)時,它會自動按照編譯流程調用不一樣的子工具,自動生成最終的二進制程序映像(.bin)。
PS:objcopy被用來複制一個目標文件的內容到另外一個文件中,可使用不一樣於源文件的格式來輸出目的文件,便可以進行格式轉換。objdump用於顯示二進制文件信息,經常使用來查看反彙編代碼。
注意:嚴格意義上來講,交叉編譯器,只是指交叉編譯的gcc,可是實際上爲了方便,咱們常說的交叉編譯器就是交叉工具鏈。本文對這兩個概念不加以區分,都是指編譯鏈。
咱們使用交叉編譯鏈時,經常會看到這樣的名字:
arm-none-linux-gnueabi-gcc
arm-cortex_a8-linux-gnueabi-gcc
mips-malta-linux-gnu-gcc
其中,對應的前綴爲:
arm-none-linux-gnueabi-
arm-cortex_a8-linux-gnueabi-
mips-malta-linux-gnu-
這些交叉編譯鏈的命名規則彷佛是通用的,有必定的規則:
arch-core-kernel-system
arch: 用於哪一個目標平臺。
core: 使用的是哪一個CPU Core,如Cortex A8,可是這一組命名好像比較靈活,在其它廠家提供的交叉編譯鏈中,有以廠家名稱命名的,也有以開發板命名的,或者直接是none或cross的。
kernel:所運行的OS,見過的有Linux,uclinux,bare(無OS)。
system:交叉編譯鏈所選擇的庫函數和目標映像的規範,如gnu,gnueabi等。其中gnu等價於glibc+oabi;gnueabi等價於glibc+eabi。
注意:這個規則是一個猜想,並無在哪份官方資料上看到過。並且有些編譯鏈的命名確實沒有按照這個規則,也不清楚這是否是歷史緣由形成的。若是有誰在資料上見到過此規則的詳細描述,歡迎指出錯誤。
Binutils是GNU工具之一,它包括連接器、彙編器和其餘用於目標文件和檔案的工具,它是二進制代碼的處理維護工具。
Binutils工具包含的子程序以下:
ld GNU鏈接器the GNU linker.
as GNU彙編器the GNU assembler.
addr2line 把地址轉換成文件名和所在的行數
ar A utility for creating, modifying and extracting from archives.
c++filt Filter to demangle encoded C++ symbols.
dlltool Creates files for building and using DLLs.
gold A new, faster, ELF only linker, still in beta test.
gprof Displays profiling information.
nlmconv Converts object code into an NLM.
nm Lists symbols from object files.
objcopy Copys and translates object files.
objdump Displays information from object files.
ranlib Generates an index to the contents of an archive.
readelf Displays information from any ELF format object file.
size Lists the section sizes of an object or archive file.
strings Lists printable strings from files.
strip Discards symbols
GNU編譯器套件,支持C, C++, Java, Ada, Fortran, Objective-C等衆多語言。
Linux上一般使用的C函數庫爲glibc。glibc是linux系統中最底層的api,幾乎其它任何運行庫都會依賴於glibc。glibc除了封裝linux操做系統所提供的系統服務外,它自己也提供了許多其它一些必要功能服務的實現。
由於嵌入式環境的資源及其緊張,因此如今除了glibc外,還有uClibc和eglibc能夠選擇,三者的關係能夠參見這兩篇文章:
GDB用於調試程序
既然明白了交叉編譯鏈的功能,那麼在針對嵌入式系統開發時,咱們須要的交叉編譯鏈從哪兒獲得?
主要有三個方式能夠獲取
使用其餘人針對某些CPU平臺已經編譯好的交叉編譯鏈。咱們只須要找到合適的,下載下來使用便可。
常見的交叉編譯鏈下載地址:
在 http://ftp.arm.linux.org.uk/pub/armlinux/toolchain/下載已經編譯好的交叉編譯鏈
在 http://www.denx.de/en/Software/WebHome下載已經編譯好的交叉編譯鏈
在https://launchpad.net/gcc-arm-embedded下載已經編譯好的交叉編譯鏈
一些製做交叉編譯鏈的工具中,包含了已經制做好的交叉編譯鏈,能夠直接拿來使用。如crosstool-NG。
若是購買了某個芯片或開發板,通常廠商會提供對應的整套開發軟件,其中就包含了交叉編譯鏈。
廠家提供的工具通常是通過了嚴格的測試,並打入了一些必要的補丁,因此這種方式每每是最可靠的工具來源。
使用現存的製做工具,以簡化製做交叉編譯鏈這個事情的複雜度。咱們只須要了解有哪些工具能夠實現,並選個合適的工具,搞懂它的操做步驟便可。
工具還有不少,各有各的優點和劣勢,你們能夠慢慢研究,在這就不細說了。
這個是最困難也最耗時間的,畢竟製做交叉編譯鏈這樣的事情,須要對嵌入式的編譯原理了解的比較透徹,至少要知道出了問題要往哪一個方面去翻閱資料。並且,也是最考耐心和細心的地方,配錯一個選項或是一個步驟,均可能出現之前歷來沒見過的問題,並且這些問題每每還沒法和這個選項或步驟直接聯繫起來。
固然若是搭建出來,確定也是收穫最大的,至少對於編譯的流程和依賴都比較清楚了,細節上的東西可能還須要去翻看相應的協議或標準,但至少骨架會比較清楚。
詳細的搭建過程能夠參看後續的文章,這裏面有詳細的參數和步驟:
爲了方便你們搭建交叉編譯鏈,我寫了一個一鍵生成的腳本(包括源碼下載和自動編譯)。若是你們本身一直搭建不成功,不妨試試這個腳本,而後對比下本身的流程是否一致,參數是否有差別,也許能幫你們邁過這個障礙:
[1] Introduction to cross-compiling for Linux
[2] binutils介紹
[3] glibc 各個庫做用介紹
[4] uclibc eglibc glibc之間的區別和聯繫
[5] Glibc vs uClibc Differences
[6] 用crosstool-ng創建本身的ARM交叉編譯工具鏈
[7] 交叉編譯鏈下載地址