交叉编译详解 一 概念篇

第 1 章 交叉编译简介

1.1 什么是交叉编译

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

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

本地编译

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

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

交叉编译

交叉编译可以理解为,在当前编译平台下,编译出来的程序能运行在体系结构不同的另一种目标平台上,但是编译平台本身却不能运行该程序:

比如,我们在 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)。

注意:严格意义上来说,交叉编译器,只是指交叉编译的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)。
  • systen:交叉编译链所选择的库函数和目标映像的规范,如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平台已经编译好的交叉编译链。我们只需要找到合适的,下载下来使用即可。

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

  1. http://ftp.arm.linux.org.uk/pub/armlinux/toolchain/ 下载已经编译好的交叉编译链
  2. http://www.denx.de/en/Software/WebHome 下载已经编译好的交叉编译链
  3. https://launchpad.net/gcc-arm-embedded下载已经编译好的交叉编译链
  4. 一些制作交叉编译链的工具中,包含了已经制作好的交叉编译链,可以直接拿来使用。如crosstool-NG
  5. 如果购买了某个芯片或开发板,一般厂商会提供对应的整套开发软件,其中就包含了交叉编译链。

厂家提供的工具一般是经过了严格的测试,并打入了一些必要的补丁,所以这种方式往往是最可靠的工具来源。

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

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

  1. crosstool-NG
  2. Buildroot
  3. Embedded Linux Development Kit (ELDK)

工具还有很多,各有各的优势和劣势,大家可以慢慢研究,在这就不细说了。

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

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

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

详细的搭建过程可以参看后续的文章,这里面有详细的参数和步骤:
交叉编译详解 二 从零制作交叉编译链

为了方便大家搭建交叉编译链,我写了一个一键生成的脚本(包括源码下载和自动编译)。如果大家自己一直搭建不成功,不妨试试这个脚本,然后对比下自己的流程是否一致,参数是否有差异,也许能帮大家迈过这个障碍:
交叉编译详解 三 使用脚本自动生成交叉编译链

4.4 对比三种构建方式

项目使用已有交叉编译链自己制作交叉编译链
安装一般提供压缩包需要自己打包
源码版本一般使用较老的稳定版本,对于一些新的GCC特性不支持可以使用自己需要的GCC特性的版本
补丁一般都会打上修复补丁普通开发者很难辨别需要打上哪些补丁,资深开发者可以针对自己的需求合入补丁
源码溯源可能不清楚源码版本和补丁情况一切都可以定制
升级一般不会升级可以随时升级
优化一般已经针对特定CPU特性和性能进行优化一般无法做到比厂家优化的更好,除非自己设计的CPU
技术支持可以通过FAE进行支持,可能需要收费只能通过社区支持,免费
可靠性验证已经通过了完善的验证自己验证,肯定没有专业人士验证的齐全

参考资料

[1] Introduction to cross-compiling for Linux

[2] binutils介绍

[3] glibc 各个库作用介绍

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

[5] Glibc vs uClibc Differences

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

  • 165
    点赞
  • 547
    收藏
  • 打赏
    打赏
  • 8
    评论
