Qt开发OpenSSL程序踩坑
背景
分别由两个人开发的代码需要被整合进入一个完整的项目并运行。
其中第一位同学使用Visual Studio开发基于C++和openSSL的加解密的程序,使用vcpkg安装和编译openSSL:x86-windows并且集成到Visual Studio中。另一位同学使用Qt Creator开发基于C++和Qt的GUI程序。
IDE选择
由于需要将两份代码合成一个完整的项目运行,我首先选择IDE为Visual Studio,但是由于并没有在VS中写过Qt程序,添加的QT VS TOOL插件总是无法正常编译。因此放弃使用Visual Studio作为项目IDE。选择Qt Creator作为开发环境。
编译
遇到的第一个问题是将openSSL集成到Qt Creator,从网上找到的资料都是从OpenSSL官网下载,并在Qt项目文件中添加库和头文件路径。如下代码所示
LIBS += \
-Lpath/lib -lssl \
-Lpath/lib -lcrypto
INCLUDEPATH += path/include
我遇到的问题是,添加头文件正常,但是在编译的时候会出现undefined reference to xxx
的报错,仔细一看是openssl库中的函数,在代码中follow symbols
可以跳转到头文件中对应的定义,因此猜测是头文件正常但库文件没有正常加载。
这里涉及到的我尝试过的库文件包括
libssl.lib
libcrypto.lib
libssl.a
libcrypto.a
libssl.dll.a
libcrypto.dll.a
libssl-1_1.dll
libcrypto-1_1.dll
libeay32.dll
ssleay32.dll
...
于是开始各种下载和添加库文件。包括但不限于
- 使用vcpkg编译x64-windows版本的openssl库并添加(考虑到32位和64位可能产生的冲突)
- 官网下载openssl安装包(由于下载速度太慢,我选择了64位light版本的安装包,但是light版本安装包没有lib文件,完整版本的安装包就不曾下载成功过)
- 将lib和include文件copy到项目目录下,再使用上述方法添加路径。
在这个时候,我查到一篇文章说qt本身是包括openssl的但是在编译的时候默认不安装,因此qt的环境下实际上是包括openssl对应的库文件和头文件的。经过一番查找我找到这个路径C:\Qt\Qt5.12.0\Tools\mingw730_64\opt
。
这个路径的lib目录下包括了libssl.a、libcrypto.a、libssl.dll.a、libcrypto.dll.a,bin目录下包括libeay32.dll、ssleay32.dll,include目录下包括openssl头文件目录。因此我修改.pro文件如下。
# 这里的$$quote我也没搞清啥意思,大概是双引号
LIBS += \
-LC:\Qt\Qt5.12.0\Tools\mingw730_64\opt\lib -lssl \
-LC:\Qt\Qt5.12.0\Tools\mingw730_64\opt\lib -lcrypto
INCLUDEPATH += \
$$quote(C:\Qt\Qt5.12.0\Tools\mingw730_64\opt\include)
经过多次编译,并注释掉一些无用的函数,终于实现了0 warnigns, 0 errors
,呜呼。
运行
接下来遇到的问题是,程序无法运行。在Qt Creator中直接运行,程序闪退并显示程序异常结束
。在Qt Creator中开启Debugger,同样也是闪退,添加的断点直接被无视了。
刚开始考虑到可能是被杀毒软件杀掉了,因此经过一番操作关闭了Windows Defender,但是仍然无法运行,陷入停滞。
这个时候查到一篇文章,详细介绍了Qt Creator中的闪退的原因并给出了一个检查的方法,就是找到编译生成的exe文件,直接双击运行。程序自然无法运行并提示缺少许多dll文件,其中包括qt的依赖库例如QtCore.dll等等,因此使用windeployqt.exe(位于C:\Qt\Qt5.12.0\5.12.0\mingw73_64\bin
)将Qt所有的依赖dll复制到exe对应的路径下,这个时候再次点击exe文件,显示缺少libeay32.dll
于是将上述的libeay32.dll和ssleay32.dll(位于C:\Qt\Qt5.12.0\Tools\mingw730_64\opt\bin
)复制到这个路径下。
双击exe,正常运行!!!经过测试,一切正常。每次使用qt编译后,将得到的exe文件拷贝到一个新的路径下,调用windeployqt和复制dll就可以正常运行。
总结反思
-
我使用Qt官网下载的安装包安装Qt时,IDE选择了QtCreator,编译环境我选择了MinGW和MSVC,因此在我的安装目录下(
C:\Qt\Qt5.12.0\5.12.0
)包括了如下四个编译环境,每一个环境中都包含了windeployqt等一系列exe文件,和完整的Qt编译环境(bin + lib + include)。mingw73_64
msvc2015_64
msvc2017
msvc2017_64
但是非常疑惑的一点是,在编译时我检查Qt Cretor的编译输出窗口,发现我编译使用的是Tools目录下的mingw730_64。进一步检查发现Tools目录下(
C:\Qt\Qt5.12.0\Tools
)包括如下目录。mingw730_64
QtCreator
前者不是一个完整的Qt编译环境,不包括qt的各种dll,而是包括了ar、ld、gcc、make、objdump等一系列工具,更像是一个编译环境。其opt目录下包括了openssl的编译环境(前文使用到的)。
那么这两个不同的mingw环境究竟有什么区别呢?后者可不可以换成我之前自己手动安装的MinGW环境呢?
-
使用vcpkg编译得到的环境和使用官方安装包以及从GitHub直接下载手动编译的环境有什么区别。
-
对于库文件来说存不存在32位和64位的差异,如果不存在的话,那么vcpkg编译时为什么提供了x86-windows和x64-windows的不同的triplets(还包括了arm、linux等其他选择)。
-
函数静态库和动态库在使用时一定要同时存在么,即编译时指定lib文件,执行时exe文件路径中要包含对应的dll文件。
-
vcpkg编译得到的libssl.lib和mingw730_64的opt路径下的libssl.a文件有什么差异,能不能简单通过改变后缀名来实现适配。同理还有.dll文件和.so文件之间的关系。
最后的最后,还是感觉任重而道远。上述问题大多都是操作系统和C语言编译的基础知识,还是要努力打好基础。