静态OpenSSL * .a库未链接目标二进制文件(使用带有SSL的静态编译Qt)

时间:2019-10-16 10:38:50

标签: c++ qt ssl openssl

马上开始,对问题的长度感到抱歉,但这是由于我提供的所有其他详细信息,希望可以帮助您更快地解决问题

我要实现什么目标?

我需要创建一个具有SSL支持的便携式(多合一)应用程序。

出了什么问题?

所以我面临的核心问题是要在我的二进制/便携式应用程序中包含SSL支持。

该应用程序的 MCVE 很简单:

项目.pro文件

QT -= gui
QT += network

CONFIG += c++11 console
CONFIG -= app_bundle

SOURCES += \
        main.cpp

INSTALLS += target

项目main.cpp

#include <QCoreApplication>
#include <QSslSocket>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "Is SSL Enabled? " << QSslSocket::supportsSsl();
    qDebug() << "SSL Library Build Version (Qt compiled against): " << QSslSocket::sslLibraryBuildVersionString();
    qDebug() << "SSL Library Version String (available locally): " << QSslSocket::sslLibraryVersionString();

    return a.exec();
}

  • 我的 DEV计算机上的输出

    Is SSL Enabled?  true
    SSL Library Build Version (Qt compiled against):  "OpenSSL 1.1.1d  10 Sep 2019"
    SSL Library Version String (available locally):  "OpenSSL 1.1.1d  10 Sep 2019"

开发人员信息

    C:\Users\cybex>echo %PATH%
    C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Strawberry\c\bin;C:\Strawberry\perl\site\bin;C:\Strawberry\perl\bin

    C:\Users\cybex>openssl
    WARNING: can't open config file: /z/extlib/_openssl_/ssl/openssl.cnf
    OpenSSL> version
    OpenSSL 1.0.2g  1 Mar 2016

  • 在新的Windows 10 x86计算机上运行相同的二进制文件会导致:

    Is SSL Enabled?  false
    SSL Library Build Version (Qt compiled against):  "OpenSSL 1.1.1d  10 Sep 2019"
    SSL Library Version String (available locally):  ""

测试机信息(完全全新安装-Windows 10 x86)

    C:\Users\cybex>echo %PATH%
    C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\
    C:\Users\cybex>openssl
    'openssl' is not recognized as an internal or external command,
    operable program or batch file.

  • 在新的Windows 7 x64计算机上运行相同的二进制文件会导致:

    Is SSL Enabled?  false
    SSL Library Build Version (Qt compiled against):  "OpenSSL 1.1.1d  10 Sep 2019"
    SSL Library Version String (available locally):  ""

测试机信息(已安装驱动程序的Windows 7 x64笔记本电脑)

    C:\Users\Home>echo %PATH%
    C:\Program Files (x86)\OpenSSL\libs;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x64;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x64;C:\Program Files (x86)\OpenSSL\libs;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\
    C:\Users\Home>openssl
    'openssl' is not recognized as an internal or external command, operable program or batch file.

通过查看以上结果,我得出结论,安装OpenSSL可解决此问题。很好,但是我想将其包含在便携式应用程序中。

要实现这一目标,我必须

  1. 通过OpenSSL支持静态编译Qt

我是在this scriptps1 powershell script改编的here on Qt's wiki的帮助下完成此操作的。我添加了以下内容:

  • OpenSSL主页$OPENSSL_HOME

  • 线程数$threads

  • 要使用的体系结构类型$arch

Qt编译详细信息和OpenSSL信息

  • 编译器:mingw32位于C:\Qt\Qt5.13.1\Tools\mingw730_32\bin

  • mkspec:win32-g++(如果有区别)。

  • OpenSSL版本(32位):1.1.1d

配置如下

