编译开源软件kaidan+qt for visual studio 2015踩的坑

编译开源软件kaidan+qt for visual studio 2015踩的坑

Kaidan是我浏览xmpp官方网站的时候发现的一个开源软件,xmpp官网关于客户端的介绍有如下截图

kandan是基于xmpp协议的IM开源软件客户端,从界面上看起来还不错,之前做过im开发,一个机灵就想下载来看看。其官方地址为:https://git.kaidan.im/kaidan/kaidan/

从其官网来看,没有windows的build教程啊,但其基于CMakelists.txt,可以跨平台编译。加之我对qt不是很熟,借此工程试着搭建vs+qt环境,知道估计会遇到大坑,还是抱着学习和试一试的心态搞起来了。

拿到工程源代码后,就直接用cmake-gui.exe跃跃欲试了,我用的编译环境vs2015。直接configure,configure出错,正如预想,会提示需要依赖第三方库。

提示案例如下,我一个一个的下载源码,安装好,并添加第三方的库目录依赖。

CMake Error at CMakeLists.txt:2 (find_package):
Could not find a package configuration file provided by "ECM" (requested
version 5.40.0) with any of the following names:
ECMConfig.cmake
ecm-config.cmake
Add the installation prefix of "ECM" to CMAKE_PREFIX_PATH or set "ECM_DIR"
to a directory containing one of the above files. If "ECM" provides a
separate development package or SDK, be sure it has been installed.

其中ECM、Krigami2和Qt的依赖解决的很顺利,因为其Cmake规则是基于find_package函数来做的。当然,Qt下载要比较久哈,之前有一篇文章介绍过。

但qxmpp就没这么简单咯。他的编译错误提示是这样的。

CMake Error at I:/installer/cmake-3.12.4-win32-x86/share/cmake-3.12/Modules/FindPkgConfig.cmake:659 (message):
None of the required 'qxmpp>=0.9' found
Call Stack (most recent call first):
CMakeLists.txt:46 (pkg_search_module)

这个我查了很多资料,大概花了我3个小时,差点放弃用cmake-gui.exe改用mingw环境来搞了,网上很少有关于windows的解决方法,据说是要依赖pkg-config.exe啊,我本地也有mingw的环境,也配了pkg-config.exe,还是不行,也不知道有啥预定义参数能给它配置地址的。

网上解答说windows环境尽量不用pkg_search_module来配,用find_package更好,我也尝试用find_package来依赖qxmpp,但qxmpp会提示错误。搞不懂。

参考地址:https://stackoverflow.com/questions/28651088/how-to-use-cmakes-pkg-search-module-when-compiling-under-windows

后来我想既然是依赖,可不可以后面再添加啊,所以我直接在CMakelists里面把qxmpp的依赖删了,然后还提示要openssl依赖,也删了(最后发现openssl依赖好像没啥用)。

Qxmpp的依赖也尝试过用如下方法(第一行是自带的方式)

#pkg_search_module(qxmpp REQUIRED qxmpp>=0.9)

include_directories("C:/qxmpp/include/qxmpp")

link_libraries("C:/qxmpp/lib/qxmpp.lib")

Cmake能编译过,但后面的vs里面编译的时候好像会出错,没深究原因,反正后面再在vs里面加依赖也行。

最后Cmake还提示一个问题:

CMake Error at E:/Program Files (x86)/ECM/share/ECM/modules/ECMAddAppIcon.cmake:110 (message):
No ICONS argument given to ecm_add_app_icon
Call Stack (most recent call first):
CMakeLists.txt:110 (ecm_add_app_icon)

我翻开CMakeLists.txt看原来是有个png图片找不到。我建了一个windows的目录把相关的png放进去(说明官网上的的确windows环境上是没测过的哈)。

然后再configure,和Generate,提示几个worning,其他ok。打开vs工程,编译之,期待能成功~

但是奇迹没出现,提示了几个问题。

首先依赖性问题,这个好解决,加上前面说的qxmpp依赖就好(预先编译安装好的)。

然后提示下面这个问题:

这个问题,刚开始我也摸不着头脑,对其代码不熟,也没想轻易改,最开始以为不能手动添加qxmpp库的依赖,不知道如何解决。

