安装交叉编译工具链_ARM-GCC

本地编译:编译器和目标程序都是相同构架的编译过程。
交叉编译:编译器和目标程序运行在不同架构的编译过程。

为什么需要交叉编译?
目标平台受自身性能(空间、运算速度)的限制,不能安装编译器或编译速度过慢等原因,需要其他高速硬件平台进行编译。

编译器类型

  • arm-linux-gnueabihf-gcc:
    • 名称中的Linux表示目标应用程序是运行在Linux操作系统之上的,例如前面的hello.c程序。
  • arm-none-eabi-gcc,

    • 名称中的none表示无操作系统,目标应用程序的运行环境是不带操作系统的,例如裸机代码、uboot、内核代码本身。

      安装方式

  • 直接在Ubuntu下使用APT包管理工具下载安装,操作简单,在本章节我们直接使用该方式安装即可。

  • 自行下载第三方制作好的工具链,如Linaro,好处是选择丰富,能找到很多不同的版本。
  • 使用crosstool-ng根据需要自己制作,过程复杂,不推荐。

在主机上执行如下命令

  1. sudo apt install gcc-arm-linux-gnueabihf

安装完成后使用如下命令查看版本
arm-linux-gnueabihf-gcc –v
可以看到下图的内容,它表明交叉编译工具链安装成功了,输出信息表明了它是7.4.0版本的编译器,其中的 “Target:arm-linux-gnueabihf”也表明了它的目标架构。

安装完成后输入**arm-linux-gnueabihf-**
再按两下TAB键,终端会提示可用的相关命令,如下图包含了ARM-GCC工具链Binutils的各种工具。

image.png

如何选择编译器

我们可以在它官网的如下地址找到它提供的ARM交叉编译器:https://releases.linaro.org/components/toolchain/binaries/

image.png

  1. #在hello.c程序所在的目录执行如下命令
  2. arm-linux-gnueabihf-gcc hello.c o hello
  3. #以下命令在主机上运行
  4. readelf -a hell

以下命令在开发板上的终端上执行#切换至共享的NFS目录,下面的目录根据自己的配置修改cd /mnt/example/hello_c

查看是否有存在前面编译生成的文件

ls

执行主机编译的ARM平台程序

./h

```

编译器名称

arch [-os] [-(gnu)eabi(hf)] -gcc

字段含义 含义
arch 目标芯片架构
OS 操作系统
gnu C标准库类型
eabi 应用二进制接口
hf 浮点模式

arm-linux-gnueabihf-gcc编译器为例 :::info 表示它的目标芯片架构为ARM,
目标操作系统为Linux,
使用GNU的C标准库即glibc,
使用嵌入式应用二进制接口(eabi),
编译器的浮点模式为硬浮点hard-float。 :::

而另一种名为arm-linux-gnueabi- gcc的编译器与它的差别就在于是否带“hf”,
不带“hf”表示它使用soft-float模式。

编译器字段说明

目标芯片架构

指交叉编译器生成的程序运行的平台,如ARMMIPS,其中ARM交叉编译器又分为ARMv7、ARMv8及aarch64架构。
本书使用的i.MX 6ULL的内核为Cortex-A7,它使用的是ARMv7架构。 arm-linux-gnueabihf-gcc直接以arm表示ARMv7架构。

大小端

指目标芯片的大小端模式,i.MX 6ULL使用的是小端模式。
若是大端模式(big edian),编译器名字中会带“be”或“eb”字段进行标标注
boundary-end ———

目标操作系统

要有Linux或bare-metal(无操作系统)两种。

严格来说,我们编译Linux应用程序时应该使用带“linux”的编译器,而编译uboot、裸机程序时,应该使用“bare-metal”类型的裸机编译器,但很多开发者常常把它们混用也没有出现问题,这一般是因为开发者编写的裸机程序本身就没有使用到Linux系统提供的API,所以才不会出错。

C标准库类型

通常有gnu、uclibc等,别表示GNU的glibc库和uclibc库。
除了裸机编译器不带C库之外,其它编译器的C库类型都是glibc库的,如arm-linux-gnueabihf-gcc。

应用二进制接口

应用二进制接口(Application Binary Interface),描述了应用程序和操作系统之间或其他应用程序的低级接口。
在编译器选项中主要有“abi”和“eabi”两种类型,
abi通常用在x86架构上
eabi表示embed abi,即嵌入式架构,如ARM、MIPS等。

浮点模式

部分ARM处理器带浮点运算单元,代码需要进行浮点运算时若交给fpu处理,可以加快运算速度。编译器针对浮点运算的不同处理情况提供了以下几种模式:

  • hard: 硬浮点类型(hard-float),采用fpu参与浮点运算。 arm-linux-gnueabihf-gcc、armeb-linux-gnueabihf-gcc都是硬浮点类型,即名字中带“hf”。
  • soft:软浮点类型(soft-float),即使有fpu浮点运算单元也不用,而是使用软件模式,arm-linux-gnueabi-gcc、armeb-linux-gnueabi-gcc都是软浮点类型,即名字中不带“hf”。
  • softfp:允许使用浮点指令,但保持与软浮点ABI的兼容性。

i.MX6ULL带有fpu,对于soft-float和hard-float模式都支持,不过本开发板中提供Linux文件系统中的库都是使用hard模式编译的,所以编写应用程序时也需要使用相同类型的编译器,否则会应用程序运行时会提示找不到库文件。

编译器版本号

通常来说高版本的编译器是向后兼容的,但开发特定程序时会使用固定的某个版本编译器,所以程序可能会依赖该版本的编译器,根据自己要编译的程序的要求选择即可。

编译器类型对程序的影响

每个系统所携带的库不同,可能会导致动态链接的程序不能运行。
软浮点类型编译器和硬浮点编译器所使用的库不同,如果软浮点编译的动态链接程序在硬浮点编译器的平台上运行,会报错(提示没有找到库文件)。

  • 解决方法(两种)
    • 采用静态链接,因为包含了所有程序执行所需的库文件。
    • 重新采用硬浮点编译器编译。

查看glibc库类型

使用readelf查看开发板的libc.so.6类型
readelf -h libc.so.6
表示开发板的glibc库文件libc.so.6为ARM架构的hard-float类型库
所以不带hf编译器生成的hello程序与它不兼容,无法正常运行。