GCC 编译器套件说明
Posted 夏沫の浅雨
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GCC 编译器套件说明相关的知识,希望对你有一定的参考价值。
写在前面:
本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。
目录
GCC 简述
The GNU Compiler Collection,通常简称 GCC ,是一套由 GNU 开发的编译器集合。
为什么是编辑器集合而不是编译器呢?
那是因为 GNU 编译器集合包括 C、C++、Objective-C,Fortran,Ada、Go 和 D 等,以及这些语言的库 (libstdc++,…)。 GCC 最初是作为 GNU 操作系统的编译器编写的。 GNU 系统被开发为 100% 的自由软件 ,即从某种意义上说它是自由的,尊重用户的自由。另外 GCC 对硬件平台的支持,可以说无所不在,它不仅支持 x86 处理器架构, 还支持 ARM, Motorola 68000, Motorola 8800,AtmelAVR,MIPS 等处理器架构。
GCC 主要构成
- gcc-core:顾明之意是 GCC 的核心部分,这部分是只包含 c 的编译器及公共部分,而对其他语言(C++、Ada 等)的支持包需要另外安装,这也是 GCC 为何如此强大的重要原因 。gcc-core 依赖于 Binutils。
- Binutils:它是一组开发工具,包括连接器,汇编器和其他用于目标文件和档案的工具。关于 Binutils 的介绍可以参考官方的 Binutils 介绍。这个软件包依赖于不同的目标机平台,因为不同目标机的指令集是不一样的,比如 arm 跟 x86 就不一样。
常用的工具有:- as:汇编器,把汇编语言代码转换为机器码(目标文件)。
- ld:链接器,把编译生成的多个目标文件组织成最终的可执行程序文件。
- readelf:可用于查看目标文件或可执行程序文件的信息。
- objcopy: 可用于目标文件格式转换,如
.elf
转换成.bin
。 - objdump:可用于查看目标文件的信息,最主要的作用是反汇编。
- addr2line:可用于将程序指令地址转换为所对应的函数名、以及函数所在的源文件名和行号。
- Glibc:包含了主要的 c 库,这个库提供了基本的例程,用于分配内存,搜索目录,读写文件,字符串处理等等。
ARM 编译工具链
编译器主要用来编译源文件,而在编译一个源文件时需要经过以下 4 步:
- 预处理:为把头文件的代码、宏之类的内容转换成生成的
.i
文件,还是 C 代码。 - 编译:把预处理后的
.i
文件通过编译成.s
文件,汇编语言。 - 汇编:将汇编语言文件生成目标文件
.o
文件,机器码。 - 链接:将每个源文件对应的
.o
文件链接起来,就生成一个可执行程序文件。
交叉编译器:如果我们希望编译器运行在 x86 架构平台上,然后编译生成 ARM 架构的可执行程序,这种编译器和目标程序运行在不同架构的编译过程,被称为 “交叉编译”,而对应使用的编译工具就成为交叉编译器。
GNU 交叉编译器的命名规则:
arch [-vendor] [-os] [-(gnu)abi] [-language]
- arch:体系架构,如
arm
、aarch64
或者mips
等; - vendor:工具链提供商,没有 vendor 时,用
none
代替; - os:目标操作系统,没有 os 支持时,用
none
代替; - abi:应用二进制接口(Application Binary Interface),对于嵌入式平台命名为
eabi
,e
表示 Embedded; - language:编译器支持的语言,如:
gcc
、g++
。
note:如果同时没有 vendor 和 os 支持,则只用一个 none 代替。例如 arm-none-eabi 中的 none 表示既没有 vendor 也没有 os 支持。
关于 ABI 和 EABI 的区别
ABI:应用二进制接口(Application Binary Interface)。在计算机中,应用二进制接口描述了应用程序(或者其他类型)和操作系统之间或其他应用程序的低级接口。
EABI:嵌入式应用二进制接口(Embedded Application Binary Interface)。嵌入式应用二进制接口指定了文件格式、数据类型、寄存器使用、堆积组织优化和在一个嵌入式软件中的参数的标准约定。开发者使用自己的汇编语言也可以使用 EABI 作为与兼容的编译器生成的汇编语言的接口。
两者主要区别是:ABI 是计算机上的,EABI 是嵌入式平台上(如 ARM,MIPS 等)的;EABI 去掉了用户代码和系统内核之间的抽象,可以让用户代码直接访问硬件,提高了性能。
关于 gcc 和 g++ 的区别
实际上,只要是 gcc 编译器支持的语言都可以使用 gcc 编译器完成编译,而 g++ 编译器只会按照 C++ 的风格编译代码。虽然很多情况下我们都认为 C++ 是对 C 语言兼容的,但是实际上在一些具体的语法规则上,C++ 在编译过程中的语法检查会更加严格。此外,C++ 语言本身在编译 过程中也会引入 C++ 的标准库,如果使用 gcc 编译器直接编译 C++ 语言会在编译过程中添加额外的参数,这样会显得编译过程较为繁琐(因为大部分情况下我们希望标准库可以直接引入,而不是再需要手动指定,否则对于初级使用者会带来额外的学习负担)。为了更方便使用编译器,我们选择 g++ 来编译 C++ 代码。总结一下,gcc 可以完成 C++ 语言的编译,但是使用过程会较为繁琐,而 g++ 就是简化后的编译指令。
与 gnueabi 相关的 gnueabi 和 gnueabihf 的区别
gcc-arm-linux-gnueabi – The GNU C compiler for armel architecture
AND
gcc-arm-linux-gnueabihf – The GNU C compiler for armhf architecture
这两个交叉编译器分别适用于 armel 和 armhf 两个不同的架构,armel 和 armhf 这两种架构在对待浮点运算采取了不同的策略(有 fpu 的 ARM 才能支持这两种浮点运算策略)。
这两个交叉编译器是 gcc 的选项 -mfloat-abi
的默认值不同;该选项有三种值 soft、softfp、hard(其中后两者都要求 ARM 里有 fpu 浮点运算单元,soft 与后两者是兼容的,但 softfp 和 hard 两种模式互不兼容):
-
soft: 不用 fpu 进行浮点计算,即使有 fpu 浮点运算单元也不用,而是使用软件模式。
-
softfp: armel 架构(对应的编译器为 arm-linux-gnueabi-gcc )采用的默认值,用 fpu 计算,但是传参数用普通寄存器传,这样中断的时候,只需要保存普通寄存器,中断负荷小,但是参数需要转换成浮点的再计算。
-
hard: armhf架构(对应的编译器 arm-linux-gnueabihf-gcc )采用的默认值,用 fpu 计算,传参数也用 fpu 中的浮点寄存器传,省去了转换,性能最好,但是中断负荷高。
几种常见的编译 ARM 的交叉编译器:
arm-none-eabi:用于编译裸机程序或系统,这个是没有操作系统的,不支持那些系统调用等系列接口,可调用 newlib
库,适用于 ARM7/Cortex-M/Cortex-R。
arm-none-linux-gnueabi:用于编译 ARM 架构的 u-boot、Linux 内核、Linux 应用等,使用 glibc
库,适用于 ARM9/ARM11/Cortex-A。
arm-eabi: 用于安卓程序编译。
armcc:早期 Keil 软件公司(现已被 ARM 公司收购)出品的支持相应器件的编译工具,可以编译裸机程序,一般和 ARM 开发工具一起,Keil MDK 内置。
基于 GCC 的 ARM 编译工具链提供商
目前,为 ARM 平台提供交叉编译工具链的提供商,本人所找到的只有两家:ARM 官方和 Linaro 公司。
Arm GNU Toolchain
ARM 除了有自己的专用编译器之外,还维护了一套基于 GCC 的交叉编译工具链,被称为 Arm GNU Toolchain。截至于 2022 年,Arm GNU Toolchain 被分为了 A family(GNU Toolchain for the Cortex-A Family) 和 R & M family(GNU Arm Embedded Toolchain)两大类,但是自 2022 年开始,ARM 对其进行了统一。
Linaro Toolchain
Linaro 是一间非营利性质的开放源代码软件工程公司,主要的目标在于开发不同半导体公司系统单片机(SoC)平台的共通软件。其维护的工具链下载地址为:https://snapshots.linaro.org/gnu-toolchain/ 。另外,从 https://www.linaro.org/downloads/ 的描述上看,目前 Linaro 仅针对于 Cortex-A 内核的编译工具链进行维护,而对用于 ARM 嵌入式处理器的 Cortex-R 和 Cortex-M 裸机编译工具链,则需要去 ARM 官网下载!
Reference
https://www.cnblogs.com/xiaotlili/p/3306100.html
https://blog.csdn.net/ZCShouCSDN/article/details/89553323
以上是关于GCC 编译器套件说明的主要内容,如果未能解决你的问题,请参考以下文章
17.3 构建LinuxPC端QT软件上的ARM编译套件并进行测试
cygwin 中如何安装arm-linux-gcc交叉编译器
arm-linux-gcc 常用参数讲解 gcc编译器使用方法