cmd /C "configure.bat -static -debug-and-release -platform win32-g++ -prefix $QtDir `
        -qt-zlib -qt-pcre -qt-libpng -qt-libjpeg -qt-freetype -opengl desktop -sql-sqlite -ssl -openssl -I $($OPENSSL_HOME)\include -L$($OPENSSL_HOME)\lib\MinGW`
        -opensource -confirm-license `
        -make libs -nomake tools -nomake examples -nomake tests -v"
cmd /C "mingw32-make -k -j$($threads)"

注释1:

我正在使用-openssl,而不是-openssl-linked。我尝试使用-openssl-openssl-linked构建Qt的几种变体。 -openssl-linked永远无法成功构建,请参阅this post我对原因的解释。

注释2:

我唯一成功完成的静态Qt编译是启用了-ssl -openssl配置标志

OpenSSL安装(仅在DEV计算机上)位于

`$OPENSSL_HOME = "C:\OpenSSL-Win32"` 

我在其中使用

中的OpenSSL静态编译的MinGW
`$OPENSSL_HOME = "C:\OpenSSL-Win32\lib\MinGW",`

C:\OpenSSL-Win32\lib\MinGW的文件内容为:

Directory: C:\OpenSSL-Win32\lib\MinGW

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2019/09/11     18:11        3347286 libcrypto.a
-a----       2019/09/11     18:10         109020 libcrypto.def
-a----       2019/09/11     18:11         385126 libssl.a
-a----       2019/09/11     18:10          14033 libssl.def
  1. 将链接项目.pro添加到OpenSSL库

我使用2种方法将OpenSSL库添加到.pro文件中(库是在C:\OpenSSL-Win32\lib\MinGW找到的静态编译的MinGW OpenSSL库)

将库手动输入.pro文件

QT -= gui
QT += network

# OpenSSL static .a libraries
INCLUDEPATH += "C:\OpenSSL-Win32\include"
LIBS += -L"C:\OpenSSL-Win32\lib\MinGW\libssl.a"
LIBS += -L"C:\OpenSSL-Win32\lib\MinGW\libcrypto.a"

CONFIG += c++11 console
CONFIG -= app_bundle

SOURCES += \
        main.cpp

INSTALLS += target

注释3

带有和不带有上面链接的库的二进制大小保持不变

带有上面添加的库的二进制文件(在我的开发机上)的LDD输出为:

Start-Process -PassThru .\SSL-Test.exe | Get-Process -Module

   Size(K) ModuleName                                         FileName
   ------- ----------                                         --------
      6280 SSL-Test.exe                                       C:\Users\cybex\QtProjects\build-SSL-Test-Desktop_Qt_Op...
      1512 ntdll.dll                                          C:\Windows\SYSTEM32\ntdll.dll
       596 KERNEL32.DLL                                       C:\Windows\system32\KERNEL32.DLL
      1500 KERNELBASE.dll                                     C:\Windows\system32\KERNELBASE.dll

具有上面添加的库的二进制文件(在Windows 10 x86测试机上)的LDD输出为:

Start-Process -PassThru .\SSL-Test.exe | Get-Process -Module

   Size(K) ModuleName                                         FileName
   ------- ----------                                         --------
      6280 SSL-Test.exe                                       C:\Users\cybex\Desktop\SSL-Test.exe
      1512 ntdll.dll                                          C:\Windows\SYSTEM32\ntdll.dll
       596 KERNEL32.DLL                                       C:\Windows\system32\KERNEL32.DLL
      1500 KERNELBASE.dll                                     C:\Windows\system32\KERNELBASE.dll

Qt库导入到.pro文件

使用(External Library>导入.a文件> StaticWindows仅带有后缀no debug的选项导入)

QT -= gui
QT += network

CONFIG += c++11 console
CONFIG -= app_bundle

SOURCES += \
        main.cpp

INSTALLS += target

win32: LIBS += -L$$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW/ -lssl

INCLUDEPATH += $$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW
DEPENDPATH += $$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW

win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW/ssl.lib
else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW/libssl.a

win32: LIBS += -L$$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW/ -lcrypto

