news 2026/10/21 7:59:05

Qt 5.15.12 Windows 10下编译32位动态库完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Qt 5.15.12 Windows 10下编译32位动态库完整指南

简介:面向Windows 10 32位应用开发的Qt 5.15.12动态库编译包,基于MSVC2019编译器构建,专为需要维护32位兼容性、或希望避开复杂编译配置的C++开发者准备。压缩包内共2000个文件,以Qt头文件(.h)为主,覆盖Core、Widgets、Network、GUI等核心模块的公共接口声明,整体大小约360.47MB;同时提供Debug与Release两种模式,分别用于调试期错误定位和发布期性能优化。动态库方式支持多个应用程序在运行时共享同一份代码,有效减少内存占用与重复拷贝,也便于按模块独立更新和维护。该版本未集成Qt WebEngine,但完整保留TLS加密支持,既缩小了库体量,又保障了网络传输过程中的数据安全。目前已有586人学习下载,可作为32位Qt环境配置、接口文档查阅以及旧项目迁移时的实用参考;借助这批头文件,开发者可以快速核对类定义与函数签名,理清模块依赖关系,在Windows 10 32位系统上更顺畅地构建轻量级、可维护的Qt应用程序。

1. Qt 5.15.12 在 Windows 10 下编译 32 位动态库:被很多人跳过却值得做的一件事

如果你手上还有老项目需要在 32 位 Windows 环境下运行,或者合作的某公司系统至今保留着 Win10 32 位终端,你一定遇到过这样的尴尬:新装的 Qt 预编译包是 64 位,跑几年前的 Win32 程序直接报“不是有效的 Win32 应用程序”。Qt 5.15.12 是 Qt 5 LTS 补丁序列里比较靠后的一个版本,它补了不少 5.15 早期版本在 Windows 上的问题,同时又保留了 Qt Widgets / Qt QML 的老接口,适合拿来做 32 位动态库的再编译。这篇文章记录的是我从空环境开始,把 Qt 5.15.12 源码编译成 32 位 DLL 动态库的完整过程,包括工具链选型、configure 参数、编译命令和四次翻车之后的排错思路。适合要把旧工程迁到新 Qt 版本、又必须继续支持 32 位系统的开发者;看完你能直接照着敲命令,不需要再去翻那堆零散的文档。

2. 编译工具链选型与 32 位环境搭建:MinGW 还是 MSVC

2.1 两条路线,一个终点:动态库与受控环境的差别

Qt 在 Windows 上做 32 位编译,工具链基本只有两选:MinGW(准确说是 MinGW-w64 的 i686 目标)和某个商业 IDE 自带的 MSVC 工具链。这两者的差别不在 Qt 本身,而在最终交付物依赖的运行环境和编译器的二进制接口。

MSVC 路线产出的 DLL 依赖 UCRT 和 VC 运行库,你的 Qt 程序部署到干净机器上时,通常要额外带上运行库安装包或者用部署工具把 msvcp140.dll 之类一起拷进应用目录。MinGW 路线用的是 GNU 工具链,产出的程序依赖 libgcc_s_dw2-1.dll、libstdc++-6.dll、libwinpthread-1.dll,这些 DLL 体积不大,windeployqt 部署时也会自动带出来,对老系统环境的侵入相对小。

如果只看“能不能编译出 32 位 Qt”,两条路都通。我的实际建议是:机器上已经装了商业 IDE、且后续项目都要用它的调试器时,走 MSVC;如果你只是想尽快拿到 32 位的 Qt5 动态库,Windows 又没有额外要求使用某个编译器的 ABI,MinGW 是更省事的一条路。以下主线就用 MinGW 的 32 位目标做演示,MSVC 的环境准备在 2.3 里单独列。

另外要提前想清楚“动态库”这个要求。Qt 默认 configure 出来的就是动态库,也就是每个模块一个 DLL,外加对应的小导入库文件。只有在 configure 时明确加了-static才会产出静态库。所以发布会上你只要别手滑加-static,最终结果就是带.dll的发布包。这一点后面在 configure 参数里会再讲。

