有没有一种方法可以构建带有静态OpenSSL的静态Qt?

17

原始问题略有不同,但是是一个更重要问题的一部分。

我正试图在Windows上以静态方式构建带有静态OpenSSL的Qt 5.2。

我的最终目标是 发布单个二进制文件,而无需提供libeay32.dll和ssleay32.dll。然而,对我来说似乎这是不可能的。我使用静态openssl库构建了静态Qt,但似乎Qt完全忽略了所提供的库,并且总是搜索DLL。

这个答案还建议QtNetwork总是搜索DLL并忽略其他所有内容,但它还说明“两个选项是将OpenSSL编译到Qt中...”,但事实并非如此。

有人可以提供明确的答案吗?

这是我的Qt配置(为了方便阅读添加了换行符):

configure -static -qmake -opensource -nomake examples -opengl desktop
-platform win32-msvc2010 -openssl -I C:\git\openssl\build\include
-L C:\git\openssl\build\lib OPENSSL_LIBS="-llibeay32 -lssleay32 -lgdi32"

为什么不提供相关的 nmake VERBOSE= 输出以查看传递给工具链的包含路径? - László Papp
@Laszlo Papp:已编辑。 - cen
你能具体说明要执行哪个命令吗?因为这是我得到的输出.. 我会尝试清理配置以防万一。 - cen
顺便问一下,你不介意无法通过这种方式提供openssl的安全修复吗?另外,你尝试过-openssl-linked吗? - László Papp
据我理解,openssl-linked 的唯一作用就是如果找不到 ssl 库,你的程序甚至无法启动。没有它,只有在通过 https 发送请求时才会失败。此外,我认为安全修复并不是问题...因为我要么必须通过更新提供新的 DLL,要么只需更新整个二进制文件,这是相同的事情。目前,我决定简单地将 DLL 与安装程序一起分发,一切都正常工作,但我仍然很好奇是否可能做到这一点。 - cen
显示剩余5条评论
4个回答

14

有没有一种方法可以使用静态OpenSSL构建静态Qt?

当配置Qt时,您需要使用以下选项:

-openssl-linked

原因是QtNetwork默认使用QLibrary类动态打开库以获取所需的符号。

这是告诉Qt不要这样做,而尊重正常的链接规则。

话虽如此,如果需要为终端用户提供安全更新而不需要您的参与,则建议不使用openssl的静态链接。考虑一下,如果您离开了,不再从事该项目等情况会发生什么。

此外,这种设置并没有经常进行测试,因此您可能会遇到一些问题,这些问题应该由上游解决,但这是针对所讨论的用例的解决方案设计。

免责声明:由于SO是关于编程的,所以我忽略了静态链接Qt的许可后果,因此我想快速提醒您注意正确使用方式,以免陷入法律纠纷。


1

OPENSSL_LIBS="-llibeay32 -lssleay32"...

避免使用-l(以及-L-Wl,-Bstatic)。链接器有时会忽略对静态链接的请求(苹果公司),有时脚本会修改它(我无法告诉你有多少自定义构建脚本给我带来了麻烦)。

相反,像使用对象文件一样使用完全指定的存档文件。在您的LDLIBS中添加以下内容,以便没有脚本可以弄乱事情或链接器忽略您的请求:

/usr/local/ssl/lib/libssl.a /usr/local/ssl/lib/libcrypto.a

显然,你应该更改 libssl.alibcrypto.a 的路径以匹配你的安装。
如果你没有 LDLIBS,那么将其添加到 LDFLAGS 中(或者在 IDE 中添加到“其他链接器标志”中)。
在 Qt 中,看起来应该是 QMAKE_LFLAGSLIBS。或者你可以尝试这篇文章:如何添加“其他依赖项”(链接器设置)
相同的技巧也适用于共享对象(但链接器更喜欢共享对象,所以通常不会成为问题)。也就是说,你可以指定:
/usr/local/ssl/lib/libssl.so /usr/local/ssl/lib/libcrypto.so

指定类似上述共享对象时需要记住的是,您必须指定一个“rpath”以确保运行时链接器得到消息。也就是说,您应该将以下内容添加到“LDFLAGS”或“其他链接器选项”中:
-Wl,-rpath=/usr/local/ssl/lib

我在使用位于/usr/local/ssl/lib的OpenSSL FIPS可用库时,当指定共享对象时,有几次被咬了一口,因为运行时链接器使用分发的OpenSSL(位于/usr/lib/usr/lib64)。 OpenSSL FIPS可用库是您调用FIPS_mode_set的库。
您还可以从该位置删除(或重命名)共享对象,仅留下静态存档。在构建iPhone的Xcode中使用此技术过去曾经是我必须采取的方法。即使正确放置了-Bstatic,Xcode仍然拒绝使用静态存档。(交叉编译器和修改后的工具链有时是最糟糕的使用方式之一)。我认为您不应该修改安装目录,因此通常不使用此技术。
总之,不要留给机会,避免使用-l-L-Wl,-Bstatic。完全指定您想要的内容,并使用完全限定的库路径名称,并像对象文件一样使用它们。如果您正在指定共享对象,请使用rpath

