1. 为什么2026年还要聊MinGW64
如果你在Windows上写过C或者C++,大概率绕不开一个东西:编译器。Visual Studio自带的MSVC当然好用,但它绑定IDE、体积大、配置重;而MinGW64这套工具链,轻量、免费、开源,配合VS Code几乎成了个人开发者和学生党的标配组合。我这些年帮人配环境没有一百次也有八十次,十次里有八次卡在MinGW64的下载和安装上——不是找不到靠谱的下载入口,就是下完了解压了却配不对环境变量,再不然就是版本选错,编译出来的程序在别人机器上跑不起来。
这篇内容就是把我自己反复踩坑之后总结出来的一套完整流程写清楚。它解决的核心问题有三个:第一,从哪里拿到干净的、没有捆绑的MinGW64发行包;第二,怎么根据自己的系统选对版本和线程模型;第三,怎么把它和命令行、编辑器正确接起来,让gcc、g++、gdb这些命令真正能用。适合刚接触C/C++的新手,也适合换了新电脑、想快速把环境搭起来的老手。整个过程不需要任何特殊网络手段,全部走公开渠道,跟着做就行。
我先把结论放前面:MinGW64本身是一个“项目”,它不直接提供安装包,真正下载的是各个发行版(distribution)。这一点是新手最大的认知误区,很多人搜“MinGW64官网”结果进了一个看起来像官网的页面,下下来的东西要么版本老旧,要么夹带私货。搞清楚“项目”和“发行版”的关系,后面就顺了。
2. 先把概念理清楚:MinGW、MinGW-w64、发行版到底啥关系
2.1 三个名字,别被绕晕
很多人第一次接触会被MinGW、MinGW-w64、MinGW64这几个词搞混。我用大白话解释一下。
MinGW是“Minimalist GNU for Windows”的缩写,最早是把GNU工具链(gcc、binutils这些)移植到Windows上的一个项目。它让Windows上也能用gcc编译程序,而且编译出来的可执行文件不依赖额外的第三方运行库,直接就是原生的Windows程序。
后来原来的MinGW项目对64位支持不好,更新也慢,社区就分出了一个分支叫MinGW-w64。这个分支同时支持32位和64位,支持更新的Windows API,维护也更活跃。所以现在大家说的“MinGW64”,绝大多数情况下指的就是MinGW-w64。
至于“发行版”,你可以这样理解:MinGW-w64是“菜谱”,而发行版是“做好的菜”。不同的团队按照这套工具链打包出可以直接下载使用的压缩包,这就是发行版。常见的发行版有MSYS2、WinLibs、LLVM-MinGW等。你下载的其实是某个发行版,而不是“MinGW-w64官网”直接给你的东西。
提示:搜索时如果看到某个页面自称“MinGW64官网”并让你下载一个exe安装器,先别急着点。真正的MinGW-w64项目页面只提供源码和构建说明,不提供一键安装包。
2.2 为什么推荐用发行版而不是自己编译
理论上你可以从源码自己编译整套工具链,但那个过程对新手极不友好:需要先有一个能用的编译器(鸡生蛋问题)、需要配置一堆依赖、编译一次动辄一两个小时。发行版就是别人帮你把这些活干完了,你解压即用。
我个人的选择顺序是这样的:追求省心就用WinLibs的独立压缩包,解压配环境变量就能用;需要包管理和更多Unix工具就用MSYS2;想尝鲜LLVM那套就用LLVM-MinGW。下面重点讲最通用的独立压缩包方案,因为它最干净、最不容易出幺蛾子。
2.3 选版本前必须搞懂的三个参数
下载页面上一堆选项,什么x86_64、i686、posix、win32、seh、sjlj、ucrt、msvcrt,新手看了直接懵。我一个个拆开讲。
架构方面,x86_64是64位,i686是32位。现在除非你有明确的32位需求,否则一律选x86_64。
线程模型方面,posix和win32二选一。如果你要用C++的std::thread、std::mutex这些标准库线程功能,必须选posix,因为win32模型对C++11线程支持不完整。这一点极其关键,选错了后面写多线程代码会直接编译报错。
异常处理模型方面,seh是64位下的首选,性能好、支持64位结构化异常;sjlj是老的、兼容性好但慢;32位下一般用dwarf或sjlj。64位就选seh,不用犹豫。
运行时库方面,ucrt是较新的通用C运行时,对应较新的Windows;msvcrt是老的。现在主流选ucrt,除非你要兼容很老的系统。
把这些组合起来,2026年最通用的选择就是:x86_64 + posix + seh + ucrt。记住这个组合,下载时直接对号入座。
3. 下载环节:认准渠道,避开捆绑陷阱
3.1 我实际用的下载渠道
前面说了,MinGW-w64项目本身不提供二进制包,所以“官网下载”这个说法本身就不太准确。我平时用的是WinLibs这个发行版,它的特点是提供单个压缩包,里面工具链齐全,更新也勤快,而且不夹带安装器。
具体操作是这样的:打开搜索引擎,搜“WinLibs MinGW-w64”,进入它的页面后找到下载区。页面上会列出很多版本,文件名一般长这样:winlibs-x86_64-posix-seh-gcc-xx.x.x-mingw-w64ucrt-xx.x.x.zip。你对照前面说的组合,找x86_64、posix、seh、ucrt的那一个就行。
注意:下载页面上通常有两个版本,一个是带LLVM/Clang的,一个是不带的。如果你只是用gcc/g++,选不带LLVM的那个,体积小很多。带LLVM的适合需要clang的场景。
3.2 怎么判断下载的东西是干净的
我踩过的坑里,最恶心的就是下到一个被二次打包、夹带了推广软件的版本。判断方法有几个:正规发行版的压缩包解压后就是一堆文件夹(bin、lib、include、share等),不会有额外的exe安装向导;文件大小通常在几百MB量级,太小可能是残缺的,太大可能夹带了别的东西;压缩包内不应该有让你“先运行某个程序”的说明。
另外,下载完成后建议核对一下文件完整性。WinLibs页面一般会给出校验值,你可以用系统自带的certutil命令算一下哈希对比。这一步很多人嫌麻烦跳过,但真遇到下载中断导致文件损坏的情况,解压报错时你会感谢自己做了校验。
certutil -hashfile 下载的文件名.zip SHA256把输出的哈希值和页面上的对比,一致就说明文件没问题。
3.3 解压位置的选择有讲究
解压到哪里,这个细节很多人不在意,但后面配环境变量时会影响到体验。我的建议是放在一个路径里没有空格、没有中文、层级不要太深的地方。比如D:\dev\mingw64这种就很好。
为什么不放C:\Program Files?因为那个路径带空格,某些老旧的构建脚本对带空格的路径处理不好,会在链接阶段报莫名其妙的错。为什么不放桌面或者“下载”文件夹?因为那些路径往往带中文用户名,同样容易出问题。路径干净这一条,能帮你省掉后面至少一半的玄学问题。
解压完成后,进去看看bin目录,里面应该有gcc.exe、g++.exe、gdb.exe、mingw32-make.exe这些。看到它们,说明解压没问题。
4. 配置环境变量:让命令行认识这些命令
4.1 环境变量到底在配什么
环境变量Path的作用,说白了就是告诉系统:“当我在命令行敲一个命令时,去哪些文件夹里找对应的可执行文件。”你不配Path,敲gcc系统就找不到,会提示“不是内部或外部命令”。
我们要做的,就是把MinGW64的bin目录加到Path里。这样系统在找gcc时,会顺藤摸瓜找到D:\dev\mingw64\bin\gcc.exe。
4.2 手把手配置步骤
在Windows搜索框输入“环境变量”,选择“编辑系统环境变量”,在弹出的窗口点“环境变量”按钮。在“系统变量”区域找到名为Path的变量,选中后点“编辑”。在新窗口点“新建”,把D:\dev\mingw64\bin这个路径粘贴进去,然后一路点确定保存。
这里有个细节:一定要加到“系统变量”而不是“用户变量”里,除非你只想当前用户能用。加到系统变量里,所有用户都能用,一劳永逸。
注意:配置完环境变量后,已经打开的终端窗口不会自动生效,必须关掉重新开一个。这个坑我见过太多人踩,配完了在旧窗口里敲命令发现没用,以为配错了,其实是没重启终端。
4.3 验证配置是否成功
重新打开一个命令行窗口,依次敲下面几条命令:
gcc --version g++ --version gdb --version mingw32-make --version如果每条都能打印出版本信息,说明配置成功。如果某一条提示找不到命令,回去检查Path里加的路径对不对,bin目录下是不是真有对应的exe。
我一般还会多敲一条where gcc,它会告诉你系统实际找到的是哪个gcc。如果你电脑上装过多个编译器(比如以前装过别的),这条命令能帮你确认当前生效的是哪一个,避免“我明明配了新的,怎么用的还是旧的”这种问题。
5. 第一个程序:从写代码到跑起来
5.1 写一个最小可运行的程序
环境配好了,得跑个东西验证一下。新建一个文件叫hello.c,内容如下:
#include <stdio.h> int main(void) { printf("Hello, MinGW64!\n"); return 0; }保存到一个你方便找的目录,比如D:\code\test。然后在命令行里cd到这个目录。
5.2 编译并运行
敲下面这条命令编译:
gcc hello.c -o hello.exe这条命令的意思是:用gcc编译hello.c,输出文件叫hello.exe。如果没有任何输出,恭喜你,编译成功。然后运行:
hello.exe屏幕上应该打印出Hello, MinGW64!。
这里解释一下-o参数,它是output的意思,指定输出文件名。不加的话gcc默认输出a.exe,也能用,但名字不好认。养成加-o的习惯。
5.3 C++的情况
如果你写的是C++,把源文件后缀改成.cpp,用g++编译:
g++ hello.cpp -o hello.exeg++和gcc的区别在于,g++会自动链接C++标准库,而gcc默认不链接。所以C++代码用g++编译,省得手动加-lstdc++。
5.4 编译参数的实际意义
新手常问-Wall、-O2、-g这些参数是干嘛的。我简单说一下我常用的几个。
-Wall打开大部分警告,能帮你发现很多潜在bug,强烈建议一直开着。-O2是二级优化,发布版本用,编译出来的程序跑得快。-g生成调试信息,配合gdb调试时用。-std=c++17指定C++标准版本,现在写C++至少用c++17。
一个我常用的编译命令长这样:
g++ -std=c++17 -Wall -O2 -g main.cpp -o main.exe开发阶段用-g方便调试,发布时去掉-g加上-O2。
6. 和编辑器配合:VS Code的配置要点
6.1 为什么命令行能跑,VS Code却报错
很多人命令行里gcc用得好好的,一进VS Code就提示找不到编译器。原因是VS Code的终端和系统终端可能不是同一个环境,或者它的C/C++插件需要单独指定编译器路径。
解决办法是在VS Code里配置c_cpp_properties.json,把compilerPath指向你的gcc.exe完整路径。这个文件在项目目录的.vscode文件夹下,没有就自己建一个。
{ "configurations": [ { "name": "Win32", "includePath": ["${workspaceFolder}/**"], "compilerPath": "D:/dev/mingw64/bin/gcc.exe", "cStandard": "c17", "cppStandard": "c++17", "intelliSenseMode": "windows-gcc-x64" } ], "version": 4 }注意路径里的反斜杠要写成正斜杠,或者用双反斜杠转义,否则JSON解析会出错。
6.2 配置构建任务
光有智能提示还不够,得能一键编译。在.vscode下建tasks.json:
{ "version": "2.0.0", "tasks": [ { "label": "build", "type": "shell", "command": "g++", "args": [ "-std=c++17", "-Wall", "-g", "${file}", "-o", "${fileDirname}/${fileBasenameNoExtension}.exe" ], "group": { "kind": "build", "isDefault": true } } ] }配好之后按Ctrl+Shift+B就能编译当前文件。${file}是当前文件路径,${fileBasenameNoExtension}是不带后缀的文件名,这些是VS Code的预定义变量。
6.3 调试配置
调试需要launch.json,关键是miDebuggerPath要指向gdb.exe:
{ "version": "0.2.0", "configurations": [ { "name": "gdb debug", "type": "cppdbg", "request": "launch", "program": "${fileDirname}/${fileBasenameNoExtension}.exe", "miDebuggerPath": "D:/dev/mingw64/bin/gdb.exe", "preLaunchTask": "build" } ] }preLaunchTask指定调试前先执行build任务,这样改了代码直接按F5就能重新编译并调试,很顺手。
7. 常见问题与排查实录
7.1 问题速查表
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 提示“不是内部或外部命令” | Path没配或没重启终端 | 检查Path,重开终端 |
| 编译报错找不到头文件 | include路径问题或版本不匹配 | 检查-I参数,确认工具链完整 |
| 链接报错undefined reference | 库没链接或线程模型选错 | 检查-l参数,确认posix模型 |
| 程序在别人机器上跑不了 | 缺运行库 | 加-static静态链接 |
| gdb无法启动 | 调试信息缺失或路径错 | 编译加-g,检查miDebuggerPath |
| 中文乱码 | 编码不一致 | 源文件存UTF-8,终端切UTF-8 |
7.2 几个我踩过的深坑
第一个坑是线程模型选错。有次帮人配环境,随手下了个win32模型的版本,结果他写std::thread死活编译不过,报一堆模板错误。折腾半天才发现是模型问题。从那以后我下载前一定先确认posix。
第二个坑是路径带空格。有个朋友把MinGW解压到C:\Program Files\mingw64,编译简单程序没事,一链接复杂库就报错。后来换到D:\mingw64就好了。带空格的路径在某些构建脚本里会被拆成两段,导致找不到文件。
第三个坑是多个编译器冲突。电脑上如果同时装了MSVC、MinGW、还有别的工具链,Path里的顺序决定了用哪个。where gcc能帮你确认。如果发现用的不是你想用的那个,调整Path顺序,把想要的放前面。
7.3 静态链接:让程序到处能跑
默认情况下,MinGW编译出来的程序依赖一些运行库DLL。如果目标机器上没有这些DLL,程序就跑不起来。解决办法是静态链接:
g++ -static -static-libgcc -static-libstdc++ main.cpp -o main.exe-static让所有库静态链接,-static-libgcc和-static-libstdc++分别针对gcc和C++标准库。这样编译出来的exe体积会大一些,但拿到任何Windows机器上都能直接跑,不用管对方装没装运行库。我做小工具分发时一律加这几个参数。
提示:静态链接不是万能的,如果程序用了系统API之外的第三方动态库,还是得把对应的DLL一起带上。静态链接只解决标准库和gcc运行时的问题。
8. 版本管理与后续维护
8.1 怎么升级到新版本
MinGW64这类工具链更新挺频繁的,新版本会支持更新的C++标准、修bug、提升优化。升级方法很简单:下载新版压缩包,解压到一个新目录,然后把环境变量指向新目录,或者直接把旧目录改名、新目录改成旧名字。
我一般保留旧版本一段时间,确认新版本没问题了再删。因为偶尔会遇到新版本引入的回归问题,留个后路。
8.2 多版本共存的技巧
如果你需要同时用多个版本(比如一个稳定版、一个尝鲜版),可以都解压到不同目录,然后通过切换Path或者用批处理脚本临时设置环境变量来切换。
写个switch-mingw.bat:
@echo off set PATH=D:\dev\mingw64-new\bin;%PATH% cmd双击这个脚本会打开一个临时用了新版本环境的命令行窗口,不影响系统全局设置。这个技巧在测试新版本时特别有用。
8.3 备份配置
环境变量、VS Code的配置文件这些,配一次挺费劲的。我习惯把.vscode文件夹里的几个json备份一份,换电脑时直接拷过去改改路径就能用。环境变量没法直接备份,但可以把配置过程记在一个文本文件里,重装系统时照着做一遍,比重新摸索快得多。
9. 一些提高效率的实操心得
编译大型项目时,mingw32-make是标配。但它的名字有点长,我一般做个别名或者直接把它复制一份改名成make.exe放在同目录,这样敲make就行。注意别和系统里其他make冲突,where make确认一下。
调试的时候,gdb的命令行界面对新手不太友好。可以配合VS Code的图形化调试,断点、单步、看变量都直观很多。但底层还是gdb在干活,所以-g参数不能省。
还有个小技巧:编译时加-ftime-report能看到各个编译阶段花了多少时间,优化编译速度时有用。加-v能看到gcc实际调用了哪些子命令,排查链接问题时很有帮助。
最后说个关于头文件路径的经验。如果你用了第三方库,头文件不在默认搜索路径里,用-I指定;库文件用-L指定路径,-l指定库名。顺序很重要,-l要放在源文件后面,否则链接器可能找不到符号。这个顺序问题坑过无数人,记住“源文件在前,库在后”。
写到这里,这套流程基本覆盖了从下载到跑通第一个程序的全过程。我自己的习惯是每换一台机器就照这个流程走一遍,熟练之后十分钟内能搞定。真正花时间的往往不是操作本身,而是遇到问题时知道往哪个方向排查。上面那些坑和技巧,都是我一次次实际踩出来的,希望能帮你少走点弯路。工具链这东西,配好一次能用很久,前期花点时间搞扎实,后面写代码就顺了。