这是这个系列 “折腾笔记” 的第一篇,希望能用更直白的方式去展现交叉编译的时候做了些什么。因此,这个教程并不是最佳实践,但是可以让小伙伴们有一个更直白的理解。之后,我会把笔记的重点放在 bazel 上交叉编译的最佳实践,并配一些小的实践案例,如交叉编译能在树莓派上运行的含有深度学习模型的小程序。

PS:个人平时用的电脑的系统是 MacOS,值得一提的是 MacOS 不等于 Linux。它的交叉编译其实有很多坑,比如 tensorflowlite 中提供的交叉编译的工具或 Linaro 只能在 Linux 下通过。因此,个人建议 MacOS 下的交叉编译方式为采用 docker 运行 Linux 系统然后进行交叉编译。

关于交叉编译的小理解与实践思路

交叉编译其实就是使用能够把代码源码转换为目标平台机器语言的编译器。比如,树莓派的就需要的是不是 x86 的 gcc 而是支持 arm 处理器的 arm-linux-gnueabihf-gcc。那么是不是我们把相关的依赖环境搞过来就可以编译了呢?我个人认为是的,于是进行一番调研,还真的发现了一个想法相似的教程。这个方法的核心就是把树莓派上的环境拷过来,然后使用 llvm 结合 arm-linux-gnueabihf-binutils 进行交叉编译。

实践步骤

使用 brew 安装一些依赖项



brew install arm-linux-gnueabihf-binutils llvm rsync 
# brew 的管网安装脚本如下 、
# /bin/bash -c "$(curl -fsSL <https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh>)"



从树莓派上拷过来相关的 gcc 和其相关环境



rsync -rzLR --safe-links 
      pi@raspberrypi:/usr/lib/arm-linux-gnueabihf 
      pi@raspberrypi:/usr/lib/gcc/arm-linux-gnueabihf 
      pi@raspberrypi:/usr/include 
      pi@raspberrypi:/lib/arm-linux-gnueabihf 
      sysroot/
# 这里面的 pi 是树莓派的 ip 或者 ssh 别名。
# raspberrypi 是树莓派中的用户名
# 如,gpu@deamov 代表着 ssh 的别名为 gpu,deamov 是我的用户



检查下当前的目录



.
├── hello_cross_compile.cc
└── sysroot # 这个就是我们刚才用 rsync 传过来的根目录
    ├── lib
    └── usr



hello_cross_comile.cc 的内容如下



#include <iostream>

using namespace std;

int main(int argc, char *argv[]) {
  cout << "Hello ResPi compiled by MacOS" << endl;
  return 0;
}



使用 llvm 进行交叉编译

执行如下命令 (扔到一个 .sh 文件里),即可生成可以在树莓派下执行的文件 hello 。之后拷到树莓派上就可以成功执行了。



HOME=`pwd` # 设置 $HOME 为当前目录
`brew --prefix llvm`/bin/clang++ 
    --target=arm-linux-gnueabihf 
    --sysroot $HOME/sysroot 
    -isysroot=$HOME/sysroot 
    -isystem $HOME/sysroot/usr/include/c++/8 
    -isystem $HOME/sysroot/usr/include/arm-linux-gnueabihf/c++/8 
    -L$HOME/sysroot/usr/lib/gcc/arm-linux-gnueabihf/8 
    -Wl,--rpath-link $HOME/sysroot/lib/arm-linux-gnueabihf 
    -B$HOME/sysroot/usr/lib/gcc/arm-linux-gnueabihf/8 
    --gcc-toolchain=`brew --prefix arm-linux-gnueabihf-binutils` 
    -o hello 
    ./hello_cross_compile.cc -v



推荐阅读

https://embed-linux-tutorial.readthedocs.io/zh_CN/latest/linux_app/arm_gcc_hello_world.htmlembed-linux-tutorial.readthedocs.io


docker构建交叉编译环境 docker 交叉编译arm_交叉编译

4. ARM-GCC和开发板的HelloWorld - [野火]i.MX Linux开发实战指南 文档

4. ARM-GCC和开发板的HelloWorld - [野火]i.MX Linux开发实战指南 文档embed-linux-tutorial.readthedocs.io

docker构建交叉编译环境 docker 交叉编译arm_交叉编译


一个非常完整且详细的交叉编译指南,虽然不支持 MacOS,但是我们可以通过开一个 Linux 的 docker 来解决问题。

Documentationcrosstool-ng.github.io

Crosstool-ng 是目前原生在 MacOS 下确认可支持的交叉编译方案,但是需要你去在硬盘上开空间操作复杂。有把主系统搞崩的风险。

Docker-nano/crosstool-NGgithub.com


docker构建交叉编译环境 docker 交叉编译arm_交叉编译_03


如果你铁了心要用 crosstool-ng,个人推荐可以看看这个别人写好的 Dockfile。但还是回到了原来的问题,如果你都起了 docker 了。ubuntu 或者其他 Linux 的镜像不香嘛。