标题：交叉编译
词义
一个经常会被问到的问题就是，“既然我们已经有了主机编译器，那为什么还要交叉编译呢？”其实答案很简单，没办法啊！有时是因为目的平台上不允许或不能够安装我们所需要的编译器，而我们又需要这个编译器的某些特征；有时是因为目的平台上的资源贫乏，无法运行我们所需要编译器；有时又是因为目的平台还没有建立，连操作系统都没有，根本谈不上运行什么编译器。  
另一个经常会被问到的问题就是：“既然可以交叉编译，那还要主机编译干吗？”其实答案也很简单，交叉编译是不得已而为之！与主机编译相比，交叉编译受的限制更多，虽然在理论上我们可以做任何形式的交叉编译，但事实上，由于受到专利、版权、技术的限制，并不总是能够进行交叉编译，尤其是在业余条件下！举例来说，我们至今无法生成惠普公司专有的som格式的可执行文件，因此我们根本无法做目的平台为HPPA-HPUX的交叉编译。
就我们这个项目而言，需要交叉编译的原因有两个：首先，在项目的起始阶段，目的平台尚未建立，因此需要做交叉编译，以生成我们所需要的bootloader（启动引导代码）以及操作系统核心；其次，当目的平台能启动之后，由于目的平台上资源的限制，当我们编译大型程序时，依然可能需要用到交叉编译。
交叉编译这个概念的出现和流行是和嵌入式系统的广泛发展同步的。我们常用的计算机软件，都需要通过编译的方式，把使用高级计算机语言编写的代码（比如C代码）编译（compile）成计算机可以识别和执行的二进制代码。比如，我们在Windows平台上，可使用Visual C++开发环境，编写程序并编译成可执行程序。这种方式下，我们使用PC平台上的Windows工具开发针对Windows本身的可执行程序，这种编译过程称为native compilation，中文可理解为本机编译。然而，在进行嵌入式系统的开发时，运行程序的目标平台通常具有有限的存储空间和运算能力，比如常见的 ARM 平台，其一般的静态存储空间大概是16到32MB，而CPU的主频大概在100MHz到500MHz之间。这种情况下，在ARM平台上进行本机编译就不太可能了，这是因为一般的编译工具链（compilation tool chain）需要很大的存储空间，并需要很强的CPU运算能力。为了解决这个问题，交叉编译工具就应运而生了。通过交叉编译工具，我们就可以在CPU能力很强、存储空间足够的主机平台上（比如PC上）编译出针对其他平台的可执行程序。
要进行交叉编译，我们需要在主机平台上安装对应的交叉编译工具链（cross compilation tool chain），然后用这个交叉编译工具链编译我们的源代码，最终生成可在目标平台上运行的代码。常见的交叉编译例子如下：
1、在Windows PC上，利用ADS（ARM 开发环境），使用armcc编译器，则可编译出针对ARM CPU的可执行代码。
2、在Linux PC上，利用arm-linux-gcc编译器，可编译出针对Linux ARM平台的可执行代码。
3、在Windows PC上，利用cygwin环境，运行arm-elf-gcc编译器，可编译出针对ARM CPU的可执行代码。
基础知识
在做实际工作之前，我想我们应该先掌握一些关于交叉编译的基本知识，其实说白了也就是理解一些我们经常会碰到的英文单词：
宿主机（host） ：编辑和编译程序的平台，一般是基于X86的PC机，通常也被称为主机。
目标机（target）：用户开发的系统，通常都是非X86平台。host编译得到的可执行代码在target上运行。
prefix: 交叉编译器的安装位置。
xxx-xxxx-xxxxx 平台描述。
我们在主机平台上开发程序，并在这个平台上运行交叉编译器，编译我们的程序；而由交叉编译器生成的程序将在目的平台上运行。这里值得说明得是平台描述，象arm-linux、i386-pc-linux2.4.3这样的字符串我们经常会看到，其实它是用来描述平台的，它有完整格式、缩减格式和别名之分。完整格式是：CPU-制造厂商-操作系统，如sparc-sun-sunos4.1.4，说明平台所使用的CPU是sparc，制造厂商是sun，上面运行的操作系统是SunOS，版本是4.1.4。当然，我们都不愿记这么长的东西，因此可以使用短格式，短格式中有选择地去除了制造厂商、软件版本等信息，因此我们同样可以用sparc-sunos或sparc-sunos-sunos4来描述这个平台。如果觉得这个还是太麻烦，那就可以使用别名，sun4m就可以很简单地描述这个平台。需要注意的是，并不是所有的平台都有别名，也不是所有的短格式都可以正确地描述平台。
准备素材
怎么说呢，你先得准备好主机平台，对我们这个项目来说，我们建议采用x86 Linux做主机平台，因为这样需要的设置工作最少。当然你也可以使用你所喜欢的平台或你所能得到的平台，其中的区别在于你可能必须做更多的设置工作，当然也有这种可能，就是你所选择的主机平台根本不能生成适用于目标平台的正确的交叉编译器。
对于交叉编译器，可以自己生成，也可以从网上下载。区别在于从网上下载非常简单方便，但也许你找不到适合你所选择的平台的。而自己生成交叉编译器，有时会遇到很多挫折，但这的确是个有趣的值得怀念的经历。
如果你想自己生成交叉编译器，那你必须先准备下面这些东西
1、磁盘空间。至少要500M左右的空间，如果想一气呵成的话，那就要900M-1G的空间。
2、各种源代码。你至少要准备binutils-2.11.2、gcc-2.95.3、linux-2.4.6、newlib-1.8.2或glibc-2.2.2的源代码。
如果你所使用的主机平台不是运行的linux，那你还必须注意以下这些问题
1、GNU bash必须是默认shell，所以你也许得把/bin/sh改成bash。
2、你要确认已经安装了GNU bison，因为这些软件同样使用了bison扩展。
3、GNU gmake最好是系统默认的make，因为这些软件都使用了gmake扩展，如果不是，在需要make时，记得使用gmake。
4、如果你想生成交叉glibc，则GNU gsed必须是默认sed，因为glibc会用到gsed的扩展。
5、如果你想生成交叉glibc，那还必须准备glibc-linuxthreads-2.2.2的源代码。
6、确认正确的路径搜索顺序，最好让GNU软件首先被执行。
编译器
我们建议使用现成的脚本来生成交叉编译器，因为在配置交叉编译器时，会经常使用一些难以理解的开关项。
研究实现
伴随着以计算机技术、通讯技术为主的信息技术的飞速发展和互联网的广泛应用，3C(Computer、Communication、ConsumerElectronic)合一将成为必然趋势。信息家电，手持设备，移动设备等嵌入式产品的迅速发展，使得嵌入式软件开发再度成为一个研究热点。 由于嵌入式设备的性能局限，往往不能通过本机编译得到所需软件的可执行程序。因此，以Linux为主机操作系统，搭配一个交叉编译系统，为嵌入式设备生成可执行程序已成为日益流行的编译嵌入式软件的解决方案。而开放源码的编译器GCC，经过多年的发展，已能支持几乎所有知名厂商的处理器，是嵌入式软件开发中理想的交叉编译器。 但现有GCC支持的平台并不能满足层出不穷的嵌入式产品的开发需要，仍有许多平台得不到支持。本论文以交叉编译系统ZLTCG的开发为背景，详细介绍了交叉编译系统GCC的体系结构，对其高度可移植性所依赖的中间表示和机器描述技术进行深入研究，并在此基础上完成了GCC在目标机MIPSX上的移植工作。本文根据新目标机的特点，利用了指令拆分，延时槽调度，窥孔优化等技术，既实现了对新目标机的支持，又吸收了原有系统高度优化和可移植的优点。 论文首先概述了编译系统的发展背景和原理，重点介绍了编译器系统的系统结构、自举与移植。然后介绍了交叉编译系统ZLTCG的开发背景和体系结构。第二章详细分析了编译器GCC，重点说明了GCC的设计思想，系统结构及其中间语言和机器描述文件机制。第三章介绍了交叉编译系统的移植过程，重点解释了移植的思路和方法，移植的准备工作，移植的具体步骤，实现难点及相关的一些技术细节，并给出了移植成功后的测试结果。其中移植的准备工作中详细说明了目标机MIPSX的系统结构和应用二进制接口的定义，而移植的具体步骤中详细阐述了对编译器后端的移植过程。最后是一点总结和展望。