搬運自本人 CSDN 博客:https://blog.csdn.net/ajianyingxiaoqinghan/article/details/70917569
交叉編譯學習筆記(一)——交叉編譯和交叉工具鏈
最近看論文看的煩,又重新拾起之前沒有完全完成的交叉編譯,準備在網上找資料,好好研究一下。
參考鏈接:
http://blog.csdn.net/zqixiao_09/article/details/51822943
http://blog.csdn.net/shenjianxz/article/details/52130111
http://www.crifan.com/files/doc/docbook/binutils_intro/release/html/binutils_intro.html
一. 交叉編譯
了解交叉編譯之前,首先要介紹本地編譯,才能進一步對比本地編譯與交叉編譯的區別。
1. 本地編譯
我們之前常見的軟件開發,都是屬于本地編譯:在當前的PC下,x86的CPU下,直接編譯出來程序,可以運行的程序(或者庫文件),其可以直接在當前的環境,即x86的CPU下,當前電腦中,運行。
此時的編譯叫做<font color=#ff0000>本地編譯</font>,即編譯出來的程序是由當前目標平臺編譯出的,且只是放到當前平臺下運行。
2. 交叉編譯
交叉編譯是和本地編譯相對應的概念。交叉編譯是指在當前平臺下編譯出在<font color=#ff0000>其他平臺下運行的程序</font>,即編譯出來的程序運行環境與編譯它的環境不一樣,所以稱為交叉編譯(Cross Compile)。
3. 交叉編譯的意義
交叉編譯的概念一般用于嵌入式系統開發。
使用交叉編譯的主要原因,是嵌入式系統中<font color=#ff0000>配置較低,資源過少</font>,遠不及PC的編譯效率。
以筆者為例,筆者的畢業設計是把在ARM上運行一個搭建一個小型監控系統,所以就需要在ARM上配置OpenCV。一方面,筆者的ARM是Cortex-A9的四核1.0GHz的芯片(且已經算比較高的配置),但編譯速度依舊遠遠不如筆者的PC機(i7處理器,8核3.6GHz)。如果在ARM上編譯OpenCV,編譯過程中生成的中間文件可能大于ARM存儲容量不說,且編譯速度也遠不如本地編譯。另一方面,PC機的CPU架構是x86型的,ARM的CPU架構是ARM型的,所以這時候就需要用交叉編譯器(此處即為ARM的編譯器)編譯程序代碼,然后移植到ARM平臺運行。所以這就是交叉編譯的意義所在。
二. 交叉工具鏈
工具鏈可以被拆分為兩部分:工具、鏈。下面分別對其進行解釋:
1. 工具
工具就是用來工作的。此處工作的目的是為了<font color=#ff0000>生成庫文件或(可運行)程序</font>。
此處為了將程序代碼編譯成可執行文件,中間涉及到了編譯、鏈接等其他步驟,過程中依賴很多相關工具,其中最核心的便是編譯器(如gcc)、鏈接器(ld)。此處所謂的工具,就是gcc,ld等與程序編譯、鏈接等操作相關的工具。
達成此目標的工作流程中主要包含了<font color=#ff0000>編譯</font>、<font color=#ff0000>鏈接</font>兩個步驟。
(1) 編譯
- 輸入對象:程序源碼
- 輸出目標:目標文件
- 工具:編譯器
- 常見編譯器:PC上的gcc,ARM上的arm-linux-gcc
(2) 鏈接
- 輸入對象:庫文件(程序運行時依賴的庫文件,或者是某個庫所依賴的另外一個庫文件)
- 輸出目標:
- 程序的可執行文件
- 可被其他可執行文件/庫文件調用的庫文件
- 工具:鏈接器(ld)
這里有一個不得不提的二進制工具集——GNU Binutils。
GNU Binutils,即GNU Binary Utilities的簡寫,是一組二進制工具的集合。主要包含的工具有:
- ld:鏈接器,將多個目標文件鏈接成一個可執行文件/目標庫文件
- as:匯編器,將匯編源代碼編譯為機器代碼
- ranlib:對靜態庫的符號索引表進行更新
- addr2line:將地址轉換為行號(一般用于反匯編)
- ar:用來操作.a檔案文件,如創建、修改、提取內容等
- nm:列出目標文件中的符號
- objcopy:拷貝并轉換文件,可用于不同格式的二進制文件轉換
- objdump:顯示目標文件中的信息
- readelf:顯示ELF格式的目標文件信息
- size:顯示目標文件或檔案文件的節(section)大小
- strings:顯示文件中可打印字符串信息
其中最重要的工具是ld, as。
關于編譯、鏈接,筆者也寫過一篇簡析:《程序生成之編譯、鏈接、加載淺析》,關于編譯與鏈接的內容可查閱該博客。
2. 鏈
鏈(chain)的意義在于,按照對應的邏輯,將多個工具串聯在一起。
工具,即為前面說到的與程序編譯、鏈接相關的gcc等工具;對應的邏輯,指程序本身編譯鏈接的先后順序。即先編譯,后鏈接,最后進行其他后期處理(如用objcopy操作相應目標文件等)。
如此將程序編譯鏈接相關工具,按照先編譯后鏈接的內在編譯邏輯串起來,就成了我們所謂的工具鏈。
3. 交叉工具鏈
一般所說的工具鏈,指的是本地平臺自己的工具鏈。而用于交叉編譯的工具鏈,就是交叉工具鏈。交叉工具鏈中,gcc編譯器、ld鏈接器以及其他的相關工具,都是用來跨平臺交叉編譯的。
交叉工具鏈與本地工具鏈類似,也有交叉編譯版本的gcc, ld, as等工具,與本地工具鏈兩兩對應。交叉工具鏈中最重要的工具還是編譯器gcc,所以我們也經常把交叉工具鏈簡稱為交叉編譯器,即嚴格意義上來講,交叉編譯器指的是交叉編譯版本的gcc,但為了叫法上的方便,我們平常說的交叉編譯,其實指的都是交叉工具鏈。
例如常用的交叉編譯器arm-linux-gcc,其實是一系列交叉編譯版本的交叉工具鏈,其中包含了arm-linux-gcc, arm-linux-ld, arm-linux-as等工具。
總結:
交叉編譯,就是在一種平臺上編譯出能運行在體系結構不同的另一種平臺上的程序。例如在x86平臺下交叉編譯出了ARM平臺上的程序,雖然兩個平臺用的都是Linux系統,但編譯得到的程序只能在ARM平臺下運行,x86平臺下不可運行。