Jetson Nano交叉编译教程

背景:

        由于工作需要,在现场调试时需要在笔记本中修改代码,然后将源码拷贝到Jetson Nano中编译(或者自带一台Jetson Nano、显示屏和无线键鼠等,在现场接好后修改和编译代码)。但是由于现场环境条件有限,无论哪种方式都极其不便,极大的降低了工作效率。因此,我决定尝试在笔记本虚拟机中实现Jetson Nano的交叉编译。

实现效果:

  • 在虚拟机上可以编译Jetson Nano平台上的代码
  • 将虚拟机中的编译好的可执行文件同步到Jetson Nano的指定路径
  • 在虚拟机上可以远程Debug和运行Jetson Nano平台上的代码

环境:

虚拟机:VMware® Workstation 15 Pro

操作系统:Ubuntu 18.04.4 LTS

嵌入式设备:Jetson Nano(L4T 32.4.3)

编译工具:QT Creator4.5.2 Based on Qt 5.9.5 (GCC 7.3.0, 64 bit)

步骤:

准备工作:

  • 确保虚拟机和Jetson Nano保持网络连接状态;
  • 确保Jetson Nano已经装好你需要的依赖库(可以正常运行你需要可执行文件即可);
  • 查看Jetson Nano中是否存在如图所示的文件夹以及文件:
  • 虚拟机中新建交叉编译、sysroot和qt编译目录:
mkdir ~/qt_jnano
mkdir ~/qt_jnano/sysroot
mkdir ~/qt_jnano/qt5build

配置过程:

下载并解压交叉编译工具链: 

cd ~/qt_jnano/
wget http://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/aarch64-linux-gnu/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz
tar -xf gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz

为交叉编译工具链创建环境变量:

export PATH=$PATH:/home/smuvision/qt_jnano/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin  

vim ~/.bashrc
#在最后一行添加:
export PATH=$PATH:/home/smuvision/qt_jnano/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin

#检查环境变量是否添加
echo $PATH
#查看交叉编译工具链版本
aarch64-linux-gnu-g++ -v

下载并解压qt源码:

cd ~/qt_jnano/
wget https://download.qt.io/archive/qt/5.9/5.9.5/single/qt-everywhere-opensource-src-5.9.5.tar.xz
tar -xf qt-everywhere-opensource-src-5.9.5.tar.xz

拷贝Jetson Nano中的必要文件至虚拟机的sysroot:

rsync -avz [email protected]:/usr ~/qt_jnano/sysroot
rsync -avz [email protected]:/lib ~/qt_jnano/sysroot

#我担心会出现拷贝不完整的问题,将usr文件夹下的全部内容都拷贝了,如果不想这么做可以尝试:
rsync -avz [email protected]:/usr/inlcude ~/qt_jnano/sysroot/usr
rsync -avz [email protected]:/usr/lib ~/qt_jnano/sysroot/usr
rsync -avz [email protected]:/lib ~/qt_jnano/sysroot

下载并运行路径同步脚本:

地址:sysroot-relativelinks.py

cd ~/qt_jnano
sudo chmod +x sysroot-relativelinks.py
python3 sysroot-relativelinks.py sysroot

重复以上步骤(拷贝Jetson Nano中的必要文件至虚拟机的sysroot)。

在qt源码中为Jetson Nano配置qmake:

cp /home/smuvision/qt_jnano/qt-everywhere-opensource-src- 5.9.5/qtbase/mkspecs/devices/linux-jetson-tx1-g++ /home/smuvision/qt_jnano/qt-everywhere-opensource-src-5.9.5/qtbase/mkspecs/devices/linux-jetson-nano

vim /home/smuvision/qt_jnano/qt-everywhere-opensource-src-5.9.5/qtbase/mkspecs/devices/linux-jetson-nano/qmake.conf

##################################将文本替换为如下内容:###################################

#
# qmake configuration for the Jetson Nano
#
# Note that this environment has been tested with X11 only.
#
# A typical configure line might look like:
# configure \
#   -device linux-jetson-nano \
#   -device-option CROSS_COMPILE=/home/smuvision/qt_jnano/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- \
#   -sysroot /home/smuvision/qt_jnano/sysroot

include(../common/linux_device_pre.conf)

QMAKE_INCDIR_POST += \
    $$[QT_SYSROOT]/usr/include \
    $$[QT_SYSROOT]/usr/include/aarch64-linux-gnu

QMAKE_LIBDIR_POST += \
    $$[QT_SYSROOT]/usr/lib \
    $$[QT_SYSROOT]/lib/aarch64-linux-gnu \
    $$[QT_SYSROOT]/usr/lib/aarch64-linux-gnu

QMAKE_RPATHLINKDIR_POST += \
    $$[QT_SYSROOT]/usr/lib \
    $$[QT_SYSROOT]/usr/lib/aarch64-linux-gnu \
    $$[QT_SYSROOT]/lib/aarch64-linux-gnu

QMAKE_INCDIR_EGL = $$[QT_SYSROOT]/usr/lib/aarch64-linux-gnu/tegra-egl

