☰
Qt 5.15.12 Windows 10 32位动态库编译实战:从环境配置到验证
2026/10/26 12:42:37 网站建设 项目流程

简介:面向Windows 10平台32位Qt应用开发者的Qt5.15.12动态库编译包,由MSVC2019构建,适合需要在Win32架构上搭建或维护Qt项目的初中级开发者。压缩包约360.47MB,共2000个文件,全部为头文件(.h),涵盖Widgets、Network、Core等核心模块及OpenGL相关扩展接口声明,可与配套的.dll、.lib文件配合完成工程编译与依赖配置。该版本不含Qt WebEngine,但保留TLS支持,并同时兼容Debug与Release两种构建模式,便于调试与发布切换。已有586人学习下载。对于仍需支持32位系统的项目,这份头文件集合可用于核对接口声明、排查编译期缺失依赖,并配合动态库完成模块化集成与后续更新维护。

1. Qt 5.15.12 在 Windows 10 上编 32 位动态库:先别急着点 configure

上周帮一个做工业上位机的朋友收拾残局:他在 Windows 10 上要编 Qt 5.15.12 的 32 位动态库,结果源码解压了三遍、configure 跑了五次,每次都在nmake阶段报找不到qmake,最后发现是 MSVC 的位数和 Qt 的目标位数对不上。这类翻车在 Qt 5.15 上特别常见——5.15 是 LTS 分支,最后一个开源维护版本停在 5.15.2,而 5.15.12 属于商业补丁线,源码包和在线安装器的行为差异不小,网上教程又大多按 5.15.2 写,照着抄很容易踩空。这篇笔记按我实际装过的一套流程走:环境先列清、configure 参数逐个解释、nmake 编完怎么验证 32 位动态库真的能用。适合需要在 Win10 上产出 32 位 Qt 动态库、给老设备或老项目做兼容的开发者。

2. 环境准备:MSVC 2019、Perl 与 Python 的版本取舍

2.1 为什么 32 位编译必须锁 MSVC 2019 的 x86 工具链

Qt 5.15.12 官方支持的编译器组合里,MSVC 2019 是最稳的一档。关键点不在“装没装 VS”,而在“用哪个 Developer Command Prompt”。编 32 位库必须进x86 Native Tools Command Prompt for VS 2019,不是 x64 那个,也不是普通的 cmd。很多人图省事在 PowerShell 里直接跑 configure,环境变量里没有cl.exe的路径,configure 会静默跳过 MSVC 检测,最后 fallback 到 MinGW 或者直接报Cannot detect the compiler。

我一般会先验证当前 shell 的位数,这一步比什么都重要:

# 在 x86 Native Tools Command Prompt 里执行 cl

正常输出第一行会带x86,类似Microsoft (R) C/C++ Optimizing Compiler Version 19.29.xxxxx for x86。如果显示for x64,说明你进错窗口了,后面所有产物都会是 64 位,白编。另一个快速确认方式是看环境变量:

echo %VSCMD_ARG_TGT_ARCH%

输出x86才对。这个变量是 VS 的 vcvars 脚本写进去的,比肉眼判断可靠。

VS 安装时勾选的组件也有讲究。Workload 选“使用 C++ 的桌面开发”,右侧单个组件里必须包含MSVC v142 - VS 2019 C++ x64/x86 生成工具(注意名字里带 x86)和Windows 10 SDK。SDK 版本我一般选 10.0.19041.0 或更新的,太老的 SDK 在链接 QtWebEngine 时会缺d3dcompiler相关库。装完别急着往下走,先确认rc.exe能找到——Qt 的 qmake 生成 rc 文件时依赖它,缺了会在编译资源阶段报Cannot run program "rc"。

2.2 Perl 和 Python:版本不是越新越好

Qt 5.15 的构建系统里,Perl 用于跑syncqt等脚本,Python 用于部分模块的代码生成。这两个依赖的坑在于“新版不兼容”。

Perl 我固定用Strawberry Perl 5.30 或 5.32 的 64 位版。5.36 之后某些模块的默认行为变了,syncqt在解析头文件包含路径时偶发报错。安装时勾选“Add Perl to PATH”,装完在同一个 x86 命令行里执行:

perl -v

能看到版本号即可。注意 Perl 本身是 64 位不影响 Qt 编 32 位,它只是构建期脚本解释器,不参与链接。

Python 用3.8.x,别上 3.11、3.12。Qt 5.15 的部分构建脚本用了distutils,Python 3.12 已经把它从标准库移除,configure 阶段会报ModuleNotFoundError: No module named 'distutils'。装 Python 3.8 时同样勾选加入 PATH,然后验证:

python --version

如果机器上已经装了多个 Python,用where python看清楚当前 shell 解析到的是哪个。我遇到过系统里 3.12 排在 PATH 前面,configure 直接挂掉的情况,把 3.8 的路径手动提到最前面才解决。

2.3 源码包与目录规划

源码用官方qt-everywhere-src-5.15.12的 zip 包。解压路径有个血泪经验:不要放在带空格或中文的目录,也不要放在C:\Program Files下面。qmake 和 nmake 对路径里的空格处理不干净,编到一半报The system cannot find the path specified时你根本想不到是路径问题。

我一般这样规划:

D:\build\qt-everywhere-src-5.15.12 # 源码 D:\build\qt-5.15.12-x86 # 编译输出(shadow build)

Qt 官方推荐 shadow build,即源码目录和构建目录分开。好处是编坏了直接删构建目录重来,源码不用重新解压。构建目录提前建好,configure 时用-prefix指定安装位置,我习惯装到D:\Qt\Qt5.15.12-x86,和在线安装器的目录结构错开,避免混淆。

提示:解压后先确认源码根目录下有configure.bat。如果只有configure(无扩展名),说明你下的是 Linux 源码包,Windows 上跑不了。

3. configure 参数逐个拆:32 位动态库到底该开哪些

3.1 最小可用参数集与每个开关的含义

Qt 的 configure 参数多到吓人,但编一个“能用的 32 位动态库”,核心就那几个。我常用的最小集是这样:

configure -prefix D:\Qt\Qt5.15.12-x86 ^ -platform win32-msvc ^ -opensource -confirm-license ^ -debug-and-release ^ -shared ^ -nomake examples -nomake tests ^ -skip qtwebengine ^ -opengl dynamic

逐条说清楚,因为每一条都对应一个实际取舍:

-platform win32-msvc是目标平台,win32在这里指 32 位 Windows,不是“Windows 32 位系统”的意思,配合 x86 工具链才生效。-opensource -confirm-license跳过交互式许可确认,自动化脚本里必须带。-debug-and-release同时产出 debug 和 release 两套库,体积翻倍但省得以后补编——我一般建议第一次就带上,后面单独补编 debug 很折腾。-shared是动态库的关键,不加它默认编静态库,产物是.lib而不是.dll。

-nomake examples -nomake tests砍掉示例和测试,能省将近一半编译时间。-skip qtwebengine跳过 WebEngine 模块,这个模块依赖 Chromium,编一次动辄几小时,还容易因为网络和 SDK 版本失败。如果你的项目确实要用 WebEngine,单独处理,别混在第一次编译里。

-opengl dynamic让 Qt 在运行时动态选择 OpenGL 实现(桌面 OpenGL 或 ANGLE),对老显卡兼容性好。32 位环境里很多老设备只有 OpenGL 2.x,这个参数能避免程序启动就崩。

3.2 需要按项目补开的模块参数

最小集编出来的库不含一些常用模块。如果你的项目用到数据库、图片格式或多媒体,configure 时要显式打开:

-qt-sqlite -qt-sql-odbc ^ -qt-libjpeg -qt-libpng -qt-zlib ^ -qt-freetype

-qt-sqlite和-qt-sql-odbc把 SQLite 和 ODBC 驱动编进 QtSql,不然后面QSqlDatabase::addDatabase("QSQLITE")会返回无效驱动。-qt-libjpeg -qt-libpng -qt-zlib用 Qt 自带的第三方库副本,避免依赖系统里版本不明的 DLL。-qt-freetype对中文渲染有影响,缺了在某些字体环境下文字发虚。

