建交叉编译环境,方便在笔记本中调试代码
一、准备
确保虚拟机和Jetson保持网络连接状态;
确保Jetson已经装好你需要的依赖库(可以正常运行你需要可执行文件即可);
查看Jetson 是否存在如图所示的文件夹以及文件:
二、新建交叉编译、sysroot和qt编译目录:
mkdir ~/qt_xavier
mkdir ~/qt_xavier/sysroot
mkdir ~/qt_xavier/qt5build
下载并解压交叉编译工具,根据jetpack版本下载对应的交叉编译工具,否则编译时可能会因gcc版本不对应报错
jetson官网查询版本对应关系,进行下载:
https://developer.nvidia.com/embedded/jetson-linux-archive
此处对应下载的版本为gcc9.3:aarch64–glibc–stable-final.tar.gz
解压后为交叉编译工具创建环境变量
vim ~/.bashrc
#在最后一行添加:
export PATH=$PATH:export PATH=$PATH:/home/zhangcj/ZhangTest/Jetson/qt-jxavier/gcc9.3-nx_new/bin
#使环境变量生效
source ~/.bashrc
#检查环境变量是否添加
echo $PATH
#查看交叉编译工具链版本
aarch64-buildroot-linux-gnu-g++ -v
三、下载并解压qt源码
Qt源码下载(最好下载tar.xz,tar格式)
本次下载qt5.15.2 :
https://download.qt.io/archive/qt/5.15/5.15.2/single/
四、拷贝jetson中的必要文件至sysroot
rsync -avz nvidia@192.168.1.201:/usr ~/qt_xavier/sysroot
rsync -avz nvidia@192.168.1.201:/lib ~/qt_xavier/sysroot
rsync -avz nvidia@192.168.1.201:/etc ~/qt_xavier/sysroot
#我担心会出现拷贝不完整的问题,将usr文件夹下的全部内容都拷贝了,如果不想这么做可以尝试:
rsync -avz nvidia@192.168.1.201:/usr/inlcude ~/qt_xavier/sysroot/usr
rsync -avz nvidia@192.168.1.201:/usr/lib ~/qt_xavier/sysroot/usr
rsync -avz nvidia@192.168.1.201:/lib ~/qt_xavier/sysroot
修改sysroot软链接
在同步库后,然后需要修改sysroot里面的软链接,里面有很多软连接使用的都是绝对路径,那就会直接链接到你PC的/usr、/lib目录里面去,那肯定是错的,我们希望它们链接到 sysroot里面对应的库。所以我们需要把绝对路径改成相对路径。直接用网上现成的python脚本完成.
地址:sysroot-relativelinks.py
cd ~/qt_xavier
sudo chmod +x sysroot-relativelinks.py
python3 sysroot-relativelinks.py sysroot
在qt源码中为Jetson配置qmake
cp /home/zhangcj/ZhangTest/Jetson/qt-jxavier/qt-everywhere-src-5.15.2/qtbase/mkspecs/devices/linux-jetson-tx1-g++ /home/zhangcj/ZhangTest/Jetson/qt-jxavier/qt-everywhere-src-5.15.2/qtbase/mkspecs/devices/linux-jetson-nx_new
vim /home/zhangcj/ZhangTest/Jetson/qt-jxavier/qt-everywhere-src-5.15.2/qtbase/mkspecs/devices/linux-jetson-nx_new/qmake.conf
##################################将文本替换为如下内容:###################################
qmake configuration for Jetson TX1 boards running 64-bit Linux For Tegra
# (tested with R24.2, sample root filesystem)
#
# Note that this environment has been tested with X11 only.
#
# A typical configure line might look like the following:
#
# configure \
# -device linux-jetson-tx1-g++ \
# -device-option CROSS_COMPILE=/opt/gcc-linaro-5.3.1-2016.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- \
# -sysroot /opt/Linux_for_Tegra/rootfs
#
# Note that this builds for GLX + OpenGL. To use EGL + OpenGL ES instead, pass
# -opengl es2 and ensure the rootfs has the headers (rootfs/usr/include/EGL,
# GLES2, GLES3), which may not be the case out of the box.
#
# Check the configure output carefully, some features may be disabled due to the
# rootfs not having the necessary dev files.
#
# If getting cryptic linker errors from static libs like libm.a, check that the
# symlinks libm.so, libz.so, etc. under rootfs/usr/lib/aarch64-linux-gnu are not
# broken. If they are, due to using absolute paths, change them so that they are
# relative to rootfs.
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_xavier/qt5build
#下面是我的配置选项,qt creator对我而言只是编译工具,我不需要任何qt自带的库,如果有需要,可以通过configure --help 来选择你所需的配置。但是不同的配置会有很大概率造成编译报错,需要根据报错信息逐个排查,有一定难度。
../qt-everywhere-src-5.15.2/configure -prefix /usr/local/linux-jetson-nx_new -confirm-license -opensource -device linux-jetson-nx_new -device-option CROSS_COMPILE=/home/zhangcj/ZhangTest/Jetson/qt-jxavier/gcc9.3-nx_new/bin/aarch64-buildroot-linux-gnu- -sysroot /home/zhangcj/ZhangTest/Jetson/qt-jxavier/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 -j16
make install
#注意!!!
#如果需要重新配置选项,需要将qt5build中的文件清空后,再重新配置。
#如果出现编译失败的情况,一定要先删除交叉编译工具链和qt源码,然后重新解压后重复之前的操作。
采用gcc7.3编译时,正常无报错,后适配jetson环境改为gcc9.3编译,在配置时报错:
/home/zhangcj/ZhangTest/Jetson/qt-jxavier/gcc9.3-nx_new/bin/…/lib/gcc/aarch64-buildroot-linux-gnu/9.3.0/…/…/…/…/aarch64-buildroot-linux-gnu/bin/ld: cannot find crt1.o: No such file or directory
/home/zhangcj/ZhangTest/Jetson/qt-jxavier/gcc9.3-nx_new/bin/…/lib/gcc/aarch64-buildroot-linux-gnu/9.3.0/…/…/…/…/aarch64-buildroot-linux-gnu/bin/ld: cannot find crti.o: No such file or directory
解决办法:
#查找ctt1.o所在路径
sudo find / -name “crt1.o”
#获取路径:/home/zhangcj/ZhangTest/Jetson/qt-jxavier/gcc9.3-nx_new/aarch64-buildroot-linux-gnu/sysroot/usr/lib/crt1.o
将crt1.o等文件分别放入/home/zhangcj/ZhangTest/Jetson/qt-jxavier/gcc9.3-nx_new/bin/…/lib/gcc/aarch64-buildroot-linux-gnu/9.3.0/…/…/…/…/aarch64-buildroot-linux-gnu/bin中
编译完成后在~/qt_xavier/sysroot/usr/local中生成linux-jetson-nx_new,将其复制到jetson设备中
rsync -avz ~/qt_xavier/sysroot/usr/local/linux-jetson-nx_new nvidia@192.168.1.201:/home/nvidia
sudo mv ~/linux-jetson-nano /usr/local
六、配置QT Creator中的交叉编译工具
add-GCC-C
add-GCC-C++
七、交叉编译工具使用:
将qt的.pro文件中的所有INCLUDEPATH和LIBS前加上
$$[QT_SYSROOT]
添加交叉编译可执行文件重命名和远程部署路径:
TARGET = 目标文件名
target.path = 目标路径(jetson)
INSTALLS += target
选择交叉编译工具
Build->Deploy Project **:将编译好的可执行文件传送到Jetson Nano的target.path中;
Build->Run Project **:在Jetson Nano中运行可执行文件。
问题:代码可在jetson中正常编译,在笔记本搭建的交叉编译环境中报错:
由于在jetson中,qt可自动搜索jetson中/usr/lib等目录中的动态连接库,而在笔记本的交叉编译环境中没有自动搜索~/sysroot/usr/lib等目录,导致出现undefiend reference等错误,可根据compile output提示内容确定缺少的依赖,或者采用objdump工具查看缺少依赖(objdump是一个更通用的工具,用于显示二进制文件的信息),在pro文件中手动添加缺少的依赖。
objdump -p /path/to/your/library.so | grep NEEDED
另外:以下类型报错为gcc编译器版本不对应导致,参考:https://blog.csdn.net/swimmer2000/article/details/114802939,可在第二节中下载正确的gcc版本。
undefine reference to ‘std::__cxx11::basic_stringstream<char, std::char_traits, std::allocator >::basic_stringstream()’
undefine reference to ‘std::__cxx11::basic_ostringstream<char, std::char_traits, std::allocator >::basic_ostringstream()’
关于 pro中引用libcudnn.so,确找不到该文件,而在路径下确真实存在该文件的问题,原因是libcudnn.so指向的软连接/etc/alternatives/libcudnn_so不存在,或者libcudnn_so存在,但是与其他软连接存在冲突
解决:重新建立软连接 查看软连接ls -l ,建立软连接:ln -s 目标 源
ln -sf /home/zhangcj/ZhangTest/Jetson/qt-jxavier/sysroot/usr/lib/aarch64-linux-gnu/libcudnn.so.8 libcudnn_so
ln -sf ../../../etc/alternatives/libcudnn_so libcudnn.so
说明(下文为参考文章记录的一些问题及解决方法)
如果编译好的文件在Jetson Nano中运行提示某某文件缺失(提示的路径是虚拟机中的路径),可以尝试在.pro文件中将该文件前的$$[QT_SYSROOT]去掉。
可能出现的问题以及解决方法:
问题:无法远程运行带窗口显示的代码(比如opencv的imshow)。
在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}'
在QT Creator中进行如下设置(Projects->JetsonNano->Run):
参考:
https://blog.csdn.net/K_K_yl/article/details/117741753
https://blog.csdn.net/sinat_34774688/article/details/132315521?spm=1001.2014.3001.5502