专栏首页HackforFun一次搞定 Arm Linux 交叉编译

一次搞定 Arm Linux 交叉编译

为什么要交叉编译

交叉编译其实是相对于本地编译(native build)来说的,我相信大家最开始学习 C/C++ 这些语言的时候,都是在电脑上写程序,然后在电脑上编译生成可执行文件,最后在电脑上运行。程序的编辑——》编译——》运行,整个过程都是在一台 X86 电脑上。

当我们开始接触嵌入式开发后,事情变的不一样了,你在电脑上写程序,在电脑上编译出可执行文件,最后这个可执行文件需要下载到你的开发板上运行。程序最后运行的环境变了,比如你的开发板是基于 Arm 的——程序在 X86 上编辑,编译,最终运行在另一个和 X86 完全不同的架构的 Arm 芯片上。

之所以整个流程变成了这个样子,这是由嵌入式系统的特性决定的:一般嵌入式系统里面使用的芯片性能都比较弱,而且绝大部分都不能像 X86 一样运行 Windows/Ubuntu 桌面系统,即使能运行,性能也很弱,无法给你提供一个在开发板上写代码、编译代码的环境。所以我们还是离不开 X86 电脑强大高效的桌面环境进行软件开发。

但是这样有一个问题,X86、Arm、MIPS、RISC-V 这些芯片,它们的指令集是由不同的组织或者公司设计的,彼此并不兼容——Arm 和 MIPS 的 CPU 无法运行以 X86 的指令集编码的程序,反之亦然。所以我们要在 X86 的电脑上编译出能够在 Arm 上运行的程序,我们必须明确告诉编译器,编译生成的可执行文件需要以 Arm 指令集的标准编码。为了让这个流程变得简单,开发者们为不同的芯片开发了不同的编译器,比如针对 Arm 平台的 arm-linux-gcc,针对 mips 平台的 mips-linux-gnu-gcc,这些编译器都是基于 GCC 针对具体的架构指令集进行对应配置,所以它们在运行的时候就就会生成和该目标平台对应的可执行文件。

这篇文章主要讲 Arm 的交叉编译,所以这里后面都以 Linux 开发环境下的 Arm gcc 为例。

工具链的种类

GCC 的命名规则为:arch [-vendor] [-os] [-(gnu)eabi]-gcc

比如 arm-linux-gnueabi-gccarm-none-eabi-gccaarch64-linux-gnu-gcc

  • 带 [] 的是可选部分。
  • arch:芯片架构,比如 32 位的 Arm 架构对应的 arch 为 arm,64 位的 Arm 架构对应的 arch 为 aarch64。
  • vendor :工具链提供商,大部分工具链名字里面都没有包含这部分。
  • os :编译出来的可执行文件(目标文件)针对的操作系统,比如 Linux。

arm-none-eabi-gcc 一般适用用于 Arm Cortex-M/Cortex-R 平台,它使用的是 newlib 库。

arm-linux-gnueabi-gcc 和 aarch64-linux-gnu-gcc 适用于 Arm Cortex-A 系列芯片,前者针对 32 位芯片,后者针对 64 位芯片,它使用的是 glibc 库。可以用来编译 u-boot、linux kernel 以及应用程序。

另外需要补充一点的是,32 位的 Arm 和 64 位的 Arm,它们的指令集是不同的,所以需要使用不同的工具链。当然,Arm64 为了保证前向兼容,提供了一个 32 位的兼容模式,所以我们用 arm-linux-gnueabi-gcc 编译的应用程序也是可以直接在Arm64 的系统上运行的,但是 Linux Kernel 和 U-Boot 就不行,除非你提前把 CPU 切换到 32 位模式。曾经有个项目使用了一颗四核的 Arm64 芯片,但是内存只有64M,为了节省空间,在 CPU 运行到 U-Boot 之前,我们就把它切到了 32 位模式,后面的 U-Boot、Linux Kernel,应用全部都用 32 位编译,加上 Thumb 指令集,节省了不少空间。

工具链的下载安装

下载地址

现在 Arm 平台上用的最广泛的工具链是 Linaro 发布的,大家可以到 Linaro 官网下载,地址如下:

http://releases.linaro.org/components/toolchain/binaries/

同时我发现 Linaro 申明称后续新版本的工具链会通过 Arm 官方发布。

https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain

4.9、6.3、7.4 这些是工具链的版本号,理论上越新的版本,性能越好。

在一次优化 u-boot 大小的时候我发现 6.3 版本的工具链生成的二进制文件要比 4.9 版本生成的小几百个字节,进一步对比分析后发现是因为 6.3 版本的工具链把代码中没用到的一些字符串全部过滤掉了,虽然 4.9 的版本也有过滤,但是没有 6.3 做的干净。

目前用的多的版本应该是 6.x,当然我也看到有些开发组织在使用 7.x 的工具链,比如 Armbian 目前在用 7.4 编译内核。