2.2 安装 32 位 MinGW-w64 工具链:编译器与 make 的版本匹配

MinGW-w64 这个项目虽然名字里有 64,但它的 32 位目标同样存在,安装包通常在“i686”目录下。很多人翻车就是因为下载了名字里带 x86_64 的编译器,编译出来的 Qt 一看却是 64 位 DLL。

我一般把工具链单独放一个目录,比如D:\work\my_toolchain\mingw32,避免和装 Qt 预编译包自带的 MinGW 混在一起。解压后依次检查三个东西:gcc 目标架构、g++ 版本、mingw32-make 是否存在。

set PATH=D:\work\my_toolchain\mingw32\bin;%PATH% gcc -v g++ -v mingw32-make -v

第一行命令执行后,注意看输出里“Target”字段。如果是i686-w64-mingw32,说明当前编译器是以 32 位为目标的;如果显示x86_64-w64-mingw32,那就是 64 位工具链,必须换掉。Qt 5.15.12 源码要求编译器支持 C++17,gcc 至少要到 7 以上,建议直接用和官方 Qt 5.15 离线安装包配套的 MinGW 8.1 版本,省得 configure 阶段因为语法特性报错。

这里要说一下mingw32-make和make的关系。MinGW-w64 发布的二进制里,make 的名字往往叫mingw32-make.exe,就是为了避免和同目录下的 Unix 工具冲突。编译 Qt 时你用它,不要习惯性敲make。

2.3 MSVC 2019 作为备选:vcvarsall.bat 与 x86 参数

如果你的机器上有 2019 或更新版本的商业 IDE,用它的 32 位命令提示符也行。关键是不要直接打开普通的 cmd 就去跑 configure,那样 cl.exe、nmake 都不在 PATH 里,configure 会报“compiler cannot create executables”。

我习惯的做法是用工具链安装目录里自带的vcvarsall.bat脚本,后面跟x86,然后才在当前会话里调用 cl 和 nmake。

call D:\myide\VC\Auxiliary\Build\vcvarsall.bat x86 cl nmake /?

注意参数是x86,不是amd64。32 位目标对应x86,x64对应的是 64 位目标。执行完 vcvarsall 后,cl 的输出版本信息能正常显示,说明当前 cmd 会话已经是 32 位 MSVC 环境。之后 configure 时要用-platform win32-msvc2019(根据你实际的 IDE 版本选择后缀),而不是-platform win32-g++。

MSVC 路线还有一个常见问题:默认的nmake是单线程的,编译 Qt 这种大工程会很痛苦。常见的做法是下载一个叫jom的并行构建工具,它兼容 nmake 的 Makefile,但能利用多核并行编译。如果你手头有这个工具,编译阶段用 jom 替代 nmake 即可。

3. configure 与源码编译:一条完整命令行跑出 32 位 DLL

3.1 源码解压与目录约定:路径是第一个隐藏条件

Qt 5.15.12 的源码包解压后,目录名是类似于qt-everywhere-src-5.15.12这样的一整包,里面同时包含了源码和构建系统文件。解压路径和安装前缀是两个概念:源码目录只负责构建过程,安装前缀是 make install 之后 Qt 库实际落盘的位置。

我建议把源码放一个尽量短的纯英文路径。不要放在带空格、带中文的目录下,虽然很多情况下也能编,但 configure 生成的 Makefile 里会含路径变量,某些模块会因为这些特殊字符报出莫名其妙的文件找不到错误。下面是我在这台模拟项目X机器上的目录布局:

C:\work\qt-everywhere-src-5.15.12 # 源码根目录,只读不解 D:\work\qt-out\5.15.12-mingw32 # make install 后的安装前缀

前缀目录D:\work\qt-out\5.15.12-mingw32就是以后 qmake、windeployqt、头文件和库文件的位置。源码目录建议保留干净,不要往里面塞东西,因为如果编译到一半失败需要重新 configure,源码树足够干净能省不少麻烦。

3.2 configure 命令的参数拆解:关键开关与含义

