凡是做过Qt客户端开发的人,多少都被“打包”这件事折磨过。我最早用Qt 5.9写了一个不到两千行的小工具,开发调试一切正常,结果把exe发给朋友,对方直接双击,弹了个“no qt platform plugin could be initialized”的窗口就把我整懵了。从那一刻起我才意识到:Qt开发真正的后半场,不是写功能,而是能把你写的功能顺顺利利带到别人电脑上。而“Qt打包工具”怎么选、怎么配、怎么避坑,就成了绕不开的一道坎。
这篇内容主要聊三件事:Qt程序在打包时会遇到的依赖和插件机制,目前市面上常用的几类Qt打包工具各自的优缺点,以及我在Windows、Linux两种平台上实际打包过程中走通的完整流程和踩过的坑。不管你是刚接触Qt的初学者,还是已经写过几个正式项目的开发者,只要还在为发布版本发愁,这篇内容应该都能给你省下不少时间。
1. 为什么Qt打包总让人头大:先从依赖机制说起
很多人上来就先纠结“用哪个打包工具”,其实方向反了。打包工具的每一种选择,本质上都是在应对Qt那套特殊的依赖和插件机制。先把底层逻辑讲清楚,你后面看工具参数就能一眼明白它在干什么,出了问题也知道去哪查。
1.1 动态库依赖:一场“连锁反应”
Windows下开发Qt程序,你链接的是Qt5Core.dll、Qt5Gui.dll、Qt5Widgets.dll这些动态库。运行exe时,系统会按顺序去exe所在目录、系统目录、PATH环境变量里找这些dll。Qt开发环境里跑得起来,是因为Qt安装目录里的bin目录就在PATH里。发布的时候把exe单独拷出来发给别人,系统自然找不到Qt库,程序起不来是常态,能起来才是奇迹。
这种动态库依赖不只是“缺一两个文件”这么简单,它是一串连锁反应。Qt5Core.dll自身还依赖系统的VC运行库、某些系统API,而Qt5Gui.dll可能会依赖显卡驱动相关的组件。打个比方,你点了一份外卖,不止要配齐菜和饭,连筷子、餐巾纸、封口贴都得备好,差一样用户体验就打了折扣。这就是为什么Qt官方提供了windeployqt这类工具——它要做的不是简单把exe和几个dll塞在一起,而是把那棵完整的依赖树解析出来,把必要的文件全部收集到发布目录里。
1.2 插件机制:真正的Helloworld杀手
相比动态库依赖,插件机制才是Qt打包里最容易翻车的部分。Qt5Gui.dll本身不直接操作具体窗口系统,它通过插件来加载对应平台的底层接口。Windows上这个插件叫qwindows.dll,在Qt安装目录的plugins\platforms文件夹里。windeployqt没帮你部署这个插件,或者插件版本和主程序不匹配,程序启动时就会抛出文章开头那句“no qt platform plugin could be initialized”,这几乎是每个用Qt的人都会碰到的经典报错。
插件机制覆盖的范围远不止平台插件。QML程序需要qml文件夹里那一堆模块插件,用Qt SQL需要sqldrivers里的数据库插件,用Qt Multimedia需要多媒体后端插件,用Qt Image Formats需要对应的图片格式插件。这些插件在你开发机上都是现成的,所以开发期永远测不出问题;发布时少一个,用户那边就是启动闪退或功能失效。所以我一直强调一个观念:打包工具不是“复制粘贴工具”,而是一个“依赖解析器+资源收集器”,理解了插件机制,你才能判断一个打包工具到底算不算合格。
1.3 平台差异:换台电脑就崩溃的原罪
同样是Qt程序,Windows和Linux的打包逻辑完全不一样。Windows讲究“把库带到exe旁边”,DLL同目录搜索优先级最高;Linux讲究“系统级共享”,传统做法是make install把二进制放到/usr/bin,把库放到/usr/lib。但Linux发行版太多了,Qt版本五花八门,用户机器上很可能没有对应版本的Qt库,这种“系统级共享”的思路在分发民用软件时非常不友好,于是有了AppImage这种自带依赖的格式。
另外还有编译器运行时和系统ABI问题。用MinGW编译的程序,要带libgcc_s_seh-1.dll、libstdc++-6.dll、libwinpthread-1.dll;用MSVC编译的,要考虑VC++运行库(msvcp140.dll、vcruntime140.dll、vcruntime140_1.dll)。如果程序用到了OpenSSL,还得额外带上libcrypto和libssl。这些东西不属于Qt,但windeployqt基本都能一并收集,这也是我推荐新手优先用Qt官方工具的原因——它至少把大多数常规情况都考虑过了。
2. Qt常用打包工具全方位横评:各平台的拳头选手
“Qt打包工具”其实是一个比较宽泛的叫法,严格说可以分为两层:第一层负责收集运行依赖,也就是把dll、插件、资源文件部署到程序目录;第二层负责把程序目录封装成安装包或免安装压缩包。很多新手混淆了这两步,以为用windeployqt就算“打包完成”,结果发出去一堆散文件,用户根本不知道点哪个。下面按这两层分别聊。
2.1 官方亲儿子:windeployqt与linuxdeployqt
windeployqt是Qt官方提供的Windows部署工具,会扫描你指定的exe,将依赖的Qt库、插件、翻译文件等复制到exe所在目录。它的最大优势就是跟Qt版本强绑定,你用的Qt 5.15.2就带5.15.2的windeployqt,不会出现版本错配的问题。命令行使用非常简单:
windeployqt --release --compiler-runtime --qmldir C:\myapp\qml C:\myapp\release\MyApp.exe这里--release表示部署release版本;--compiler-runtime表示把VC运行库一起带出来,目标机器没装VC运行时也能跑;如果项目用了QML,--qmldir指定源码qml目录,它就能把用到的QML模块依赖一并解析收集。
Linux那边对应的官方方案其实已经有点年久失修。Qt官方没有提供长期维护的linuxdeployqt,目前社区用得比较多的是probonopd维护的一个fork版本,配合linuxdeploy或linuxdeploy-plugin-qt使用。它的核心作用是把程序依赖的Qt库收集起来,并在AppImage格式中生成一个可执行入口,让程序在多数Linux发行版上无需安装即可运行。相比Windows工具,Linux这头要折腾一些,后面第四章我会附上完整的操作步骤。
2.2 跨平台新秀:cqtdeployer
如果你觉得“同一个项目要记两套打包工具”很烦,可以试试cqtdeployer。它由QuasarApp组织开发,真正做到了一个工具通吃Windows、Linux和macOS,目标是替代windeployqt和linuxdeployqt,并且不仅收集依赖,还能直接调NSIS生成安装包。命令大致长这样:
cqtdeployer -bin MyApp -qmake C:/Qt/5.15.2/mingw81_64/bin/qmake.exe它会自动识别程序依赖并部署到默认的dist目录,如果你想生成安装包,加一个-qif参数可以调用Qt Installer Framework,加-nsis参数可以调用NSIS。对经常跨平台发布项目的开发者来说,它的意义在于能把“记住两套命令”变成“记住一套命令”,学习成本明显降低。当然代价就是多一层工具抽象,遇到极端问题的时候,你还是得回到windeployqt手动排查。
2.3 安装包制作层:Inno Setup、NSIS与Qt Installer Framework
依赖收集完成之后,是“封装”环节。这一层最常用的三款工具分别是Inno Setup、NSIS和Qt Installer Framework(简称Qt IFW)。
Inno Setup是我个人最常用的一款,免费、脚本语法简单、生成的安装包界面专业,支持安装目录选择、开始菜单快捷方式、卸载程序、注册表写入等功能。一个最小可用的脚本只有三十多行,后面第三章会给出模板。NSIS的历史更早,脚本系统更灵活,插件生态非常丰富,很多老牌软件在用,但对新手来说语法偏底层,学习曲线更陡。
Qt IFW则是Qt官方出品的安装包框架,走的是“向导式”安装流程,支持组件选择、在线/离线安装、更新和卸载,特别适合功能模块多、需要让用户自选组件的企业级产品。它的缺点是配置过程较繁琐,要写config.xml、package.xml,还要维护组件目录结构,如果只是发一个小工具,没有必要上Qt IFW。
2.4 一键横向对比速查表
下面这张表是我按日常使用体验整理的,覆盖了“依赖收集”和“安装包制作”两层的主要工具,方便你快速定位需求:
| 工具 | 适用平台 | 解决什么问题 | 上手难度 | 维护状态 | 适合场景 |
|---|---|---|---|---|---|
| windeployqt | Windows | 收集Qt依赖到发布目录 | 低 | Qt官方随版本维护 | 常规Windows桌面程序 |
| linuxdeployqt | Linux | 收集Qt依赖并制作AppImage | 中 | 社区fork维护 | 面向Linux发行版分发 |
| cqtdeployer | 跨平台 | 替代前两者,还可生成安装包 | 中 | 活跃 | 多平台发布、想要统一工具链 |
| Inno Setup | Windows | 制作专业安装包 | 低 | 活跃 | 中小型Windows软件分发 |
| NSIS | Windows | 制作安装包,高度可定制 | 中高 | 活跃 | 需要深度定制脚本的安装程序 |
| Qt IFW | 跨平台 | 向导式安装、组件选择、在线更新 | 高 | Qt官方维护 | 大型企业级、模块化产品 |
实际项目里最常见的组合是:Windows端用windeployqt收集依赖,再用Inno Setup打包成安装程序;Linux端用linuxdeployqt或cqtdeployer生成AppImage。这一步做完,软件才算真正具备了“分发给普通用户”的资格。
3. 实操:Windows下用windeployqt + Inno Setup打出一个能跑的安装包
前面把工具讲得再细,不如亲手走一遍流程。这一章我以Windows平台为例,用Qt 5.15.2 + MinGW的组合,带大家把exe变成一个体面的安装程序。
3.1 环境准备:别把Qt装到中文路径
先检查两件事:Qt安装路径和构建版本。我个人强烈建议Qt安装目录不要出现任何中文、空格和特殊符号,比如C:\Qt\5.15.2\mingw81_64,而不是D:\软件\Qt。虽然windeployqt本身对路径空格有一定兼容能力,但很多第三方工具和脚本在遇到带空格的路径时会出现各种奇怪问题,能避就避。
构建方面,发布版本必须用Release模式而不是Debug模式。Debug版本依赖一堆带d后缀的调试库,体积大,而且分发时必须附带调试符号,基本没人会这么发布。在Qt Creator里选择Release构建,拿到构建目录下的exe,建议先单独建一个干净的发布目录,比如C:\release\MyApp,把exe拷进去,后面所有操作都基于这个目录。
3.2 windeployqt命令详解:参数不是随便加的
接下来在命令行里执行windeployqt。建议从Qt安装目录的对应工具链目录下启动命令行工具,或者手动把qmake所在目录加到PATH中。以MinGW 64位版本为例,命令如下:
set PATH=C:\Qt\5.15.2\mingw81_64\bin;%PATH% cd /d C:\release\MyApp windeployqt --release --compiler-runtime --translations zh_CN MyApp.exe这里我加了--translations zh_CN,目的是让Qt自带的控件翻译文件(比如标准对话框的“打开”“保存”按钮)能变成中文,提升用户体验。如果你的程序没用QML,不需要--qmldir;如果用了QML,必须加上源码qml目录,否则程序跑起来会报qml模块相关的错误。
执行完命令后,发布目录里除了exe,应该会出现Qt5Core.dll、Qt5Gui.dll、Qt5Widgets.dll这些库文件,以及platforms、styles、imageformats等插件文件夹。这里有个细节:windeployqt对不需要的库会做一定过滤,但绝不是“只拷贝必要文件”级别的精准,所以部署完别急着压缩,先双击exe跑一遍,功能、界面、图片、数据库都得过一遍。
3.3 用Inno Setup生成安装包:一份能直接改的脚本
windeployqt部署出来的是一堆散文件,直接发给用户虽然能跑,但体验很糙。下一步我们用Inno Setup把它们封装成一个正规的安装程序。下载安装Inno Setup后,新建一个脚本文件,下面这份是我常用的精简版模板,直接替换项目名和路径就能用:
#define MyAppName "MyApp" #define MyAppVersion "1.0.0" #define MyAppPublisher "MyCompany" #define MyAppExeName "MyApp.exe" [Setup] AppId={{8F0A3B6B-8B6C-4C2F-9B53-5F0A1C3E2D41} AppName={#MyAppName} AppVersion={#MyAppVersion} AppPublisher={#MyAppPublisher} DefaultDirName={autopf}\{#MyAppName} DefaultGroupName={#MyAppName} OutputDir=installer OutputBaseFilename=MyAppSetup_{#MyAppVersion} Compression=lzma2 SolidCompression=yes ArchitecturesInstallIn64BitMode=x64compatible [Languages] Name: "chinesesimplified"; MessagesFile: "compiler:Default.isl" [Tasks] Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}" [Files] Source: "C:\release\MyApp\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs [Icons] Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon [Run] Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent几个说明:DefaultDirName用{autopf},Inno Setup会在64位系统上默认安装到Program Files目录,32位则用Program Files (x86);SolidCompression=yes能显著压缩体积;Source那行C:\release\MyApp\*会把这个目录下所有文件递归复制到安装目录,windeployqt部署的内容就全部装进安装包了。脚本写好后,按Ctrl+F9编译,installer目录下会出现一个MyAppSetup_1.0.0.exe,这个就是最终分发的安装包。
3.4 额外的QML依赖、编译器运行时与OpenSSL处理
如果你的程序是QML项目,windeployqt只加--qmldir还不够保险。我遇到过qml文件夹里某些模块的插件没被正确复制,导致在用户机器上运行时只有部分控件能显示的情况。最稳妥的方法是执行完windeployqt后,手动去Qt安装目录的qml文件夹里,把你用到的模块整个复制到发布目录的qml文件夹里。虽然体积会变大,但至少不会出现“开发机正常、用户机白屏”的问题。
编译器运行时这块,windeployqt的--compiler-runtime会把MinGW运行库一并带出,但如果你用的是MSVC编译器,光靠windeployqt不一定能带上VC运行时,最好再单独安装VC++ Redistributable,或者手动把vcruntime140.dll、msvcp140.dll复制到发布目录。用OpenSSL做HTTPS请求的话,记得把libcrypto-1_1-x64.dll和libssl-1_1-x64.dll(Qt 5.15对应OpenSSL 1.1)也放进发布目录,否则程序运行到网络请求时会直接提示找不到动态库。
4. 实操:Linux下用linuxdeployqt打AppImage
Linux打包在中文社区里资料相对少,很多人在Windows上打包很熟练,一换到Linux就有点不知道从哪里下手。实际上Linux最省心的发布方案就是AppImage:一个文件、可执行权限、双击或命令行运行,而且不依赖目标机器上是否装了Qt,非常适合给不同发行版的用户分发。
4.1 linuxdeployqt操作步骤
先准备工具和Qt环境。假定你的Qt安装在~/Qt/5.15.2/gcc_64,程序构建在~/build/MyApp,那么先下载linuxdeployqt的连续构建版(GitHub上probonopd/linuxdeployqt的releases里有AppImage格式的预编译包),然后按下面步骤执行:
export PATH=~/Qt/5.15.2/gcc_64/bin:$PATH export LDAI_DIR=~/tools/linuxdeployqt chmod +x ~/tools/linuxdeployqt/linuxdeployqt.AppImage mkdir -p ~/appimage/MyApp.AppDir/usr/bin cp ~/build/MyApp ~/appimage/MyApp.AppDir/usr/bin/ cd ~/appimage ~/tools/linuxdeployqt/linuxdeployqt.AppImage MyApp.AppDir/usr/bin/MyApp -qmldir=~/src/MyApp/qml -bundle-non-qt-libs关键参数是-bundle-non-qt-libs,它会把程序依赖的、不属于Qt的库也一并收集,比如libstdc++、libgcc_s等。执行完之后,linuxdeployqt会自动生成AppRun文件和.desktop文件,但.desktop文件里的图标和名称可能需要你手动补一个。最简单的做法是在MyApp.AppDir目录下放一个MyApp.desktop文件,内容类似:
[Desktop Entry] Type=Application Name=MyApp Comment=My Qt Application Exec=MyApp Icon=myapp Categories=Utility;图标方面,把一张256x256的png命名为myapp.png放到MyApp.AppDir目录下。然后执行最后的AppImage打包命令:
~/tools/linuxdeployqt/linuxdeployqt.AppImage MyApp.AppDir/usr/bin/MyApp -appimage顺利的话当前目录会生成一个MyApp-x86_64.AppImage,把它拷到别的发行版机器上chmod +x之后就可以运行了。
4.2 linuxdeployqt的补丁版问题
这里必须提醒一句:官方linuxdeployqt的更新速度很慢,对Qt 5.15及以上版本支持不算好,有时会报“Could not find qmake”或者“Qt path could not be determined”这类错误。我实际用下来,推荐用linuxdeploy这个更活跃的社区项目,或者直接用cqtdeployer的Linux版本,它们在处理新版本Qt时更省心。
如果坚持用linuxdeployqt,遇到报错先检查两点:qmake是否真的在PATH里,以及Qt的qmake和linuxdeployqt是否同为64位。另一个常见坑是打包出来在Ubuntu上能跑,到CentOS 7或openEuler上报“GLIBC_2.18 not found”,这是因为制作AppImage的机器glibc版本太新,AppImage没有完全做到“越老越香”。解决办法是用比较老但稳定的发行版(比如Ubuntu 18.04的容器或虚拟机)来做打包,这样生成的AppImage兼容性最好。
4.3 或者换cqtdeployer一步到位
说实话,配置linuxdeployqt的AppDir目录结构、desktop文件和图标,一两次还好,次数多了真有点烦。如果你的目标平台既有Windows又有Linux,我更推荐直接上cqtdeployer。Linux下先装好依赖,然后命令很简单:
cqtdeployer -bin MyApp -qmake ~/Qt/5.15.2/gcc_64/bin/qmake它会自动识别程序依赖并生成Deploy目录,你可以再执行下面的命令把Deploy目录打成AppImage:
cqtdeployer -bin MyApp -qmake ~/Qt/5.15.2/gcc_64/bin/qmake -appimage从实际体验看,cqtdeployer生成的AppImage稳定性不输linuxdeployqt,而且省掉了很多手工步骤,对没耐心反复配置的开发者来说很友好。
5. 常见问题与排查技巧实录
打包这行最不缺的就是“奇奇怪怪”的问题。有些报错看一眼就知道咋回事,有些折腾半天才能定位。我把这几年遇到的同类问题做了个整理,很多都是在官方文档里翻不到的实操经验。
5.1 “no qt platform plugin could be initialized”根治思路
这个问题太经典了,几乎可以称为Qt打包第一坑。它出现的原因多半是platforms文件夹下的qwindows.dll没有被正确复制,或者exe和插件的位数不匹配。检查顺序可以按下面来:先确认发布目录下有platforms文件夹,且里面有qwindows.dll;再确认qwindows.dll和exe是同一编译位数(32位exe配32位dll,64位配64位);最后确认exe和Qt库版本一致,不要把Qt 5.12的库配到Qt 5.15的程序里。
我也遇到过一种更隐蔽的情况:程序开发时用Qt Creator的Shadow Build,exe在build-release目录里能运行,windeployqt也成功部署了,但用户机器上依然报平台插件错误。排查后发现是杀毒软件把某些dll隔离了,导致platforms文件夹只剩一个空壳。所以遇到这种报错,不妨先让用户在杀毒软件隔离区里看一眼,避免白折腾。
5.2 换电脑运行报缺dll
程序在自己电脑上跑得好好的,拷到别的电脑上就提示缺少msvcp140.dll或vcruntime140.dll,这是典型的VC运行库缺失。虽然windeployqt加--compiler-runtime可以解决大部分情况,但有些精简版系统本身就没带完整的VC运行库。最快解决办法是下载微软官方的vc_redist.x64.exe,在目标机器上安装一次;或者更粗暴一点,手动把这两个dll放进发布目录,和exe放同一个文件夹。
注意别乱拷贝vc run库到Windows系统目录,现在64位系统对系统目录的写保护很严格,不推荐修改系统目录,只有“拷贝到exe同目录”这种方案最省心、最安全。
5.3 杀毒软件误报,不只是个技术问题
用MinGW编译的Qt程序,由于没有数字签名,很容易被Windows Defender或其他杀毒软件标记为“不常见程序”,甚至直接拦截。这个问题在某些打包压缩壳(比如UPX)下会更严重。我试过用UPX压缩exe,结果好几个杀毒引擎直接报毒,后来就不折腾压缩壳了,改用Inno Setup的lzma2压缩,效果差不多而且误报率低很多。
有条件的话,购买代码签名证书对exe和安装包进行签名是最正规的解决方案,签名之后不仅杀毒软件的白名单问题大有改善,用户在Windows SmartScreen弹窗里也不会看到红色警告。个人开发者暂时不想买证书,至少可以在发布说明里提前告知用户“首次运行可能触发Windows SmartScreen,点击'更多信息'->'仍要运行'”,降低使用门槛。
5.4 路径和权限问题
打包脚本里如果硬编码了绝对路径,比如C:\Users\你的名字\MyApp,那换台机器就完蛋。Inno Setup里我习惯用{app}、{autopf}这类内置常量,不要写死路径。另外windeployqt执行时,如果路径里有中文,有些老版本的Qt部署工具会解析出错,虽然后续版本有修复,但还是建议发布目录全程使用英文路径。Linux下AppImage涉及权限,生成出来的AppImage记得chmod +x,发布到网盘时也要注意压缩包解压后是否保留了可执行权限,不然用户在终端里会提示“Permission denied”。
5.5 常见错误速查表
| 错误现象 | 可能原因 | 解决思路 |
|---|---|---|
| no qt platform plugin could be initialized | platforms/qwindows.dll缺失或位数不匹配 | 用windeployqt重新部署,检查插件位数 |
| 缺少msvcp140.dll/vcruntime140.dll | VC运行库未安装 | 拷dll到exe目录或安装vc_redist |
| 程序启动后白屏 | QML模块插件缺失 | 手动复制qml目录,检查--qmldir参数 |
| AppImage启动无反应 | 缺少FUSE或权限不足 | chmod +x,安装libfuse2,或在终端运行看输出 |
| 杀毒软件报毒 | 缺少数字签名或使用UPX | 放弃UPX,考虑添加签名 |
| 部署后文件体积异常大 | windeployqt复制了多余模块 | 清理用不到的plugins、qml模块 |
这张表我建议截图保存或者收藏起来,真到发布前照着过一遍,能少走很多弯路。
6. 到底选哪个?我的选型建议
聊到这里,工具本身都讲得差不多了,接下来回答最容易被问到的问题:我到底该选哪个?我自己的选型思路是按场景走,而不是按工具名气走。
6.1 按场景而不是按偏好
如果你只是给同事或朋友发一个内部工具,目标平台是Windows,那最省事的是windeployqt部署,然后直接把整个发布目录压缩成zip发过去,连安装包都不用做。收件人解压后双击exe就能用,零学习成本。
如果你要把软件发布到公开下载站、给非技术用户安装,Windows端至少要用Inno Setup或NSIS做一个安装包,因为普通用户真的不会看“使用说明.txt”,他们习惯双击Setup.exe,一步步点“下一步”。依赖收集层继续用windeployqt,或者用cqtdeployer一步到位。
如果你做的是跨平台开源软件,希望用户能一键在任何Linux发行版上运行,优先做AppImage,再附上Windows安装包和macOS的dmg。这时候用cqtdeployer统一管理三端依赖,能省掉很多重复劳动。
如果你负责的是企业级产品,模块多、需要组件化安装、甚至要求支持自动更新,那就老老实实上Qt Installer Framework,它的组件选择、卸载、在线安装能力是Inno Setup和NSIS很难替代的。当然代价是前期学习成本偏高,建议至少留出一到两天专门研究config.xml和package.xml的写法。
6.2 一条诚实的经验总结
做Qt开发这几年,我越来越觉得,打包工具本身不是核心,核心是你有没有一套“每次发布都可靠”的流程。工具选A选B都可以,真正拉开差距的是:你会不会每次发布前都跑一遍干净环境验证?会不会把windeployqt和Inno Setup的脚本纳入版本管理?会不会在发版说明里附带文件的SHA256校验值?
我现在的做法是,把windeployqt命令和Inno Setup脚本都放到项目仓库的deploy目录下,用批处理或CMake的自定义target一键触发,版本号从项目配置里读取,打完包自动命名成MyApp_1.0.0_setup.exe。发布前在虚拟机里从零装一遍,确认没问题再上传。这套流程跑顺之后,我再也没遇到过“用户说跑不了,但我这边明明没问题”的尴尬局面。
如果你时间比较紧,只想记一个结论:Windows选windeployqt + Inno Setup,Linux选cqtdeployer生成AppImage,这套组合能覆盖绝大多数Qt桌面应用的分发需求。等你真的遇到性能瓶颈或复杂安装需求,再回头研究NSIS和Qt IFW也不迟。
最后再分享一个小技巧:打完包不要急着关电脑,把那个安装包放到一台没装过Qt的虚拟机里测一遍,顺便看一下首次启动时间。很多Qt程序第一次启动慢是因为在加载插件和字体,如果超过三秒,可以考虑在启动画面上下点功夫。这一步做完,你就能真正松口气了。