简介
- 交叉编译相关笔记
交叉编译器(维基百科)
交叉编译器(Cross compiler)是指一个在某个系统平台下可以产生另一个系统平台的可执行文件的编译器。交叉编译器在目标系统平台(开发出来的应用程序所运行的平台)难以或不容易编译时非常有用
交叉编译器的存在对于一个开发主机为多个平台编译代码是非常有必要的。直接在平台上编译有时行不通,例如在一个嵌入式系统的单片机,因为他们没有完整的现代操作系统环境,无法直接编译
交叉编译器和源代码至源代码编译器不同,交叉编译器用于二进制代码的跨平台软件开发,而源到源编译器是将某种编程语言的程序源代码作为输入,生成以另一种编程语言构成的等效源代码的编译器,但是两者都是编程工具。
交叉编译器的基本用法就是将构建环境和目标环境分开。常常在下面几种情况中使用
- 嵌入式电脑
- 编译多个目标库
- 在服务器上编译
- 引导一个新平台(Booststrapping)
程序虚拟机(例如JVM)也借鉴了当初开发交叉编译器的理念。它可以用同一份输出在多个目标系统上运行,但是编译后的代码必须运行在虚拟机上。
理解交叉编译(Cross compile)
三个名词: build, host, target
- build: 构建gcc编译器的平台系统环境,编译该软件使用的平台
- host: 是执行gcc编译器的平台系统环境,该软件运行的平台
- target: 是让gcc编译器产生能在什么格式运行的平台的系统环境,该软件处理的目标平台
build和host不同是交叉编译器
build和target不同是交叉编译链
三者都相同则为本地编译
什么是交叉编译
- 在解释什么是交叉编译之前,先要明白什么是本地编译
- 本地编译可以理解为,在当前编译平台下,编译出来的程序只能放到当前平台下运行。
- 交叉编译可以理解为,在当前编译平台下,编译出来的程序能运行在体系结构不同的另一种目标平台上,但是编译平台本身却不能运行该程序
为什么会有交叉编译
- Speed: 目标平台的运行速度往往比主机慢的多,许多专用的嵌入式硬件被设计为低成本和低功耗,没有太高的性能
- Capability: 整个编译过程是非常消耗资源的,嵌入式系统往往没有足够的内存或磁盘空间
- Availability: 即使目标平台资源很充足,可以本地编译,但是第一个目标平台上运行的本地编译器总需要通过交叉编译获得
- Flexibility: 一个完整的Linux编译环境需要很多支持包,交叉编译使我们不需要花时间将各种支持包移植到目标板上
为什么交叉编译比较困难
不同的体系架构拥有不同的机器特性
- word size: 是64位还是32位系统
- endianness: 是大端还是小端系统
- alignment: 是否必须按照4字节对齐方式进行访问
- default signedness: 默认数据类型是有符号还是无符号
- nommu: 是否支持MMU
交叉编译时的主机环境与目标环境不同
- configuration issues
- HOSTCC vs TARGETCC
- toolchain leaks
- libraries
- testing
什么是交叉编译链
- 编译过程是按照不同的子功能,依照先后顺序组成的一个复杂的流程
- 编译过程包括了预处理,编译,汇编,链接等功能。既然有不同的子功能,那每个子功能都是一个单独的工具来实现,它们组合在一起形成了一个完整的工具集。
- 同时编译过程又是一个有先后顺序的流程,他必然牵涉到工具的使用顺序,每个工具按照先后关系串联在一起,这就形成一个链式结构。
- 因此,交叉编译链就是为了编译跨平台体系结构的程序代码而形成的由多个子工具构成的一套完整的工具集。同时,它隐藏了预处理,编译,汇编,链接等细节,当我们指定了源文件时,它会自动按照编译流程调用不同的子工具,自动生成最终的二进制程序映像(.bin)
- 注意:
- 严格意义上,交叉编译器,只是指交叉编译的gcc,但是实际上为了方便,我们常说的交叉编译器就是交叉工具链。这两个概念,都是指编译链
交叉编译链的命名规则
我们使用交叉编译链时,常常会看到这样的名字
1
2
3arm-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-这些交叉编译链的命名规则是通用的,有一定的规则: 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等价于 glib + eabi
注意:这个规则是一个猜测,并没有在哪份官方资料上看到过。而且有些编译链的命名确实没有按照这个规则,也不清楚这是不是历史原因造成的
交叉编译包含的工具
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
GNU编译器套件,支持C, C++, Java, Ada, Fortran, Objective-C等众多语言。
Linux上通常使用的C函数库为glibc。glibc是linux系统中最底层的api,几乎其它任何运行库都会依赖于glibc。glibc除了封装linux操作系统所提供的系统服务外,它本身也提供了许多其它一些必要功能服务的实现。
因为嵌入式环境的资源及其紧张,所以现在除了glibc外,还有uClibc和eglibc可以选择
GDB用于调试程序
如何得到交叉编译链
下载已经做好的交叉编译链
- 使用其他人针对某些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
- 如果购买了某个芯片或开发板,一般厂商会提供对应的整套开发软件,其中就包含了交叉编译链。
- 厂家提供的工具一般是经过了严格的测试,并打入了一些必要的补丁,所以这种方式往往是最可靠的工具来源。
使用工具定制交叉编译链
- 使用现存的制作工具,以简化制作交叉编译链这个事情的复杂度。我们只需要了解有哪些工具可以实现,并选个合适的工具,搞懂它的操作步骤即可。
- crosstool-NG
- Buildroot
- Embedded Linux Development Kit(ELDK)
- 使用现存的制作工具,以简化制作交叉编译链这个事情的复杂度。我们只需要了解有哪些工具可以实现,并选个合适的工具,搞懂它的操作步骤即可。