后来仔细看了一下这个dllimport类和成员,发现是kaidan工程自己写的类然后继承qxmpp来做的,自己实现的类哪里用dllimport啊(QXmppUploadRequestManager继承qxmpp库的导出类QXmppClientExtension)。直接把QXMPP_EXPORT注释掉就可以了。我只是举个例子,后面好几个编译和链接错误都和这个QXMPP_EXPORT宏有关系,都注释了,编译链接即可通过。

 

我是怎么发现这个问题的呢?我最开始用notepad++打开qxmpp.lib来看staticMetaObject是否在导出列(这是个好用的方法,看函数、变量和类等是否是导出的),的确有啊,但类不同,于是我怀疑是不是代码写法有问题。刚开始差点全部改为静态全局变量来实现staticMetaObject了(其实也是可以的)。

一些编译错误如下,好像有点乱,反正乱也要能看懂啊:

1>QXmppUploadManager.obj : error LNK2001: 无法解析的外部符号 "__declspec(dllimport) public: __thiscall QXmppHttpUploadRequestIq::QXmppHttpUploadRequestIq(void)" (__imp_??0QXmppHttpUploadRequestIq@@QAE@XZ)

1>QXmppUploadRequestManager.obj : error LNK2019: 无法解析的外部符号 "__declspec(dllimport) public: virtual __thiscall QXmppHttpUploadRequestIq::~QXmppHttpUploadRequestIq(void)" (__imp_??1QXmppHttpUploadRequestIq@@UAE@XZ),该符号在函数 "public: class QString __thiscall QXmppUploadRequestManager::requestUploadSlot(class QFileInfo const &,class QString)" (?requestUploadSlot@QXmppUploadRequestManager@@QAE?AVQString@@ABVQFileInfo@@V2@@Z) 中被引用

1>QXmppUploadManager.obj : error LNK2001: 无法解析的外部符号 "__declspec(dllimport) public: virtual __thiscall QXmppHttpUploadRequestIq::~QXmppHttpUploadRequestIq(void)" (__imp_??1QXmppHttpUploadRequestIq@@UAE@XZ)

1>QXmppUploadManager.obj : error LNK2019: 无法解析的外部符号 "__declspec(dllimport) public: __thiscall QXmppHttpUploadRequestIq::QXmppHttpUploadRequestIq(class QXmppHttpUploadRequestIq const &)" (__imp_??0QXmppHttpUploadRequestIq@@QAE@ABV0@@Z),该符号在函数 "public: __thiscall QXmppHttpUpload::QXmppHttpUpload(class QXmppHttpUpload const &)" (??0QXmppHttpUpload@@QAE@ABV0@@Z) 中被引用

1>QXmppUploadManager.obj : error LNK2019: 无法解析的外部符号 "__declspec(dllimport) public: class QXmppHttpUploadRequestIq & __thiscall QXmppHttpUploadRequestIq::operator=(class QXmppHttpUploadRequestIq const &)" (__imp_??4QXmppHttpUploadRequestIq@@QAEAAV0@ABV0@@Z),该符号在函数 "public: class QXmppHttpUpload & __thiscall QXmppHttpUpload::operator=(class QXmppHttpUpload const &)" (??4QXmppHttpUpload@@QAEAAV0@ABV0@@Z) 中被引用

 

最后可以运行啦,把前面的几个依赖dll拷贝到exe底下去,qt5的依赖有点多,需要用到windeployqt.exe来自动部署。

然后运行,我去,没反应。调试发现是engine.rootObjexts().inEmpty()退出了,也就是engine.load函数执行失败了。

最开始以为我的qt依赖库环境等有问题,写了一些测试例子。比如

int main(int argc, char *argv[])

{

QApplication app(argc, argv);

QWidget wdg;

wdg.show();

return app.exec();

}

这个例子可以跑,弹出一个窗口,qt环境应该没问题,又试了一个qml的例子如下:

int main(int argc, char *argv[])

{

QGuiApplication app(argc, argv);

QQmlApplicationEngine engine;

engine.load("D:\\opensource\\kaidan-master\\src\\qml\\main.qml");

QObject *topLevel = engine.rootObjects().value(0);

QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);

window->show();

return app.exec();

}

对不起这个例子执行失败了。发现vs输出信息的地方会提示如下错误(最开始没发现输出这个重要线索,以至于用QtCreator跑了一下上面的例子,发现可以才回到vs查问题的。顺便说下,其中用QtCreator的时候改变头文件后要用Qmake执行一下再debug才可以成功,否则会出现link错误):