DISTRO_OPTS                  += aarch64
COMPILER_FLAGS               += -march=armv8-a+crypto+crc

EGLFS_DEVICE_INTEGRATION = eglfs_kms_egldevice

include(../common/linux_arm_device_post.conf)
load(qt_config)

#########################################################################################

配置qt源码编译选项,以及编译:

cd ~/qt_jnano/qt5build

#下面是我的配置选项,qt creator对我而言只是编译工具,我不需要任何qt自带的库,如果有需要,可以通过configure --help 来选择你所需的配置。但是不同的配置会有很大概率造成编译报错,需要根据报错信息逐个排查,有一定难度。
../qt-everywhere-opensource-src-5.9.5/configure -prefix /usr/local/linux-jetson-nano -confirm-license -opensource -device linux-jetson-nano -device-option CROSS_COMPILE=/home/smuvision/qt_jnano/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- -sysroot /home/smuvision/qt_jnano/sysroot -no-opengl -skip qtscript -skip wayland -skip qtwebengine -force-debug-info -skip qtdatavis3d -skip qtlocation -nomake examples -make libs -pkg-config -no-use-gold-linker -v -no-openssl -shared -release -pch -no-cups -no-glib -no-dbus -no-xcb -no-separate-debug-info -no-fontconfig -nomake tests -no-iconv -no-tslib

#还有一种方法就是在../qt-everywhere-opensource-src-5.9.5/qtbase中编译,可以不附带任何qt库,比较纯净,但是我没有验证过。

make
make install

#注意!!!
#如果需要重新配置选项,需要将qt5build中的文件清空后,再重新配置。
#如果出现编译失败的情况,一定要先删除交叉编译工具链和qt源码,然后重新解压后重复之前的操作。

拷贝虚拟机中的编译好的文件至Jetson Nano:

rsync -avz ~/qt_jnano/sysroot/usr/local/linux-jetson-nano [email protected]:/home/smuvision

sudo mv -r ~/linux-jetson-nano /usr/local

配置QT Creator中的交叉编译工具:

(Tools->Options->Devices->Add->Generic Linux Device)

按步骤填写Jetson Nano的相关信息即可。

(Tools->Options->Build&Run)

Jetson Nano交叉编译教程_第1张图片

Jetson Nano交叉编译教程_第2张图片

Jetson Nano交叉编译教程_第3张图片

Jetson Nano交叉编译教程_第4张图片

Jetson Nano交叉编译教程_第5张图片

交叉编译工具使用:

  • 将qt的.pro文件中的所有INCLUDEPATH和LIBS前加上:
    $$[QT_SYSROOT]
  • 添加交叉编译可执行文件重命名和远程部署路径:
    TARGET = TruckDetect_Cross
    target.path = /home/smuvision/work/Truck/build-TruckDetect-Desktop-Debug
    INSTALLS += target

  • 选择交叉编译工具:

Jetson Nano交叉编译教程_第6张图片

  • Build->Deploy Project **:将编译好的可执行文件传送到Jetson Nano的target.path中;
  • Build->Run Project **:在Jetson Nano中运行可执行文件。

说明:

  • 如果编译好的文件在Jetson Nano中运行提示某某文件缺失(提示的路径是虚拟机中的路径),可以尝试在.pro文件中将该文件前的$$[QT_SYSROOT]去掉。

可能出现的问题以及解决方法:

  • 问题:无法远程运行带窗口显示的代码(比如opencv的imshow)。

       解决方法:

  1. 在Jstson Nano中进行如下设置:
    #远程打开图像窗口需要访问X11 server,访问X11 server我们需要两个东西:DISPLAY和XAUTHORITY两个环境变量。但是,由于它们在不同的发型版和Display Manager下都有些不同,所以需要下面的操作来获取:
    DISPLAY=$(w -hs | awk 'match($2, /:[0-9]+/) {print $2; exit}')
    #下面的指令会出现用户名显示不全的问题,通过USER=**代替(**为你的用户名)
    USER=$(w -hs | awk 'match($2, /:[0-9]+/) {print $1; exit}')
    eval XAUTHORITY=/run/user/$(id -u $USER)/gdm/Xauthority
    export DISPLAY
    export XAUTHORITY
    DIMENSIONS=$(xdpyinfo | grep 'dimensions:' | awk '{print $2;exit}')
  2. 在QT Creator中进行如下设置(Projects->JetsonNano->Run):Jetson Nano交叉编译教程_第7张图片

  • 问题:QT Creator的Application Output窗口在运行时打印不实时。

       解决方法: 在main函数开头添加:

#由于打印消息已经被输出到stdout的缓冲区之中,如果把缓冲区的大小设置成0,日志就可以直接输出
setbuf(stdout, NULL);
  • 问题:原本在x86环境中可以正常编译并运行的程序,通过交叉编译工具可能会编译报错某文件没有被包含。

       解决方法:需要单独把缺失文件的路径包含进去。

你可能感兴趣的:(qt,linux,交叉编译)