Ⅰ 交叉编译器 arm-linux-gnueabi 和 arm-linux-gnuea
一. 什么是ABI和EABI
1) ABI: 二进制应用程序接口(Application Binary Interface (ABI) for the ARM Architecture)
在计算机中,应用二进制接口描述了应用程序(或者其他类型)和操作系统之间或其他应用程序的低级接口.
ABI涵盖了各种细节,如:
数据类型的大小、布局和对齐;
调用约定(控制着函数的参数如何传送以及如何接受返回值),例如,是所有的参数都通过栈传递,还是部分参数通过寄存器传递;哪个寄存器用于哪个函数参数;通过栈传递的第一个函数参数是最先push到栈上还是最后;
系统调用的编码和一个应用如何向操作系统进行系统调用;
以及在一个完整的操作系统ABI中,目标文件的二进制格式、程序库等等。
一个完整的ABI,像Intel二进制兼容标准 (iBCS) ,允许支持它的操作系统上的程序不经修改在其他支持此ABI的操作体统上运行。
ABI不同于应用程序接口(API),API定义了源代码和库之间的接口,因此同样的代码可以在支持这个API的任何系统中编译,ABI允许编译好的目标代码在使用兼容ABI的系统中无需改动就能运行。
2) EABI: 嵌入式ABI
嵌入式应用二进制接口指定了文件格式、数据类型、寄存器使用、堆积组织优化和在一个嵌入式软件中的参数的标准约定。
开发者使用自己的汇编语言也可以使用EABI作为与兼容的编译器生成的汇编语言的接口。
支持EABI的编译器创建的目标文件可以和使用类似编译器产生的代码兼容,这样允许开发者链接一个由不同编译器产生的库。
EABI与关于通用计算机的ABI的主要区别是应用程序代码中允许使用特权指令,不需要动态链接(有时是禁止的),和更紧凑的堆栈帧组织用来节省内存。广泛使用EABI的有Power PC和ARM.
二. gnueabi相关的两个交叉编译器: gnueabi和gnueabihf
在debian源里这两个交叉编译器的定义如下:
gcc-arm-linux-gnueabi – The GNU C compiler for armel architecture
gcc-arm-linux-gnueabihf – The GNU C compiler for armhf architecture
可见这两个交叉编译器适用于armel和armhf两个不同的架构, armel和armhf这两种架构在对待浮点运算采取了不同的策略(有fpu的arm才能支持这两种浮点运算策略)
其实这两个交叉编译器只不过是gcc的选项-mfloat-abi的默认值不同. gcc的选项-mfloat-abi有三种值soft,softfp,hard(其中后两者都要求arm里有fpu浮点运算单元,soft与后两者是兼容的,但softfp和hard两种模式互不兼容):
soft : 不用fpu进行浮点计算,即使有fpu浮点运算单元也不用,而是使用软件模式。
softfp : armel架构(对应的编译器为gcc-arm-linux-gnueabi)采用的默认值,用fpu计算,但是传参数用普通寄存器传,这样中断的时候,只需要保存普通寄存器,中断负荷小,但是参数需要转换成浮点的再计算。
hard : armhf架构(对应的编译器gcc-arm-linux-gnueabihf)采用的默认值,用fpu计算,传参数也用fpu中的浮点寄存器传,省去了转换, 性能最好,但是中断负荷高。
Ⅱ 如何设置NDK的编译选项
1. 概述
首先回顾一下 Android NDK 开发中,Android.mk 和Application.mk 各自的职责。
Android.mk,负责配置如下内容:
(1) 模块名(LOCAL_MODULE)
(2) 需要编译的源文件(LOCAL_SRC_FILES)
(3) 依赖的第三方库(LOCAL_STATIC_LIBRARIES,LOCAL_SHARED_LIBRARIES)
(4) 编译/链接选项(LOCAL_LDLIBS、LOCAL_CFLAGS)
Application.mk,负责配置如下内容:
(1) 目标平台的ABI类型(默认值:armeabi)(APP_ABI)
(2) Toolchains(默认值:GCC 4.8)
(3) C++标准库类型(默认值:system)(APP_STL)
(4) release/debug模式(默认值:release)
由此我们可以看到,本文所涉及的编译选项在Android.mk和Application.mk中均有出现,下面我们将一个个详细介绍。
2. APP_ABI
ABI全称是:Application binary interface,即:应用程序二进制接口,它定义了一套规则,允许编译好的二进制目标代码在所有兼容该ABI的操作系统和硬件平台中无需改动就能运行。(具体的定义请参考网络或者维基网络)
由上述定义可以判断,ABI定义了规则,而具体的实现则是由编译器、CPU、操作系统共同来完成的。不同的CPU芯片(如:ARM、Intel x86、MIPS)支持不同的ABI架构,常见的ABI类型包括:armeabi,armeabi-v7a,x86,x86_64,mips,mips64,arm64-v8a等。
这就是为什么我们编译出来的可以运行于Windows的二进制程序不能运行于Mac OS/Linux/Android平台了,因为CPU芯片和操作系统均不相同,支持的ABI类型也不一样,因此无法识别对方的二进制程序。
而我们所说的“交叉编译”的核心原理也跟这些密切相关,交叉编译,就是使用交叉编译工具,在一个平台上编译生成另一个平台上的二进制可执行程序,为什么可以做到?因为交叉编译工具实现了另一个平台所定义的ABI规则。我们在Windows/Linux平台使用Android NDK交叉编译工具来编译出Android平台的库也是这个道理。
这里给出最新 Android NDK 所支持的ABI类型及区别:
下面是我总结的一些常用的CFLAGS编译选项:
(1)通用的编译选项
-O2 编译优化选项,一般选择O2,兼顾了优化程度与目标大小
-Wall 打开所有编译过程中的Warning
-fPIC 编译位置无关的代码,一般用于编译动态库
-shared 编译动态库
-fopenmp 打开多核并行计算,
-Idir 配置头文件搜索路径,如果有多个-I选项,则路径的搜索先后顺序是从左到右的,即在前面的路径会被选搜索
-nostdinc 该选项指示不要标准路径下的搜索头文件,而只搜索-I选项指定的路径和当前路径。
--sysroot=dir 用dir作为头文件和库文件的逻辑根目录,例如,正常情况下,如果编译器在/usr/include搜索头文件,在/usr/lib下搜索库文件,它将用dir/usr/include和dir/usr/lib替代原来的相应路径。
-llibrary 查找名为library的库进行链接
-Ldir 增加-l选项指定的库文件的搜索路径,即编译器会到dir路径下搜索-l指定的库文件。
-nostdlib 该选项指示链接的时候不要使用标准路径下的库文件
(2) ARM平台相关的编译选项
-marm -mthumb 二选一,指定编译thumb指令集还是arm指令集
-march=name 指定特定的ARM架构,常用的包括:-march=armv6, -march=armv7-a
-mfpu=name 给出目标平台的浮点运算处理器类型,常用的包括:-mfpu=neon,-mfpu=vfpv3-d16
-mfloat-abi=name 给出目标平台的浮点预算ABI,支持的参数包括:“soft”, “softfp” and “hard”
Ⅲ 用gcc 4.7.1的源代码编译出来arm-eabi-gcc。编译的时候指定了cpu类型,但是编译出来的程序,不能运行。
去掉 -march=arm6试下吧。
Ⅳ arm-none-eabi-gcc对比mdk编译效率和实际效果怎么样
eabi是arm新的二进制文件接口的标准,elf是二进制目标文件的格式,而名称为arm-elf的编译器一般是老的OABI接口,裸奔程序到影响不大,在嵌入式linux中,要注意系统的接口,是老的oabi还是eabi,新的内核一般是eabi接口,但编译内核时会有兼用oab...
Ⅳ 如何使用arm-none-eabi-gcc 编译
交叉编译环境搭建后 arm-linux-gcc -v 显示 No such file or directory 使用which命令可以找到,环境变量没有问题,更详细的描述问题就是which找到的命令所在的目录下的所有命令都是同样的问题。
Ⅵ v7a软件和v8a软件的区别
v7a和v8a区别:
armeabi默认选项,32位,支持基于ARM*v5TE的设备,支持软浮点运算(不支持硬件辅助的浮点计算),支持所有ARM*设备,armeabi-v7a32位,支持基于ARM*v7的设备,支持硬件FPU指令,支持硬件浮点运算。
armeabi-v8a64位,支持基于ARM*v8的设备,支持硬件FPU指令,支持硬件浮点运算不同手机由于cpu的不同,使用不同的驱动。
ABI:指应用基于哪种指令集来进行编译,ABI总共有四种,分别是armeabi、armeabi-v7a、mips、x86,它们都是表示cpu的类型。
为了减小apk体积,只保留armeabi和armeabi-v7a两个文件夹,并保证这两个文件夹中.so数量一致。
对只提供armeabi版本的第三方.so,原样复制一份到armeabi-v7a文件夹。
早期的Android系统几乎只支持ARMv5的CPU架构,现在支持7种!
Android系统目前支持以下七种不同的CPU架构:ARMv5,ARMv7(从2010年起),x86(从2011年起),MIPS(从2012年起),ARMv8,MIPS64和x86_64(从2014年起),每一种都关联着一个相应的ABI。
应用程序二进制接口(ApplicationBinaryInterface)定义了二进制文件(尤其是.so文件)如何运行在相应的系统平台上,从使用的指令集,内存对齐到可用的系统函数库。
在Android系统上,每一个CPU架构对应一个ABI:armeabi,armeabi-v7a,x86,mips,arm64- v8a,mips64,x86_64。
Ⅶ 在ubuntu系统连接jz2440开发板 出现Illegal instruction
我帮你查了下,看看有没有用。虽然是转载的~希望能帮上忙
Illegal instruction的解决方法
最新解决方法:
把/usr/local/arm/compiler/arm-none-linux-gnueabi/libc/armv4t/lib目录(也就是你的编译器的库目录)下
的所有文件拷贝到目标板子的根目录的lib目录下就好了。
这样无论你的hello是动态编译还是静态编译,跑起来都不会有Illegal instruction的问题。
////////////////////////////////
老的解决方法:
开发板配置: ARM9 + linux-3.6.30
编译器:arm-linux-4.3.2
在移植好jffs2文件系统以后,当然想写个hello world 来验证一下自己的成果了。好,开始:
1.编辑编译
#vi hello.c
#include <stdio.h>
int main(void)
{
printf("welcome to my rootfs!/n");
return 0;
}
#arm-linux-gcc –o hello hello.c
2.把hello复制到用来制作文件系统的文件夹,制作文件系统rootfs.jffs2,下载运行,开发板能够成功启动,能够出现shell交互界面。这点肯定地说明busybox是没有问题的。运行hello
./hello出现:
Illegal instruction
从网上找了很多资料,大部分把责任归于EABI,但我想想,既然kernel和busybox都能正常启动,那它们都应该是eabi编译的了,hello也肯定是eabi的,因为他们都是用arm-linux-4.3.2编译的(编译内核的时候make menuconfig要选山EABI选项).所以网上大部分资料都不适合解决我遇到的问题。但最终还是找到了一边能够帮我解决问题的文章:
http://hi..com/caicry/blog/item/ede3b8fa01ebc89059ee908a.html
虽然他还是把问题归咎于EABI,但是却给我指点了解决问题的方向。
既然busybox(这里的busybox是指编译busybox-1.15.2生成的busybox二进制文件)能够成功运行,hello不能运行,那就看看他们的区别:
#file buxybox
busybox: ELF 32-bit LSB executable, ARM, version 1 (SYSV),statically linked, for GNU/Linux 2.6.14, stripped
#file hello
# file hello
hello: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
这时候恍然大悟了,hello在ram+linux系统上找不到运行所需的动态库,所以Illegal instruction。重新编译hello.c
#gcc –static –o hello hello.c
#file hello
hello_static: ELF 32-bit LSB executable, ARM, version 1 (SYSV),statically linked, for GNU/Linux 2.6.14, not stripped
重新制作jffs2文件系统,下载运行:
#hello出现
welcome to my rootfs!
完!
现在EABI已经开始在嵌入式中流行起来,确保软件的EABI匹配性,应该注意下面几点:
1. 编译kernel的时候要选上EABI。
2. 交叉编译的所有的软件都要用支持EABI的编译器(例如arm-linux-4.3.2)来编译。
Ⅷ linux下如何把一个.c文件通过arm-none-eabi-交叉编译生成一个.bin的文件然后在qemu上运行
eabi标准的要好些,可能arm-linux-gcc就是arm-none-linux-gnueabi的一个链接
终于,郁闷已久的问题攻破了,用了三种配置交叉编译的方法,最终在开发板上实现成功了,现在想一想,有的时候真的也是运气。
之前已经试验过使用arm-linux-gcc-3.4.1配置交叉编译编译环境,配置成功了,在开发板上失败了~
后来使用脚本创建交叉编译环境(crosstool-0.43),配置成功了(这个用了相当长的时间),在开发板上失败了~
Ⅸ 交叉编译器 arm-linux-gnueabi 和 arm-linux-gnueabihf 的区别
自己之前一直没搞清楚这两个交叉编译器到底有什么问题,特意google一番,总结如下,希望能帮到道上和我有同样困惑的兄弟…..
一. 什么是ABI和EABI
1) ABI: 二进制应用程序接口(Application Binary Interface (ABI) for the ARM Architecture)
在计算机中,应用二进制接口描述了应用程序(或者其他类型)和操作系统之间或其他应用程序的低级接口.
ABI涵盖了各种细节,如:
数据类型的大小、布局和对齐;
调用约定(控制着函数的参数如何传送以及如何接受返回值),例如,是所有的参数都通过栈传递,还是部分参数通过寄存器传递;哪个寄存器用于哪个函数参数;通过栈传递的第一个函数参数是最先push到栈上还是最后;
系统调用的编码和一个应用如何向操作系统进行系统调用;
以及在一个完整的操作系统ABI中,目标文件的二进制格式、程序库等等。
一个完整的ABI,像Intel二进制兼容标准 (iBCS) ,允许支持它的操作系统上的程序不经修改在其他支持此ABI的操作体统上运行。
ABI不同于应用程序接口(API),API定义了源代码和库之间的接口,因此同样的代码可以在支持这个API的任何系统中编译,ABI允许编译好的目标代码在使用兼容ABI的系统中无需改动就能运行。
2) EABI: 嵌入式ABI
嵌入式应用二进制接口指定了文件格式、数据类型、寄存器使用、堆积组织优化和在一个嵌入式软件中的参数的标准约定。
开发者使用自己的汇编语言也可以使用EABI作为与兼容的编译器生成的汇编语言的接口。
支持EABI的编译器创建的目标文件可以和使用类似编译器产生的代码兼容,这样允许开发者链接一个由不同编译器产生的库。
EABI与关于通用计算机的ABI的主要区别是应用程序代码中允许使用特权指令,不需要动态链接(有时是禁止的),和更紧凑的堆栈帧组织用来节省内存。广泛使用EABI的有Power PC和ARM.
二. gnueabi相关的两个交叉编译器: gnueabi和gnueabihf
在debian源里这两个交叉编译器的定义如下:
gcc-arm-linux-gnueabi – The GNU C compiler for armel architecture
gcc-arm-linux-gnueabihf – The GNU C compiler for armhf architecture
可见这两个交叉编译器适用于armel和armhf两个不同的架构, armel和armhf这两种架构在对待浮点运算采取了不同的策略(有fpu的arm才能支持这两种浮点运算策略)
其实这两个交叉编译器只不过是gcc的选项-mfloat-abi的默认值不同. gcc的选项-mfloat-abi有三种值soft,softfp,hard(其中后两者都要求arm里有fpu浮点运算单元,soft与后两者是兼容的,但softfp和hard两种模式互不兼容):
soft : 不用fpu进行浮点计算,即使有fpu浮点运算单元也不用,而是使用软件模式。
softfp : armel架构(对应的编译器为gcc-arm-linux-gnueabi)采用的默认值,用fpu计算,但是传参数用普通寄存器传,这样中断的时候,只需要保存普通寄存器,中断负荷小,但是参数需要转换成浮点的再计算。
hard : armhf架构(对应的编译器gcc-arm-linux-gnueabihf)采用的默认值,用fpu计算,传参数也用fpu中的浮点寄存器传,省去了转换, 性能最好,但是中断负荷高。
把以下测试使用的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’ ‘-march=armv7-a’ ‘-mfloat-abi=hard’ ‘-mfpu=vfpv3-d16′ ‘-mthumb’
-mfloat-abi=hard,可看出使用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模式。
三. 拓展阅读
下文阐述了ARM代码编译时的软浮点(soft-float)和硬浮点(hard-float)的编译以及链接实现时的不同。从VFP浮点单元的引入到软浮点(soft-float)和硬浮点(hard-float)的概念
VFP (vector floating-point)
从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公用寄存器。
硬浮点Hard-float
编译器将代码直接编译成发射给硬件浮点协处理器(浮点运算单元FPU)去执行。FPU通常有一套额外的寄存器来完成浮点参数传递和运算。
使用实际的硬件浮点运算单元FPU当然会带来性能的提升。因为往往一个浮点的函数调用需要几个或者几十个时钟周期。
软浮点 Soft-float
编译器把浮点运算转换成浮点运算的函数调用和库函数调用,没有FPU的指令调用,也没有浮点寄存器的参数传递。浮点参数的传递也是通过ARM寄存器或者堆栈完成。
现在的Linux系统默认编译选择使用hard-float,即使系统没有任何浮点处理器单元,这就会产生非法指令和异常。因而一般的系统镜像都采用软浮点以兼容没有VFP的处理器。
armel ABI和armhf ABI
在armel中,关于浮点数计算的约定有三种。以gcc为例,对应的-mfloat-abi参数值有三个:soft,softfp,hard。
soft是指所有浮点运算全部在软件层实现,效率当然不高,会存在不必要的浮点到整数、整数到浮点的转换,只适合于早期没有浮点计算单元的ARM处理器;
softfp是目前armel的默认设置,它将浮点计算交给FPU处理,但函数参数的传递使用通用的整型寄存器而不是FPU寄存器;
hard则使用FPU浮点寄存器将函数参数传递给FPU处理。
需要注意的是,在兼容性上,soft与后两者是兼容的,但softfp和hard两种模式不兼容。
默认情况下,armel使用softfp,因此将hard模式的armel单独作为一个abi,称之为armhf。
而使用hard模式,在每次浮点相关函数调用时,平均能节省20个CPU周期。对ARM这样每个周期都很重要的体系结构来说,这样的提升无疑是巨大的。
在完全不改变源码和配置的情况下,在一些应用程序上,使用armhf能得到20%——25%的性能提升。对一些严重依赖于浮点运算的程序,更是可以达到300%的性能提升。
Soft-float和hard-float的编译选项
在CodeSourcery gcc的编译参数上,使用-mfloat-abi=name来指定浮点运算处理方式。-mfpu=name来指定浮点协处理的类型。
可选类型如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等。
使用-mfloat-abi=hard (等价于-mhard-float) -mfpu=vfp来选择编译成硬浮点。使用-mfloat-abi=softfp就能兼容带VFP的硬件以及soft-float的软件实现,运行时的连接器ld.so会在执行浮点运算时对于运算单元的选择,
是直接的硬件调用还是库函数调用,是执行/lib还是/lib/vfp下的libm。-mfloat-abi=soft (等价于-msoft-float)直接调用软浮点实现库。
在ARM RVCT工具链下,定义fpu模式:
–fpu softvfp
–fpu softvfp+vfpv2
–fpu softvfp+vfpv3
–fpu softvfp+vfpv_fp16
–fpu softvfp+vfpv_d16
–fpu softvfp+vfpv_d16_fp16.
定义浮点运算类型
–fpmode ieee_full : 所有单精度float和双精度double的精度都要和IEEE标准一致,具体的模式可以在运行时动态指定;
–fpmode ieee_fixed : 舍入到最接近的实现的IEEE标准,不带不精确的异常;
–fpmode ieee_no_fenv :舍入到最接近的实现的IEEE标准,不带异常;
–fpmode std :非规格数flush到0、舍入到最接近的实现的IEEE标准,不带异常;
–fpmode fast : 更积极的优化,可能会有一点精度损失。
Ⅹ 怎么关闭Linux的EABI选项,Kernel Features
kernel future