GCC交叉编译器的命名与用法

本文内容,分别在Ubuntu 14.04/18.04使用arm-none-eabi-gcc 4.8.2/6.3.1、arm-linux-gnueabi[hf]-gcc 4.8.4/7.4.0、aarch64-linux-gnu-gcc 4.8.4/7.4.0、arm-linux-androideabi-gcc 4.7.3/4.8验证过。

在Android或是嵌入式开发时,常常会用到交叉编译器,这些编译器的命名有arm-linux-androideabi-gcc,arm-eabi-gcc,在Ubuntu上,也有gcc-arm-linux-gnueabihf、gcc-arm-linux-gnueabi、gcc-arm-none-eabi这些包可供安装,那么,这些不同名字的编译器有什么区别,用在什么场景?这就是本文要说明的。

命名规则

一般来讲,gcc交叉编译器的命名有这几部分组成[arch-][vendor-][os-][eabi-]name,其中:

  • arch:指体系结构,例如arm、x86_64、aarch64。

  • vendor:指工具链提供商。

  • os:指目标操作系统,如果这一部分没有或者为none,则是为编译bootloader这种不依赖操作系统接口的软件制作的,经常可以看到的是linux,即编译器可用来生成运行在Linux系统上的程序。

  • eabi:全称为Embedded Application Binary Interface(应用二进制接口),定义了数据类型大小、布局和对齐、文件格式、调用约定等一系列底层接口,使用某一EABI编译好的目标代码在兼容这一EABI的系统中无需改动即可运行,一般来讲,这个也代表了使用的C库是什么。

    这一部分可能还会出现hf后缀,用来指定浮点数二进制接口,实际影响到的是gcc的-mfloat-abi选项默认值。-mfloat-abi有三种值,soft表示浮点运算不使用FPU,而是使用软件来实现,并使用软件浮点调用约定,这是不带hf的编译器的默认值。softfp表示允许浮点运算使用硬件浮点指令,但仍旧使用软件浮点调用约定。hard表示使用硬件浮点指令,并使用FPU特定的调用约定,这是带hf后缀的编译器的默认值,通常也只有带hf后缀的编译器才能指定这个值。软件浮点和硬件浮点,在链接时是不能兼容的,整个程序必须使用相同的ABI,并链接兼容的库才行,由于soft和softfp都使用软件浮点调用约定,因此,这两个选项编译出来的目标文件和库是兼容的。而hard模式不与其它两种选项兼容。-mfloat-abi选项的具体验证,可以在命令行选项中指定-v来查看一下输出。

  • name:工具链中具体的程序名字,例如gcc、as、nm等。

示例

  • arm-none-eabi-gcc/arm-eabi-gcc

用于编译ARM架构的程序,包括bootloader、ARM Linux kernel,不适用于编译ARM Linux应用程序,因其不支持那些与操作系统关系密切的函数,比如各种系统调用。arm-eabi-gcc一般出现在Android源码树中,不适宜于用在其它项目,所需要的头文件和库等都没有打包在一起。

  • arm-linux-androideabi-gcc

用于编译ARM架构的程序,主要用于Android源码里的应用程序,因为它使用了Android的bionic库,要用于其它目的需要进行较复杂的处理。Ubuntu 14.04提供了一个安装后直接可用的包gcc-arm-linux-androideabi,但后续Ubuntu版本没有再看到。

  • aarch64-linux-android-gcc

用于编译ARM 64位架构的程序,主要用于Android源码里的应用程序,因为它使用了Android的bionic库,要编译其它类型的程序需要进行较复杂的处理。

  • aarch64-linux-gnu-gcc

用于编译ARM 64位架构的程序,包括bootloader、ARM Linux kernel、ARM Linux应用程序,使用GNU C库及其调用约定。

  • arm-linux-gnueabihf-gcc

用于编译ARM架构的程序,包括bootloader、ARM Linux kernel、ARM Linux应用程序,使用GNU C库及其调用约定。浮点数运算默认使用hard模式。

参考

armel、armhf和arm64区别选择
GCC online documentation