Windows平台部署:MinGW vs MSVC、静态编译与动态编译、打包工具与安装包制作

Windows部署,说实话是Qt开发里最让人头疼的一环。我刚开始做跨平台项目时,在Mac和Linux上顺风顺水,一到Windows就各种缺DLL、崩溃、路径不对。后来摸爬滚打几年,总算把这条路走通了。今天我把这些经验掰开揉碎讲给你听。

编译器之争:MinGW还是MSVC?

很多新手会问:Qt Creator里这两个选项到底选哪个?我直接说结论——看你的目标用户。

核心区别一句话:MinGW是GCC的Windows移植版,MSVC是微软自家的编译器。两者生成的二进制不兼容。

对比项MinGWMSVC
调试器GDBWinDbg / VS调试器
STL兼容性较好(GCC风格)与Windows API更贴合
性能中等较高(微软优化)
第三方库需自行编译很多库直接提供MSVC版
部署难度相对简单需注意CRT运行时

我个人习惯:给企业内部用选MSVC,因为性能好、调试方便;给普通用户用选MinGW,部署起来省心。为什么?你想想看,MSVC编译的程序需要安装VC++运行库,用户电脑上没有就得弹窗报错。MinGW则没这个烦恼。

我的经验:有一次给客户做演示,MSVC编译的程序在对方Win7上直接崩溃,就是因为缺少VC++ 2015运行库。后来换成MinGW编译,一把过。从那以后,对外发布我优先用MinGW。

静态编译 vs 动态编译

这是个老生常谈的问题。说白了:动态编译生成小exe + 一堆DLL;静态编译生成一个大exe。

动态编译(默认方式)

  • exe只有几百KB到几MB
  • 运行时需要Qt的DLL(QtCore.dll、QtGui.dll等)
  • 更新时只需替换exe
  • 多个Qt程序可以共享DLL

静态编译

  • exe有几十MB甚至上百MB
  • 不需要额外DLL,直接双击运行
  • 更新需要重新编译整个exe
  • 每个程序都包含一份Qt库副本

我遇到过最尴尬的事:用动态编译给客户发了个工具,结果对方把exe拷走了,DLL全留在压缩包里。打开软件直接报错。嗯,从那以后,给非技术人员用的工具,我全用静态编译。

注意:Qt官方安装包默认不支持静态编译。你需要自己编译Qt源码,配置时加上-static参数。而且静态编译后,插件(如数据库驱动、图片格式插件)也需要静态链接,配置起来比较麻烦。

静态编译的配置命令示例:

configure -static -prefix C:\Qt\Qt5.15.2_static -opensource -confirm-license
mingw32-make -j4

这个过程大概要编译1-2小时,我建议你泡杯咖啡等着。

打包工具:windeployqt

这是Qt官方提供的部署工具,能自动找出程序依赖的DLL、QML文件、插件等。用法极其简单:

windeployqt.exe your_app.exe

它会扫描exe的依赖,把需要的文件全部复制到exe所在目录。我常用的完整命令:

windeployqt --release --no-translations --no-system-d3d-compiler your_app.exe

参数说明:

  • --release:只复制release版DLL
  • --no-translations:不复制翻译文件(省空间)
  • --no-system-d3d-compiler:不复制Direct3D编译器(大多数场景用不到)

避坑指南:我曾经遇到windeployqt漏掉某些插件的情况,比如数据库驱动。这时候手动把plugins\sqldrivers目录下的qsqlmysql.dll等复制过去就行。另外,如果你用了第三方库(如OpenCV),windeployqt不会帮你处理,得自己手动复制。

运行完windeployqt后,你的发布目录大概长这样:

your_app.exe
Qt5Core.dll
Qt5Gui.dll
Qt5Widgets.dll
...
platforms/
    qwindows.dll
styles/
    qwindowsvistastyle.dll
...

安装包制作:NSIS vs Inno Setup

打包完一堆文件后,总不能给用户发个文件夹吧?这时候就需要制作安装包了。我常用的两个工具:NSIS和Inno Setup。

对比项NSISInno Setup
脚本语言类汇编风格类Pascal
学习曲线较陡平缓
功能极其强大足够用
压缩率高(LZMA)高(LZMA)
界面默认简陋默认美观

我个人推荐:新手用Inno Setup,半小时就能上手。下面给个Inno Setup的示例脚本:

[Setup]
AppName=我的Qt应用
AppVersion=1.0.0
DefaultDirName={pf}\MyQtApp
DefaultGroupName=MyQtApp
OutputDir=.\installer
OutputBaseFilename=MyQtApp_Setup

[Files]
Source: "release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs

[Icons]
Name: "{group}\MyQtApp"; Filename: "{app}\your_app.exe"
Name: "{commondesktop}\MyQtApp"; Filename: "{app}\your_app.exe"

这个脚本做了三件事:

  1. 指定安装路径和输出文件名
  2. 把release目录下所有文件复制到安装目录
  3. 创建开始菜单和桌面快捷方式

我的习惯:用Inno Setup配合windeployqt,写一个批处理脚本一键完成。先运行windeployqt收集依赖,再调用Inno Setup编译器生成安装包。整个过程自动化,省时省力。

NSIS虽然难学,但功能确实更强。比如要做多语言安装包、自定义安装界面、写注册表等,NSIS更灵活。不过说实话,大部分Qt应用用Inno Setup就够了。

知识体系总览

下面这张图帮你理清Windows部署的完整流程:

Windows平台Qt部署流程 选择编译器 MinGW / MSVC 编译方式 静态编译 / 动态编译 编译生成 your_app.exe 打包依赖 windeployqt.exe your_app.exe 制作安装包 NSIS(功能强大) Inno Setup(简单易用) MyQtApp_Setup.exe

整个流程走下来,就是从源码到安装包的一条完整链路。每一步都有坑,但踩过一次就记住了。

最后分享个小技巧:写一个deploy.bat脚本,把windeployqt和安装包制作串起来。以后每次发布,双击一下就行。我团队现在就是这么干的,省去了大量重复劳动。

可可精品资料库