【问题标题】:Static OpenSSL *.a libraries not linked target binary (using Statically Compiled Qt with SSL)静态 OpenSSL *.a 库未链接目标二进制文件(使用带 SSL 的静态编译 Qt)
【发布时间】:2020-02-13 02:52:19
【问题描述】:

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

我想达到什么目的?

我需要创建一个支持 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 script 的帮助下完成了这项工作,改编自 ps1 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"` 

我在哪里使用静态编译的 MinGW OpenSSL 库,在

中找到
`$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 文件> Static & Windows 仅带有 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 库的情况下,在非开发(新/客户端)机器上请求 SSL 连接时会导致以下错误:

QSslSocket::connectToHostEncrypted: TLS 初始化失败

这是 OpenSSL 库未作为依赖项包含在二进制文件中的结果。所以基本上,在项目文件中添加一个静态 OpenSSL 库是行不通的,或者我在某处做错了。

注 4: 为什么问题的标题不是:How to Import a static library into Qt?

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

我们将不胜感激有关解决此问题的建议。


更新 1

我已经解决了-openssl-linked 的问题。原因(或者更确切地说是修复)是没有将 OpenSSL 安装到您的机器上。相反,将.ainclude 目录提取到单独的目录中。所以一切都是一样的,除了你没有安装libs & include

然后使用标准配置(上面提到),将-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 的必需项。

【问题讨论】:

  • 您是否尝试过将 .pro 文件 win32: LIBS += -L... -lssl 更改为以 -l:libssl.a 结尾 gcc 将尝试尽可能链接到共享库,因此如果该目录中存在共享库,则链接器将使用自动动态库。
  • @TinfoilPancakes 也会尝试,但会先试一试n.m.的答案

标签: c++ qt ssl openssl


【解决方案1】:

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

【讨论】:

  • 是的......这是一个让我发疯的问题。如果我找到解决方案,会尝试解决并报告
  • 所以,我能够使用-openssl-linked 编译Qt,配置指向我的包含文件夹和*.a 库。在构建和运行我的应用程序时,它说找不到libcrypto.dlllibssl.dll。我已经取得了进展,但是这些库应该编译成 exe。有什么建议吗?
  • 在构建时在运行时?
  • 运行时。构建成功,但运行需要这些库。我已经用 & w/o LIBS += ... 到静态库 & INCLUDEPATH += ...include 目录进行了测试,两者都报告相同的缺失 dll's
  • 还使用Start-Process -PassThru .\SSL-Test.exe | Get-Process -Module 查看缺少的dll,但dll 似乎不是依赖项。查看更新。
【解决方案2】:

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

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

【讨论】:

  • 这应该是一条评论,而且我知道可以为安装程序添加所需的 dll。但是,该问题旨在创建完全可移植的应用程序,因此“运送 4 个 DLL 文件”不是独立的可移植应用程序的可行选项。
【解决方案3】:

如果您正确构建了 Qt,将 ssl 作为静态链接,则您不需要 不再需要将 ssl 显式链接到应用程序,只需链接 Qt。

gcc 的正确形式是-Lrelative-or-absolute/path(我使用*nix 路径),-L 指定 库所在的路径和 xyz 所在的 -lxyz 要链接的库的名称,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 文件。

Qt 文档对支持 ssl 的事实并不清楚(恕我直言) 静态链接,我认为是这样,但应该检查一下

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

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

【讨论】:

    【解决方案4】:

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

    1. Bukd openSSL 作为静态库

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

      SET CL=/MP

      perl 配置 VC-WIN64A no-shared --prefix=C:\Build-OpenSSL-VC-64-STATIC

      nmake

      nmake 安装

    2. 使用静态 SSL 构建 Qt:

      ..\configure -static -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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-14
      • 2015-03-19
      • 2019-08-10
      • 2015-04-02
      • 1970-01-01
      相关资源
      最近更新 更多