确认工具链没问题后进入源码根目录,执行 configure.bat。MinGW 路线下的完整命令大致是这样:

cd /d C:\work\qt-everywhere-src-5.15.12 set PATH=D:\work\my_toolchain\mingw32\bin;%PATH% configure.bat ^ -opensource -confirm-license ^ -release ^ -shared ^ -prefix D:\work\qt-out\5.15.12-mingw32 ^ -platform win32-g++ ^ -skip qtwebengine ^ -skip qtwebview ^ -nomake examples -nomake tests ^ -mp

先解释几个必选项。-opensource -confirm-license是确认采纳开源许可,不写这个会在配置中途停下来要你手动输入;-release表示只编 release 版,不加这个默认可能是 debug 和 release 都编,时间和磁盘占用翻倍;-shared是告诉构建系统输出动态库,对应我们标题里的“动态库”需求;-prefix指定最终 make install 的安装目录。

-platform win32-g++是 MinGW 路线绕不开的参数,它告诉 Qt 构建系统“我要用 GNU 工具链”。后面跟的^是 Windows cmd 的续行符。-skip qtwebengine和-skip qtwebview建议加上,这两个模块编译时间长、依赖多,如果不做基于 Chromium 的界面压根用不上;-nomake examples -nomake tests同样是为了缩减编译工作量。-mp让编译器在支持多核的机器上开启多进程编译。

3.3 编译过程:从 configure 到 make install

configure 正常结束后,屏幕最后会出现一段当前构建配置摘要,列出接下来会构建哪些模块,比如 qtbase、qtdeclarative、qtmultimedia 等。这时候再执行编译,MinGW 工具链对应的命令是:

mingw32-make -j8

-j8中的 8 是并行执行的编译任务数,通常设置为 CPU 物理核心数的 1.5 到 2 倍。如果不想手算,可以直接写mingw32-make -j%NUMBER_OF_PROCESSORS%,Windows 系统变量里一般存了当前处理器的逻辑核心数。

这里有个容易被忽略的操作:不要把编译输出直接打到屏幕上,一是滚动太快看不出问题,二是后面排查时没有日志可翻。我一般先重定向一份日志:

mingw32-make -j8 > build.log 2> build.err

编译完成后再执行安装,把产物放到前面指定的前缀目录:

mingw32-make install > install.log 2> install.err

install 阶段主要是把 DLL、lib、头文件、mkspec 和工具拷贝到D:\work\qt-out\5.15.12-mingw32下。整个过程在 8 核机器上通常要一小时到数小时不等,取决于你保留的模块数量。编译 Qt 不像编译普通应用,期间最好别开太多重型程序,内存不足时编译器子进程会被系统杀掉,日志里就会莫名出现“killed”或者“out of memory”字样。

3.4 编译产物解析:DLL、导入库与 bin 目录

make install 完成后,进入安装前缀目录,你会看到一个比较熟悉的 Qt 布局:

D:\work\qt-out\5.15.12-mingw32 ├── bin │ ├── qmake.exe │ ├── windeployqt.exe │ └── Qt5Core.dll ... ├── lib │ ├── libQt5Core.a # MinGW 风格的导入库 │ └── cmake ... ├── include └── mkspecs

其中lib下面的libQt5Core.a不是静态库,而是导入库(import library)。动态库的导出函数信息记录在 DLL 里,导入库的作用是链接时告诉链接器“这个符号在哪个 DLL 里、序号是多少”。MinGW 工具链产出的导入库命名是libQt5Core.a,而同路径下生成的Qt5Core.dll才是运行时真正加载的文件。这也就是 windeployqt 部署时既要带 DLL、又要把导入库链接进可执行文件的原因。

你可以抽查一下 DLL 的目标架构,确认确实是 32 位。MinGW 工具链没有 dumpbin,可以这样确认:

objdump -f D:\work\qt-out\5.15.12-mingw32\bin\Qt5Core.dll | findstr /i "file format"

输出如果显示pei-i386,说明是 32 位 PE 格式,目标架构对了;要是显示pei-x86-64,说明工具链选错,回去换 i686 版本再编。

