交叉编译Qt5.15.2并移植到GEC6818

主机环境:Ubuntu20.04虚拟机

交叉工具链:粤嵌提供的arm-linux-gnueabi-5.4.0,一般开发板厂商都会提供相应的工具链

多嘴几句

Qt程序从X86平台Linux移植到ARM平台Linux需要做什么

1.在X86交叉编译Qt库

2.拷贝交叉编译好的库到开发板上并设置好环境变量(库路径啥的)

前两步一劳永逸,做一次就行

3.X86上写好程序代码,通过交叉工具链进行程序的交叉编译,(动态)链接交叉编译的Qt库(粤嵌),或者厂商提供的Qt-sdk(友善),总之不能直接用开发板文件系统里的Qt库,那个是在arm上运行的

4.程序拷贝到开发板上运行

一般厂商会提供库,为什么我要自己来交叉编译Qt库,还发毫无技术含量的水贴?

答:第一个问题,因为粤嵌提供的Qt库是5.7.0版本,且包括qtlocation,multimedia,qml,qtquick等在内的很多模块被裁剪掉了,导致我想移植的程序无法正常交叉编译,更不要说放开发版上运行;第二个问题:本人属于啥都不会的菜鸡,很多步骤即使做完了也不明白原理,过一段时间就忘记该咋操作,故发帖记录下步骤,以防未来还要干交叉编译库这种糟心事。贴子中步骤大都是参考网上大佬的帖子,我就做个领路人

1.安装可能用到的依赖及下载源码包

安装依赖参照QT安装_George P的博客-CSDN博客,Ubuntu有apt-get install,十分方便

装好依赖后从Index of /archive/qt/5.15/5.15.2/single下载Qt5.15.2源码的压缩包并在虚拟机中解压 

2.创建配置编译选项的脚本

进入解压出来的目录中,创建一个.sh脚本文件用于配置编译选项(图中的autoconfig.sh)

交叉编译Qt5.15.2并移植到GEC6818_第1张图片

编译配置参考了自动驾驶开发入门(一)---交叉编译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

3.编译配置的各选项含义

命令行输入 ./configure -help 即可查看,这里简单说一下部分我用到的

-xplatform是选择交叉工具链的配置文件

-sysroot是编译时查找依赖库的路径,需要选择开发板厂商提供的交叉编译工具链中的sysroot文件夹路径(有的工具链里不一定有该文件夹,挺奇怪的)

-prefix是安装路径,和-sysroot一起用实际的安装路径就成了/sysroot/prefix/

-skip选项用于跳过Qt的某个模块(上上图中基本每个文件夹都是一个模块),即完全不编译该模块。网上很多关于交叉编译的帖子都会-skip qtlocation -skip qtscript -skip qtdecarative..............,就没见过完全不跳,老老实实全部编译的。这主要是因为某些模块交叉编译时特别容易出错

-no类似-skip,但是是用于跳过一些模块的子模块

-pch是预编译头,据说能加快编译速度

其余的上网搜吧。顺便说一下,-mtdev-xinput2应该能添加多点触控功能,但我或许是依赖没装全,系统无法识别-xinput2这一配置项

4.指定并修改qmake.conf文件

 在qtbase/mkspecs/目录下,根据之前在-xplatform指定的编译器名称选一个或新建一个并进入。

交叉编译Qt5.15.2并移植到GEC6818_第2张图片

交叉编译Qt5.15.2并移植到GEC6818_第3张图片

我的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)

5.回到根目录下执行autoconfig.sh 

有些模块依赖多,而且往往依赖的库还有它自己的依赖,很麻烦,不是必需要用的话,能裁则裁

6.make执行编译

每次编译时删掉之前编译过整个源码文件夹重新解压,这么大一个Qt源码包不是make distclean能把握住的,总会有点问题

7.make install执行安装中出现的错误及解决

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后面接核数)大概率会导致错误,可能是由于不同模块间存在依赖关系,多核并行编译导致本应放在后面编译的模块先编译,听着不太靠谱,但我之前用多核一直编译不过,单核编译一次就过了,呃。。。。。。。

8.设置QtCreator的Kit

9.拷贝Qt库到开发板

利用nfs功能将编译好后的库打包发送到开发板上,解包,设置/etc/profile中的QTDIR。

10.存在问题

1.multimedia模块存在问题,在粤嵌6818上五子棋小程序无法播放音效,报错提示:

defaultServiceProvider::requestService(): no service found for - "org.qt-project.qt.mediaplayer"

我试着将五子棋移植到友善上,但是播放音频的那段代码编译无法通过,音频代码和报错如下, 注释掉后能编译通过:

2.没有多点触控(驱动不支持),参考INPUT输入子系统的测试方式 evtest_匠芯筑梦-CSDN博客用evtest测试触摸屏驱动程序

交叉编译Qt5.15.2并移植到GEC6818_第4张图片

如上图,从上到下四个红框依次是:

        1.可测的输入设备

        2.我选的触屏输入设备(名称gslx680是一种电容触屏驱动)

        3.单点按下时获取的信息(坐标以及应该是表示按下的value 1)

        4.单点按下后释放时获取的信息(没有坐标信息,只有应该是表示释放的value 0)

        单点释放时的信息连坐标都没有,如何判断释放的是哪个按下的点,可见该驱动不支持多点触控,实际上多点触摸时第一个点能正常按下,但第二个点按下时会被视作将第一个点释放。

        这样的话瓦片地图无法放大和缩小,只能考虑加个控件控制缩放。地图程序地址:

QML QtLocation地图应用学习-5:实现自己的plugin加载瓦片地图_龚建波-CSDN博客_qml地图插件

3.(已发现原因)qml地图在开发板上运行很卡顿,不确定是程序自身问题还是硬件性能不足,至少电脑上比较顺畅

        说到qml,它是Qtquick项目采用的一种脚本语言,需要引入代码中使用的qtquick模块,如下

交叉编译Qt5.15.2并移植到GEC6818_第5张图片

        友善的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'问题 - 我的白银时代 - 博客园

未完待续

你可能感兴趣的:(qt,开发语言)