INCLUDEPATH += $$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW
DEPENDPATH += $$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW

win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW/crypto.lib
else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW/libcrypto.a

使用自动二进制导入,带有上面添加的库的二进制文件(在我的开发机上)的LDD输出为:

Start-Process -PassThru .\SSL-Test.exe | Get-Process -Module

   Size(K) ModuleName                                         FileName
   ------- ----------                                         --------
      6280 SSL-Test.exe                                       C:\Users\cybex\QtProjects\build-SSL-Test-Desktop_Qt_Op...
      1512 ntdll.dll                                          C:\Windows\SYSTEM32\ntdll.dll
       596 KERNEL32.DLL                                       C:\Windows\system32\KERNEL32.DLL
      1500 KERNELBASE.dll                                     C:\Windows\system32\KERNELBASE.dll

使用自动库导入,带有上面添加的库的二进制文件(在Windows 10 x86测试机上)的LDD输出为:

Start-Process -PassThru .\SSL-Test.exe | Get-Process -Module

   Size(K) ModuleName                                         FileName
   ------- ----------                                         --------
      6280 SSL-Test.exe                                       C:\Users\cybex\Desktop\SSL-Test.exe
      1512 ntdll.dll                                          C:\Windows\SYSTEM32\ntdll.dll
       596 KERNEL32.DLL                                       C:\Windows\system32\KERNEL32.DLL
      1500 KERNELBASE.dll                                     C:\Windows\system32\KERNELBASE.dll

开发机器的应用程序输出为SSL enabled,如我在我的帖子中先前提到的(用于手动和自动输入库):

Is SSL Enabled?  true
SSL Library Build Version (Qt compiled against):  "OpenSSL 1.1.1d  10 Sep 2019"
SSL Library Version String (available locally):  "OpenSSL 1.1.1d  10 Sep 2019"

测试机器(未安装OpenSSL)的应用程序输出也与以前相同(对于手动和自动输入库):

Is SSL Enabled?  false
SSL Library Build Version (Qt compiled against):  "OpenSSL 1.1.1d  10 Sep 2019"
SSL Library Version String (available locally):  ""

因此,如果不存在OpenSSL库,则在Non-Dev(新鲜/客户端)计算机上请求SSL连接时,它将导致以下错误:

  

QSslSocket :: connectToHostEncrypted:TLS初始化失败

这是OpenSSL库没有作为依赖项包含在二进制文件中的结果。因此,基本上,将静态OpenSSL库添加到项目文件中是行不通的,否则我在某处做某事是不正确的。

注释4: 为什么标题不是这样的问题:如何将静态库导入Qt?

导入静态库很简单,也并不复杂。我假设在启用了SSL支持的Qt静态编译中某个地方犯了一个错误。

解决此问题的建议将不胜感激。


更新1

我已经解决了-openssl-linked的问题。原因(或更确切地说,是修复)是未将OpenSSL安装到您的计算机上。而是将.ainclude伪指令提取到单独的目录中。因此,除了没有安装的libinclude以外,其他一切都相同。

然后使用标准配置(如上所述),将-openssl替换为-openssl-linked,您应该可以成功编译。

更新的问题

使用新的 Linked OpenSSL Qt工具包构建和运行应用程序时,我收到一条消息,提示:

  

因为找不到libcrypto.dll,所以无法继续执行代码。重新安装程序可能会解决此问题。

随后是另一个对话框

  

因为找不到libssl.dll,所以无法继续执行代码。重新安装程序可能会解决此问题

LDD要求:

Start-Process -PassThru .\MyAwesomeApp.exe | Get-Process -Module

   Size(K) ModuleName                                         FileName
   ------- ----------                                         --------
     22708 MyAwesomeApp.exe                                     C:\Users\CybeX\QtProjects\build-MyAwesomeApp-Desktop_Qt_OpenSSL_Linked_5_13_1_MinGW_32bit-Release\release\MyAwesomeApp.exe
      1924 ntdll.dll                                          C:\WINDOWS\SYSTEM32\ntdll.dll
       328 wow64.dll                                          C:\WINDOWS\System32\wow64.dll
       480 wow64win.dll                                       C:\WINDOWS\System32\wow64win.dll
        40 wow64cpu.dll                                       C:\WINDOWS\System32\wow64cpu.dll