另外目前最新版本的 U-Boot 已经强制必须使用 6.0 以上版本的 GCC 进行编译。

这两个网站下载可能会比较慢,可以考虑使用国内的镜像下载:

https://mirrors.tuna.tsinghua.edu.cn/armbian-releases/_toolchains/

下载

可以直接点击下载,也可以通过命令行用 wget 命令下载:

wget https://mirrors.tuna.tsinghua.edu.cn/armbian-releases/_toolchains/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf.tar.xz
wget https://mirrors.tuna.tsinghua.edu.cn/armbian-releases/_toolchains/gcc-linaro-6.4.1-2017.11-x86_64_aarch64-linux-gnu.tar.xz

下载了两个,arm 针对是是 32 位的, aarch64 针对 Arm64.

安装

解压:

xz -d gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf.tar.xz
xz -d gcc-linaro-6.4.1-2017.11-x86_64_aarch64-linux-gnu.tar.xz

安装到 /usr/local/toolchain/ 目录下,当然也可以放在其他任何你喜欢的地方:

sudo mkdir -p /usr/local/toolchain
tar -xvf gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf.tar -C /usr/local/toolchain/
sudo tar -xvf gcc-linaro-6.4.1-2017.11-x86_64_aarch64-linux-gnu.tar -C /usr/local/toolchain/

成功后执行 ls 命令,可以看到两个 toolchain 都被安装到 /usr/local/toolchain/ 目录下了。

添加环境变量

只有把可执行文件对应的路径加入到 PATH 环境变量里,系统才可以认到这些命令。

这里的路径就是上面截图中 pwd 命令显示的路径,可以添加到 ~/.bashrc 文件的最后:

PATH=$PATH:/usr/local/toolchain/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf/bin:/usr/local/toolchain/gcc-linaro-6.4.
1-2017.11-x86_64_aarch64-linux-gnu/bin

注意:两个独立的路径之间用 冒号 : 隔开。

执行 source~/.bashrc 命令让配置生效,然后我们就可以在命令行里执行这些命令了:

比如 arm-linux-gnueabihf-gcc-vaarch64-linux-gnu-gcc-v 查看编译器版本:

能看到如图的信息,说明已经大功告成了。

编译内核

这里下载 imx 的官方内核:

git clone https://source.codeaurora.org/external/imx/linux-imx

切换到 4.19 版本:

git checkout -b imx_v2019.04_4.19.35_1.0.0  origin/imx_v2019.04_4.19.35_1.0.0

编译:

make ARCH=arm imx_v7_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

如果你电脑上其他的依赖库都安装的完整,就能顺利编译成功。

本文分享自微信公众号 - HackforFun(gh_c8e36f389b90),作者:HackforFun

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-10-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 在 RK3399 上部署最新的 Linux 5.4 和 U-Boot v2020 .01

    可能很多玩 Linux 的同学都听过 mainline 或者 upstream 这两个词,但是又搞不清他们到底指的是什么。

    HackforFun
  • Linux Kernel 和 U-Boot 编译的那些事

    之前的文章:《一次搞定交叉编译》 给大家讲了如何安装交叉编译工具链,搭建交叉编译环境。

    HackforFun
  • U-Boot 驱动模型

    DM 是 U-Boot 中的驱动框架,全称 Driver Mode。像 Linux Kernel 中的驱动三要素 device 、bus 、driver 一样,...

    HackforFun
  • 分享一个很通用c语言的Makefile

    俺踏月色而来
  • 梯度下降法理论与实践

    理论基础 现在比如有两个参数的损失函数 ? 我们的目的是使之最小也就是得到能够使J函数最小的 ? , ? ,公式表示为: ? 我们画出当 ? ?...

    zenRRan
  • “HTTPS”安全在哪里?

    背景 最近基于兴趣学学习了下 HTTPS 相关的知识,在此记录下学习心得。 在上网获取信息的过程中,我们接触最多的信息加密传输方式也莫过于 HTTPS 了。每当...

    腾讯Bugly
  • 使用Python模拟伪随机数生成原理

    伪随机数生成有很多种方法,其中一个是这样的:rNew = (a*rOld + b) % (end-start),然后设置rOld = rNew,一般要求用户指定...

    Python小屋屋主
  • Linux修改用户名和所属组

    腾讯云的云服务器的,初始的用户名和主机名都是分配的。主机名其实还好了,用户名总是一个ubuntu有点看的不爽,正好看到了用户管理,就在这准备改一下,mianhk...

    小二三不乌
  • Ubuntu 常用命令

    1、查看Linux当前操作系统位数   sudo uname --m   如果显示 i686,你安装了32位操作系统   如果显示 x86_64,你安装了64位...

    随机来个数
  • 如何部署 Jenkins 服务

    Jenkins是一个开源自动化服务器,可以自动执行持续集成和交付软件所涉及的重复技术任务。Jenkins是基于Java的,可以从Ubuntu软件包安装,也可以通...

    大数据弄潮儿

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动