简析交叉编译器的命名规则
为什么要交叉编译
嵌入式系统中的资源太少,硬件资源紧张。交叉编译出来的程序在目标环境中,各种资源都相对有限,所以很难进行直接的本地编译。因而需要在PC侧先行进行交叉编译,再将生成的程序放到目标板上运行。
02
什么是交叉编译工具链
用于交叉编译的工具链,即可以编译跨平台程序的工具链。一般是PC侧执行编译,在嵌入式目标平台执行程序。
常说的交叉编译版本的gcc,比如arm-linux-gcc,实际上指代了包含一系列交叉编译版本的交叉工具链(arm-linux-gcc,arm-linux-ld,arm-linux-as等等)。
03
交叉编译器命名规则
arch [-vendor][-kernel][-system]
名称含义如下:
arch:体系架构,如ARM, MIPS
vendor:工具链提供商
kernel:目标内核
-
system:目标系统
1. arch
arch,即系统架构,交叉编译器的目标系统平台架构,即用该交叉编译器编译出的程序是运行在哪种CPU上。
常用的arch值如:
<code>arm-cortex_a8-linux-gnueabi</code>中的arm
<code>mips-ar2315-linux-gnu中</code>的mips
<code>powerpc-e500v2-linux-gnuspe</code>中的powerpc
-
<code>x86_64-unknown-mingw32</code>中的x86_64
2. [-vendor]
vendor,即工具链提供商,表示该交叉编译器提供者。
vendor 但一般情况下,大家把vendor写成体系架构的型号。如:
<code>arm-cortex_a8-linux-gnueabi</code>中的cortex_a8
<code>mips-ar2315-linux-gnu</code>中的ar2315
<code>powerpc-e500v2-linux-gnuspe</code>中的e500v2
另外,也有把vendor写成交叉编译器作者名字的。
3. [-kernel]
kernel,即内核,指使用该编译器编译出程序的目标系统。对应的环境或系统主要有两种:
(1) Linux:表示有操作系统(此处主要指Linux)的环境。
(2) bare-metal:表示无操作系统的环境。
比如用该交叉编译器编译一个U-boot或者其他小程序,是运行在无嵌入式Linux系统环境中单独运行的一个程序。又比如平常我们购买的嵌入式系统开发板中,常带有一些如跑马灯的小程序,这种也是运行在无操作系统环境的程序。
4. [-system]
system,直译为系统,其实主要表示交叉编译器所选择的库函数和目标系统。
常见的值有:
<code>gnu</code>,
<code>gnueabi</code>,
<code>uclibcgnueabi</code>
(1) gnu
GNU是一个自由软件工程项目。至于其他更多的信息,可以自行百度……
(2) eabi
在说明eabi之前,需要先讲一下abi:
ABI即二进制应用程序接口(Application Binary Interface(ABI) for the ARM Architecture)。计算机中,应用二进制接口描述了应用程序和操作系统之间或其他应用程序的低级接口。一个完整的ABI,像Intel二进制兼容标准(iBCS),允许支持它的操作系统上的程序不经修改在其他支持此ABI的操作系统上运行。
ABI不同于API(应用程序接口)。API定义了源代码和库之间的接口,所以同样的代码可以在支持该API的任何系统中编译。而在使用兼容ABI的系统中,ABI允许编译好的目标代码无需改动,就能运行。
EABI为嵌入式ABI,即Embedded ABI。EABI指定了文件格式、数据类型、寄存器使用、堆积组织优化和在一个嵌入式软件中参数的标准约定。
EABI与ABI的主要区别,是应用程序代码中允许使用特权指令,不需要动态链接,并且使用更紧凑的堆栈帧组织用来节省内存。广泛使用EABI的有Power PC和ARM。
(3) uclibc
uclibc,是c库中的一种。
04
交叉编译器举例
1. arm-none-eabi-gcc
arch: arm (ARM architecture)
vendor: none (NO vendor)
kernel: (empty) (not target an operating system)
system: eabi (complies with the ARM EABI)
该编译器一般用于编译ARM架构的裸机系统(包括 ARM Linux 的 boot、kernel,不适用编译 Linux 应用 Application),一般适合 ARM7、Cortex-M 和 Cortex-R 内核的芯片使用,所以不支持那些跟操作系统关系密切的函数(比如fork(2),他使用的是 newlib 这个专用于嵌入式系统的C库)。
2. arm-none-linux-gnueabi-gcc
arch: arm (ARM architecture)
vendor: none (NO vendor)
kernel: linux (creates binaries that run on the Linux operating system)
system: gnueabi (uses the GNU EABI)
该编译器主要用于基于ARM架构的Linux系统,可用于编译 ARM 架构的u-boot、Linux内核、linux应用等。
arm-none-linux-gnueabi基于 gcc ,使用 glibc 库,是经过 Codesourcery 公司优化过推出的编译器,且该交叉编译工具的浮点运算非常优秀。一般ARM9, ARM11, Cortex-A 内核,带有 Linux 操作系统的会用到。
3. arm-eabi-gcc
该编译器是Android ARM编译器。
4. armcc
ARM 公司推出的编译工具,功能和 arm-none-eabi 类似,可以编译裸机程序(u-boot, kernel),但是不能编译 Linux 应用程序。
armcc一般和ARM开发工具一起,Keil MDK、ADS、RVDS和DS-5中的编译器都是armcc,所以 armcc 编译器都是收费的。
5. arm-linux-gnueabi-gcc & arm-linux-gnueabihf-gcc
两个交叉编译器名称上的区别在于 gnueabi 与 gnueabihf,分别适用于 armel 和 armhf 两个不同的架构,armel 和 armhf 这两种架构在浮点运算上采用了不同的策略(有 fpu 的 arm 才能支持这两种浮点运算策略)。
其实这两个交叉编译器只是在 gcc 的选项 -mfloat-abi 的默认值不同。gcc的选项-mfloat-abi有三种值:soft, softfp, hard,其值含义如下:
soft: 不用fpu进行浮点计算(即使有fpu浮点运算单元,也不使用fpu);
softfp: armel架构(对应编译器是arm-linux-gnueabi-gcc)的默认值,用 fpu 计算,但传参数时使用普通寄存器。这样中断的时候,只需要保存普通寄存器,且中断负荷小,但参数需要转换成浮点数之后再计算;
-
hard: armhf架构(对应编译器是arm-linux-gnueabihf-gcc)的默认值,用 fpu 计算,传参数也用 fpu 中的浮点寄存器传递。这样省去了转换,性能最好,但中断负荷高。
参考文献
1. Crifan Li的《交叉编译详解》
2. 琦小虾的《交叉编译学习笔记(二)——交叉编译器的命名规则》