戰(zhàn):QT 5.3.1 與 MSVC 工具鏈全解析)
簡(jiǎn)介這是一份Telegram開源IM在Windows環(huán)境下的編譯實(shí)戰(zhàn)記錄主要面向有一定C基礎(chǔ)、嘗試自行編譯Telegram桌面版或QT5.3.1的開發(fā)者。作者基于VS2013和tdesktop官方MSVC指南完整記錄了從環(huán)境準(zhǔn)備、OpenSSL/LZMA/zlib/libexif等依賴搭建到Telegram源碼編譯中各類典型錯(cuò)誤的定位與處理并單獨(dú)整理了QT5.3.1的編譯過程包括Perl/Python/Ruby環(huán)境配置、ICU可選安裝、VS2013開發(fā)人員命令提示下的configure與nmake參數(shù)等。整份資源為1個(gè)doc文檔壓縮包僅29KB內(nèi)容高度濃縮適合作為編譯Telegram/QT時(shí)快速查閱的排錯(cuò)手冊(cè)。目前已有569人學(xué)習(xí)下載。文檔中對(duì)openssl頭文件路徑錯(cuò)誤、Qt5Widgets.lib缺失、libeay32MT.lib鏈接失敗等高頻問題給出了具體修改方法和命令示例能幫助讀者少走彎路。1. 從源碼編譯 Telegram Desktop為什么非要碰 QT 5.3.1Telegram Desktop 的官方預(yù)編譯包能滿足日常使用但當(dāng)你需要定制客戶端、修改 UI 邏輯、或者想在離線內(nèi)網(wǎng)環(huán)境部署時(shí)從源碼編譯就成了繞不開的路徑。更麻煩的是Telegram Desktop 的歷史版本和 QT 5.3.1 綁定得很死——新版 Qt 的接口變化會(huì)讓老代碼直接編譯失敗。我拆這個(gè)項(xiàng)目時(shí)踩了十幾個(gè)坑從 MSVC 工具鏈到 qscintilla 靜態(tài)庫每一步都有值得記錄的細(xì)節(jié)。這篇筆記直接給你可復(fù)現(xiàn)的完整流程包括 configure 參數(shù)、jom 并行編譯設(shè)置、以及cannot find -lpublic這類高頻報(bào)錯(cuò)的定位思路。如果你正準(zhǔn)備在自己的機(jī)器上完整編譯一遍 Telegram Desktop尤其是用 QT 5.3.1 這個(gè)老版本這篇就是給你寫的。2. 環(huán)境準(zhǔn)備與工具鏈選型先把三種“編譯器”的賬算清2.1 MSVC vs MinGWQT 5.3.1 的兼容性真相Telegram Desktop 官方推薦的編譯環(huán)境是 MSVCMicrosoft Visual C而不是很多人習(xí)慣的 MinGW。原因很直接QT 5.3.1 時(shí)代的 Windows 版本對(duì) MinGW 的支持不完整Telegram 源碼里大量使用了windows.h底層 API 和 MSVC 特有的#pragma指令MinGW 的 GCC 解釋不了這些代碼。我見過有人硬用 MinGW 編 Telegram最后在鏈接階段遇到幾百個(gè)未解析符號(hào)那個(gè)排查過程非常痛苦。正確做法是安裝 Visual Studio 2013 或 2015 的社區(qū)版——注意版本的匹配。Telegram Desktop 在 QT 5.3.1 分支時(shí)官方測(cè)試環(huán)境是 VS2013用 VS2015 也能編但 VS2017 以上的工具鏈會(huì)對(duì)老代碼里的某些類型轉(zhuǎn)換報(bào)錯(cuò)因?yàn)閟td::auto_ptr被徹底移除了。如果你只有 VS2019 或 VS2022也不是完全沒救需要額外做一件事安裝“單個(gè)組件”里的Windows 7 SDK和MSVC v120 工具集VS2013 的編譯器核心。沒有這個(gè)QT 5.3.1 的qmake生成的 Makefile 里的-GL-參數(shù)會(huì)直接報(bào)錯(cuò)。提示MSVC 工具鏈和 MinGW 的區(qū)別不只在編譯速度最重要的是 ABI應(yīng)用二進(jìn)制接口不同。QT 庫如果用的是 MSVC 編譯的你的業(yè)務(wù)代碼也必須用 MSVC混著鏈接會(huì)出LNK2038這類 mismatch 錯(cuò)誤。2.2 源碼獲取Telegram 倉(cāng)庫的完整克隆方式Telegram Desktop 的源碼在 GitHub 上倉(cāng)庫地址是telegramdesktop/tdesktop。因?yàn)轫?xiàng)目體積很大超過 2GB加上子模塊眾多直接git clone經(jīng)常會(huì)中斷。常見做法是先用--depth1做淺克隆再拉子模塊。git clone --depth1 --branch v1.0.0 https://github.com/telegramdesktop/tdesktop.git cd tdesktop git submodule init git submodule update --depth1這段命令的邏輯是--depth1只拉最新的一次提交大幅減少傳輸量--branch v1.0.0指定了你要編譯的分支——如果你要編 QT 5.3.1 版本需要切到對(duì)應(yīng)歷史分支比如v0.9.6或v1.0.0。git submodule update會(huì)把 Telegram 依賴的第三方庫如libtgvoip、ffmpeg、qscintilla等拉下來。這里有個(gè)重點(diǎn)子模塊必須拉全否則編譯到一半會(huì)報(bào)fatal error: libtgvoip/Media.h file not found之類的頭文件缺失錯(cuò)誤。檢查子模塊是否完整的命令是ls telgui/ThirdParty/正常情況下你應(yīng)該看到libtgvoip、ffmpeg、qscintilla、catch等目錄都在。缺哪個(gè)就單獨(dú)初始化哪個(gè)比如缺 qscintilla 就執(zhí)行g(shù)it submodule update --init --recursive telgui/ThirdParty/qscintilla。2.3 依賴庫清單QT 5.3.1 之外還需要什么Telegram Desktop 的依賴庫比想象中多QT 只是其中一塊。核心依賴包括依賴庫用途獲取方式QT 5.3.1主界面框架、網(wǎng)絡(luò)、事件循環(huán)官方源碼編譯或預(yù)編譯包qscintilla代碼編輯器控件用于 Telegram 的代碼高亮源碼編譯注意必須與 QT 同版本libtgvoipVoIP 語音通話子模塊拉取ffmpeg音視頻編解碼子模塊拉取如果不需要語音和視頻可以禁用OpenSSL加密協(xié)議系統(tǒng)自帶或另行編譯其中最容易出問題的是 qscintilla。它本身是個(gè)獨(dú)立的 QT 控件庫Telegram 的TelegramMessenger里用它實(shí)現(xiàn)消息代碼塊的語法高亮。qscintilla 的編譯必須和 QT 5.3.1 嚴(yán)格同版本否則會(huì)出現(xiàn) slots 信號(hào)連接失敗——這個(gè)報(bào)錯(cuò)在運(yùn)行時(shí)才暴露編譯期是看不出來的。另外如果你不需要語音通話編譯時(shí)可以加TDESKTOP_DISABLE_TGVOIP1這個(gè)開關(guān)省掉 libtgvoip 的編譯時(shí)間。我一般會(huì)禁用因?yàn)檎Z音通話模塊依賴的 WebRTC 編譯復(fù)雜度很高動(dòng)不動(dòng)就要 40 分鐘起步。3. QT 5.3.1 完整編譯configure 參數(shù)與 qscintilla 聯(lián)動(dòng)3.1 configure 參數(shù)怎么給靜態(tài)鏈接的關(guān)鍵配置QT 5.3.1 的編譯是整個(gè)流程里耗時(shí)最長(zhǎng)的環(huán)節(jié)用默認(rèn)參數(shù)編一次大約 2 小時(shí)所以 configure 參數(shù)必須一次給對(duì)。我實(shí)際使用的參數(shù)組合是這樣的cd qt-5.3.1 configure.bat -prefix D:\Qt\5.3.1\msvc2013 -opensource -confirm-license -debug-and-release -static -opengl desktop -no-openssl -no-icu -no-angle -nomake tests -nomake examples -mp逐個(gè)拆解這些參數(shù)的含義-prefix指定安裝路徑務(wù)必放在空間充足的盤QT 編譯后占用約 5GB。-debug-and-release同時(shí)生成調(diào)試版和發(fā)布版。Telegram 的 qmake 文件里默認(rèn)兩個(gè)版本都會(huì)用省掉后面再次配置的麻煩。-static是關(guān)鍵——Telegram Desktop 默認(rèn)要求靜態(tài)鏈接 QT因?yàn)楣俜桨l(fā)布的 Windows 版就是這樣打包的動(dòng)態(tài)鏈接反而需要額外拷貝大量 dll。-no-openssl在 configure 階段跳過 OpenSSL 檢測(cè)Telegram 會(huì)自己處理加密庫這能避免 QT 的 OpenSSL 版本和系統(tǒng)版本沖突。-no-angle很重要。ANGLE 是 QT 用來把 OpenGL ES 翻譯成 DirectX 的庫Telegram 不需要它而 ANGLE 編譯極慢去掉能省 20 分鐘。-mp開啟多處理器編譯配合后面的jom使用否則單線程編譯 QT 是災(zāi)難。configure 執(zhí)行完后會(huì)生成Makefile然后跑編譯jom -j8 jom install第一條命令里的-j8表示 8 個(gè)并行任務(wù)。你要根據(jù) CPU 核心數(shù)調(diào)整一般-j4到-j16之間。如果內(nèi)存只有 8GB建議-j4因?yàn)椴⑿芯幾g每個(gè)任務(wù)會(huì)吃 700MB 左右內(nèi)存8 個(gè)任務(wù)可能直接爆內(nèi)存導(dǎo)致編譯進(jìn)程被系統(tǒng)殺掉。3.2 編譯失敗時(shí)怎么看jom 輸出與日志定位jom 編譯失敗是常態(tài)關(guān)鍵是學(xué)會(huì)快讀日志。QT 編譯報(bào)錯(cuò)的常見形式有兩種Error 1 (for counter) : cl開頭——這是真正的 MSVC 編譯錯(cuò)誤說明某個(gè) C 源文件編譯不過。NMAKE : fatal error U1077—— 這是依賴錯(cuò)誤通常是因?yàn)樯弦粋€(gè)文件沒有正確生成導(dǎo)致鏈接階段缺文件。處理策略就一條先修第一個(gè)報(bào)錯(cuò)不要往下翻。因?yàn)楹罄m(xù)錯(cuò)誤大概率是同一個(gè)原因?qū)е碌倪B鎖反應(yīng)。比如qtbase編譯時(shí)報(bào)cannot open input file qtmain.lib這時(shí)候要檢查是不是qtmain這個(gè)子項(xiàng)目還沒 build 完——順序亂了。QT 5.3.1 在 Windows 上編譯時(shí)的“黃金順序”是configure生成后手動(dòng)構(gòu)建qtbase這個(gè)子模塊因?yàn)樗瞧渌心K如qtscript、qtsvg的基礎(chǔ)。命令行單獨(dú)構(gòu)建cd qtbase jom -j8 cd ..如果qtbase順利通過剩下的模塊基本不會(huì)有大問題。3.3 qscintilla 下載與編譯必須手動(dòng)干預(yù)的一步qscintilla 是個(gè)獨(dú)立的庫不跟隨 QT 的 configure 流程。Telegram 的源碼里雖然包含了 qscintilla 子模塊但它的 build 文件需要單獨(dú)執(zhí)行。這個(gè)庫的編譯極其挑剔網(wǎng)上很多人在這里翻車。先看源碼目錄結(jié)構(gòu)cd telgui/ThirdParty/qscintilla這個(gè)目錄下有Qt4Qt5子目錄里面有qscintilla.pro文件。進(jìn)入這個(gè)目錄執(zhí)行cd Qt4Qt5 D:\Qt\5.3.1\msvc2013\bin\qmake.exe qscintilla.pro -spec win32-msvc2013 jom -j8如果你用的是 VS2015 工具鏈把-spec win32-msvc2013換成win32-msvc2015。這一步非常容易出錯(cuò)的地方是qmake 中間不能有空格或者中文路徑。D:\Qt\5.3.1\msvc2013這個(gè)路徑中如果出現(xiàn)中文qscintilla 的.vcxproj文件生成會(huì)失敗報(bào)一堆Cannot find file的詭異錯(cuò)誤。編譯完成后把生成的qscintilla2.lib和頭文件復(fù)制到 QT 的 lib 和 include 目錄copy Qt4Qt5\release\qscintilla2.lib D:\Qt\5.3.1\msvc2013\lib\ copy Qt4Qt5\Qsci\qsciscintilla.h D:\Qt\5.3.1\msvc2013\include\注意qscintilla 是 LGPL 協(xié)議靜態(tài)鏈接進(jìn) Telegram 后如果你不打算開源自己的改動(dòng)需要仔細(xì)確認(rèn)一下合規(guī)要求。這里只提編譯技術(shù)問題不展開法律細(xì)節(jié)。4. Telegram Desktop 主程序編譯qmake、jom 與生成目錄4.1 生成主工程 Makefile兩個(gè)關(guān)鍵文件缺一不可QT 編譯完畢、qscintilla 就位之后才輪到 Telegram 主工程。項(xiàng)目根目錄下的Telegram文件夾里有Telegram.pro文件需要先手動(dòng)指定 qmake 路徑cd Telegram D:\Qt\5.3.1\msvc2013\bin\qmake.exe Telegram.pro -spec win32-msvc2013 CONFIGdebug_and_release這一步的坑在于CONFIGdebug_and_release必須加不加的話后面編譯會(huì)報(bào)debug\...obj : fatal error LNK1181: cannot open input file release\...obj——它試圖鏈接一個(gè)不存在的 release 目錄下的文件。qmake 成功執(zhí)行后會(huì)生成Makefile和Makefile.Release兩個(gè)文件。老手習(xí)慣直接打開Makefile.Release看編譯選項(xiàng)——如果里面DEFINES那行沒有TDESKTOP_DISABLE_CRASH_REPORTS和TDESKTOP_DISABLE_AUTOUPDATE建議手動(dòng)加上。這兩個(gè)宏分別關(guān)閉崩潰上報(bào)和自動(dòng)更新純本地編譯時(shí)開著它們會(huì)額外引入網(wǎng)絡(luò)請(qǐng)求邏輯反而讓程序啟動(dòng)變慢。4.2 主程序編譯jom 并行與內(nèi)存調(diào)優(yōu)Telegram 主工程的編譯同樣用 jom但這個(gè)項(xiàng)目的并發(fā)度不能貪高。Telegram 的代碼里包含大量模板類特別是Streaming模塊單個(gè)編譯單元內(nèi)存消耗極大-j8在 Telegram 主工程上實(shí)測(cè)容易把 16GB 內(nèi)存吃滿后觸發(fā) OOM。jom -j4如果內(nèi)存足夠32GB 以上可以嘗試-j6內(nèi)存 8GB 的機(jī)器老老實(shí)實(shí)-j2雖然慢但至少不會(huì)中途崩。編譯時(shí)間上-j4環(huán)境下大概 1 小時(shí)左右跑完。編譯過程中最常見的一道坎是fatal error C1060: compiler is out of heap space這是 MSVC 編譯器自己內(nèi)存不足的表現(xiàn)不是你系統(tǒng)內(nèi)存不足。解決方法是把cl.exe的/Zm參數(shù)調(diào)大在 qmake 的QMAKE_CXXFLAGS里追加/Zm800。這個(gè)參數(shù)是給編譯器預(yù)留更多預(yù)編譯頭文件內(nèi)存的800 是一個(gè)比較安全的數(shù)值。4.3 編譯產(chǎn)物路徑與驗(yàn)證拿到 Telegram.exe 只是第一步編譯完成后可執(zhí)行文件在Telegram\Release\Telegram.exe。但別急著雙擊運(yùn)行——這個(gè) exe 還缺Telegram\Resources目錄下的資源文件圖標(biāo)、語言包、字體等。如果不拷貝資源目錄程序啟動(dòng)后界面是空白的或者直接閃退。復(fù)制資源的命令xcopy /E /I Telegram\Resources Telegram\Release\Resources拷完之后運(yùn)行 Telegram.exe如果一切正常會(huì)彈出登錄界面。這時(shí)候注意一個(gè)細(xì)節(jié)Telegram 首次啟動(dòng)會(huì)向官方服務(wù)器請(qǐng)求配置如果你的機(jī)器在國(guó)內(nèi)網(wǎng)絡(luò)環(huán)境下這個(gè)請(qǐng)求可能會(huì)超時(shí)。這不是你編譯的問題是網(wǎng)絡(luò)環(huán)境問題換個(gè)方式處理即可。另外Release 目錄下除了 Telegram.exe還會(huì)看到Telegram.obj和一堆.pdb文件。.pdb是調(diào)試符號(hào)文件如果是自己本地編譯建議保留但如果你要分發(fā)這個(gè) exe.pdb會(huì)暴露源碼路徑信息不介意的話可以刪掉。4.4 快速驗(yàn)證編譯配置是否生效編譯完之后驗(yàn)證你的自定義配置是否真的編進(jìn)去了可以用這個(gè)命令strings Telegram.exe | findstr TDESKTOP_DISABLE_CRASH_REPORTS如果輸出里有1或者宏名說明編譯配置生效了。注意strings是 GNU 工具Windows 上可以裝個(gè)sysinternals的替代品或者直接用find命令搜二進(jìn)制里的文本。這個(gè)方法在排查“我明明改了配置為什么編譯出的 exe 沒變化”這種問題時(shí)非常實(shí)用。5. 編譯避坑指南五條高頻報(bào)錯(cuò)的定位與修復(fù)5.1 報(bào)錯(cuò)cannot find -lpublicQT 庫路徑?jīng)]配對(duì)現(xiàn)象鏈接階段報(bào)LINK : fatal error LNK1181: cannot open input file public.lib或者 GCC 系的cannot find -lpublic。原因qmake 生成的 Makefile 中LIBS變量引用了名為public的庫源自代碼里的QT public或類似的錯(cuò)誤拼寫但你的 QT 庫里根本沒有public.lib。這個(gè)問題的本質(zhì)是 Telegram 的老代碼里有一處對(duì)QtPlatformHeaders的錯(cuò)誤引用。解決修改Telegram.pro文件把QT public刪除或者改成QT gui。改完后重新執(zhí)行 qmake不要只重新跑 jom——因?yàn)?Makefile 不會(huì)自動(dòng)感知.pro文件的變化。一定要先刪掉舊的 Makefile 再重新 qmakedel Makefile Makefile.Release qmake.exe Telegram.pro -spec win32-msvc2013 jom -j45.2 qscintilla 編譯后鏈接報(bào)錯(cuò)版本不一致的無聲失敗現(xiàn)象Telegram 主程序鏈接時(shí)報(bào)unresolved external symbol public: virtual struct QMetaObject const * __thiscall QsciScintilla::metaObject(void)const之類的錯(cuò)誤。原因qscintilla 編譯時(shí)用的 QT 版本和 Telegram 主程序編譯時(shí)用的 QT 版本不一致。最常見的情況是你機(jī)器上原來裝過另一個(gè)版本的 QT比如 5.12qmake 時(shí)誤用了舊版本的qmake.exe導(dǎo)致 qscintilla 的 moc 文件基于 5.12 生成但鏈接時(shí)用的 QT 5.3.1 的頭文件布局對(duì)不上。解決檢查 qscintilla 的 Makefile 里QTDIR變量指向哪里。確保D:\Qt\5.3.1\msvc2013\bin\qmake.exe在你的 PATH 最前面。再?gòu)氐滓稽c(diǎn)的做法是清掉 qscintilla 的 build 緩存重編cd telgui/ThirdParty/qscintilla/Qt4Qt5 del Makefile* *debug *release /s /q然后重新 qmake、重新 jom。這件事沒有捷徑只能重來。5.3 編譯中內(nèi)存不足C1060玄學(xué)但可解的編譯器堆問題現(xiàn)象fatal error C1060: compiler is out of heap space而且每次報(bào)錯(cuò)的代碼文件都不一樣看起來像是隨機(jī)崩潰。原因MSVC 編譯器在編譯大量使用模板的現(xiàn)代 C 代碼時(shí)預(yù)編譯頭PCH緩存占用會(huì)膨脹。這跟系統(tǒng)內(nèi)存大小沒有直接關(guān)系更像編譯器內(nèi)部堆的分配策略問題。解決在.pro文件里添加QMAKE_CXXFLAGS /Zm800這個(gè)參數(shù)把編譯器的預(yù)編譯頭內(nèi)存上限從默認(rèn)值調(diào)高。如果還不行再把/MP多進(jìn)程編譯關(guān)掉——/MP會(huì)啟動(dòng)多個(gè) cl.exe 實(shí)例每個(gè)實(shí)例各自維護(hù)堆總內(nèi)存消耗成倍增加。QMAKE_CXXFLAGS /Zm800 /MP1/MP1是強(qiáng)制單進(jìn)程編譯雖然慢一點(diǎn)但穩(wěn)。我用這個(gè)方法解決了十幾臺(tái)機(jī)器上的相同報(bào)錯(cuò)。5.4 編譯產(chǎn)物能跑但界面空白資源文件缺失的迷局現(xiàn)象Telegram.exe能啟動(dòng)進(jìn)程也在后臺(tái)但窗口一片白色沒有任何響應(yīng)。原因缺少Resources目錄下的樣式表.tdesktop文件和圖標(biāo)資源。Telegram 的程序架構(gòu)里所有 UI 資源都是運(yùn)行時(shí)從Resources目錄加載的而不是編譯進(jìn) exe。這個(gè)設(shè)計(jì)初看很蠢但它是為了讓設(shè)計(jì)資源能獨(dú)立更新。解決從源碼目錄的Telegram\Resources完整拷貝到Release目錄注意Resources下還有一個(gè)qrc子目錄里面是字體文件不能漏拷貝。完成后目錄結(jié)構(gòu)應(yīng)該是Release/ Telegram.exe Resources/ default.tdesktop icon.ico qrc/ font.ttf5.5LNK2038 mismatch detected for RuntimeLibraryMT 和 MD 之爭(zhēng)現(xiàn)象編譯到最后一個(gè)鏈接階段報(bào)LNK2038: mismatch detected for RuntimeLibrary: value MD_DynamicRelease doesnt match value MT_StaticRelease。原因你的某個(gè)依賴庫比如 qscintillarelease版本是用動(dòng)態(tài)運(yùn)行時(shí)/MD編譯的但 Telegram 主工程用靜態(tài)運(yùn)行時(shí)/MT編譯。Windows 不允許混合鏈接這兩種運(yùn)行時(shí)的目標(biāo)文件。解決明確統(tǒng)一策略。如果主工程用/MT靜態(tài)運(yùn)行時(shí)則 qscintilla 也必須用/MT重新編。qscintilla 的qscintilla.pro里追加一行QMAKE_CXXFLAGS_RELEASE /MT然后重新編譯 qscintilla。反過來如果主工程用/MD那在 Telegram.pro 里設(shè)QMAKE_CXXFLAGS_RELEASE /MD。關(guān)鍵是全項(xiàng)目一個(gè)標(biāo)準(zhǔn)不能混。6. 進(jìn)階驗(yàn)證與產(chǎn)物檢查編譯結(jié)果到底能不能直接分發(fā)6.1 用 dumpbin 檢查 DLL 依賴鏈本地編譯的Telegram.exe能不能在其他機(jī)器上運(yùn)行關(guān)鍵看依賴鏈?zhǔn)欠裢暾?。?MSVC 自帶的 dumpbin 工具檢查dumpbin /dependents Telegram.exe輸出里會(huì)出現(xiàn)一長(zhǎng)串 DLL 列表。其中值得關(guān)注的是Qt5Core.dll、Qt5Gui.dll、Qt5Widgets.dll這幾項(xiàng)——如果你用的是-static編譯的 QT這些 DLL 不應(yīng)該出現(xiàn)在依賴列表里。如果出現(xiàn)了說明你的靜態(tài)編譯配置沒生效通常是-static參數(shù)沒被 qmake 讀到這個(gè) exe 拷到別的機(jī)器就會(huì)因缺 DLL 跑不起來。另外注意看有沒有l(wèi)ibgcc_s_seh-1.dll或libstdc-6.dll——出現(xiàn)這兩個(gè)基本上可以判定你混入了 MinGW 編譯的目標(biāo)文件這個(gè) exe 在純凈 Windows 環(huán)境一定缺 DLL。6.2 版本號(hào)與數(shù)字簽名的修改編譯出來的 Telegram.exe 默認(rèn)版本號(hào)是源碼分支的版本比如 1.0.0。如果你準(zhǔn)備分發(fā)到公司內(nèi)部或者自定義品牌需要改.rc資源文件里的版本信息。Telegram 的版本號(hào)定義在Telegram/Resources/telegram.rc里#define VERSION_MAJOR 1 #define VERSION_MINOR 0 #define VERSION_PATCH 0修改后需要重新編譯才生效因?yàn)?rc文件是編譯期嵌入 exe 的資源。這一步注意編碼格式——.rc文件必須是 UTF-16 LE 編碼否則rc.exe會(huì)報(bào)資源解析錯(cuò)誤。數(shù)字簽名這塊如果只是內(nèi)部使用可以不簽。但要跨機(jī)器分發(fā)Windows SmartScreen 會(huì)因?yàn)闊o簽名彈紅窗警告。條件夠的話用自簽名證書簽一下也行代碼signtool sign /fd SHA256 /f mycert.pfx /p yourpassword Telegram.exe注意自簽名證書依然會(huì)觸發(fā) SmartScreen 警告只是少一點(diǎn)威脅提示。6.3 環(huán)境變量隔離避免老 QT 殘留的坑編譯后的 Telegram.exe 啟動(dòng)時(shí)會(huì)先找同目錄下的Qt5Core.dll如果用的是動(dòng)態(tài)鏈接。但 Windows DLL 搜索順序是優(yōu)先系統(tǒng)目錄的如果另一套 QT比如 5.12的 DLL 路徑在你的系統(tǒng) PATH 里可能出現(xiàn)“加載了錯(cuò)誤的 Qt5Core.dll”導(dǎo)致運(yùn)行崩潰。一個(gè)簡(jiǎn)單的驗(yàn)證方法設(shè)置環(huán)境變量QT_DEBUG_PLUGINS1后啟動(dòng) Telegram.exe觀察輸出內(nèi)容。set QT_DEBUG_PLUGINS1 Telegram.exe輸出里會(huì)打印實(shí)際加載的 QT 插件路徑。如果指向的不是你的編譯目錄D:\Qt\5.3.1\msvc2013\plugins說明 PATH 污染。這時(shí)候把 Telegram.exe 所在的目錄拷貝到一個(gè)干凈的臨時(shí)目錄單獨(dú)運(yùn)行問題通常就消失了。6.4 關(guān)于低配機(jī)器編譯的最后提醒如果你用了-j8編譯時(shí)內(nèi)存吃滿直接黑屏死機(jī)不要以為是硬件問題。這是 jom 并行任務(wù)把內(nèi)存條榨干了Windows 直接觸發(fā) OOM killer。從那以后我每次編譯 Telegram 都會(huì)做三件事打開任務(wù)管理器看內(nèi)存占用、把 jom 并發(fā)數(shù)壓到內(nèi)存允許的下限、再設(shè)置頁面文件至少 16GB。這個(gè)習(xí)慣救了我至少三次每次都能避免編譯到 70% 時(shí)系統(tǒng)崩潰前功盡棄。希望這篇編譯筆記幫到你也祝你在踩坑路上少走點(diǎn)彎路。本文還有配套的精品資源點(diǎn)擊獲取