4. 避坑记录:32 位 Qt 编译与运行中的五次排错

4.1 编出来的 Qt5Core.dll 一看是 64 位

现象:configure 和编译都正常通过,install 也顺利,结果检查 Qt5Core.dll 的格式时发现是 64 位,32 位程序加载它直接报0xc000007b。

原因:工具链下载错了。MinGW-w64 的压缩包分 i686 和 x86_64 两套,i686 才是 32 位目标;部分下载站把名字简化成“mingw32”包装 64 位编译器,骗过了人眼。

解决:编译前先用gcc -v看输出里的 Target,必须是i686-w64-mingw32,不能只凭目录名字判断。如果不确认当前 PATH 里先命中哪个版本,执行where gcc把实际路径打出来。

4.2 编译到中段报 “cannot find -lstdc++”

现象:Qt 编译到某个模块的链接阶段,屏幕输出cannot find -lstdc++,定位不到标准 C++ 库。

原因:-lstdc++是 GNU C++ 库的链接名,找不到它说明g++的库搜索路径没配置好。在一些精简的 MinGW 安装包里,libstdc++-6.dll 存在但对应的导入库libstdc++.a缺失,或者工具链的 lib 目录在 PATH 之外。

解决:检查D:\work\my_toolchain\mingw32\lib下有没有libstdc++.a;没有的话回到完整的编译器分发包里找。另外确认 PATH 里gcc.exe与g++.exe在同目录,不能混用两个不同版本的 bin 目录。

4.3 链接时报 “Unsupported or malformed archive”

现象:用 MSVC 工具链编译 Qt 时,链接阶段突然报LNK1103或 GCC 侧中文提示“不支持的或格式错误的存档”,怀疑是导入库文件损坏。

原因:多半是把 MinGW 生成的.a导入库拿给 MSVC 链接器用了,或者反过来把.lib拿给 MinGW 的链接器用。两种工具链的导入库格式并不完全兼容,MSVC 用的是 COFF 格式的.lib,MinGW 用的是 GNU 格式的.a。

解决:按工具链分类隔离开导入库文件。如果项目里同时装了 Qt5 的 MinGW 版和 MSVC 版,链接参数里要用与编译器同源的 qmake,不能跨编译器指定-L路径。检查实际链接命令里的LIBS参数,确认指向前缀目录的lib而不是另一个前缀。

4.4 程序拷到干净机器上运行提示缺少 api-ms-win-crt-runtime-l1-1-0.dll

现象:Qt 程序在开发机上正常跑,复制到没有安装过任何运行库的 Win10 32 位终端上,启动时弹窗说找不到 API 集 DLL。

原因:MSVC 工具链编译出来的 Qt 依赖通用 C 运行时,API 集 DLL 属于系统组件。老版本 Win10 或未开启自动更新的终端上,UCRT 组件不完整。MinGW 路线一般不带这个坑,MSVC 路线基本躲不开。

解决:部署阶段使用部署工具时加上--compiler-runtime参数,强制把 VC 运行库对应的 DLL 一并复制到程序目录。如果目标机器是 Win10 早期版本,也可以直接在资源包里带上 UCRT 更新包,安装一次就好。

4.5 windeployqt 跑完程序还是提示缺少 Qt5Core.dll

现象:用 windeployqt 部署之后,双击程序仍然提示缺少Qt5Core.dll。

原因:windeployqt 是依靠调用目标程序所在路径的 Qt 来定位依赖的。如果你 PATH 里先命中了一个 64 位 Qt 的 bin 目录,部署的结果很可能是带出了一堆 64 位 DLL,或者部署进程自己崩溃。

解决:先执行set PATH=D:\work\qt-out\5.15.12-mingw32\bin;%PATH%再执行windeployqt,并且部署完用 4.1 里的手段抽查Qt5Core.dll是否与目标应用同为 32 位。更稳的做法是调用带完整路径的windeployqt.exe,彻底避开 PATH 干扰。

5. 把编译好的 Qt 固化成可持续用的工具链:验证与后续用法