QQmlApplicationEngine failed to load component

qrc:/main.qml:2 module "QtQuick.Controls" is not installed

qrc:/main.qml:1 module "QtQuick" is not installed

qrc:/main.qml:2 module "QtQuick.Controls" is not installed

 

拷贝一个网上的解决方案(这个我也查了很久)

调试运行提示

QQmlApplicationEngine failed to load component

qrc:/main.qml:2 module "QtQuick.Controls" is not installed

qrc:/main.qml:1 module "QtQuick" is not installed

qrc:/main.qml:2 module "QtQuick.Controls" is not installed

解决方案

看了几篇文章解决方案都不优雅,提供一个自认为比较好的方法,告诉程序去哪里加载qml

int main(int argc, char *argv[])

{

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    engine.addImportPath("C:\\Qt\\Qt5.6.2\\5.6\\static-vs2015-qt5.6.2\\qml");

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

 

    return app.exec();

}

原文:https://blog.csdn.net/x356982611/article/details/62421140

我加了这个:

然后还会提示org.kde.dirigami找不到,打开对应的main.qml发现还依赖了这个。

把之前安装的Kirigami库中qml目录地下的org目录拷贝到E:\Qt\5.11.0\msvc2015\qml里面来。注意还有个bin下的KF5Kirigami2.dll要放到对于的exe底下去,前面的QtQuick和QtQuick.Controls的dll也拷贝了。可以想象,对于的一个qml import ** component会对于一个dll库文件和好多qml文件

最后的最后,当当当当...可以出来了~~

Visual studio 2015+qt的环境就这样搭建好了哈,看看工程的依赖头文件和库文件:

D:\opensource\kaidan-master\build-15

D:\opensource\kaidan-master

D:\opensource\kaidan-master\build-15\kaidan_autogen\include_Debug

E:\Qt\5.11.0\msvc2015\include

E:\Qt\5.11.0\msvc2015\include\QtCore

E:\Qt\5.11.0\msvc2015\.\mkspecs\win32-msvc

E:\Qt\5.11.0\msvc2015\include\QtSql

E:\Qt\5.11.0\msvc2015\include\QtQml

E:\Qt\5.11.0\msvc2015\include\QtNetwork

E:\Qt\5.11.0\msvc2015\include\QtQuick

E:\Qt\5.11.0\msvc2015\include\QtGui

E:\Qt\5.11.0\msvc2015\include\QtANGLE

E:\Qt\5.11.0\msvc2015\include\QtSvg

E:\Qt\5.11.0\msvc2015\include\QtWidgets

E:\Qt\5.11.0\msvc2015\include\QtXml

E:\Qt\5.11.0\msvc2015\include\QtQuickControls2

E:\Program Files (x86)\kirigami2\include\KF5\Kirigami2

E:\Program Files (x86)\kirigami2\include\KF5

C:\Program Files (x86)\qxmpp\include\qxmpp

E:\Qt\5.11.0\msvc2015\lib\Qt5Sqld.lib

E:\Qt\5.11.0\msvc2015\lib\Qt5Svgd.lib

E:\Qt\5.11.0\msvc2015\lib\Qt5Xmld.lib

E:\Qt\5.11.0\msvc2015\lib\Qt5Widgetsd.lib

C:\Program Files (x86)\qxmpp\lib\qxmpp.lib

E:\Program Files (x86)\kirigami2\lib\KF5Kirigami2.lib

E:\Qt\5.11.0\msvc2015\lib\Qt5QuickControls2d.lib

E:\Qt\5.11.0\msvc2015\lib\Qt5Quickd.lib

E:\Qt\5.11.0\msvc2015\lib\Qt5Qmld.lib

E:\Qt\5.11.0\msvc2015\lib\Qt5Networkd.lib

E:\Qt\5.11.0\msvc2015\lib\Qt5Guid.lib

E:\Qt\5.11.0\msvc2015\lib\Qt5Cored.lib

E:\Qt\5.11.0\msvc2015\lib\qtmaind.lib

最后再说一下,其实qt for vistual studio没这么麻烦,vistual studio有个qt插件。在“工具”》“扩展和更新”里面,搜索“qt”,安装即可,可以参考:

https://blog.csdn.net/liang19890820/article/details/53931813

 

猜你喜欢

转载自blog.csdn.net/fripy/article/details/86512521
今日推荐