windows - 如何在 Windows 下将 Qt5 构建为静态库
问题描述
要将 Qt 应用程序作为简单的 .exe 文件分发给 Windows 用户,需要静态链接 Qt 库的静态版本。假设我们在开放许可证下分发我们的许可证,以便允许 Qt 的静态链接。所以我们只需要 Qt5Core、Qt5Gui、Qt5Widgets 的静态库二进制文件。如何得到它们?
Qt5 的二进制发行版仅带有动态库。它还包含一些 .lib 文件 - 但请注意,这些不是静态库,而是一些辅助文件。它们可以通过大小与真正的静态库区分开来:真正的静态库要大得多(在 Qt5 组件的情况下很多 MB)。所以我们需要自己静态编译Qt5。事实证明这非常困难。
官方说明(http://doc.qt.io/qt-5/windows-building.html)几乎没有用:太短了,他们甚至没有传达任务难度的想法。目前缺少如何将 Qt5 编译为静态库的精确、最新、分步指南。我们应该在这里拥有它。
解决方案
简短的回答:不要在这上面浪费你的时间。动态链接,并让安装程序分发您的应用程序。这是 Qt5 和 CMake 认真支持的唯一模式。在没有他们的支持和反对他们的建议的情况下工作几乎是绝望的。设置安装程序要容易得多(尽管也没有乐趣 - 我们目前使用来自https://hk.saowen.com/a/d1cf90fcfea6d511629fd5a6c8113808721a7f19656677e8a5fab370a8d35cd4的黑魔法)。
长长的(但不完整的)答案,以防你想比我聪明:
以下步骤使我看似接近解决方案。我成功地构建了静态库,但我无法链接我的应用程序:由于神秘的未解析外部符号导致数百个 LNK2001 和 LNK2019 错误,我不得不放弃。
因此,这里逐步描述了 2018 年 10 月在 Windows10 虚拟桌面上对我有用的方法。对于每个安装步骤,都会进行检查。如果检查失败,则在继续进行之前解决问题。
首先,安装一些稍后需要的工具:
- Perl,需要 zlib 和 openssl 配置:
- 如果“perl -v”有效,则跳过。
- 从https://www.activestate.com/activeperl获取安装程序
- 运行安装程序 -> 将安装到 C:\Perl64。
- 检查:重新启动终端并尝试“perl -v”。
- 一个可以处理 Unix 行尾的编辑器。记事本不行。安装vim、emacs或其他任何东西。
- 巧克力包管理器,需要安装 flex 和 bison:
- 运行管理员外壳(圆形菜单>搜索“命令”>右键单击“命令提示符”>以管理员身份运行)
- 从https://chocolatey.org/install#install-with-cmdexe复制下载命令
- 将命令粘贴到 admin shell,并观看安装
- 检查:在终端中,尝试命令“choco”
- qtbase 编译需要的flex和bison:
- 获得正确版本的 flex 并不明显。从 gnuwin32.sourceforge.net 我得到了一个过时的 flex,它错过了 Qt 编译期间所需的命令行参数。从源代码编译 flex 引入了进一步的依赖关系。我找到的最简单的解决方案是使用 Chocolatey 包管理器。
- 在 admin shell 中,运行:“choco install winflexbison3”。这将创建一个目录X,其中包含二进制文件 win_flex.exe 和 win_bison.exe 以及一个支持的“数据”文件夹。找出X的位置。就我而言,X =C:\ProgramData\chocolatey\lib\winflexbison3\tools
- 检查: cd X,然后运行“win_flex --version”、“win_bison --version”。
- 在 Qt 编译期间,将需要这些工具的标准名称为“flex”和“bison”。因此我们需要符号链接 flex->win_flex、bison->win_bison。
- mlink X \flex.exe X \win_flex.exe
- mlink X \bison.exe X \win_bison.exe
- 注意:mklink 需要绝对路径才能可靠地工作
- 注意:符号链接不能转到另一个目录,以免野牛找不到“数据”文件夹
- 将X添加到 %PATH%
- 检查:在任何 shell 中,尝试“flex --version”和“bison --version”
到目前为止的工具。现在我们需要两个必须静态链接到 Qt 的库(从https://stackoverflow.com/a/41815812/1017348学到的魔法):
- 构建静态zlib:
- 下载https://zlib.net/zlib1211.zip
- 解压到 C:\Development\zlib-1.2.11
- 使用可以处理 Unix EOL 的编辑器编辑文件 win32\Makefile.msc:
- 查找以 CFLAGS 开头的行
- 将 -MD 替换为 -GL -MT -Zc:wchar_t-
- 查找以 LDFLAGS 开头的行
- 将 -debug 替换为 -opt:icf -dynamicbase -nxcompat -ltcg /nodefaultlib:msvcrt
- 查找以 CFLAGS 开头的行
- 使用以下命令构建 zlib(应该不到一分钟):
- nmake -f win32/Makefile.msc AS=ml64 LOC="-DASMV -DASMINF -DNDEBUG -I." OBJA="inffasx64.obj gvmat64.obj inffas8664.obj"
- 检查:因此,源目录必须包含 zlib.lib (856kB) 等。
- 构建静态openssl库:
- 下载https://www.openssl.org/source/openssl-1.1.1.tar.gz
- 解压到 C:\Development\openssl-1.1.1
- 从 zlib 复制文件:cd zlib-1.2.11;xcopy zconf.h ..\openssl-1.1.1\ ; zlib.h zlib.lib zlib.pdb 相同
- cd ..\openssl-1.1.1
- perl 配置 VC-WIN64A no-asm no-shared zlib no-zlib-dynamic threads --prefix=C:\opt\local_x64
- 注意:我添加了“no-asm”以避免安装 NASM(Netwide Assembler)
- 注意:我更改了前缀,因为只有管理员可以安装到 C:\Windows
- 编辑文件''makefile'':
- 找到以 CFLAG 开头的行
- 附加:/Zc:wchar_t- /GL /Zi
- 找到开头的行:LDFLAGS
- 将 /debug 替换为 /incremental:no /opt:icf /dynamicbase /nxcompat /ltcg /nodefaultlib:msvcrt
- 找到以:CNF_EX_LIBS 开头的行
- 用 zlib.lib 替换 ZLIB1
- 找到以 CFLAG 开头的行
- 构建:“nmake”
- 检查:目录必须包含 openssl.lib(大小?)
现在我们准备好使用 Visual Studio C++ 编译器的命令行版本从源代码构建qtbase :
- 下载(最新Qt的更新位置):https ://download.qt.io/archive/qt/5.11/5.11.2/submodules/qtbase-everywhere-src-5.11.2.zip
- 拆包需要 20'
- 将源目录移动到本地磁盘 (C:\Development)
- 要使用 Visual Studio,请使用专门配置的终端。使用 Taskbar>Circle>Search 启动“x64 Native Tools Command Prompt for VS 2017”
- cd qtbase...
- 检查:配置 --help
- 配置 -platform win32-msvc2017 -opensource -confirm-license -release -static -openssl-linked no-dbus -no-libpng -no-libjpeg -nomake 示例 -nomake 测试 -prefix C:\opt\local_x64 -IC:\Development \openssl-1.1.1\include -LC:\Development\openssl-1.1.1 -D OPENSSL_LIBS=C:\Development\openssl-1.1.1\libssl.lib
- 在调试“配置”时,可能需要删除 config.cache。
- 选项 -I 不适用于相对路径
- 如果我们想在 64 位应用程序中使用 Qt,标签“win32”可能看起来不对,但我们建议不要担心:在 Windows 下构建 Qt:真的使用“-platform win32-msvc2017”吗?
- 我不知道如何摆脱 Sql:https ://bugreports.qt.io/browse/QTBUG-71253
- 可选代码需要 libpng 和 libjpeg。它们在 src/3rdparty 中提供,这往往会引发与系统提供的库版本的冲突。因此,我们构建时不支持 PNG 和 JPG。
- 制作
- 检查:静态库(大 .lib 和小 .prl)位于目录 lib/
- 54.7 MB Qt5Core.lib
- 23.4 MB Qt5Widgets.lib
- 18.2 MB Qt5Gui.lib
- 07.4 MB Qt5Network.lib
- ...
就是这样,我们有静态 Qt 库。只是,如上所述,当我尝试将我的应用程序与这些库链接时,这对我没有帮助。
推荐阅读
- vb.net - 如何在特定位置/索引处将文本行附加到 Richtextbox 中?
- windows - kerberos TGT 解释
- spring - 是否可以在 k8s configMaps 中进行参数替换?
- python-3.x - 如何从 np.where() 而不是 True/False 获取单元格的值
- r - ggplot2 图例标题不尊重 Google 字体的粗体
- reactjs - 如何在 Ant Design Form 中使用 async onFinish 方法
- firebase - Firebase SwiftUI and Firebase Auth - not reading user ID?
- gradle - Gradle 如何自动更新依赖的版本?
- scala - Spark - 从数组对象中选择多列
- debugging - 通过 UART 将缓冲区作为 USB 数据发送到 VCP 时无法访问内存位置