1、 移植环境
开发板:正点原子 IMX6ULL 开发板
Ubuntu:20.04
Ubuntu Qt版本:5.12.9
Buildroot Qt5版本:5.15.8
2、 下载 Qt5Mqtt 库
Qt 开发 MQTT 程序有两种方式,一个是 Qt 官方提供的基于 MQTT 的封装,一个是第三方(EMQ)开发的用于 Qt 调用 MQTT 的接口,二者使用方法大同小异,并且均提供了源码。那么,这里介绍第一种,如基于 Qt 官方提供的封装来使用 MQTT。
Qt 官方虽然在 2017 年就已经提供了对 MQTT 的封装,但是并没有正式加入到 Qt 的标准库里面,所以需要自己下载源码进行编译。
Qt 官方介绍文档地址:https://doc.qt.io/QtMQTT/qtmqtt-index.html
Qt 官方在 github 上提供了源代码,地址:https://github.com/qt/qtmqtt
这里我使用的 Ubuntu 中的 Qt 版本是 5.12.9 ,Buildroot Qt5 版本是 5.15.8 所以这里下载 5.15.2 版本的,尽量下载和自己使用的版本相同或者相近的,相差太大的可能会出问题。
3、 编译 Ubuntu 下的 Qt5Mqtt 库
将下载的文件复制到 Ubuntu 中,执行如下命令解压缩文件
sudo tar -vzxf qtmqtt-5.15.2.tar.gz //解压所有的文件
sudo chmod 777 -R qtmqtt-5.15.2/ //赋予所有的文件执行权限
解压后的文件如下
因为下载的下来的源码并不能直接的编译使用还需要修改一些代码,所有我们先使用 Ubuntu 下的 QT5 编译测试,测试完成之后再编译 arm 上面的 Qt5Mqtt 库。其实之所以这样是因为我没有找到相关的资料,只能先用编译 Ubuntu 下的 Qt5Mqtt 库测试,在测试成功之后再按照相应的移植方法去编译移植 arm 上面的 Qt5Mqtt 库。
使用 Ubuntu 下的 Qt5 打开 qtmqtt.pro ,打开之后选择 Release 模式,点击下面的小锤子进行编译
3.1 错误解决方式
点击编译之后会报很多的错误,接下来我们就需要逐条的解决这些错误
-
问题1
-
qmqttauthenticationproperties.h:33: error: C1083: 无法打开包括文件: “QtMqtt/qmqttglobal.h”: No such file or directory
打开 qmqttauthenticationproperties.h 文件,发现有这么两句:
#include <QtMqtt/qmqttglobal.h> #include <QtMqtt/qmqtttype.h>
-
解决方式
将源码下面的 /home/xiaoming/桌面/qtmqtt-5.15.2/src/mqtt 里面的所有文件复制到 Qt 的安装目录下面的 Gcc 编译器下面
我的Qt安装在 opt/Qt5.12.9 下面,所以将mqtt文件夹复制到 /opt/Qt5.12.9/5.12.9/gcc_64/include 文件下面并改名为 QtMqtt ,再编译就不报这个错误了。
-
-
问题2
-
qmqttconnection.cpp:169: error: C2039: “errorOccurred”: 不是“QAbstractSocket”的成员
qmqttconnection.cpp 中 168行有这么一句:
connect(socket, &QAbstractSocket::errorOccurred, this, &QMqttConnection::transportError);
就是这句出了问题。查帮助文档或者源代码都可以发现 QAbstractSocket 没有 errorOccurred 这个 信号。有的那个信号叫:
void error(QAbstractSocket::SocketError socketError)
-
解决方式
要改写成:
connect(socket, static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)> (&QAbstractSocket::error), this, static_cast<void(QMqttConnection::*)(QAbstractSocket::SocketError)>(&QMqttConnection::transportError));
-
-
问题3
-
还有错误:
qmqtttopicname.cpp:148: error: C2039: “KeepEmptyParts”: 不是“Qt”的成员
qmqtttopicname.cpp 148 行代码是这样的:
return d->name.split(QLatin1Char('/'), Qt::KeepEmptyParts);
-
解决方式
改写成:
return d->name.split(QLatin1Char('/'), QString::KeepEmptyParts);
-
-
问题4
-
还有最后一个错误:
qmqtttopicname.cpp:189: error: call to 'qHash' is ambiguous
qmqtttopicname.cpp 189行是:
return qHash(name.d->name, seed);
类似的还有:
return qHash(filter.d->filter, seed);
-
解决方式
改为:
return qHash(static_cast<QString>(name.d->name), static_cast<uint>(seed));
改为:
return qHash(static_cast<QString>(filter.d->filter), static_cast<uint>(seed));
-
至此,编译就没什么问题了。
3.2 移植 Qt5Mqtt 库文件
在上面编译完成之后就可以将 Qt5Mqtt 库文件移植到编译器里面使用了。要使用它有两种方式,一种是直接在项目中导入外部库和头文件,还有一种是将其以模块的形式移植到 Qt 的安装目录,其中第二种的好处就是,只需要做一次操作,以后需要再用 Mqtt 库就可以直接调用了,不需要每次都导入外部库。这里我们直接将库以模块的形式移植到 Qt 里面方便后续的操作。
-
查看编译后的文件
这里移植我们需要使用的就是 /lib 和 /mkspecs 两个文件夹,/lib文件夹里面主要是 Qt5Mqtt 库,/mkspecs 是要将 Qt5Mqtt 库作为 Qt 模块使用要用到的文件
-
查看 /lib下面文件夹下面的内容可以看到和 Qt Gcc 编译器下面的 /lib 文件夹下面的内容是一样的,所以直接将编译后的 /lib 文件夹下的所有内容复制到 Qt Gcc 编译器下面的 /lib 文件夹下面就可以了。
执行如下命令:
sudo cp -r /home/xiaoming/桌面/build-qtmqtt-Desktop_Qt_5_12_9_GCC_64bit-Release/lib/* /opt/Qt5.12.9/5.12.9/gcc_64/lib/
-
再将编译后的 /mkspecs/modules-inst 文件夹下面的内容复制到 Qt Gcc 编译器下面的 /mkspecs/modules 下面,这样在引用模块的时候才可以找到,执行如下命令
sudo cp -r /home/xiaoming/桌面/build-qtmqtt-Desktop_Qt_5_12_9_GCC_64bit-Release/mkspecs/modules-inst/* /opt/Qt5.12.9/5.12.9/gcc_64/mkspecs/modules
这样我们移植完成了,这种方式配置在新建工程中引用只需要引入模块就可以直接使用了:
QT += mqtt
包含头文件:
#include "QtMqtt/qmqttclient.h"
4、 测试 Ubuntu 下的 Qt5Mqtt 库
为了方便演示,我们直接使用 Qt Mqtt 源码中自带的示例来编译运行。
使用 Ubuntu 下的 Qt 打开文件,修改一下头文件的引用,改为 #include "QtMqtt/qmqttclient.h" ,然后直接编译运行,就可以看到已经运行成功。
我们来输入一个ip地址来测试一下,这里我已经在服务器上搭建了 EMQX ,没有的自行搭建或者使用例如阿里云之类的免费 MQTT 也是可以的,可以看已经能够正常运行,至此 Ubuntu 下的 Qt5Mqtt 库下的移植就完成了。
5、 编译 ARM 下的 Qt5Mqtt 库
将下载的文件复制到 Ubuntu 中,执行如下命令解压缩文件
sudo tar -vzxf qtmqtt-5.15.2.tar.gz //解压所有的文件
sudo chmod 777 -R qtmqtt-5.15.2/ //赋予所有的文件执行权限
解压后的文件如下
因为下载的下来的源码并不能直接的编译使用还需要修改一些代码,所有我们先使用 Ubuntu 下的 QT5 编译测试,测试完成之后再编译 arm 上面的 Qt5Mqtt 库。其实之所以这样是因为我没有找到相关的资料,只能先用编译 Ubuntu 下的 Qt5Mqtt 库测试,在测试成功之后再按照相应的移植方法去编译移植 arm 上面的 Qt5Mqtt 库。
使用 Ubuntu 下的 Qt5 打开 qtmqtt.pro ,打开之后选择 Release 模式,点击下面的小锤子进行编译
5.1 查找 Buildroot 的 Qt 编译器目录
因为我们使用的是 Buildroot 下面的 Qt 编译器,所以首先就需要先找到编译器的目录是在什么地方的,这个也很简单,我们使用命令行的方式编译文件,在输出的编译信息就能看到编译器所在的目录了。先切换到下载的 QtMqtt 源码目录下面执行如下指令
/home/linux/buildroot/buildroot-2022.02.3/output/host/usr/bin/qmake //使用buildroot的qmake构建用于编译的makefile文件
make //进行编译
根据编译出来的调试信息可以看到编译所需的头文件在 /home/linux/buildroot/buildroot-2022.02.3/output/host/arm-buildroot-linux-uclibcgnueabihf/sysroot/usr/include 目录下面,我们需要将问题1中的 mqtt 文件下的所有文件复制到这个目录下面。
5.2 错误解决方式
在上面移植 Ubuntu 下的 Qt5Mqtt 库的时候我们已经对源码中的一些错误进行了修改,这里我们在编译 ARM 下的 Qt5Mqtt 库的时候就不需要进行修改了。如果不需要移植 Ubuntu 下的 Qt5Mqtt 库,可以直接看3.1的错误处理方式。唯一一点不同的是问题1下面的文件头文件复制问题,使用下面的方式。
-
问题1
-
qmqttauthenticationproperties.h:33: error: C1083: 无法打开包括文件: “QtMqtt/qmqttglobal.h”: No such file or directory
打开 qmqttauthenticationproperties.h 文件,发现有这么两句:
#include <QtMqtt/qmqttglobal.h> #include <QtMqtt/qmqtttype.h>
-
解决方式
将源码下面的 /home/xiaoming/桌面/qtmqtt-5.15.2/src/mqtt 里面的所有文件复制到 Qt 的安装目录下面的 Gcc 编译器下面
我的 Qt 安装在 opt/Qt5.12.9 下面,所以将 mqtt 文件夹复制到 /home/linux/buildroot/buildroot-2022.02.3/output/host/usr/arm-buildroot-linux-uclibcgnueabihf/sysroot/usr/include/qt5 文件下面并改名为 QtMqtt ,再编译就不报这个错误了。
-
5.3 命令行编译 Qt5Mqtt 库源文件
这里我们使用命令行的方式在编译 Qt 文件,当然也可以使用 Qt creator 里面编译,当然需要额外的设置编译器为 Buildroot 里面的。
先切换到下载的 QtMqtt 源码目录下面执行如下指令
/home/linux/buildroot/buildroot-2022.02.3/output/host/usr/bin/qmake //使用buildroot的qmake构建用于编译的makefile文件
make //进行编译
编译完成之后会报一个错误,这个不用管。
查看源文件目录下面就得到了我们需要移植的文件了
5.4 移植 Qt5Mqtt 库文件
在上面编译完成之后就可以将 Qt5Mqtt 库文件移植到编译器里面使用了。要使用它有两种方式,一种是直接在项目中导入外部库和头文件,还有一种是将其以模块的形式移植到 Qt 的安装目录,其中第二种的好处就是,只需要做一次操作,以后需要再用 Mqtt 库就可以直接调用了,不需要每次都导入外部库。这里我们直接将库以模块的形式移植到 Qt 里面方便后续的操作。
-
查看编译后的文件
这里移植我们需要使用的就是 /lib 和 /mkspecs 两个文件夹,/lib文件夹里面主要是 Qt5Mqtt 库,/mkspecs 是要将 Qt5Mqtt 库作为 Qt 模块使用要用到的文件
-
查看 /lib 下面文件夹下面的内容可以看到和 Buildroot 编译器下面的 /lib 文件夹下面的内容是一样的,所以直接将编译后的 /lib 文件夹下的所有内容复制到 Buildroot 编译器下面的 /lib 文件夹下面就可以了。
执行如下命令:
sudo cp -r /home/xiaoming/桌面/qtmqtt-5.15.2/lib* /home/linux/buildroot/buildroot-2022.02.3/output/host/arm-buildroot-linux-uclibcgnueabihf/sysroot/usr/lib/
-
再将编译后的 /mkspecs/modules-inst 文件夹下面的内容复制到 Buildroot 编译器下面的 /mkspecs/modules 下面,这样在引用模块的时候才可以找到,执行如下命令
sudo cp -r /home/xiaoming/桌面/qtmqtt-5.15.2/mkspecs/modules-inst/* /home/linux/buildroot/buildroot-2022.02.3/output/host/mkspecs
这样我们移植完成了,这种方式配置在新建工程中引用只需要引入模块就可以直接使用了:
QT += mqtt
包含头文件:
#include "QtMqtt/qmqttclient.h"
6、 测试 ARM 下的 Qt5Mqtt 库
为了方便演示,我们直接使用 Qt Mqtt 源码中自带的示例来编译运行。
使用 Ubuntu 下的 Qt 打开文件,修改一下头文件的引用,改为 #include "QtMqtt/qmqttclient.h" ,然后直接使用命令行进行编译,编译完成之后就可以看到编译成功后的文件。
编译完成之后就可以把文件复制到开发板的根文件系统下面了。
在进行运行测试之前还需要将 Qt5Mqtt 库文件也移植到开发板上面,将源码下面的所有 Qt5Mqtt 文件复制到开发板的 /lib 目录下面
开发板上面的 /lib 目录下面的内容如下
在开发板上执行 ./simpleclient 查看屏幕上就可以显示了
至此,我们移植ARM下的Qt5Mqtt就成功了。
评论区