Loading

有关Xavier交叉编译环境那些事

前言

最近公司升级交叉编译环境,需要配置的目标机为Nvidia AGX xavier with Jetpack 4.5这里记录一些坑。

正文

总体概要

所谓cross-compile其实就是在amd64(下称host)上生成arm64(下称target)的binary
明确一点,所有与编译相关的工具都是运行在本地,比如cmake比如aarch64-gcc比如tclsh版本为host
而对应的rootfs可以简单理解为库,所有编译过程中需要的.so .a都会在rootfs里面找,版本为target
至于cuda这种比较特殊的交叉编译,就需要host_bin(例如nvcc)+ target_lib(例如libcublas.so)进行配合
莫慌,上述这些Nvidia SDK manager会提供下载。

前期准备

从SDKmanager下载到的sample rootfs里面不含任何nv三方库,需要自己安装deb
通过SDK manager可以下载对应型号的rootfs+三方库以及CUDA交叉环境,其中的json文件将指导每个deb的具体安装
host这边安装好cmake, autoconf, automake, libtool, m4 and tclsh这些编译相关工具,准备好与target一致的aarch64-gcc-7.5

仿真环境

使用qemu对target环境进行模拟,对应命令sudo apt install qemu-user-static注意不要装错了
至此host已经具备执行target bin的能力,直接chroot将报错failed to run command ‘/bin/bash’: No such file or directory
复制对应的文件sudo cp /usr/bin/qemu-aarch64-static <rootfs>/usr/bin/
有了这两步就可以chroot到target rootfs进行操作sudo chroot <rootfs> /bin/bash
成功后使用uname -a检查架构是否为aarch64

装依赖库

理论上我们可以通过chroot + qemu的方式进入target rootfs进行包管理apt install ...但这样比较费时费力
更糟糕的是,现阶段SDK manager刷机后半段会通过ssh访问Xavier安装一些在线内容,如此一来本地deb安装可能不全
我个人建议使用sample_rootfs作为底包并从刷好的Xavier迁移/usr /lib /opt /etc进行覆盖升级
完成后更新整个rootfs的符号链接为相对路径symlinks -cr /
此举可避免编译过程中rootfs中的文件链接到host 效果如下:
更新前<rootfs>/etc/resolv.conf -> /run/resolvconf/resolv.conf
更新后<rootfs>/etc/resolv.conf -> ../run/resolvconf/resolv.conf

打包技巧

可以使用fakeroot替代sudo实现对rootfs的去权限打包,解压也不再需要root权限。

交叉编译

这里提供两种思路:

  1. 编写交叉编译专用CMakeists参考cmake-toolchains(7)
  2. 编写通用CMakeLists通过传入外置-DCMAKE_TOOLCHAIN_FILE=xxx.cmake参数控制platform类型,使得多种架构复用同一套native CMakeLists变为可能

个人倾向第二种,典型的Linux交叉编译toolchain.cmake包含如下信息:

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(CMAKE_SYSROOT /home/devel/rasp-pi-rootfs)
set(CMAKE_STAGING_PREFIX /home/devel/stage)

set(tools /home/devel/gcc-4.7-linaro-rpi-gnueabihf)
set(CMAKE_C_COMPILER ${tools}/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${tools}/bin/arm-linux-gnueabihf-g++)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

奇技淫巧

对于编译过程中可能遇到的三方依赖,尽量使用cmake官方find_package提供的Modules如FindCUDA.cmake
官方版本经过迭代能很好的适应三方库因更新引入的文件结构变化,不用自己费心处理
而对于某些没有官方实现的package则需要自己编写,例如FindTensorRT.cmake其中就有不小的坑
原先trt5中nvonnxparser_runtime在trt7中已经弃用,比较简单的方法是强制版本>=7
若希望保留向前兼容能力,需要通过正则表达式提取NvInfer.hNvInferVersion.h中的版本号进行区别处理

展望

本质上只要是ubuntu-18.04-aarch64的平台可以复用一套basic rootfs节省硬盘空间
特化项目所需lib与gcc全部外置,通过cmake参数传入搜索路径,实现模块化管理!
最后,期待有朝一日Nvidia放出一套类似MDC的交叉编译全家桶!

posted @ 2021-07-19 17:00  azureology  阅读(1493)  评论(0编辑  收藏  举报