vlambda博客
学习文章列表

嵌入式杂谈之交叉编译器

这次扯一下嵌入式开发过程中经常用到的交叉编译器,虽说在之前的文章也提到过这个问题,不过上次是着重介绍为什么使用交叉编译器(主要是为了劝服自己从单片机的思想中脱离出来,慢慢的接受嵌入式Linux开发的一些约定俗成的工具与方法),而这次的重点一方面是科普交叉编译器的相关知识,另一方面着重介绍怎么使用交叉编译器提供的各种工具完成相应的任务。

废话少说,上干货。

交叉编译器选择

首先认可一点,交叉编译器是一个软件工具,那既然是一个软件,那就必须知道这个软件是怎么来的,目前分为 两种情况。
芯片厂商提供的或者开源的自己制作的交叉编译器。
自己制作交叉编译器比较麻烦,虽说制作步骤单一,但版本依赖关系大,而且必须了解编译原理等知识,耗时费力。
所以我们果断使用 芯片厂商提供的或者 开源的交叉编译工具链。

交叉编译器命名规则

arm-none-linux-gnueabi-
最最常用的一种,
第一个单词表示编译得的什么目标架构的
第二个单词是厂商名,可以是三星或者恩智浦等,但开源的一般都为none
第三个单词表示程序编译出来的程序默认应用的系统,因为编译器的标准C库等是与Linux兼容的
第四个单词gnu表示gnu项目
第四个单词eabi指的是嵌入式接口
可以简写为以下形式
arm-linux-
arm-none-eabi-
表示编译出来的程序不支持操作系统

交叉编译器源码目录介绍

交叉编译器包含的目录如上图所示

  • bin目录相当于交叉编译的命令集合,包含了数十种工具。
  • lib相当于交叉编译器运行的时候需要的库以及目标程序所需要的库。在这里我们需要知道,交叉编译器本身是一个程序软件,所以交叉编译器的运行工作需要依赖相关的库文件。
    另一方面交叉编译器需要将源文件进行编译,而编译得到的另一种架构上的代码运行也需要库文件。
    这就说明,交叉编译器需要两种库文件,一种是它本身需要的,另一种是编译出来的程序需要的。

添加交叉编译器命令到环境变量

为了让交叉编译器的命令不用指定绝对路径使用,所以需要添加环境变量 (如果有不明白什么是环境变量的,还是最好百度一下)。

  • 方案一:

echo $PATH查看当前系统环境变量

echo xxx >> PATH追加路径到环境变量,只针对当前shell起作用

  • 方案二:

编辑/etc/environment文件添加环境变量,可以永久保存。

但是修改完这个文件以后需要使用source /etc/environment命令将环境变量进行更新

交叉编译器中嵌入式工具集合

一、readelf
我们通常理解的程序软件都是运行在 操作系统 之上的,但是有的程序不能在不同的操作系统之上运行,也就是常说的不能跨平台。
这是因为:
我们最终编译出来的可执行程序分两部分: 真正的程序文件以及头信息 不同操作系统的 的格式是不同的,Windows上称为 PE头 ,Linux上称为 ELF头 这个头部信息是专门给 操作系统 识别的。
开发裸机的时候需要使用 objcopy 这个命令将头部信息取出来,留下真正的程序文件。 因为带有头文件的程序刚开始不是可执行代码,裸机状态下无法执行,会导致程序一开始就卡死。
所以我们在裸机开发的时候,在得到二进制文件以后再处理一下得到真正要烧写的文件就是可以理解的了(说实话,这一点我当时非常疑惑)
readelf 是读取可执行程序的头部信息
objcopy 是抽取头部信息然后丢弃掉 
使用方法: read -h 可执行程序名

综上所述,在可执行文件的头部有一个头信息可以被操作系统识别,进行解析。

在Linux上使用file命令可以查看可执行文件的相关信息,比如运行平台架构。嵌入式杂谈之交叉编译器

二、size 

读取可执行程序的大小 包含代码段,数据段,bss段等。嵌入式杂谈之交叉编译器当改变全局变量或者其他的时候,可以看到代码信息的改变。

关于程序的各种也是一块比较大的知识点,有机会补一篇文章(嵌入式杂谈之交叉编译器嵌入式杂谈之交叉编译器嵌入式杂谈之交叉编译器)

三、nm 

符号列表的概念,最精简,最好用的工具。

可以查看可执行程序的符号表,比如程序中的全局标签。嵌入式杂谈之交叉编译器嵌入式杂谈之交叉编译器T表示全局函数

D表示全局变量区

d表示 static 修饰的变量

t表示被 static 修饰的函数。

四、strip

剔除符号表。

相当于将刚才说的符号表进行剔除。因为程序运行的时候不需要符号表 ,剔除以后程序所占空间会大大减少。

使用file命令可以查看是否剔除符号表嵌入式杂谈之交叉编译器剔除符号表以后文件大小会变得更小一点。一般情况下,生产过程最后将最后的程序进行剔除符号表 

注意:arm架构的交叉编译器工具只能剔除arm架构程序的符号表,不能混用。

五、strings 

查看可执行程序的常量字符串。

六、objcopy 

表示将头部信息拷出来,不然无法识别相应程序。

七、objdump 

反汇编程序

objdump -d <name> 或者 -D表示反汇编文件。

为了分析程序以及定位错误,非常常用。

八、addr2line 

调试过程中将出错的结果以及行号标志出来 ,但一般用不到。