一、交叉编译是什么?
交叉编译就是“我帮你做了你不擅长或者不能做的编译工作”。交叉编译通常出现在以下场景:
- 一台机器不能进行编译工作
- 一台机器能进行但编译过于缓慢
那么怎么解决这个问题呢?用另一台性能较好的机器帮助完成编译,这过程需要安装对应平台的交叉编译工具链,它通常包括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