【概念版】交叉编译相关介绍
一、参考资料
交叉编译器 arm-linux-gnueabi 和 arm-linux-gnueabihf 的区别
ARM交叉编译器GNUEABI、NONE-EABI、ARM-EABI、GNUEABIHF等的区别
Hi3516编译 OpenCV
二、相关介绍
模式 | 适用架构 | 编译器 | 解释说明 | 优点 | 缺点 |
---|---|---|---|---|---|
soft | - | - | 浮点运算全部由软件层实现 | - | - |
softfp | armel | gcc-arm-linux-gnueabi | soft-float(软浮点),浮点运算使用FPU,函数传参使用普通寄存器(整型) | - | 中断负荷小,函数参数需要转换成浮点的再计算 |
hard | armhf | gcc-arm-linux-gnueabihf | hard-float(硬浮点),浮点运算使用FPU,函数传参使用FPU寄存器 | 性能最好 | 中断负荷高 |
ABI和EABI
应用二进制接口(Application Binary Interface (ABI) for the ARM Architecture)。
在计算机中,应用二进制接口描述了应用程序(或者其他类型)和操作系统之间或其他应用程序的低级接口。ABI涵盖了各种细节,比如:
- 数据类型的大小、布局和对齐;
- 调用约定(控制着函数的参数如何传送以及如何接受返回值),例如,是所有的参数都通过栈传递,还是部分参数通过寄存器传递;哪个寄存器用于哪个函数参数;通过栈传递的第一个函数参数是最先push到栈上还是最后;
- 系统调用的编码和一个应用如何向操作系统进行系统调用。
ABI不同于应用程序接口(API),API定义了源代码和库之间的接口,因此同样的代码可以在支持这个API的任何系统中编译,ABI允许编译好的目标代码在使用兼容ABI的系统中无需改动就能运行。一个完整的ABI,像Intel二进制兼容标准 (iBCS) ,允许支持它的操作系统上的程序不经修改即可在其他支持此ABI的操作系统上运行。
EABI是嵌入式平台上(如ARM,MIPS等),EABI与通用计算机的ABI的主要区别是应用程序代码中允许使用特权指令,不需要动态链接(有时是禁止的),和更紧凑的堆栈帧组织用来节省内存。广泛使用EABI的有Power PC和ARM。
VFP
从ARMv5开始,就有可选的 Vector Floating Point (VFP) 模块,当然最新的如 Cortex-A8, Cortex-A9 和 Cortex-A5 可以配置成不带VFP的模式供芯片厂商选择。
VFP经过若干年的发展,有VFPv2 (一些 ARM9 / ARM11)、 VFPv3-D16(只使用16个浮点寄存器,默认为32个)和VFPv3+NEON (如大多数的Cortex-A8芯片) 。对于包含NEON的ARM芯片,NEON一般和VFP共用寄存器。
FPU
硬件浮点运算单元
soft/softfp/hard 浮点运算模式
在gcc的编译参数上,使用 -mfloat-abi=<name>
来指定浮点运算处理方式,并使用 -mfpu=<name>
来指定浮点协处理的类型。
-mfloat-abi
包括 soft
、softfp
、hard
三种模式,其中后两者都要求ARM有 FPU浮点运算单元。在兼容性方面,soft与后两者是兼容的,但 softfp 和 hard 两种模式互不兼容。
-mfpu
可选类型如 fpa,fpe2,fpe3,maverick,vfp,vfpv3,vfpv3-fp16,vfpv3-d16,vfpv3-d16-fp16,vfpv3xd,vfpv3xd-fp16,neon,neon-fp16,vfpv4,vfpv4-d16,fpv4-sp-d16,neon-vfpv4等。
soft模式
在soft模式下,浮点运算全部由软件层实现。soft模式会存在不必要的浮点到整数、整数到浮点的转换,只适合于早期没有浮点计算单元的ARM处理器。
softfp模式
在softfp模式下,编译器会将浮点运算交给硬件浮点运算单元(FPU)处理,但函数参数的传递使用通用的整型寄存器而不是浮点寄存器。这种模式的优点是可以在支持硬件浮点运算的系统上提高浮点运算的性能,同时保持与不支持硬件浮点运算的系统的兼容性。
hard模式
在hard模式下,编译器会使用FPU来执行浮点运算,并且使用浮点寄存器将函数参数传递给FPU处理。这种模式的优点是可以充分利用硬件浮点运算的性能优势,尤其是在处理大量浮点运算的应用程序时。然而,hard模式生成的代码只能在支持硬件浮点运算的系统上运行,不兼容没有硬件浮点单元的系统。
armel和armhf 架构
softfp模式适用于armel架构,hard模式适用于armhf 架构。
armel 架构
armel(ARM EABI Little Endian)是ARM架构的一种,主要用于早期的ARM设备或者不带FPU 的设备。在这种架构下,浮点运算通常由软件模拟而非硬件直接执行,这可能会导致性能上的损失。armel架构的设备通常使用gcc编译器的softfp模式,这种模式将浮点计算交给FPU处理,但函数参数的传递使用通用的整型寄存器而不是FPU寄存器。
armhf 架构
armhf(ARM Hard Float)是ARM架构的另一种形式,主要用于较现代的ARM设备,这些设备至少实现了ARMv7架构,并且支持 第3版ARM矢量浮点规范(VFPv3)。armhf架构利用了硬件浮点运算,因此在浮点运算性能上相较于armel架构有显著提升。在编译时,armhf架构使用gcc编译器的hard模式,这种模式使用FPU浮点寄存器将函数参数传递给FPU处理。
在完全不改变源码和配置的情况下,在一些应用程序上,使用armhf能得到20%-25%的性能提升。对一些严重依赖于浮点运算的程序,更是可以达到300%的性能提升。
gnueabi和gnueabihf 交叉编译器
gnueabi和gnueabihf是两种用于编译ARM架构程序的交叉编译器,主要区别在于对浮点运算的支持和使用的C库版本。
在debian源里,这两种交叉编译器的定义如下:
gcc-arm-linux-gnueabi
– The GNU C compiler for armel architecture
gcc-arm-linux-gnueabihf
– The GNU C compiler for armhf architecture
gnueabi和gnueabihf两种交叉编译器分别适用于armel和armhf两种不同的架构,对待浮点运算采取了不同的策略。它们的gcc选项 -mfloat-abi
的默认值不同,分别采用softfp和hard模式。
gnueabi
特点:使用Glibc库,支持fork等函数。
适用场景:如果目标设备的浮点运算能力较弱,或者对浮点运算的性能要求不高,可以选择gnueabi。
gnueabihf
特点:使用hf(hard float)版本的Glibc库,支持硬件浮点运算。
适用场景:如果目标设备支持硬件浮点运算,并且对浮点运算的性能有较高要求,那么gnueabihf可能是更好的选择。
简单示例
把以下测试使用的c文件内容保存为 mfloat.c
文件:
#include <stdio.h>
int main(void)
{
double a,b,c;
a = 23.543;
b = 323.234;
c = b/a;
printf(“the 13/2 = %f\n”, c);
printf(“hello world !\n”);
return 0;
}
(1)使用 arm-linux-gnueabihf-gcc
编译,使用“-v”选项以获取更详细的信息:
arm-linux-gnueabihf-gcc -v mfloat.c
COLLECT_GCC_OPTIONS='-v' '-shared-libgcc' '-mfloat-abi=hard' '-mfpu=neon-vfpv4' '-mtls-dialect=gnu' '-mthumb' '-march=armv7-a+neon-vfpv4'
可看出使用hard硬件浮点模式。
(2)使用 arm-linux-gnueabi-gcc
编译:
arm-linux-gnueabi-gcc -v mfloat.c
COLLECT_GCC_OPTIONS='-v' '-march=armv7-a' '-mfloat-abi=softfp' '-mfpu=vfpv3-d16' '-mthumb' -mfloat-abi=softfp
可看出使用softfp模式。
交叉编译工具链
下载交叉编译工具链:https://developer.arm.com/downloads/-/gnu-a
一次搞定 Arm Linux 交叉编译
Windows (mingw-w64-i686) hosted cross compilers
AArch32 bare-metal target (arm-none-eabi)
- gcc-arm-10.3-2021.07-mingw-w64-i686-arm-none-eabi.tar.xz
- gcc-arm-10.3-2021.07-mingw-w64-i686-arm-none-eabi.tar.xz.asc
AArch32 target with hard float (arm-none-linux-gnueabihf)
- gcc-arm-10.3-2021.07-mingw-w64-i686-arm-none-linux-gnueabihf.tar.xz
- gcc-arm-10.3-2021.07-mingw-w64-i686-arm-none-linux-gnueabihf.tar.xz.asc
AArch64 bare-metal target (aarch64-none-elf)
- gcc-arm-10.3-2021.07-mingw-w64-i686-aarch64-none-elf.tar.xz
- gcc-arm-10.3-2021.07-mingw-w64-i686-aarch64-none-elf.tar.xz.asc
AArch64 GNU/Linux target (aarch64-none-linux-gnu)
- gcc-arm-10.3-2021.07-mingw-w64-i686-aarch64-none-linux-gnu.tar.xz
- gcc-arm-10.3-2021.07-mingw-w64-i686-aarch64-none-linux-gnu.tar.xz.asc
x86_64 Linux hosted cross compilers
AArch32 bare-metal target (arm-none-eabi)
- gcc-arm-10.3-2021.07-x86_64-arm-none-eabi.tar.xz
- gcc-arm-10.3-2021.07-x86_64-arm-none-eabi.tar.xz.asc
AArch32 target with hard float (arm-none-linux-gnueabihf)
- gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf.tar.xz
- gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf.tar.xz.asc
AArch64 ELF bare-metal target (aarch64-none-elf)
- gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz
- gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz.asc
AArch64 GNU/Linux target (aarch64-none-linux-gnu)
- gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz
- gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz.asc
AArch64 GNU/Linux target (aarch64_be-none-linux-gnu)
- gcc-arm-10.3-2021.07-x86_64-aarch64_be-none-linux-gnu.tar.xz
- gcc-arm-10.3-2021.07-x86_64-aarch64_be-none-linux-gnu.tar.xz.asc
GCC (GNU Compiler Collection)
arm-linux-gnueabi-gcc
:用于32位ARM体系结构的交叉编译工具链。aarch64-linux-gnu-gcc
:用于64位ARM体系结构的交叉编译工具链。mips-linux-gnu-gcc
:用于MIPS体系结构的交叉编译工具链。x86_64-linux-gnu-gcc
:用于x86-64体系结构的交叉编译工具链。
GCC 的命名规则为: arch [-vendor] [-os] [-(gnu)eabi]-gcc
解释说明:
-
带
[]
的是可选部分。 -
arch
: 芯片架构,如ARM,MIPS。- 32 位 Arm 架构:arm;
- 64 位 Arm 架构:aarch64;
-
vendor
:交叉编译工具链提供商,通常为none。 -
os
:目标操作系统。根据对操作系统的支持与否,ARM GCC可分为支持和不支持操作系统,例如:-
arm-none-eabi
:这个是没有操作系统的,不支持那些跟操作系统关系密切的函数,比如fork(2),且使用的是 newlib 这个专用于嵌入式系统的C库。 -
arm-none-linux-eabi
:使用Linux,且使用Glibc
-
-
eabi
:嵌入式应用二进制接口。
ARM GCC Toolchain
-
GNU Arm Embedded Toolchain
:这是一个社区支持的预构建GNU编译器工具链,适用于基于ARM的CPU。它提供了针对不同主机操作系统(如GNU/Linux、Windows和macOS)的交叉工具链,支持裸机和Linux目标。 -
xPack GNU Arm Embedded GCC
:这是一个跨平台的二进制分发版本,专为GNU Arm嵌入式GCC工具链设计。它支持Windows、macOS和GNU/Linux系统,提供了稳定、可重复使用的编译环境,适用于嵌入式系统开发、教育与研究以及开源项目。 -
ARM CMake Toolchains
:这是一个CMake工具链配置项目,提供了针对不同ARM架构的工具链文件,如arm-linux-gnueabihf.toolchain.cmake
和arm-none-eabi.toolchain.cmake
,帮助CMake在交叉编译时正确选择编译器和工具链。 -
arm-none-eabi-gcc
:这是一个用于编译ARM架构裸机系统(包括ARM Linux的boot、kernel)的工具链,不适用编译Linux应用程序。它适用于ARM7、Cortex-M和Cortex-R内核的芯片使用 -
arm-none-linux-gnueabi-gcc
:这是一个主要用于基于ARM架构的Linux系统的工具链,可用于编译ARM架构的u-boot、Linux内核、Linux应用等。它基于GCC,使用Glibc库,经过Codesourcery公司优化过推出的编译器,适用于ARM9、ARM11、Cortex-A内核,带有Linux操作系统的情况 -
arm-linux-gnueabi-gcc
和arm-linux-gnueabihf-gcc
:这两个交叉编译器分别适用于armel和armhf两个不同的架构,对待浮点运算采取了不同的策略。它们是gcc的选项-mfloat-abi
的默认值不同,分别采用softfp和hard模式
交叉编译基本配置
指定编译后的文件的安装目录:
--prefix=/usr/local/opencv-4.1.0
指定编译后使用文件的平台:
--host=arm-linux # arm
--host=x86-linux # x86
--host=arm-none-linux-gnueabi
--host=aarch64-linux-gnu
指定gcc/g++编译器:
CC=aarch64-linux-gnu-gcc
CXX=aarch64-linux-gnu-g++