如何进行交叉编译?

一、交叉编译是什么?

交叉编译就是“我帮你做了你不擅长或者不能做的编译工作”。交叉编译通常出现在以下场景:

  • 一台机器不能进行编译工作
  • 一台机器能进行但编译过于缓慢

那么怎么解决这个问题呢?用另一台性能较好的机器帮助完成编译,这过程需要安装对应平台的交叉编译工具链,它通常包括arm-linux-gcc,arm-linux-ld,arm-linux-as等的工具,我们既可以使用现成的交叉编译工具,也可以自己定制自己的编译链。

工具链来源 已有的 自定义的
优化情况 通用的优化 特定的优化
更新情况 更新滞后 随时更新
掌控情况 未知 已知
时间成本 基本没有 高昂

这里选用通用的工具链,已有的工具链可以是付费的,也可以是开源的。Linaro将定期更新最新的交叉编译工具链,这些工具可能存在一些问题,不推荐在生产环境中使用;在Arm官网下,你可以找到一些比较稳定的交叉编译工具,稳定的交叉编译工具点这里。根据你的编译机器类型和gcc版本选择即可:

  • Windows (mingw-w64-i686) hosted cross compilers
  • x86_64 Linux hosted cross compilers
  • AArch64 Linux hosted cross compilers[1]

因为我是Linux系统的x86_64架构的,所以选择第二个就可以了。一般来说,交叉编译工具链的命名规则为:

arch [-vendor][-os] [-(gnu)eabi]
  • arch - 体系架构,如ARM,MIPS
  • vendor - 工具链提供商
  • os - 目标操作系统
  • eabi - 嵌入式应用二进制接口(Embedded Application Binary Interface)
    根据对操作系统的支持与否,ARM GCC可分为支持和不支持操作系统,如

arm-none-eabi:没有出现目标操作系统,因此不能使用操作系统相关的函数;
arm-none-linux-eabi:目标操作系统是Linux,可以使用系统相关的函数;
arm-linux-gnueabihf:使用glibc库,经过 Codesourcery 公司优化过推出的编译器。

在编译选用对应目标平台的交叉编译器进行编译的可执行文件,便可在目标平台执行了。下面,以树莓派B4为例子完成交叉编译测试。

二、交叉编译测试

这里以我的树莓派为例,进行交叉编译练习。首先查看目标机器的指令架构cat /proc/cpuinfo
如何进行交叉编译?
确定计算机位数getconf LONG_BIT:
如何进行交叉编译?
上述两条指令结果告诉目标主机是树莓派的架构是Armv7,位数是32位。因为只是简单的测试,所以选用了在Arm官网下载的通用交叉编译器,下载地址

  • Windows (mingw-w64-i686) hosted cross compilers
  • x86_64 Linux hosted cross compilers(因为我准备用Ubuntu20.04 x86-64作为编译主机,所以我选择了这个
  • AArch64 Linux hosted cross compilers

如何进行交叉编译?
点击下载并解压,下载解压后有以下几个文件:

.
├── 10.2-2020.11-x86_64-arm-none-linux-gnueabihf-manifest.txt
├── arm-none-linux-gnueabihf
├── bin
├── include
├── lib
├── lib64
├── libexec
└── share

7 directories, 1 file

查看交叉编译工具的g++的版本

junwu@junwu-ZHENGJIUZHE-REN7000:~/Downloads/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf/bin$ ./arm-none-linux-gnueabihf-g++ --version
arm-none-linux-gnueabihf-g++ (GNU Toolchain for the A-profile Architecture 10.2-2020.11 (arm-10.16)) 10.2.1 20201103
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

确认无误后,将其添加到操作系统中并添加相应的环境变量:

sudo cp -r ~/Downloads/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf /usr/local/
echo 'export PATH=$PATH:/usr/local/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf/bin' >> ~/.bashrc

检查环境变量是否添加成功:

junwu@junwu-ZHENGJIUZHE-REN7000:~/Desktop$ arm
arm2hpdl                                arm-none-linux-gnueabihf-gcov-tool
arm-none-linux-gnueabihf-addr2line      arm-none-linux-gnueabihf-gdb
arm-none-linux-gnueabihf-ar             arm-none-linux-gnueabihf-gdb-add-index
arm-none-linux-gnueabihf-as             arm-none-linux-gnueabihf-gfortran
arm-none-linux-gnueabihf-c++            arm-none-linux-gnueabihf-gprof
arm-none-linux-gnueabihf-c++filt        arm-none-linux-gnueabihf-ld
arm-none-linux-gnueabihf-cpp            arm-none-linux-gnueabihf-ld.bfd
arm-none-linux-gnueabihf-dwp            arm-none-linux-gnueabihf-ld.gold
arm-none-linux-gnueabihf-elfedit        arm-none-linux-gnueabihf-lto-dump
arm-none-linux-gnueabihf-g++            arm-none-linux-gnueabihf-nm
arm-none-linux-gnueabihf-gcc            arm-none-linux-gnueabihf-objcopy
arm-none-linux-gnueabihf-gcc-10.2.1     arm-none-linux-gnueabihf-objdump
arm-none-linux-gnueabihf-gcc-ar         arm-none-linux-gnueabihf-ranlib
arm-none-linux-gnueabihf-gcc-nm         arm-none-linux-gnueabihf-readelf
arm-none-linux-gnueabihf-gcc-ranlib     arm-none-linux-gnueabihf-size
arm-none-linux-gnueabihf-gcov           arm-none-linux-gnueabihf-strings
arm-none-linux-gnueabihf-gcov-dump      arm-none-linux-gnueabihf-strip

没有问题,编写测试程序:

#include <iostream>

using namespace std;

int main()
{       
        cout<<"Hello Pi, Cross compile! OK"<<endl;
        return 0;
}  

进行编译:

arm-none-linux-gnueabihf-g++  test.cpp

将生成的可执行程序拷贝到树莓派,运行:
如何进行交叉编译?
至此,交叉编译已完成。


Tips:libc和glibc都是Linux下的标准库,glibc作为标准库目前Linux发行版的主流,最初glibc是libc的一个分支,在glibc2.0发行后表现突出,逐渐取代了libc,总结来说,glibc是主流,libc曾经是主流。libc.so.6,由于历史原因,他通常是指向glibc的软连接,在ubuntu20.04位置位于:/usr/lib/x86_64-linux-gnu/libc.so.6运行libc.so.6,你可看到其详细版本信息:

junwu@junwu-ZHENGJIUZHE-REN7000:~/Downloads/gcc-arm-10.2-2020.11-x86_64-arm-none-linux-gnueabihf/bin$ /usr/lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Ubuntu GLIBC 2.31-0ubuntu9.2) stable release version 2.31.
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 9.3.0.
libc ABIs: UNIQUE IFUNC ABSOLUTE
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.

[1] AArch64是ARMv8 架构的一种执行状态
[2] http://www.crifan.com/files/doc/docbook/cross_compile/release/html/cross_compile.html#crosscompile_tool_eldk

上一篇:2021-04-25


下一篇:makefile错误、找不到头文件、交叉编译