已在使用.pro LIBSINCLUDEPATH的情况下对此进行了测试。两者都会导致缺少dll的要求。

4 个答案:

答案 0 :(得分:3)

-openssl配置选项将Qt配置为使用LoadLibrary或其他等效的平台功能动态加载libopenssl 。因此,从这一点出发,您的所有努力都是徒劳的。您需要返回并解决-openssl链接的问题。

答案 1 :(得分:0)

如果您正确构建了Qt,并以静态方式链接到ssl,则无需 不再需要将ssl明确链接到应用程序,只需链接 Qt。

gcc的正确格式为-Lrelative-or-absolute/path(我正在使用* nix路径),-L用于指定 库所在的路径和-lxyz的xyz所在的路径 要链接的库的名称ssl(不带前缀lib,并且不带 后缀.a

但是最终,.a文件是.o文件的集合,可以是 在链接阶段添加如下:gcc -o target file.o libssl.a (因此有时在某些情况下LIBS += /path/libssl.a可以正常工作)

根据Qt documentation,无需卸载 系统ssl,只需将OPENSSL_LIBS环境变量传递(导出)到 Qt配置脚本(OPENSSL_LIBS='-L/opt/ssl/lib -lssl -lcrypto'

如果同时存在两个文件(.a.dll),则gcc仍可以选择 动态版本,请确保您链接了静态版本 删除.dll文件。

关于支持ssl的事实,Qt文档尚不清楚(IMHO) 静态链接,我认为是这样,但是应该检查

  

默认情况下,启用SSL的Qt库动态加载任何   在运行时安装了OpenSSL库。但是,有可能   通过使用以下命令配置Qt,在编译时链接到库   -openssl链接的选项。

我应该为我做构建,我将启用详细输出,并在日志中验证它实际上是静态链接的,我将验证它是否来自正确的目录以及最终的目标Qt包含ssl符号。

答案 2 :(得分:0)

我使用VS2019作为本机win32编译器,而不是mingw:

  1. 将openSSL作为静态lib

    “ C:\ Program Files(x86)\ Microsoft Visual Studio \ 2019 \ Community \ VC \ Auxiliary \ Build \ vcvars64.bat”

    SET CL = / MP

    perl配置VC-WIN64A不共享--prefix = C:\ Build-OpenSSL-VC-64-STATIC

    nmake

    nmake安装

  2. 使用静态SSL构建Qt:

    .. \ configure -静态-IC:\ Build-OpenSSL-VC-64-STATIC \ include -LC:\ Build-OpenSSL-VC-64-STATIC \ lib OPENSSL_LIBS =“-llibcrypto -llibssl- lgdi32 -lWs2_32 -lwsock32 -ladvapi32 -luser32 -lCRYPT32“ -openssl-linked -static-runtime ...等

32位相同

perl Configure VC-WIN32 no-shared --prefix=C:\Build-OpenSSL-VC-32-STATIC

我在没有DLL的单个.exe中具有支持SSL的应用程序。 -static-runtime 没有VC_redistributable依赖项。

然后,您需要允许重新链接已关闭源的应用程序,以使其与LGPL V3兼容

例如,使用此应用程序模板:

https://marketplace.qt.io/products/qt-lgpl-app-template

答案 3 :(得分:-1)

只需将OpenSSL的4个DLL文件与您的应用程序一起发送(即,将libcrypto-1_1-x64.dll,libssl-1_1-x64.dll,libcrypto-1_1.dll和libssl-1_1.dll复制到您的应用程序的安装中)。

如果您使用的是Qt的免费版本,则静态地构建所有库可能会违反LGPL许可证。