[转] 什么是交叉编译(很好的入门文章)

第 1 章 交叉编译简介

1.1 什么是交叉编译

对于没有作过嵌入式编程的人,可能不太理解交叉编译的概念,那么什么是交叉编译?它有什么做用?html

在解释什么是交叉编译以前,先要明白什么是本地编译。linux

本地编译c++

本地编译能够理解为,在当前编译平台下,编译出来的程序只能放到当前平台下运行。平时咱们常见的软件开发,都是属于本地编译:git

好比,咱们在 x86 平台上,编写程序并编译成可执行程序。这种方式下,咱们使用 x86 平台上的工具,开发针对 x86 平台自己的可执行程序,这个编译过程称为本地编译。github

交叉编译编程

交叉编译能够理解为,在当前编译平台下,编译出来的程序能运行在体系结构不一样的另外一种目标平台上,可是编译平台自己却不能运行该程序:api

好比,咱们在 x86 平台上,编写程序并编译成能运行在 ARM 平台的程序,编译获得的程序在 x86 平台上是不能运行的,必须放到 ARM 平台上才能运行。架构

1.2 为何会有交叉编译

之因此要有交叉编译,主要缘由是:函数

Speed: 目标平台的运行速度每每比主机慢得多,许多专用的嵌入式硬件被设计为低成本和低功耗,没有过高的性能工具

Capability: 整个编译过程是很是消耗资源的,嵌入式系统每每没有足够的内存或磁盘空间

Availability: 即便目标平台资源很充足,能够本地编译,可是第一个在目标平台上运行的本地编译器总须要经过交叉编译得到

Flexibility: 一个完整的Linux编译环境须要不少支持包,交叉编译使咱们不须要花时间将各类支持包移植到目标板上

1.3 为何交叉编译比较困难

交叉编译的困难点在于两个方面:

不一样的体系架构拥有不一样的机器特性

Word size: 是64位仍是32位系统

Endianness: 是大端仍是小端系统

Alignment: 是否必修按照4字节对齐方式进行访问

Default signedness: 默认数据类型是有符号仍是无符号

NOMMU: 是否支持MMU

交叉编译时的主机环境与目标环境不一样

Configuration issues:

HOSTCC vs TARGETCC:

Toolchain Leaks:

Libraries:

Testing:

详细的对比能够参看这篇文章,已经写的很详细了,在这就不细说了:Introduction to cross-compiling for Linux

第 2 章 交叉编译链

2.1 什么是交叉编译链

明白了什么是交叉编译,那咱们来看看什么是交叉编译链。

首先编译过程是按照不一样的子功能,依照前后顺序组成的一个复杂的流程,以下图:

编译流程

那么编译过程包括了预处理、编译、汇编、连接等功能。既然有不一样的子功能,那每一个子功能都是一个单独的工具来实现,它们合在一块儿造成了一个完整的工具集。

同时编译过程又是一个有前后顺序的流程,它必然牵涉到工具的使用顺序,每一个工具按照前后关系串联在一块儿,这就造成了一个链式结构。

所以,交叉编译链就是为了编译跨平台体系结构的程序代码而造成的由多个子工具构成的一套完整的工具集。同时,它隐藏了预处理、编译、汇编、连接等细节,当咱们指定了源文件(.c)时,它会自动按照编译流程调用不一样的子工具,自动生成最终的二进制程序映像(.bin)。

PSobjcopy被用来复制一个目标文件的内容到另外一个文件中,可使用不一样于源文件的格式来输出目的文件,便可以进行格式转换。objdump用于显示二进制文件信息,经常使用来查看反汇编代码。

注意:严格意义上来讲,交叉编译器,只是指交叉编译的gcc,可是实际上为了方便,咱们常说的交叉编译器就是交叉工具链。本文对这两个概念不加以区分,都是指编译链。

2.2 交叉编译链的命名规则

咱们使用交叉编译链时,经常会看到这样的名字:

arm-none-linux-gnueabi-gcc

arm-cortex_a8-linux-gnueabi-gcc

mips-malta-linux-gnu-gcc

其中,对应的前缀为:

arm-none-linux-gnueabi-

arm-cortex_a8-linux-gnueabi-

mips-malta-linux-gnu-

这些交叉编译链的命名规则彷佛是通用的,有必定的规则:

arch-core-kernel-system