反过来,有些参数要主动关掉。-no-icu在 32 位环境里我一般加上,ICU 库体积大,32 位下链接容易出符号冲突,除非项目明确需要国际化排序规则。-no-openssl也常加,Qt 的网络模块默认不强制依赖 OpenSSL,需要 HTTPS 时再单独配。

3.3 configure 输出怎么读:三个必须确认的信号

configure 跑完会打印一大段摘要,别急着敲 nmake。先找三处:

第一处是Build type,确认显示debug and release且Shared。第二处是Target platform,应该是win32-msvc。第三处最关键,看QMAKE_CONFIG里有没有x86相关标记,以及摘要末尾的Note: Using ... as the target mkspec。

如果 configure 中途报ERROR: Cannot detect the compiler,八成是没进 x86 命令行,或者cl.exe不在 PATH。报Perl not found就回去检查 Strawberry Perl 的 PATH。报Python not found同理。这些错误 configure 不会自动回滚,改完环境要删掉构建目录里的config.cache再重跑,否则它会读缓存继续报同样的错。

注意:configure 成功后不要关这个命令行窗口。nmake 必须在同一个 shell 里跑,环境变量是会话级的,新开窗口就丢了。

4. nmake 编译与安装:耗时、并行与中断恢复

4.1 用 jom 替代 nmake 做并行编译

nmake 是单线程的,编 Qt 这种规模的项目,32 位双核机器上能跑四五个小时。我一般用jom(Qt 官方提供的 nmake 替代品)做并行:

jom -j8

-j8是并行任务数,按 CPU 核心数给,物理核心数 × 1.5 左右比较稳。内存小于 16G 的机器别开太高,链接阶段几个进程同时吃内存容易触发LNK1102: out of memory。没有 jom 的话,nmake 也能跑,就是慢,nmake直接敲即可。

编译过程中最常见的失败是某个模块的 moc 步骤报错,日志里出现moc: Cannot open options file。这通常是路径太长导致的,Windows 的 260 字符路径限制在 Qt 源码深层目录里很容易撞上。解决办法是把源码和构建目录都放在盘符根下较短的路径,比如D:\qt\src和D:\qt\build,别用D:\work\projects\2024\...这种。

4.2 中断后怎么续编,而不是从头再来

编译跑到一半断了(断电、误关窗口、某个模块失败),不用删目录重来。nmake/jom 有增量编译能力,重新进 x86 命令行、cd 到构建目录、再跑一次jom -j8,它会跳过已完成的目标。

但有个前提:环境变量必须和上次一致。如果上次在 x86 窗口、这次进了 x64 窗口,增量编译会混入 64 位目标文件,最后链接报一堆machine type conflict。我吃过这个亏,后来养成习惯,中断恢复前先echo %VSCMD_ARG_TGT_ARCH%确认一遍。

如果某个模块反复失败,可以单独进它的子目录编,比如cd qtbase\src\corelib然后jom,定位到具体文件再查。编完回到构建根目录继续整体编译,已完成的不会重编。

4.3 安装:nmake install 与 prefix 的关系

全部编完后执行:

jom install

它会把产物按-prefix指定的路径铺开:bin下是 DLL 和工具,lib下是导入库.lib,include下是头文件,plugins下是插件。装完去D:\Qt\Qt5.15.12-x86\bin看一眼,应该有Qt5Core.dll、Qt5Gui.dll、Qt5Widgets.dll这些。

验证位数最直接的办法是用 dumpbin:

dumpbin /headers D:\Qt\Qt5.15.12-x86\bin\Qt5Core.dll | findstr machine

输出里应该是machine (x86)。如果是machine (x64),说明整个编译链走错了,回去查 2.1 节的工具链确认步骤。这一步别省,我见过编了三小时发现是 64 位、全部重来的案例。

5. 避坑与排查:五条装 Qt 5.15.12 时真踩过的坑

5.1 现象:configure 报 “Cannot detect the compiler”,但 cl 明明能用

