主机环境:Ubuntu20.04虚拟机
交叉工具链:粤嵌提供的arm-linux-gnueabi-5.4.0,一般开发板厂商都会提供相应的工具链
1.在X86交叉编译Qt库
2.拷贝交叉编译好的库到开发板上并设置好环境变量(库路径啥的)
前两步一劳永逸,做一次就行
3.X86上写好程序代码,通过交叉工具链进行程序的交叉编译,(动态)链接交叉编译的Qt库(粤嵌),或者厂商提供的Qt-sdk(友善),总之不能直接用开发板文件系统里的Qt库,那个是在arm上运行的
4.程序拷贝到开发板上运行
答:第一个问题,因为粤嵌提供的Qt库是5.7.0版本,且包括qtlocation,multimedia,qml,qtquick等在内的很多模块被裁剪掉了,导致我想移植的程序无法正常交叉编译,更不要说放开发版上运行;第二个问题:本人属于啥都不会的菜鸡,很多步骤即使做完了也不明白原理,过一段时间就忘记该咋操作,故发帖记录下步骤,以防未来还要干交叉编译库这种糟心事。贴子中步骤大都是参考网上大佬的帖子,我就做个领路人
安装依赖参照QT安装_George P的博客-CSDN博客,Ubuntu有apt-get install,十分方便
装好依赖后从Index of /archive/qt/5.15/5.15.2/single下载Qt5.15.2源码的压缩包并在虚拟机中解压
进入解压出来的目录中,创建一个.sh脚本文件用于配置编译选项(图中的autoconfig.sh)
编译配置参考了自动驾驶开发入门(一)---交叉编译64位Qt5.15 (aarch64)_在路上...-CSDN博客:
./configure \
-prefix /opt/qt-5.15.2 \
-release \
-opensource \
-xplatform linux-arm-gnueabi-g++ \
-sysroot /opt/GEC6818/prebuilts/gcc/linux-x64/local/arm/5.4.0/usr/arm-none-linux-gnueabi/sysroot \
-make libs \
-optimized-qmake \
-feature-library \
-opengl es2 \
-no-sse2 \
-no-openssl \
-no-cups \
-no-glib \
-no-pkg-config \
-no-separate-debug-info \
-pch \
-shared \
-qt-libjpeg \
-qt-zlib \
-qt-libpng
命令行输入 ./configure -help 即可查看,这里简单说一下部分我用到的
-xplatform是选择交叉工具链的配置文件
-sysroot是编译时查找依赖库的路径,需要选择开发板厂商提供的交叉编译工具链中的sysroot文件夹路径(有的工具链里不一定有该文件夹,挺奇怪的)
-prefix是安装路径,和-sysroot一起用实际的安装路径就成了/sysroot/prefix/
-skip选项用于跳过Qt的某个模块(上上图中基本每个文件夹都是一个模块),即完全不编译该模块。网上很多关于交叉编译的帖子都会-skip qtlocation -skip qtscript -skip qtdecarative..............,就没见过完全不跳,老老实实全部编译的。这主要是因为某些模块交叉编译时特别容易出错
-no类似-skip,但是是用于跳过一些模块的子模块
-pch是预编译头,据说能加快编译速度
其余的上网搜吧。顺便说一下,-mtdev和-xinput2应该能添加多点触控功能,但我或许是依赖没装全,系统无法识别-xinput2这一配置项
在qtbase/mkspecs/目录下,根据之前在-xplatform指定的编译器名称选一个或新建一个并进入。
我的qmake.conf如下,在原文件内容基础上修改交叉编译器路径就行,如果已经将编译器路径写入环境变量,甚至都不用改,但在安装了多个编译器的情况下,最好写绝对路径
#
# qmake configuration for building with arm-linux-gnueabi-g++
#
MAKEFILE_GENERATOR = UNIX
CONFIG += incremental
QMAKE_INCREMENTAL_STYLE = sublib
include(../common/linux.conf)
include(../common/gcc-base-unix.conf)
include(../common/g++-unix.conf)
# modifications to g++.conf
QMAKE_CC = /opt/GEC6818/prebuilts/gcc/linux-x64/local/arm/5.4.0/usr/bin/arm-none-linux-gnueabi-gcc
QMAKE_CXX = /opt/GEC6818/prebuilts/gcc/linux-x64/local/arm/5.4.0/usr/bin/arm-none-linux-gnueabi-g++
QMAKE_LINK = /opt/GEC6818/prebuilts/gcc/linux-x64/local/arm/5.4.0/usr/bin/arm-none-linux-gnueabi-g++
QMAKE_LINK_SHLIB = /opt/GEC6818/prebuilts/gcc/linux-x64/local/arm/5.4.0/usr/bin/arm-none-linux-gnueabi-g++
# modifications to linux.conf
QMAKE_AR = /opt/GEC6818/prebuilts/gcc/linux-x64/local/arm/5.4.0/usr/bin/arm-none-linux-gnueabi-ar cqs
QMAKE_OBJCOPY = /opt/GEC6818/prebuilts/gcc/linux-x64/local/arm/5.4.0/usr/bin/arm-none-linux-gnueabi-objcopy
QMAKE_NM = /opt/GEC6818/prebuilts/gcc/linux-x64/local/arm/5.4.0/usr/bin/arm-none-linux-gnueabi-nm -P
QMAKE_STRIP = /opt/GEC6818/prebuilts/gcc/linux-x64/local/arm/5.4.0/usr/bin/arm-none-linux-gnueabi-strip
load(qt_config)
有些模块依赖多,而且往往依赖的库还有它自己的依赖,很麻烦,不是必需要用的话,能裁则裁
每次编译时删掉之前编译过整个源码文件夹重新解压,这么大一个Qt源码包不是make distclean能把握住的,总会有点问题
1.出现下图的PCH相关错误只需从报错提示中查看编译器退出时的路径,在那个路径中找到并删除.pch目录(具有隐藏属性),之后重新make install
2.在编译配置时未跳过 qtlocation模块(-skip qtlocation),但跳过了opengl模块(-no-opengl),会出现语法层面的错误(报错提示的大意是某些声明的类未被定义或重写),我在Qt官方的某个提交与讨论bug的网站上找到了关于该报错的信息,网址是:[QTBUG-88017] qdeclarativepolylinemapitem has errors in it - Qt Bug Tracker,好像是因为qt5.15系列版本的qtlocation模块非常依赖opengl。网站上有修改后的qtlocation代码,但使用其替换旧代码后依旧存在语法层面问题,于是编译配置项-no-opengl改为-opengl es2
3.网上说开多核编译(make -j后面接核数)大概率会导致错误,可能是由于不同模块间存在依赖关系,多核并行编译导致本应放在后面编译的模块先编译,听着不太靠谱,但我之前用多核一直编译不过,单核编译一次就过了,呃。。。。。。。
利用nfs功能将编译好后的库打包发送到开发板上,解包,设置/etc/profile中的QTDIR。
1.multimedia模块存在问题,在粤嵌6818上五子棋小程序无法播放音效,报错提示:
defaultServiceProvider::requestService(): no service found for - "org.qt-project.qt.mediaplayer"
我试着将五子棋移植到友善上,但是播放音频的那段代码编译无法通过,音频代码和报错如下, 注释掉后能编译通过:
2.没有多点触控(驱动不支持),参考INPUT输入子系统的测试方式 evtest_匠芯筑梦-CSDN博客用evtest测试触摸屏驱动程序
如上图,从上到下四个红框依次是:
1.可测的输入设备
2.我选的触屏输入设备(名称gslx680是一种电容触屏驱动)
3.单点按下时获取的信息(坐标以及应该是表示按下的value 1)
4.单点按下后释放时获取的信息(没有坐标信息,只有应该是表示释放的value 0)
单点释放时的信息连坐标都没有,如何判断释放的是哪个按下的点,可见该驱动不支持多点触控,实际上多点触摸时第一个点能正常按下,但第二个点按下时会被视作将第一个点释放。
这样的话瓦片地图无法放大和缩小,只能考虑加个控件控制缩放。地图程序地址:
QML QtLocation地图应用学习-5:实现自己的plugin加载瓦片地图_龚建波-CSDN博客_qml地图插件
3.(已发现原因)qml地图在开发板上运行很卡顿,不确定是程序自身问题还是硬件性能不足,至少电脑上比较顺畅
说到qml,它是Qtquick项目采用的一种脚本语言,需要引入代码中使用的qtquick模块,如下
友善的Qt库和粤嵌的版本不同,import时记得设置模块名后的版本号 ,改完版本号后能在友善6818上测试地图程序,使用&符号令程序在后台运行,再用top命令查看硬件资源使用情况,发现CPU占用率最高达到约69%,但是8个核间能合理分工,程序保持流畅运行。至于粤嵌6818,一个核100%,七个核0%(还真就一核有难,多核围观),这板子属实垃圾
4.opengl模块仍存在问题,所有示例程序均不能正常运行,报错提示与之前的Qt5.7.0库一模一样。我试着用原Qt5.7.0库编译,居然也能过编译,说明OpenGL无法运行可能不是软件层面的原因
5.(已解决)每个程序在板子上运行时都会提示:
QIconvCodec::convertToUnicode: using Latin-1 for conversion, iconv_open failed
QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv_open failed
QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-root'
前两行是说字符编码方面问题,缺少iconv这个用于字符转码的库,参考的解决方案:解决交叉编译64位Qt5.15中遇到的问题_在路上...-CSDN博客_交叉编译qt5.15,参照该方法操作后,不再报出该错误提示,但中文字符(显示乱码或不显示)的问题未解决
第三行解决方法:解决QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-root'问题 - 我的白银时代 - 博客园