编译完成的 32 位 Qt 动态库不仅是这一次的产物,它还能继续作为工具链被重复使用。安装目录下的 qmake、windeployqt 都是独立可执行程序,只要整个前缀目录不被破坏,后续工程甚至不需要重新编译 Qt。

我一般会让新工程走一遍“验证三连”:先用前缀目录下的 qmake 生成 Makefile,再用它编一个空的 Win32 Widgets 程序,最后用 windeployqt 部署并检查 DLL 位深。

set PATH=D:\work\qt-out\5.15.12-mingw32\bin;%PATH% qmake -v windeployqt --release --no-translations D:\test\app32.exe objdump -f D:\test\app32.exe | findstr /i "file format"

这里qmake -v输出中会包含一个带Qt 5.15.12的版本行,同时还能看到编译器说明是MinGW还是MSVC;--no-translations表示跳过翻译文件,可以缩短部署时间;最后一条命令用于验证 app 文件头里是pei-i386而不是pei-x86-64。部署目录下会多出一批 32 位 DLL,把它们和 exe 一起复制到干净的 Win10 32 位终端跑一遍,确认无运行库报错后再交付。

从那以后我每次拿到新环境的 32 位 Qt 需求,都强制先走一遍这套“源码目录、工具链目标、前缀目录”的验证流程。编译 Qt 本身没什么玄学,绝大多数问题都出在工具链混用和路径指向错误上。希望这篇记录能帮你少走一次弯路。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 7:59:02

C#打印设计器实战:自绘画布+JSON模板,票据打印免发版

简介:这是一份基于 C# 与 WinForms 的“简单打印设计器”完整项目,面向需要定制打印模板、贴纸或其他可变版式输出的 .NET 开发者与入门学习者。项目以 System.Drawing.Printing 命名空间的 PrintDocument 为核心,在 PrintPage 中通过 Graphi…

作者头像 李华
网站建设 2026/10/21 7:59:00

x86实模式下直写显存0xB8000显示字符串原理与实践

1. 项目概述:为什么一个“显示字符串”的汇编实验,值得花一整篇深度拆解?《汇编语言》王爽——第十章实验10(1)显示字符串,这行标题在某高校计算机组成原理与系统编程课程的作业区、某技术论坛的初学者求助帖、某在线刷题平台的打…

作者头像 李华
网站建设 2026/10/21 7:58:28

C与C++核心区别:从设计哲学到内存管理的面试指南

“C与C到底有什么区别”,要说这是C语言面试里出现频率最高的一道题,我一点都不会怀疑。从校招到社招,只要简历上写了熟悉C/C,面试官几乎都会在开场阶段抛出这个问题。我做过多年技术面试,也带过不少应届新人&#xff0…

作者头像 李华
网站建设 2026/10/21 7:55:22

SQL Server存储过程与函数:区别、实战与性能优化

做SQL Server开发的人,迟早都要和存储过程(PROCEDURE)还有函数(FUNCTION)打交道。这两个对象几乎天天见,但很多人对它们的理解停留在"能用就行"的层面,真要回答"什么场景必须用存…

作者头像 李华
网站建设 2026/10/21 7:54:49

机器视觉喷码缺陷检测实战:从光源选型到算法调参

1. 项目概述与全貌拆解1.1 这个系统到底解决什么问题先说结论:这条产线做的是消费电子类产品的外壳喷码质量检测,喷码内容包含型号、序列号、生产批次等可变信息。喷码的常见缺陷有四种:漏喷(该喷的没喷上)、断画&…

作者头像 李华
网站建设 2026/10/21 7:54:43

MySQL 8检查约束实战:把业务规则下沉到数据库,拒绝脏数据

数据库完整性这事,老生常谈,但真正落地到日常开发里,你会发现很多团队的“完整性”全靠后端代码硬撑。布尔字段存成 0/1 靠注释约定,年龄字段靠业务层 if 判断,状态字段靠枚举类在代码里兜底。一旦业务侧漏判一个分支&…

作者头像 李华