在解释什么是交叉编译之前,先要明白什么是本地编译。
本地编译
本地编译可以理解为,在当前编译平台下,编译出来的程序只能放到当前平台下运行。平时我们常见的软件开发,都是属于本地编译:
比如,我们在 x86 平台上,编写程序并编译成可执行程序。这种方式下,我们使用 x86 平台上的工具,开发针对 x86 平台本身的可执行程序,这个编译过程称为本地编译。
交叉编译
交叉编译可以理解为,在当前编译平台下,编译出来的程序能运行在体系结构不同的另一种目标平台上,但是编译平台本身却不能运行该程序:
比如,我们在 x86 平台上,编写程序并编译成能运行在 ARM 平台的程序,编译得到的程序在 x86 平台上是不能运行的,必须放到 ARM 平台上才能运行。
之所以要有交叉编译,主要原因是:嵌入式系统中的资源太少。交叉编译出来的程序,所要运行的目标环境中,各种资源,都相对有限,所以很难进行直接的本地编译。 具体地讲,可以分为4个方面的原因:
Speed: 目标平台的运行速度往往比主机慢得多,许多专用的嵌入式硬件被设计为低成本和低功耗,没有太高的性能Capability: 整个编译过程是非常消耗资源的,嵌入式系统往往没有足够的内存或磁盘空间Availability: 即使目标平台资源很充足,可以本地编译,但是第一个在目标平台上运行的本地编译器总需要通过交叉编译获得Flexibility: 一个完整的Linux编译环境需要很多支持包,交叉编译使我们不需要花时间将各种支持包移植到目标板上交叉编译的困难点在于两个方面: 1:不同的体系架构拥有不同的机器特性,如是64位还是32位系统等 2:交叉编译时的主机环境与目标环境不同
首先编译过程是按照不同的子功能,依照先后顺序组成的一个复杂的流程,如下图:
1、什么是工具链
所谓的工具链,两部分的含义:
a – 工具 工具,是用来干活的,也就是生成(可以运行的)程序或库文件
而为了达成此目标,内部的执行过程和逻辑主要包含了:
1)、编译
编译的输入(对象)是:程序代码 编译输出(目标)是:目标文件 编译所需要的工具是:编译器 编译器,常见的编译器,即为gcc2)、链接
链接的输入(对象)是:(程序运行时所依赖的,或者某个库所依赖的另外一个)库(文件) 链接的输出(目标)是:程序的可执行文件,或者是可以被别人调用的完整的库文件 链接所需要的工具是:链接器 链接器,即ld为了将程序代码,编译成可执行文件,涉及到编译,链接(等其他步骤),要依赖到很多相关的工具,最核心的是编译器gcc,链接器ld。而此处,所谓的工具,主要指的就是:和程序编译链接等相关的gcc,ld等工具 Binutils Binutils是GNU工具之一,它包括链接器、汇编器和其他用于目标文件和档案的工具,它是二进制代码的处理维护工具。
b – 链 之所以能称为链,说明是将不止一个东西按照对应的逻辑,串在一起。
不止一个东西:指的是就是和程序编译链接等相关的gcc,binutils等工具
按照对应的逻辑:指的就是,按照程序本身编译链接的先后顺序,即:先编译,后链接,再进行后期其他的处理等等,比如用objcopy去操作相应的目标文件等等。 如此的,将: 和程序编译链接等相关的gcc,binutils等工具按照先编译后链接等相关的编译程序的内在逻辑串起来,就成了我们所说的:工具链
2、什么是交叉工具链 普通所说的工具链指的是当前自己的本地平台的工具链。 用于交叉编译的工具链,就叫做交叉工具链。即编译的gcc,链接的ld等工具,用于交叉编译的,工具链,叫做交叉工具链。 交叉工具链,很明显,是用来,交叉编译,跨平台的程序所用的。交叉工具链,和(本地)工具链类似,也是包含了很多的,对应的工具,交叉编译版本的gcc,ld,as等等。但是,由于其中最最主要的是用于编译的gcc,所以,我们也常把:交叉工具链,简称为交叉编译器 即严格意义上来说,交叉编译器,只是指的是交叉编译版本的gcc。但是实际上为了叫法上的方便,我们常说的交叉编译器,都是指的是交叉工具链。常说的交叉编译版本的gcc,比如arm-linux-gcc,实际上指代了,包含一系列交叉编译版本的交叉工具链(arm-linux-gcc,arm-linux-ld,arm-linux-as等等)而此文中,后面,所说的,如无特殊指明,均用交叉编译器指代交叉工具链。
总结: 交叉编译就是在一种平台上编译出能运行在体系结构不同的另一种平台上的程序,比如在PC平台(X86 CPU)上编译出能运行在以ARM为内核的CPU平台上的程序,编译得到的程序在X86 CPU平台上是不能运行的,必须放到ARM CPU平台上才能运行,虽然两个平台用的都是Linux系统。 交叉编译工具链是一个由编译器、连接器和解释器组成的综合开发环境,交叉编译工具链主要由binutils、gcc和glibc三个部分组成。有时出于减小 libc 库大小的考虑,也可以用别的 c 库来代替 glibc,例如 uClibc、dietlibc 和 newlib。