交叉编译详解(概念篇)
第 1 章交叉编译简介
1.1 什么是交叉编译
对于没有做过嵌⼊式编程的⼈,可能不太理解交叉编译的概念,那么什么是交叉编译?它有什么作⽤?
在解释什么是交叉编译之前,先要明⽩什么是本地编译。
本地编译
本地编译可以理解为,在当前编译平台下,编译出来的程序只能放到当前平台下运⾏。平时我们常见的软件开发,都是属于本地编译:
⽐如,我们在 x86 平台上,编写程序并编译成可执⾏程序。这种⽅式下,我们使⽤ x86 平台上的⼯具,开发针对 x86 平台本⾝的可执⾏程序,这个编译过程称为本地编译。
交叉编译
交叉编译可以理解为,在当前编译平台下,编译出来的程序能运⾏在体系结构不同的另⼀种⽬标平台上,
但是编译平台本⾝却不能运⾏该程序:
⽐如,我们在 x86 平台上,编写程序并编译成能运⾏在 ARM 平台的程序,编译得到的程序在 x86 平台上是不能运⾏的,必须放到 ARM 平台上才能运⾏。
1.2 为什么会有交叉编译
之所以要有交叉编译,主要原因是:
Speed: ⽬标平台的运⾏速度往往⽐主机慢得多,许多专⽤的嵌⼊式硬件被设计为低成本和低功耗,没有太⾼的性能
Capability: 整个编译过程是⾮常消耗资源的,嵌⼊式系统往往没有⾜够的内存或磁盘空间
Availability: 即使⽬标平台资源很充⾜,可以本地编译,但是第⼀个在⽬标平台上运⾏的本地编译器总需要通过交叉编译获得Flexibility: ⼀个完整的Linux编译环境需要很多⽀持包,交叉编译使我们不需要花时间将各种⽀持包移植到⽬标板上
1.3 为什么交叉编译⽐较困难
交叉编译的困难点在于两个⽅⾯:
不同的体系架构拥有不同的机器特性
Word size: 是64位还是32位系统
Endianness: 是⼤端还是⼩端系统
Alignment: 是否必修按照4字节对齐⽅式进⾏访问
Default signedness: 默认数据类型是有符号还是⽆符号
NOMMU: 是否⽀持MMU
gnu编译器交叉编译时的主机环境与⽬标环境不同
Configuration issues:
HOSTCC vs TARGETCC:
Toolchain Leaks:
Libraries:
Testing:
详细的对⽐可以参看这篇⽂章,已经写的很详细了,在这就不细说了:
第 2 章 交叉编译链
2.1 什么是交叉编译链
明⽩了什么是交叉编译,那我们来看看什么是交叉编译链。
⾸先编译过程是按照不同的⼦功能,依照先后顺序组成的⼀个复杂的流程,如下图:
那么编译过程包括了预处理、编译、汇编、链接等功能。既然有不同的⼦功能,那每个⼦功能都是⼀个单独的⼯具来实现,它们合在⼀起形成了⼀个完整的⼯具集。
同时编译过程⼜是⼀个有先后顺序的流程,它必然牵涉到⼯具的使⽤顺序,每个⼯具按照先后关系串联在⼀起,这就形成了⼀个链式结构。因此,交叉编译链就是为了编译跨平台体系结构的程序代码⽽形成的由多个⼦⼯具构成的⼀套完整的⼯具集。同时,它隐藏了预处理、编译、汇编、链接等细节,当我们指定了源⽂件(.c)时,它会⾃动按照编译流程调⽤不同的⼦⼯具,⾃动⽣成最终的⼆进制程序映像(.bin)。注意:严格意义上来说,交叉编译器,只是指交叉编译的gcc,但是实际上为了⽅便,我们常说的交叉编译器就是交叉⼯具链。本⽂对这两个概念不加以区分,都是指编译链
2.2 交叉编译链的命名规则
我们使⽤交叉编译链时,常常会看到这样的名字:
其中,对应的前缀为:arm-none-linux-gnueabi-gcc arm-cortex_a8-linux-gnueabi-gcc mips-malta-linux-gnu-gcc
1
2
3arm-none-linux-gnueabi-arm-cortex_a8-linux-gnueabi-mips-malta-linux-gnu-
1
2
3
这些交叉编译链的命名规则似乎是通⽤的,有⼀定的规则:arch: ⽤于哪个⽬标平台。
core: 使⽤的是哪个CPU Core,如Cortex A8,但是这⼀组命名好像⽐较灵活,在其它⼚家提供的交叉编译链中,有以⼚家名称命名的,也有以开发板命名的,或者直接是none或cross的。kernel: 所运⾏的OS,见过的有Linux,uclinux,bare(⽆OS)。
systen:交叉编译链所选择的库函数和⽬标映像的规范,如gnu,gnueabi等。其中gnu等价于glibc+oabi;gnueabi等价于
glibc+eabi。
注意:这个规则是⼀个猜测,并没有在哪份官⽅资料上看到过。⽽且有些编译链的命名确实没有按照
这个规则,也不清楚这是不是历史原因造成的。如果有谁在资料上见到过此规则的详细描述,欢迎指出错误。
第 3 章 包含的⼯具
3.1 Binutils
Binutils是GNU⼯具之⼀,它包括链接器、汇编器和其他⽤于⽬标⽂件和档案的⼯具,它是⼆进制代码的处理维护⼯具。Binutils⼯具包含的⼦程序如下:ld GNU连接器the GNU linker.as GNU汇编器the GNU assembler.addr2line 把地址转换成⽂件名和所在的⾏数ar A utility for creating, modifying and extracting from archives.c++filt Filter to demangle encoded C++ symbols.dlltool Creates files for building and ld A new, faster, ELF only linker, still in beta test.gprof Displays profiling information.nlmconv Converts object code into Lists symbols from object files.objcopy Copys and translates object files.objdump Displays information from object files.ranlib Generates an index to the contents of adelf Displays information from any ELF format object file.size Lists the section sizes of an object or archive file.strings Lists printable strings from files.
strip Discards symbols
3.2 GCC
GNU编译器套件,⽀持C, C++, Java, Ada, Fortran, Objective-C等众多语⾔。
3.3 GLibc arch-core-kernel-system
1
上通常使⽤的C函数库为glibc。glibc是linux系统中最底层的api,⼏乎其它任何运⾏库都会依赖于glibc。glibc除了封装linux操作系统所提供的系统服务外,它本⾝也提供了许多其它⼀些必要功能服务的实现。
因为嵌⼊式环境的资源及其紧张,所以现在除了glibc外,还有uClibc和eglibc可以选择,三者的关系可以参见这两篇⽂章:
3.4 GDB
GDB⽤于调试程序
第 4 章如何得到交叉编译链
既然明⽩了交叉编译链的功能,那么在针对嵌⼊式系统开发时,我们需要的交叉编译链从哪⼉得到?
主要有三个⽅式可以获取
4.1 下载已经做好的交叉编译链
使⽤其他⼈针对某些CPU平台已经编译好的交叉编译链。我们只需要到合适的,下载下来使⽤即可。
常见的交叉编译链下载地址:
1. 在 下载已经编译好的交叉编译链
2. 在 下载已经编译好的交叉编译链
3. 在下载已经编译好的交叉编译链
4. ⼀些制作交叉编译链的⼯具中,包含了已经制作好的交叉编译链,可以直接拿来使⽤。如crosstool-NG
5. 如果购买了某个芯⽚或开发板,⼀般⼚商会提供对应的整套开发软件,其中就包含了交叉编译链。
⼚家提供的⼯具⼀般是经过了严格的测试,并打⼊了⼀些必要的补丁,所以这种⽅式往往是最可靠的
⼯具来源。
4.2 使⽤⼯具定制交叉编译链
使⽤现存的制作⼯具,以简化制作交叉编译链这个事情的复杂度。我们只需要了解有哪些⼯具可以实现,并选个合适的⼯具,搞懂它的操作步骤即可。
1. crosstool-NG
2. Buildroot
3. Embedded Linux Development Kit (ELDK)
⼯具还有很多,各有各的优势和劣势,⼤家可以慢慢研究,在这就不细说了。
4.3 从零开始构建交叉编译链
这个是最困难也最耗时间的,毕竟制作交叉编译链这样的事情,需要对嵌⼊式的编译原理了解的⽐较透彻,⾄少要知道出了问题要往哪个⽅⾯去翻阅资料。⽽且,也是最考耐⼼和细⼼的地⽅,配错⼀个选项或是⼀个步骤,都可能出现以前从来没见过的问题,⽽且这些问题往往还⽆法和这个选项或步骤直接联系起来。
当然如果搭建出来,肯定也是收获最⼤的,⾄少对于编译的流程和依赖都⽐较清楚了,细节上的东西可能还需要去翻看相应的协议或标准,但⾄少⾻架会⽐较清楚。
详细的搭建过程可以参看后续的⽂章,这⾥⾯有详细的参数和步骤:
为了⽅便⼤家搭建交叉编译链,我写了⼀个⼀键⽣成的脚本(包括源码下载和⾃动编译)。如果⼤家⾃⼰⼀直搭建不成功,不妨试试这个脚本,然后对⽐下⾃⼰的流程是否⼀致,参数是否有差异,也许能帮⼤家迈过这个障碍:
4.4 对⽐三种构建⽅式
项⽬使⽤已有交叉编译链⾃⼰制作交叉编译链
安装⼀般提供压缩包需要⾃⼰打包
源码版本⼀般使⽤较⽼的稳定版本,对于⼀些新的GCC特性不⽀持可以使⽤⾃⼰需要的GCC特性的版本补丁⼀般都会打上修复补丁普通开发者很难辨别需要打上哪些补丁,资深开发者可以针对⾃⼰的需求合⼊补丁源码溯源可能不清楚源码版本和补丁情况⼀切都可以定制升级⼀般不会升级可以随时升级
优化⼀般已经针对特定CPU特性和性能进⾏优化⼀般⽆法做到⽐⼚家优化的更好,除⾮⾃⼰设计的CPU
技术⽀持可以通过FAE进⾏⽀持,可能需要收费只能通过社区⽀持,免费
可靠性验
证已经通过了完善的验证⾃⼰验证,肯定没有专业⼈⼠验证的齐全
项⽬使⽤已有交叉编译链⾃⼰制作交叉编译链
参考资料
[1]
[2]
[3]
[4]
[5]
[6] 交叉编译链下载地址

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。