境配置指南)
簡(jiǎn)介面向Windows平臺(tái)C/C開(kāi)發(fā)者的MinGW-w64離線安裝包包含完整的GCC、GDB、Binutils、MINGW Runtime及MSYS組件無(wú)需聯(lián)網(wǎng)即可一鍵搭建本地編譯調(diào)試環(huán)境適合學(xué)習(xí)C語(yǔ)言或進(jìn)行跨平臺(tái)開(kāi)發(fā)的用戶。資源共2000個(gè)文件以h/hpp頭文件、a/lib靜態(tài)庫(kù)、dll動(dòng)態(tài)庫(kù)、exe可執(zhí)行程序?yàn)橹鬏o以py/pyc等配置與輔助腳本壓縮包整體約134MB可自定義選擇編譯器版本和安裝組件。安裝后只需將bin目錄加入PATH即可在命令行使用gcc/g編譯并配合gdb調(diào)試也可集成Code::Blocks、Qt Creator等IDE極大降低Windows下C/C開(kāi)發(fā)環(huán)境配置門(mén)檻。已有1489人學(xué)習(xí)使用這份離線環(huán)境包是教學(xué)實(shí)驗(yàn)和日常開(kāi)發(fā)的實(shí)用工具。 搞過(guò)Windows下C/C開(kāi)發(fā)的朋友多半都經(jīng)歷過(guò)一個(gè)尷尬時(shí)刻電腦明明配得不差結(jié)果想編譯個(gè)C程序卻卡在了“裝編譯器”這一步。尤其是當(dāng)你面對(duì)MinGW-w64的官方安裝器點(diǎn)下去之后發(fā)現(xiàn)進(jìn)度條蝸速爬行或者壓根連不上服務(wù)器那種挫敗感比編譯報(bào)錯(cuò)還讓人難受。更頭疼的是如果手頭還有一臺(tái)隔絕外網(wǎng)的機(jī)器或者機(jī)房網(wǎng)絡(luò)環(huán)境差那在線安裝基本就是死路一條。這種時(shí)候一個(gè)現(xiàn)成的MinGW-w64離線安裝包外加一套配置好的環(huán)境包成了真正能救命的玩意兒。這篇東西我打算聊聊離線包怎么獲取、版本怎么選、環(huán)境變量怎么配以及我踩過(guò)的那些坑。適合正在給新電腦裝開(kāi)發(fā)環(huán)境的人也適合做運(yùn)維、需要批量交付統(tǒng)一開(kāi)發(fā)環(huán)境的老哥還有那些剛?cè)腴T(mén)C/C、被命令行嚇到的新手朋友。讀完之后你不需要反復(fù)在線重試也能在三五分鐘內(nèi)把環(huán)境跑起來(lái)。1. 為什么MinGW-w64離線包比在線安裝省心1.1 在線安裝器的“隱藏成本”很多人第一次接觸MinGW-w64都是去官網(wǎng)下那個(gè)在線安裝器比如mingw-w64-installer.exe或者通過(guò)MSYS2的方式折騰。在線安裝器的邏輯是下載一個(gè)很小的引導(dǎo)程序然后運(yùn)行時(shí)再拉取真正的工具鏈文件。問(wèn)題就出在這兒這個(gè)工具的托管和分發(fā)鏈路在部分地區(qū)很不穩(wěn)定經(jīng)常出現(xiàn)斷流、連接超時(shí)或者下了半天顯示“Download failed”。就算網(wǎng)絡(luò)順暢在線安裝器默認(rèn)拉取的文件也挺多——核心編譯器、GNU binutils、運(yùn)行時(shí)庫(kù)、頭文件、Windows API的導(dǎo)入庫(kù)等等加在一起幾百M(fèi)B的量級(jí)。重復(fù)在不同電腦上執(zhí)行安裝等于把這些流量反復(fù)燒一遍費(fèi)時(shí)費(fèi)電費(fèi)心力。離線安裝包則是一次性把整個(gè)工具鏈下載好拷到U盤(pán)、傳到內(nèi)網(wǎng)、掛到共享盤(pán)所有機(jī)器共享這一份效率直接拉滿。1.2 環(huán)境包和安裝包到底是不是一回事很多人分不清“安裝包”和“環(huán)境包”。實(shí)際使用中我理解的安裝包是那些帶有安裝引導(dǎo)界面的可執(zhí)行文件比如setup.exe、installer.exe它會(huì)幫你處理文件釋放、注冊(cè)表寫(xiě)入、環(huán)境變量配置。而環(huán)境包更像是一個(gè)綠色版壓縮包——你解壓出來(lái)的mingw64文件夾就是一個(gè)自洽的完整工具鏈。它不寫(xiě)注冊(cè)表也不需要安裝器只要把目錄路徑加到系統(tǒng)的PATH環(huán)境變量里就能直接工作。我個(gè)人更偏愛(ài)用壓縮包形式的環(huán)境包。原因有兩個(gè)一是可遷移性極強(qiáng)整個(gè)文件夾拷走到另一臺(tái)機(jī)器上解壓、改個(gè)環(huán)境變量就能用二是便于統(tǒng)一版本團(tuán)隊(duì)開(kāi)發(fā)時(shí)大家共用一個(gè)壓縮包編譯器版本完全一致能避免“我這兒編譯好好的你那兒就報(bào)錯(cuò)”這種經(jīng)典問(wèn)題。后文要做的就是把這種環(huán)境包離線部署到Windows機(jī)器上的完整流程。2. 選對(duì)版本和線程模型先把坑埋掉一半2.1 快速看懂x86_64-posix-seh這一段字符串從網(wǎng)上下載MinGW-w64離線包時(shí)你會(huì)看到各種名字比如“x86_64-posix-seh”、“i686-win32-dwarf”等等。這些不是隨便起的每個(gè)字段都對(duì)應(yīng)了目標(biāo)平臺(tái)和異常處理機(jī)制。以最常見(jiàn)的“x86_64-posix-seh”為例x86_64指目標(biāo)架構(gòu)是64位。如果你想編譯32位程序就要選i686。posix vs win32指線程模型。posix版本支持標(biāo)準(zhǔn)C的std::thread等并行庫(kù)win32版本不支持C11的線程庫(kù)標(biāo)準(zhǔn)實(shí)現(xiàn)只能用Windows API的線程?,F(xiàn)在的代碼動(dòng)不動(dòng)就用到std::thread所以建議選posix否則編譯一些現(xiàn)代C代碼時(shí)會(huì)報(bào)一堆奇怪的錯(cuò)誤。seh vs dwarf vs sjlj指異常處理模型。SEHStructured Exception Handling結(jié)構(gòu)化異常處理是Windows原生機(jī)制性能和兼容性更好Dwarf和Sjlj在32位環(huán)境下常見(jiàn)。64位下選seh32位下選dwarf基本是共識(shí)。所以遇到離線包只要認(rèn)準(zhǔn)x86_64-posix-seh這條線大部分桌面應(yīng)用開(kāi)發(fā)場(chǎng)景都不會(huì)出大問(wèn)題。2.2 32位還是64位別拍腦袋編譯目標(biāo)架構(gòu)取決于你的程序給誰(shuí)用。如果只是本機(jī)調(diào)試系統(tǒng)是64位就裝64位工具鏈。但如果要交付兼容32位Windows或很多老舊機(jī)房系統(tǒng)的程序那就得額外準(zhǔn)備i686版本。需要注意MinGW-w64是交叉編譯友好的工具鏈也就是說(shuō)你可以在64位機(jī)器上同時(shí)安裝兩個(gè)不同的目錄mingw64和mingw32分別編譯不同位數(shù)的程序只要改一下PATH和編譯器前綴。我見(jiàn)過(guò)不少初學(xué)者直接下載“最新版”離線安裝包沒(méi)注意架構(gòu)結(jié)果編譯出來(lái)的exe在別人的32位老機(jī)器上跑不起來(lái)。這事兒真得在下載之前就確認(rèn)清楚否則裝完再換又得重新配置環(huán)境變量純屬浪費(fèi)時(shí)間。3. 離線部署完整五步走3.1 準(zhǔn)備工作確認(rèn)系統(tǒng)位數(shù)和磁盤(pán)位置開(kāi)始之前先在Windows“設(shè)置-系統(tǒng)-關(guān)于”里確認(rèn)系統(tǒng)類型是64位還是32位。然后準(zhǔn)備好一個(gè)解壓工具Windows 11和Win10 1803之后的版本自帶zip解壓能力右鍵就能解壓基本不需要額外安裝第三方工具。接下來(lái)確定安裝目錄。我習(xí)慣放在C:\mingw64這種不帶空格的短路徑。強(qiáng)調(diào)“不帶空格”是有原因的有些老舊的構(gòu)建腳本和Makefile在解析帶空格的路徑時(shí)會(huì)出錯(cuò)比如C:\Program Files\mingw64這種報(bào)錯(cuò)率很高。寧可多敲兩下鍵盤(pán)也別給后續(xù)留隱患。3.2 解壓與目錄結(jié)構(gòu)檢查把下載好的mingw64.7z或mingw64.zip離線壓縮包解壓到目標(biāo)根目錄。解壓完成后建議檢查一下目錄結(jié)構(gòu)。正常的MinGW-w64環(huán)境包解壓后根目錄下有且僅有一層前綴文件夾比如mingw64里面包含bin、lib、include、libexec、x86_64-w64-mingw32等子目錄。我遇到過(guò)一個(gè)典型問(wèn)題有人把壓縮包里的mingw64文件夾再包含一層mingw64結(jié)果路徑變成了C:\mingw64\mingw64\bin配環(huán)境變量時(shí)填錯(cuò)位置導(dǎo)致gcc命令一直找不到。解壓后第一件事看一眼bin目錄下有沒(méi)有g(shù)cc.exe、g.exe、gdb.exe這三個(gè)文件。有就說(shuō)明離線包完整沒(méi)缺東西。3.3 配置環(huán)境變量這一步是關(guān)鍵右鍵“此電腦/我的電腦” - “屬性” - “高級(jí)系統(tǒng)設(shè)置” - “環(huán)境變量”。在用戶變量或系統(tǒng)變量中找到Path變量點(diǎn)擊編輯然后新建一條填入你的bin目錄路徑例如C:\mingw64\bin。為什么優(yōu)先建議改用戶變量而不是系統(tǒng)變量因?yàn)橛脩糇兞恐挥绊懏?dāng)前登錄用戶改動(dòng)風(fēng)險(xiǎn)小不需要管理員權(quán)限而且不會(huì)干擾系統(tǒng)上其他賬戶的配置。如果你明確需要給這臺(tái)機(jī)器上的所有用戶統(tǒng)一配置那才去改系統(tǒng)變量。注意配置完環(huán)境變量不是直接生效的。已經(jīng)打開(kāi)的命令行窗口里不會(huì)讀到新的變量值要么關(guān)閉并重新打開(kāi)命令提示符要么用set PATHC:\mingw64\bin;%PATH%在當(dāng)前窗口臨時(shí)追加來(lái)測(cè)試。3.4 驗(yàn)證安裝用命令說(shuō)話配置完成后打開(kāi)一個(gè)新的命令提示符窗口輸入gcc --version如果輸出類似gcc (x86_64-posix-seh-rev1, Built by MinGW-Builds project) 13.2.0 Copyright (C) 2023 Free Software Foundation, Inc.說(shuō)明編譯器已經(jīng)正常工作了。再順手驗(yàn)證一下g --version mingw32-make --versionmingw32-make是Windows版本的make工具有些精簡(jiǎn)版離線包不一定自帶。如果提示找不到?jīng)]關(guān)系很多構(gòu)建方式比如CMake可以在不依賴make的情況下自行完成構(gòu)建實(shí)在需要再單獨(dú)補(bǔ)一個(gè)make.exe到bin目錄下即可。3.5 編寫(xiě)第一個(gè)程序跑通鏈路環(huán)境變量驗(yàn)證通過(guò)后建議寫(xiě)個(gè)Hello World把整個(gè)編譯鏈路走一遍。寫(xiě)一個(gè)hello.c#include stdio.h int main(void) { printf(Hello, MinGW-w64!\n); return 0; }在命令行執(zhí)行g(shù)cc hello.c -o hello.exe hello.exe能夠看到輸出說(shuō)明離線環(huán)境包從編譯器、鏈接器到動(dòng)態(tài)/靜態(tài)運(yùn)行庫(kù)全部工作正常。到了這一步你的MinGW-w64離線環(huán)境就算徹底落地了。4. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄4.1 “gcc不是內(nèi)部或外部命令”怎么辦執(zhí)行g(shù)cc找不到命令九成是PATH環(huán)境變量沒(méi)配對(duì)。先檢查你填進(jìn)去的路徑是否精確指向bin目錄注意目錄層級(jí)別多一層少一層。再用echo %PATH%在命令行里查看實(shí)際生效的路徑確認(rèn)之后重新開(kāi)一個(gè)cmd窗口再試。這里分享一個(gè)我常用的快速定位技巧不彈什么環(huán)境變量設(shè)置面板直接用PowerShell在當(dāng)前會(huì)話里追加路徑測(cè)試是不是路徑問(wèn)題。$env:Path C:\mingw64\bin; $env:Path gcc --version如果這個(gè)命令能成功就說(shuō)明純粹是環(huán)境變量配置或窗口沒(méi)重開(kāi)的問(wèn)題不是壓縮包壞了。4.2 編譯出來(lái)的exe運(yùn)行時(shí)缺DLL有朋友遇到過(guò)離線包裝好后能編譯但生成的exe拷到別的機(jī)器上運(yùn)行時(shí)提示缺少libgcc_s_seh-1.dll或libwinpthread-1.dll。這是典型的動(dòng)態(tài)鏈接依賴問(wèn)題——你用MinGW-w64編出來(lái)的程序運(yùn)行時(shí)需要找到對(duì)應(yīng)運(yùn)行庫(kù)文件。解決辦法有三條把MinGW-w64的bin目錄也叫上運(yùn)行時(shí)在目標(biāo)機(jī)器上也安裝完整環(huán)境包或把bin目錄里的DLL復(fù)制到exe同目錄。靜態(tài)鏈接編譯時(shí)加-static -static-libgcc -static-libstdc把GCC庫(kù)直接編進(jìn)exe里輸出文件體積會(huì)大一些但單文件就能跑發(fā)布時(shí)最省心。統(tǒng)一依賴策略如果公司內(nèi)部有多臺(tái)機(jī)制定一個(gè)規(guī)則要么全部要求安裝環(huán)境包要么統(tǒng)一用靜態(tài)鏈接避免發(fā)布后出現(xiàn)“缺這個(gè)缺那個(gè)”的問(wèn)題。4.3 離線包版本太老缺C標(biāo)準(zhǔn)支持早期版本的MinGW-w64 GCC對(duì)于C11/C14的支持不夠完善導(dǎo)致編譯含std::thread、std::filesystem等特性的代碼時(shí)失敗。如果下載的離線包是2018年甚至更早的我建議直接去更新到GCC 12或13系列的構(gòu)建版本。較新版本對(duì)C20個(gè)主流特性支持已經(jīng)很成熟std::filesystem這類庫(kù)也開(kāi)箱即用。有些項(xiàng)目為了追求“兼容性”刻意用老版本工具鏈但老版本工具鏈帶來(lái)的兼容問(wèn)題往往比解決掉的多。除非你明確知道自己要模擬老編譯器環(huán)境否則別跟自己過(guò)不去用新版。4.4 和VS Code、CLion等編輯器聯(lián)動(dòng)現(xiàn)在很多人用VS Code寫(xiě)C/C離線包裝好后還需要兩步才能舒服地F5調(diào)試。第一VS Code安裝C/C擴(kuò)展C/C extension for VS Code注意擴(kuò)展也是可以脫機(jī)安裝的code --install-extension cpptools-linux.vsix這樣指定vsix文件即可。第二在tasks.json和launch.json里指定編譯器的路徑通常就是C:\\mingw64\\bin\\g.exe以及調(diào)試器路徑C:\\mingw64\\bin\\gdb.exe。我踩過(guò)一次坑在VS Code里配了編譯器路徑但是沒(méi)重啟VS Code怎么調(diào)都找不到編譯器。做法是改完配置后完全退出重啟編輯器或者執(zhí)行“Developer: Reload Window”指令。5. 一些更省事的騷操作5.1 自制綠色便攜環(huán)境包如果你需要頻繁在不同電腦上搭開(kāi)發(fā)環(huán)境可以做一個(gè)私人定制的便攜包。具體做法是先在一臺(tái)機(jī)器上裝好MinGW-w64把所有必要的工具gcc/g/gdb/mingw32-make/CMake和依賴庫(kù)放進(jìn)同一個(gè)目錄再把整個(gè)目錄壓縮放云端或者U盤(pán)。到新機(jī)器上直接解壓配好PATH就完事。這比每次下載別人打包好的離線包更可靠因?yàn)槟愕拇a依賴什么庫(kù)自己心里最清楚別人打包的工具鏈未必覆蓋你用的所有頭文件和庫(kù)。另外如果有舊環(huán)境里曾經(jīng)編譯出好用的靜態(tài)庫(kù)直接一并打包進(jìn)去新機(jī)器上編譯項(xiàng)目時(shí)能省掉大量重新構(gòu)建的時(shí)間。5.2 內(nèi)網(wǎng)批量分發(fā)與版本統(tǒng)一團(tuán)隊(duì)開(kāi)發(fā)時(shí)最頭疼的是不同成員用的編譯器版本不統(tǒng)一導(dǎo)致“代碼寫(xiě)得對(duì)就是編不過(guò)”。說(shuō)到底編譯器的差異是玄學(xué)事故的溫床。離線包的好處在于你可以把編譯器的壓縮包和一份安裝說(shuō)明放到內(nèi)部的共享盤(pán)或Git倉(cāng)庫(kù)里所有人安裝的版本完全一致。再配合一個(gè)簡(jiǎn)單的批處理腳本一鍵完成解壓和PATH配置團(tuán)隊(duì)里連新手都能順利跑起來(lái)事故率直線下降。我把常用命令寫(xiě)成了一段簡(jiǎn)單的install.bat示例放到壓縮包同級(jí)目錄下echo off set MINGW_ROOTC:\mingw64 if exist %MINGW_ROOT%\bin\gcc.exe goto :configure echo Extracting... tar -xf mingw64.zip -C C:\ :configure setx /M PATH %MINGW_ROOT%\bin;%PATH% echo Done. Please open a new terminal.這里的setx /M是寫(xiě)系統(tǒng)變量需要管理員權(quán)限如果只想改當(dāng)前用戶把/M去掉。腳本簡(jiǎn)單粗暴但解決實(shí)際問(wèn)題。5.3 離線包不管帶不帶調(diào)試器都留一手有朋友下載的離線壓縮包體積比較小解壓后發(fā)現(xiàn)沒(méi)有g(shù)db.exe這對(duì)于命令行調(diào)試基本無(wú)損但如果你依賴IDE的斷點(diǎn)調(diào)試就有點(diǎn)痛苦。檢查GitHub上MinGW-w64的release頁(yè)面一般有多個(gè)壓縮包版本-with-gdb標(biāo)識(shí)代表附帶了GDB調(diào)試器記得選那種。如果已經(jīng)下了不帶gdb的版本也可以單獨(dú)把gdb.exe加到bin目錄里不沖突。6. 我的一些體會(huì)離線包這東西平時(shí)用不上覺(jué)得無(wú)所謂一旦碰上網(wǎng)絡(luò)受限、機(jī)房封鎖、領(lǐng)導(dǎo)突然要求三天內(nèi)給十臺(tái)機(jī)器統(tǒng)一裝好環(huán)境你就知道手里有一個(gè)驗(yàn)證過(guò)的離線包有多幸福了。我現(xiàn)在的習(xí)慣是每半年更新一次本地的MinGW-w64離線包把舊版本留一份新版本再存一份。這樣既有新特性可用又保留了舊版本應(yīng)急兜底——畢竟有些老舊項(xiàng)目真的只能在老工具鏈下編譯誰(shuí)用誰(shuí)知道。最后再根據(jù)自己的經(jīng)驗(yàn)總結(jié)幾條提醒下載離線包時(shí)優(yōu)先看文件名里的架構(gòu)、線程模型和異常模型不要見(jiàn)到x86_64一個(gè)詞就當(dāng)作萬(wàn)能包解壓后務(wù)必先編譯一個(gè)Hello World確認(rèn)鏈路通環(huán)境變量配置后一定要重新開(kāi)終端再測(cè)試如果發(fā)現(xiàn)是給整個(gè)團(tuán)隊(duì)用那就寫(xiě)個(gè)小腳本統(tǒng)一部署順手錄個(gè)兩分鐘演示視頻發(fā)群里能省掉無(wú)數(shù)個(gè)“我裝了怎么不行”的問(wèn)題。希望這份折騰過(guò)的經(jīng)驗(yàn)?zāi)茏屇闵僮唿c(diǎn)彎路。本文還有配套的精品資源點(diǎn)擊獲取