原因几乎总是 shell 位数不对。cl在 x64 窗口里也能跑,但 configure 检测的是目标架构和 mkspec 的匹配关系,x64 环境下win32-msvc这个 mkspec 会被判为不匹配。解决:关掉当前窗口,从开始菜单重新进x86 Native Tools Command Prompt for VS 2019,删掉构建目录里的config.cache,重跑 configure。

5.2 现象:nmake 链接阶段报 LNK1102 out of memory

并行度给太高,或者机器物理内存不足。32 位链接器本身有地址空间限制,同时跑多个链接进程会互相挤占。解决:把jom -j8降到-j4甚至-j2,关掉浏览器等吃内存的程序。如果单模块链接仍失败,进该模块目录单独jom,串行链接。

5.3 现象:编译到 qtdeclarative 时报 Python 相关错误

Python 版本太新,distutils缺失。Qt 5.15 的构建脚本在生成某些绑定代码时调用distutils,Python 3.12 已移除该模块。解决:装 Python 3.8,把它的路径放到 PATH 最前面,where python确认解析到 3.8,然后删config.cache重跑 configure。

5.4 现象:程序运行时提示 “找不到 Qt5Core.dll”,但 bin 目录里明明有

这是部署问题不是编译问题。32 位程序必须配 32 位 DLL,如果 PATH 里混进了 64 位的 Qt 安装目录,加载器会优先找到 64 位版本然后报位数不匹配。解决:用where Qt5Core.dll查所有候选,把 64 位的路径从 PATH 里移除,或者用windeployqt把依赖拷到 exe 同目录,彻底摆脱 PATH 依赖。

5.5 现象:中文界面显示为方块或乱码

-qt-freetype没开,或者字体插件没装。Qt 在 Windows 上默认走系统字体,但 32 位环境下某些字体回退逻辑会失效。解决:configure 时加-qt-freetype,装完后确认plugins\platforms\qwindows.dll存在,程序里显式设置QFont的 family 为系统已安装的中文字体。

6. 装完怎么验证:一个最小 32 位程序跑通全链路

编译安装完,光看 DLL 存在不算数,得让一个真实的 32 位程序加载它、跑起来。我习惯写一个最小验证工程,放在D:\verify下,main.cpp就几行:

#include <QApplication> #include <QLabel> #include <QDebug> int main(int argc, char *argv[]) { QApplication app(argc, argv); // 打印编译期和运行期的架构信息,确认是 32 位 qDebug() << "pointer size:" << sizeof(void*); qDebug() << "Qt version:" << QT_VERSION_STR; QLabel label("Qt 5.15.12 x86 OK"); label.show(); return app.exec(); }

sizeof(void*)在 32 位下是 4,64 位下是 8,这一行比任何工具都直观。工程文件verify.pro:

QT += core gui widgets TARGET = verify TEMPLATE = app SOURCES += main.cpp

用刚编出来的 qmake 生成 Makefile,注意必须用D:\Qt\Qt5.15.12-x86\bin\qmake.exe,别用系统里其他 Qt 的:

D:\Qt\Qt5.15.12-x86\bin\qmake.exe verify.pro jom

编出来的verify.exe用 dumpbin 确认位数,然后直接双击运行。窗口标题显示正常、控制台输出pointer size: 4,说明整条链路——32 位工具链、动态库、插件、运行时——全部打通。

最后一步是部署验证,模拟真实分发场景:

D:\Qt\Qt5.15.12-x86\bin\windeployqt.exe --release verify.exe

windeployqt会把Qt5Core.dll、Qt5Gui.dll、Qt5Widgets.dll和 platforms 插件拷到 exe 同目录。把整个目录拷到一台没装 Qt 的干净 Win10 机器上双击,能起来才算真正交付级可用。这一步能暴露 PATH 依赖、插件缺失、VC 运行库缺失三类问题,比在本机跑十遍都有用。

从那以后我每次编完 Qt,都强制走一遍“dumpbin 看位数 → 最小程序跑通 → windeployqt 拷干净机器”这三步,少一步都不敢说这套库能用。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询