如果没有冲突,-l和-L实际上是可以的,这也应该是推荐的方式,因为相对于指定完整路径而言,更具可移植性,后者在大多数情况下是特定于操作系统的。 - László Papp
Laszlo - 我有点同意,但我可以肯定地告诉你,链接器和脚本有时不会按照你想要的方式工作。当你放弃使用 -L-l-Bstatic,而是选择完全指定库、档案和目标文件时,这种情况永远不会发生。我举了两个问题的例子(cen也遇到了类似的问题)。这就是理论和实践之间的区别。 - jww
在我看来,这是_你个人的_做法,但当人们正确使用时,情况就不是这样。在Qt项目中编写平台相关的构建系统看起来很不合适。 - László Papp
Lazlo - 好的,随你便。你是对的。你尝试过在苹果平台上测试“只要人们正确使用它就不会出现这种情况”的理论吗?或者在替代位置使用OpenSSL的FIPS库时呢? - jww
是的,此外,根据我的理解,楼主询问的是关于Windows而不是苹果的。 - László Papp

1
这是我如何在Windows上使用MSVC 2013构建支持SSL的Qt 5.7.1的方法:

确保在PATH环境变量中可以找到Perl、Python和Ruby。

从GitHub存储库下载Qt:

cd C:\Qt
git clone https://github.com/qt/qt5.git
cd C:\Qt\qt5 
git checkout 5.7 

请确保检出提交36e7cff94fbb4af5d8de6739e66164c6e6873586。此时,检出5.7正是如此。
将下面的内容放置在位于C:\Qt\qt5qt5vars.bat中。根据需要进行调整:
@echo off

REM Set up \Microsoft Visual Studio 2015, where <arch> is \c amd64, \c x86, etc.
CALL "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86

REM Edit this location to point to the source code of Qt
SET _ROOT=C:\Qt\qt5

SET PATH=%_ROOT%\qtbase\bin;%_ROOT%\gnuwin32\bin;%PATH%

REM Uncomment the below line when using a git checkout of the source repository
SET PATH=%_ROOT%\qtrepotools\bin;%PATH%

REM Uncomment the below line when building with OpenSSL enabled. If so, make sure the directory points
REM to the correct location (binaries for OpenSSL).
SET PATH=C:\OpenSSL-Win32\bin;%PATH%

REM When compiling with ICU, uncomment the lines below and change <icupath> appropriately:
REM SET INCLUDE=<icupath>\include;%INCLUDE%
REM SET LIB=<icupath>\lib;%LIB%
REM SET PATH=<icupath>\lib;%PATH%

REM Contrary to earlier recommendations, do NOT set QMAKESPEC.

SET _ROOT=

REM Keeps the command line open when this script is run.
cmd /k

执行该文件并正确初始化代码仓库:
qt5vars.bat 
perl init-repository

最后,为了成功配置和编译库(包括调试和发布版本),请确保configure引用的路径在您的系统上也是有效的。
configure -static -static-runtime -debug-and-release -ssl -openssl -openssl-linked -opengl dynamic -platform win32-msvc2013 -prefix C:\Qt\qt5.7-msvc2013-static -nomake tests -nomake examples -I "C:\OpenSSL-Win32\include" -L "C:\OpenSSL-Win32\lib\VC\static" OPENSSL_LIBS="-lUser32 -lAdvapi32 -lGdi32 -lCrypt32" OPENSSL_LIBS_DEBUG="-lssleay32MTd -llibeay32MTd" OPENSSL_LIBS_RELEASE="-lssleay32MT -llibeay32MT"
nmake
nmake install

到目前为止,一切都应该顺利美好地运行。现在的问题是配置Qt Creator以便检测这个新的Qt版本创建一个新的工具包用于你的项目:


0

在Win 10上静态构建带有OpenSSL的Qt

  1. 从Qt Maintenance Tool下载Qt 5.15.1源代码。
  2. 安装Python、Perl、OpenSSL和jom。
  3. 确保它们在Path环境变量中。
  4. 打开VS 2019的x64本机工具命令提示符。

从这里下载OpenSSL https://slproweb.com/products/Win32OpenSSL.html

# remove previous config cache
rm /d/Qt/5.15.1/Src/config.cache

set OPENSSL_DIR=C:\Program Files\OpenSSL-Win64
configure.bat -release -opensource -confirm-license -static -no-pch -optimize-size -opengl desktop -platform win32-msvc  -prefix "D:\Qt\5.15.1\msvc2019_64_static" -skip webengine -nomake tools -nomake tests -nomake examples -openssl-linked OPENSSL_INCDIR="%OPENSSL_DIR%\include" OPENSSL_LIBDIR="%OPENSSL_DIR%\lib\VC\static" OPENSSL_LIBS="-lWs2_32 -lGdi32 -lAdvapi32 -lCrypt32 -lUser32 -llibssl64MDd -llibcrypto64MDd" OPENSSL_LIBS_DEBUG="-llibssl64MDd -llibcrypto64MDd" OPENSSL_LIBS_RELEASE="-llibssl64MD -llibcrypto64MD"  

D:\jom_1_1_3\jom.exe -j8
D:\jom_1_1_3\jom.exe -j8 install

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接