《二》概述
当我们需要从源代码编译出一个能运行在ARM 架构上的程序的时候,我们可以有两种方法。第一种是像我们平常一样,使用相同架构机器上的编译器,编译出运行在同一架构上的程序。在嵌入式系统领域,这是较难实现的。嵌入式系统的在设计的时候由于考虑到功耗,体积等要求,性能往往较弱。在编译一些比较大规模的程序时候,嵌入式系统在编译上耗费的时间,是我们无法忍受的。因此,我们需要使用交叉编译技术。
交叉编译技术,是一种在一个异构平台上编译出目标平台程序的一种技术。理论上来说,交叉工具链可以用在任何两种异构的系统中,例如,我们可以构建出PowerPC-ARM工具链,Sun Sparc-x86工具链等等。目前交叉工具链一般用于目标平台计算能力较弱,需要其他计算能力较强的平台帮助产生可运行软件的场合。在基于ARM的嵌入式系统开发中,我们一般会使用x86架构的计算机系统作为工作站,故最为常用的是x86-ARM交叉工具链。 目前市场上存在着各种各样不用的x86-ARM交叉工具链,有ARM公司自家在RVDS开发工具中整合的armcc,有Microsoft 在Platform Builder中的armv4I 编译器等。一般来说,这些由商业公司提供的工具链,都不会附有工具链相关的源代码和制作方法,灵活性不足,并且它们一般都与整套开发系统捆绑销售使用,成本较高。为了更好的理解这种技术和降低成本,获得更好的灵活性,市场上有不少的公司使用国际开源组织GNU开发的工具链作为他们产品开发的工具。本文下面的章节就为大家展示一个完整的GNU工具链构建过程。其中可能涉及到一些GNU Linux系统的基本操作知识,如果大家对此认识不深,请自行查阅相关资料。
《三》工具链原理及构建方法
3.1原理:
每一个软件,在编译的过程中,都要经过一系列的处理,才能从源代码变成可执行的目标代码。这一系列处理包括:预编译,高级语言编译,汇编,连接及重定位。这一套流程里面用到的每个工具和相关的库组成的集合,就称为工具链(tool chain)。以GNU的开发工具GCC为例,它就包括了预编译器cpp,c编译器gcc,汇编器as,和连接器ld等。在GNU自己对工具链定义中,还加进了一套额外的用于处理二进制包的工具包binutils,整个工具链应该是GCC+binutils+Glibc,不过大家后面将会看到binutils其实与Glibc无关,它是可以被独立安装的,所以GNU工具链也可以狭义地被理解为GCC+Glibc。
一般的情况下,工具链运行的环境和它产生的目标代码的环境是一致的。例如我们在VC中编译一个程序,工具链运行在x86平台,产生的也是运行在x86平台上的代码。但实际上,工具链产生的目标代码的运行平台是可以跟工具链运行的环境不一致的。这种产生与运行环境不一致的目标代码的工具链,称为交叉工具链(cross-compiler tool chain),使用这种工具链的编译过程对应地被称为交叉编译(cross-compile)。在GNU中,一般在普通工具链名称的前面加上特定的前缀,以表示是什么类型的工具链。例如x86-arm的工具链,预编译器是arm-linux-cpp,c编译器arm-linux-gcc等。
要构建出一个交叉工具链,需要解决三个问题。一是这个工具链必须是可以运行在原工作站平台上的。二是我们需要更换一个与目标平台对应的汇编器,使得工具链能产生对应的目标代码,三是要更换一套与目标平台对应的二进制库,使得工具链在连接时能找到正确的二进制库。
3.2构建方法
3.2.1建立binutils
首先我们建一个目录,作为存放工具链的地方。因为binutils和Glibc头文件的独立性,我们先把他们放到这个目录里面。如示意图1所示
示意图
1
(新加入内容以下划线标记)
3.2.2 建立GCC Stage1
然后我们使用工作站平台的工具链,编译出一条交叉工具链,通过指定工具链的类型,我们可以控制该工具链汇编器的输出类型。但此时该工具链指向库依然是工作站平台的二进制库。此阶段称为GCC Stage1。如示意图2所示
示意图2(新加入内容以下划线标记)
3.2.3 建立构建一个目标平台的二进制库
接下来我们利用刚刚建立的GCC构建一个目标平台的二进制库。由于二进制库都是自包含的,所以我们无需担心这个二进制库中会调用工作站平台的库进而产生依赖问题。见示意图3
示意图3(新加入内容以下划线标记)
3.2.4 建立GCC Stage2
最后我们使用工作站平台的工具链重新编译一次GCC,使得GCC指向新编译出来的库,此阶段称为GCC Stage2。见示意图4
示意图4(新加入内容以下划线标记)
所有评论(0)