arch: 用于哪一个目标平台。

core: 使用的是哪一个CPU Core,如Cortex A8,可是这一组命名好像比较灵活,在其它厂家提供的交叉编译链中,有以厂家名称命名的,也有以开发板命名的,或者直接是none或cross的。

kernel:所运行的OS,见过的有Linux,uclinux,bare(无OS)。

system:交叉编译链所选择的库函数和目标映像的规范,如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 using DLLs.

gold A new, faster, ELF only linker, still in beta test.

gprof Displays profiling information.

nlmconv Converts object code into an NLM.

nm 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 an archive.

readelf 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

binutils介绍

3.2 GCC

GNU编译器套件,支持C, C++, Java, Ada, Fortran, Objective-C等众多语言。

3.3 GLibc

Linux上一般使用的C函数库为glibc。glibc是linux系统中最底层的api,几乎其它任何运行库都会依赖于glibc。glibc除了封装linux操做系统所提供的系统服务外,它自己也提供了许多其它一些必要功能服务的实现。

glibc 各个库做用介绍

由于嵌入式环境的资源及其紧张,因此如今除了glibc外,还有uClibc和eglibc能够选择,三者的关系能够参见这两篇文章:

uclibc eglibc glibc之间的区别和联系

Glibc vs uClibc Differences

3.4 GDB

GDB用于调试程序

第 4 章 如何获得交叉编译链

既然明白了交叉编译链的功能,那么在针对嵌入式系统开发时,咱们须要的交叉编译链从哪儿获得?

主要有三个方式能够获取

4.1 下载已经作好的交叉编译链

使用其余人针对某些CPU平台已经编译好的交叉编译链。咱们只须要找到合适的,下载下来使用便可。

常见的交叉编译链下载地址:

http://ftp.arm.linux.org.uk/pub/armlinux/toolchain/下载已经编译好的交叉编译链

http://www.denx.de/en/Software/WebHome下载已经编译好的交叉编译链

https://launchpad.net/gcc-arm-embedded下载已经编译好的交叉编译链

一些制做交叉编译链的工具中,包含了已经制做好的交叉编译链,能够直接拿来使用。如crosstool-NG

若是购买了某个芯片或开发板,通常厂商会提供对应的整套开发软件,其中就包含了交叉编译链。

厂家提供的工具通常是通过了严格的测试,并打入了一些必要的补丁,因此这种方式每每是最可靠的工具来源。

4.2 使用工具定制交叉编译链

使用现存的制做工具,以简化制做交叉编译链这个事情的复杂度。咱们只须要了解有哪些工具能够实现,并选个合适的工具,搞懂它的操做步骤便可。

  • crosstool-NG
  • Buildroot
  • Embedded Linux Development Kit (ELDK)

工具还有不少,各有各的优点和劣势,你们能够慢慢研究,在这就不细说了。

4.3 从零开始构建交叉编译链

这个是最困难也最耗时间的,毕竟制做交叉编译链这样的事情,须要对嵌入式的编译原理了解的比较透彻,至少要知道出了问题要往哪一个方面去翻阅资料。并且,也是最考耐心和细心的地方,配错一个选项或是一个步骤,均可能出现之前历来没见过的问题,并且这些问题每每还没法和这个选项或步骤直接联系起来。

固然若是搭建出来,确定也是收获最大的,至少对于编译的流程和依赖都比较清楚了,细节上的东西可能还须要去翻看相应的协议或标准,但至少骨架会比较清楚。

详细的搭建过程能够参看后续的文章,这里面有详细的参数和步骤:

交叉编译详解 二 从零制做交叉编译链

为了方便你们搭建交叉编译链,我写了一个一键生成的脚本(包括源码下载和自动编译)。若是你们本身一直搭建不成功,不妨试试这个脚本,而后对比下本身的流程是否一致,参数是否有差别,也许能帮你们迈过这个障碍:

交叉编译详解 三 使用脚本自动生成交叉编译链

4.4 对比三种构建方式

 

参考资料

[1] Introduction to cross-compiling for Linux

[2] binutils介绍

[3] glibc 各个库做用介绍

[4] uclibc eglibc glibc之间的区别和联系

[5] Glibc vs uClibc Differences

[6] 用crosstool-ng创建本身的ARM交叉编译工具链

[7] 交叉编译链下载地址

相关文章
相关标签/搜索