http://man.chinaunix.net/linux/lfs/htmlbook/chapter06/chapter06.html参考具体的gcc相关软件安装 本人的联系方式为:549827768@qq.com,西华大学 我们采用crosstool0.42来作为我们编译交叉编译工具链的脚本。详细的用法说明请阅读网站上的文档crosstool-how to 。 [zzl@localhost] tar -xzvf crosstool-0.43.tar.gz [zzl@localhost]cd crosstool-0.42 我们可以看到目录下有很多.sh脚本和.dat配置文件。每一个支持的CPU都有它所相应的脚本,如我们选用demo-arm9tdmi.sh 需要我们记住的三个重要的变量: TARBALLS_DIR=$HOME/downloads #$HOME为用户的主目录,如fedora这个目录,是固定的,与$PWD为当前路径不同 RESULT_TOP=/usr/local/arm #做了更改 GCC_LANGUAGES="c,c++" 我们需要如下压缩包:gcc-3.4.1.tar.gz glibc-2.3.3.tar.gz linux-2.6.17binutils-2.15.tar.gz glibc-linuxthreads-2.3.3.tar.gz gdb6.0a.tar.gz,且还要下载内核arm补丁,给它打补丁,之后再压缩成原来格式,并删除解压的文件,只保留打补丁后的文件 下面为打补丁的格式,其中linux为linux内核解压后产生的目录: tar jxvf patch-2.4.18-rmk7.bz2;cp patch-2.4.18-rmk7 linux;cd linux;patch -p1<patch-2.4.18-rmk7 最后再次还原成原来的包文件:tar czvf linux-2.4.18.tar.gz linux ,即将linux目录及其文件打包为前面的文件名 首要任务是下载这些源代码软件包,并将它们放在/home/fedora/downloads下面,保证这些包的所有者为当前用户而不是根用户。 可以用chown usr 文件名,更改使用者,更改后的使用者为usr,我的用户名为fedora,可以用ll查看用户名 我们选择的配置是:demo-arm9tdmi.sh,其内容具体如下: #!/bin/sh set -ex TARBALLS_DIR=$HOME/downloads RESULT_TOP=/usr/local/arm #原本是:/opt/crosstool ,后修改了 export TARBALLS_DIR RESULT_TOP GCC_LANGUAGES="c,c++" export GCC_LANGUAGES # Really, you should do the mkdir before running this, # and chown /opt/crosstool to yourself so you don't need to run as root. mkdir -p $RESULT_TOP #应该先创建/usr/local/arm目录,并chmod fedora /usr/local/arm 目录的用户为fedora #-p, --parents 需要时创建目标目录的上层目录,但即使这些目录已存在也不当作错误处理 # Build the toolchain. Takes a couple hours and a couple gigabytes. eval `cat arm9tdmi.dat gcc-3.2.3-glibc-2.2.5.dat` sh all.sh --notest --gdb#增加调试器 echo Done. 从 eval `cat arm9tdmi.dat gcc-3.2.3-glibc-2.2.5.dat` sh all.sh --notest --gdb 可以看出,我们的gcc版本采用3.2.3,glibc版本采用2.2.5。 我们再来看gcc-3.2.3-glibc-2.2.5.dat这个文件,并做一些更改 BINUTILS_DIR=binutils-2.15 GCC_DIR=gcc-3.2.3 GLIBC_DIR=glibc-2.2.5 LINUX_DIR=linux-2.4.18 #修改后的内容,为了匹配内核 GLIBCTHREADS_FILENAME=glibc-linuxthreads-2.2.5 GDB_DIR=gdb-6.0 #增加的内容 修改 armtdmi.dat 文件如下红色部分: KERNELCONFIG=`pwd`/arm.config TARGET=arm-9tdmi-linux-gnu(这个名字可以改成你想要的交叉工具链前缀名) TARGET_CFLAGS="-O" GCC_EXTRA_CONFIG="--with-cpu=arm9tdmi --enable-cxx-flags=-mcpu=arm9tdmi" 修改all.sh 文件如下: 修改 all.sh 文件第 41 行,指定存放工具链文件夹的名称; vimall.sh +41 将:TOOLCOMBO=$GCC_DIR‐$GLIBC_DIR 改为: TOOLCOMBO=3.2.3 #gcc版本号作为文件名 修改第 70 行,更改安装路径,将: PREFIX=${PREFIX‐$RESULT_TOP/$TOOLCOMBO/$TARGET} 改为 PREFIX=${PREFIX‐$RESULT_TOP/$TOOLCOMBO} #即路径最终为:/usr/local/arm/3.2.3,gcc就在3.2.3的bin库中 最后: #vi /etc/profile在if代码 语句中添加绝对路径 PATH=$PATH :/usr/local/arm/3.2.3/gcc-3.2.3-glibc-2.2.5/arm9tdmi-linux-gnu/bin 也可以设置为临时变量:export PATH=$PATH :/usr/local/arm/3.2.3/gcc-3.2.3-glibc-2.2.5/arm9tdmi-linux-gnu/bin 但每次开机要重启,此时我们编译器就上上述的路径中,包含arm-9tdmi-linux-gnu-gcc,arm-9tdmi-linux-gnu-g++,arm-9tdmi-linux-gnu-ld 如果gcc版本太高,可以用 yum install compat-gcc-34 ,3.4版本的gcc不过之前应该在/usr/bin下重命名gcc,以保证之后还能运行,可以查看它的版 本,cat /proc/version,用它的版本号来重命名,gcc -v查看当前gcc版本号 ftp://ftp.sunet.se/pub/Linux/distributions/scientific/53/i386/SL/ 上面这个网站中有一些低版本的gcc和glibc,另外还有一些nfs工具等等,其中就有以compat开头的gcc和glibc,另外当然还有以gcc、glibc开头的 specs文件最后在/usr/local/arm/3.2.3/gcc-3.2.3-glibc-2.2.5/arm9tdmi-linux-gnu/lib中,specs文件中一般有一句/lib/ld-linux.so.2,有可能要修改为自己的库

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论 8

打赏作者

p_fly

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值