戰(zhàn))
今天整理了一套Qt 打包部署方案從 windeployqt 到 Inno Setup 安裝再到版本迭代的自動(dòng)化一步到位。第一步windeployqtwindeployqt 是 Qt 官方提供的部署工具能自動(dòng)掃描你程序依賴的 Qt 模塊和插件把需要的 DLL、資源文件一股腦拷貝到目標(biāo)目錄。但是他只能識(shí)別Qt 庫(kù)第三方庫(kù)比如 OpenCV、FFmpeg需要手動(dòng)處理基礎(chǔ)用法是在Qt命令行環(huán)境里執(zhí)行cd /d 你的構(gòu)建目錄 windeployqt --release --no-translations --compiler-runtime YourApp.exe--compiler-runtime自動(dòng)帶上 MSVC 運(yùn)行庫(kù)如果用的是MinGW,這個(gè)參數(shù)會(huì)忽略但需要把 libgcc_s_seh-1.dll、libstdc-6.dll 也拷走。注意windeployqt 只能在干凈的 release 目錄里跑如果你的 exe 旁邊有舊的 DLL它可能因?yàn)榘姹净煜鴪?bào)錯(cuò)。所以每次構(gòu)建前先把 deploy目錄清空再重新拷貝 exe 。第二步手動(dòng)補(bǔ)全第三方 DLL 和運(yùn)行時(shí)依賴程序往往還依賴一些三方庫(kù)比如串口通信用到的 FTD2XX.dll或者加密庫(kù) libcrypto-3-x64.dll。這些需要從編譯環(huán)境或者 SDK 安裝目錄里找。我用一個(gè)環(huán)境變量來(lái)管理部署目錄比如 D:\DeployRoot\YourApp然后通過(guò)腳本拷貝// 這不是代碼只是一個(gè)批處理片段但 Qt 程序里我會(huì)用 QProcess 來(lái)調(diào)用它 // copy_third_party.bat copy /Y C:\SDK\FTDI\FTD2XX.dll %DEPLOY_DIR%\FTD2XX.dll copy /Y D:\openssl3\lib\libcrypto-3-x64.dll %DEPLOY_DIR%\libcrypto-3-x64.dll拷貝以后最好在 Qt 程序啟動(dòng)時(shí)做一個(gè)靜態(tài)檢查用 QLibrary::isLibrary 驗(yàn)證關(guān)鍵 DLL 是否存在不存在就直接彈窗提示缺少運(yùn)行庫(kù)。注意處理調(diào)試版和發(fā)布版的差異debug 的 DLL 通常帶 d 后綴比如 Qt6Cored.dll打包時(shí)只拷貝 release 版本。第三步Inno Setup安裝文件齊全后開(kāi)始制作安裝包。Inno Setup 是免費(fèi)神器腳本語(yǔ)法簡(jiǎn)單先寫一個(gè)基礎(chǔ)腳本 installer.iss[Setup] AppNameYourApp AppVersion1.0.0 DefaultDirName{pf}\YourCompany\YourApp DefaultGroupNameYourApp OutputDir..\packages OutputBaseFilenameSetup_YourApp_1.0.0 Compressionlzma2 SolidCompressionyes //靜默安裝模式的關(guān)鍵參數(shù) PrivilegesRequiredadmin UninstallDisplayIcon{app}\YourApp.exe [Files] //把 windeployqt 生成的整個(gè) deploy 目錄包含進(jìn)來(lái) Source: ..\deploy\*; DestDir: {app}; Flags: recursesubdirs createallsubdirs [Icons] Name: {group}\YourApp; Filename: {app}\YourApp.exe //桌面快捷方式可選我一般不創(chuàng)建免得客戶嫌亂 [Run] //安裝完成后靜默啟動(dòng)或者不啟動(dòng)看需求 Filename: {app}\YourApp.exe; Parameters: --firstrun; Flags: nowait可以用命令行模式編譯這個(gè)腳本ISCC.exe installer.iss生成 Setup_YourApp_1.0.0.exe點(diǎn)擊安裝即可。注意權(quán)限問(wèn)題、如果你的程序要寫注冊(cè)表或者往 Program Files 下寫數(shù)據(jù)必須強(qiáng)制 PrivilegesRequiredadmin否則 Win10 的 UAC 會(huì)彈窗攔截靜默模式直接失敗。另外安裝完成后如果有驅(qū)動(dòng)或服務(wù)要注冊(cè)記得在 [Run] 里用 Flags: runhidden 跑你的批處理不然控制臺(tái)窗口一閃而過(guò)客戶以為是 bug。第四步版本迭代的自動(dòng)化從 CMake 到打包每次手動(dòng)執(zhí)行 windeployqt 再開(kāi) Inno Setup 過(guò)于繁瑣我們可以升級(jí)到 CI/CD 思路。我會(huì)使用 CMake 捕獲版本號(hào)生成一個(gè) version_info.iss 文件里面包含版本號(hào)和文件名。在 CMakeLists.txt 里加一段set(APP_VERSION 1.0.0) configure_file(${CMAKE_SOURCE_DIR}/installer.iss.in ${CMAKE_BINARY_DIR}/installer.iss ONLY)然后在 installer.iss.in 里用 APP_VERSION 占位比如AppVersionAPP_VERSION OutputBaseFilenameSetup_YourApp_APP_VERSION這樣每次改代碼只動(dòng)一個(gè)版本號(hào)打包腳本自動(dòng)變化。還可以在 CMake 里加一個(gè)自定義 target依次執(zhí)行 windeployqt 和 ISCC一條命令生成安裝包add_custom_target(package_app COMMAND windeployqt --release $TARGET_FILE:YourApp COMMAND ISCC.exe ${CMAKE_BINARY_DIR}/installer.iss DEPENDS YourApp )注意** 版本號(hào)別硬編碼在 .pro 文件如果你用 qmake因?yàn)?CMake 和 qmake 混用會(huì)亂。統(tǒng)一用一個(gè) version.h 頭文件定義 APP_VERSION_STRC 代碼和 Inno Setup 都從這里讀取保證萬(wàn)無(wú)一失。