海南澄邁網(wǎng)站建設(shè)寧波免費(fèi)建站seo排名
寫(xiě)在前面:
本文章旨在總結(jié)備份、方便以后查詢(xún),由于是個(gè)人總結(jié),如有不對(duì),歡迎指正;另外,內(nèi)容大部分來(lái)自網(wǎng)絡(luò)、書(shū)籍、和各類(lèi)手冊(cè),如若侵權(quán)請(qǐng)告知,馬上刪帖致歉。
目錄
- GCC 簡(jiǎn)述
- GCC 主要構(gòu)成
- ARM 編譯工具鏈
- 基于 GCC 的 ARM 編譯工具鏈提供商
- Arm GNU Toolchain
- Linaro Toolchain
- Reference
GCC 簡(jiǎn)述
The GNU Compiler Collection,通常簡(jiǎn)稱(chēng) GCC ,是一套由 GNU 開(kāi)發(fā)的編譯器集合。
為什么是編輯器集合而不是編譯器呢?
那是因?yàn)?GNU 編譯器集合包括 C、C++、Objective-C,Fortran,Ada、Go 和 D 等,以及這些語(yǔ)言的庫(kù) (libstdc++,…)。 GCC 最初是作為 GNU 操作系統(tǒng)的編譯器編寫(xiě)的。 GNU 系統(tǒng)被開(kāi)發(fā)為 100% 的自由軟件 ,即從某種意義上說(shuō)它是自由的,尊重用戶(hù)的自由。另外 GCC 對(duì)硬件平臺(tái)的支持,可以說(shuō)無(wú)所不在,它不僅支持 x86 處理器架構(gòu), 還支持 ARM, Motorola 68000, Motorola 8800,AtmelAVR,MIPS 等處理器架構(gòu)。
GCC 主要構(gòu)成
- gcc-core:顧明之意是 GCC 的核心部分,這部分是只包含 c 的編譯器及公共部分,而對(duì)其他語(yǔ)言(C++、Ada 等)的支持包需要另外安裝,這也是 GCC 為何如此強(qiáng)大的重要原因 。gcc-core 依賴(lài)于 Binutils。
- Binutils:它是一組開(kāi)發(fā)工具,包括連接器,匯編器和其他用于目標(biāo)文件和檔案的工具。關(guān)于 Binutils 的介紹可以參考官方的 Binutils 介紹。這個(gè)軟件包依賴(lài)于不同的目標(biāo)機(jī)平臺(tái),因?yàn)椴煌繕?biāo)機(jī)的指令集是不一樣的,比如 arm 跟 x86 就不一樣。
常用的工具有:- as:匯編器,把匯編語(yǔ)言代碼轉(zhuǎn)換為機(jī)器碼(目標(biāo)文件)。
- ld:鏈接器,把編譯生成的多個(gè)目標(biāo)文件組織成最終的可執(zhí)行程序文件。
- readelf:可用于查看目標(biāo)文件或可執(zhí)行程序文件的信息。
- objcopy: 可用于目標(biāo)文件格式轉(zhuǎn)換,如
.elf
轉(zhuǎn)換成.bin
。 - objdump:可用于查看目標(biāo)文件的信息,最主要的作用是反匯編。
- addr2line:可用于將程序指令地址轉(zhuǎn)換為所對(duì)應(yīng)的函數(shù)名、以及函數(shù)所在的源文件名和行號(hào)。
- Glibc:包含了主要的 c 庫(kù),這個(gè)庫(kù)提供了基本的例程,用于分配內(nèi)存,搜索目錄,讀寫(xiě)文件,字符串處理等等。
ARM 編譯工具鏈
編譯器主要用來(lái)編譯源文件,而在編譯一個(gè)源文件時(shí)需要經(jīng)過(guò)以下 4 步:
- 預(yù)處理:為把頭文件的代碼、宏之類(lèi)的內(nèi)容轉(zhuǎn)換成生成的
.i
文件,還是 C 代碼。 - 編譯:把預(yù)處理后的
.i
文件通過(guò)編譯成.s
文件,匯編語(yǔ)言。 - 匯編:將匯編語(yǔ)言文件生成目標(biāo)文件
.o
文件,機(jī)器碼。 - 鏈接:將每個(gè)源文件對(duì)應(yīng)的
.o
文件鏈接起來(lái),就生成一個(gè)可執(zhí)行程序文件。
交叉編譯器:如果我們希望編譯器運(yùn)行在 x86 架構(gòu)平臺(tái)上,然后編譯生成 ARM 架構(gòu)的可執(zhí)行程序,這種編譯器和目標(biāo)程序運(yùn)行在不同架構(gòu)的編譯過(guò)程,被稱(chēng)為 “交叉編譯”,而對(duì)應(yīng)使用的編譯工具就成為交叉編譯器。
GNU 交叉編譯器的命名規(guī)則:
arch [-vendor] [-os] [-(gnu)abi] [-language]
- arch:體系架構(gòu),如
arm
、aarch64
或者mips
等; - vendor:工具鏈提供商,沒(méi)有 vendor 時(shí),用
none
代替; - os:目標(biāo)操作系統(tǒng),沒(méi)有 os 支持時(shí),用
none
代替; - abi:應(yīng)用二進(jìn)制接口(Application Binary Interface),對(duì)于嵌入式平臺(tái)命名為
eabi
,e
表示 Embedded; - language:編譯器支持的語(yǔ)言,如:
gcc
、g++
。
note:如果同時(shí)沒(méi)有 vendor 和 os 支持,則只用一個(gè) none 代替。例如 arm-none-eabi 中的 none 表示既沒(méi)有 vendor 也沒(méi)有 os 支持。
關(guān)于 ABI 和 EABI 的區(qū)別
ABI:應(yīng)用二進(jìn)制接口(Application Binary Interface)。在計(jì)算機(jī)中,應(yīng)用二進(jìn)制接口描述了應(yīng)用程序(或者其他類(lèi)型)和操作系統(tǒng)之間或其他應(yīng)用程序的低級(jí)接口。
EABI:嵌入式應(yīng)用二進(jìn)制接口(Embedded Application Binary Interface)。嵌入式應(yīng)用二進(jìn)制接口指定了文件格式、數(shù)據(jù)類(lèi)型、寄存器使用、堆積組織優(yōu)化和在一個(gè)嵌入式軟件中的參數(shù)的標(biāo)準(zhǔn)約定。開(kāi)發(fā)者使用自己的匯編語(yǔ)言也可以使用 EABI 作為與兼容的編譯器生成的匯編語(yǔ)言的接口。
兩者主要區(qū)別是:ABI 是計(jì)算機(jī)上的,EABI 是嵌入式平臺(tái)上(如 ARM,MIPS 等)的;EABI 去掉了用戶(hù)代碼和系統(tǒng)內(nèi)核之間的抽象,可以讓用戶(hù)代碼直接訪(fǎng)問(wèn)硬件,提高了性能。
關(guān)于 gcc 和 g++ 的區(qū)別
實(shí)際上,只要是 gcc 編譯器支持的語(yǔ)言都可以使用 gcc 編譯器完成編譯,而 g++ 編譯器只會(huì)按照 C++ 的風(fēng)格編譯代碼。雖然很多情況下我們都認(rèn)為 C++ 是對(duì) C 語(yǔ)言兼容的,但是實(shí)際上在一些具體的語(yǔ)法規(guī)則上,C++ 在編譯過(guò)程中的語(yǔ)法檢查會(huì)更加嚴(yán)格。此外,C++ 語(yǔ)言本身在編譯 過(guò)程中也會(huì)引入 C++ 的標(biāo)準(zhǔn)庫(kù),如果使用 gcc 編譯器直接編譯 C++ 語(yǔ)言會(huì)在編譯過(guò)程中添加額外的參數(shù),這樣會(huì)顯得編譯過(guò)程較為繁瑣(因?yàn)榇蟛糠智闆r下我們希望標(biāo)準(zhǔn)庫(kù)可以直接引入,而不是再需要手動(dòng)指定,否則對(duì)于初級(jí)使用者會(huì)帶來(lái)額外的學(xué)習(xí)負(fù)擔(dān))。為了更方便使用編譯器,我們選擇 g++ 來(lái)編譯 C++ 代碼??偨Y(jié)一下,gcc 可以完成 C++ 語(yǔ)言的編譯,但是使用過(guò)程會(huì)較為繁瑣,而 g++ 就是簡(jiǎn)化后的編譯指令。
與 gnueabi 相關(guān)的 gnueabi 和 gnueabihf 的區(qū)別
gcc-arm-linux-gnueabi – The GNU C compiler for armel architecture
AND
gcc-arm-linux-gnueabihf – The GNU C compiler for armhf architecture
這兩個(gè)交叉編譯器分別適用于 armel 和 armhf 兩個(gè)不同的架構(gòu),armel 和 armhf 這兩種架構(gòu)在對(duì)待浮點(diǎn)運(yùn)算采取了不同的策略(有 fpu 的 ARM 才能支持這兩種浮點(diǎn)運(yùn)算策略)。
這兩個(gè)交叉編譯器是 gcc 的選項(xiàng) -mfloat-abi
的默認(rèn)值不同;該選項(xiàng)有三種值 soft、softfp、hard(其中后兩者都要求 ARM 里有 fpu 浮點(diǎn)運(yùn)算單元,soft 與后兩者是兼容的,但 softfp 和 hard 兩種模式互不兼容):
-
soft: 不用 fpu 進(jìn)行浮點(diǎn)計(jì)算,即使有 fpu 浮點(diǎn)運(yùn)算單元也不用,而是使用軟件模式。
-
softfp: armel 架構(gòu)(對(duì)應(yīng)的編譯器為 arm-linux-gnueabi-gcc )采用的默認(rèn)值,用 fpu 計(jì)算,但是傳參數(shù)用普通寄存器傳,這樣中斷的時(shí)候,只需要保存普通寄存器,中斷負(fù)荷小,但是參數(shù)需要轉(zhuǎn)換成浮點(diǎn)的再計(jì)算。
-
hard: armhf架構(gòu)(對(duì)應(yīng)的編譯器 arm-linux-gnueabihf-gcc )采用的默認(rèn)值,用 fpu 計(jì)算,傳參數(shù)也用 fpu 中的浮點(diǎn)寄存器傳,省去了轉(zhuǎn)換,性能最好,但是中斷負(fù)荷高。
幾種常見(jiàn)的編譯 ARM 的交叉編譯器:
arm-none-eabi:用于編譯裸機(jī)程序或系統(tǒng),這個(gè)是沒(méi)有操作系統(tǒng)的,不支持那些系統(tǒng)調(diào)用等系列接口,可調(diào)用 newlib
庫(kù),適用于 ARM7/Cortex-M/Cortex-R。
arm-none-linux-gnueabi:用于編譯 ARM 架構(gòu)的 u-boot、Linux 內(nèi)核、Linux 應(yīng)用等,使用 glibc
庫(kù),適用于 ARM9/ARM11/Cortex-A。
arm-eabi: 用于安卓程序編譯。
armcc:早期 Keil 軟件公司(現(xiàn)已被 ARM 公司收購(gòu))出品的支持相應(yīng)器件的編譯工具,可以編譯裸機(jī)程序,一般和 ARM 開(kāi)發(fā)工具一起,Keil MDK 內(nèi)置。
基于 GCC 的 ARM 編譯工具鏈提供商
目前,為 ARM 平臺(tái)提供交叉編譯工具鏈的提供商,本人所找到的只有兩家:ARM 官方和 Linaro 公司。
Arm GNU Toolchain
ARM 除了有自己的專(zhuān)用編譯器之外,還維護(hù)了一套基于 GCC 的交叉編譯工具鏈,被稱(chēng)為 Arm GNU Toolchain。截至于 2022 年,Arm GNU Toolchain 被分為了 A family(GNU Toolchain for the Cortex-A Family) 和 R & M family(GNU Arm Embedded Toolchain)兩大類(lèi),但是自 2022 年開(kāi)始,ARM 對(duì)其進(jìn)行了統(tǒng)一。
Linaro Toolchain
Linaro 是一間非營(yíng)利性質(zhì)的開(kāi)放源代碼軟件工程公司,主要的目標(biāo)在于開(kāi)發(fā)不同半導(dǎo)體公司系統(tǒng)單片機(jī)(SoC)平臺(tái)的共通軟件。其維護(hù)的工具鏈下載地址為:https://snapshots.linaro.org/gnu-toolchain/ 。另外,從 https://www.linaro.org/downloads/ 的描述上看,目前 Linaro 僅針對(duì)于 Cortex-A 內(nèi)核的編譯工具鏈進(jìn)行維護(hù),而對(duì)用于 ARM 嵌入式處理器的 Cortex-R 和 Cortex-M 裸機(jī)編譯工具鏈,則需要去 ARM 官網(wǎng)下載!
Reference
https://www.cnblogs.com/xiaotlili/p/3306100.html
https://blog.csdn.net/ZCShouCSDN/article/details/89553323