
简介这份资源是面向 64 位 Windows 开发者的 MinGW 离线安装包集成了 GCC 13.1.0 稳定版采用 posix 线程模型与 seh 异常处理并内置 UCRT 运行时适用于需要在无网或弱网环境中搭建 C/C 编译工具链的用户。压缩包为 7z 格式共 18725 个文件包含完整的编译器、链接器、头文件、库文件及辅助工具主要文件类型包括 HTML 文档、pyc 编译文件、C/C 头文件、Python 脚本、静态库与可执行程序解压后即可获得包含 bin、lib、include 等目录的完整开发环境包体约 68.89MB。已有 1642 人学习体验适合初学者快速上手也适合跨平台或原生 64 位应用开发者作为离线工具链备用。1. MinGW 最新版离线安装包先搞懂 x86-64-13.1.0 那一串版本号再解压Windows 上配 C/C 工具链我基本只用离线版 MinGW。原因很简单团队几个人、CI 机器和临时拉起来的构建环境要的是同一个编译器版本在线安装器每次拉到的文件可能都不一样而x86-64-13.1.0-release-posix-seh-ucrt-rt-v11-r这个版本串把事情彻底定死了64 位、GCC 13.1.0、posix 线程模型、SEH 异常处理、UCRT 运行时。这份资源就是把这个版本的编译器完整打包好的离线安装包解压配好 PATH 就能用不需要在线等安装器慢慢拉文件。适合要固定工具链版本的人或者被在线安装器折腾到没脾气的开发者。这篇笔记把版本串拆开讲清楚然后过一遍安装、CMake 集成、常见坑和 Qt 共存场景。2. 离线安装与 PATH 配置为什么离线包比在线安装器更适合做工具链基线在线安装器不是不能用是做不了基线。今天装出个 GCC 12下周官网构建脚本一改拉回来就是 GCC 13 的某个 rc 版没人知道 CI 里跑的是哪一套。离线包把版本号完整写在文件名里13.1.0后面release-posix-seh-ucrt-rt-v11-r这一长串全部是有效信息。团队里传同一个压缩包所有人解压出来的编译器完全一致这才叫工具链基线。2.1 版本串拆解x86-64、13.1.0、posix、seh、ucrt 各管什么现在说的 MinGW在 64 位时代基本指 MinGW-w64 项目。这个版本串每一段都不是装饰先看总表版本字段含义选型影响x86-6464 位目标架构生成 64 位 exe/dll没有这个前缀或写 i686 的是 32 位13.1.0GCC 版本编译器本体版本决定 C/C 语言标准支持程度posix线程模型支持 std::thread、std::mutex 等 C11 并发原语seh异常处理模型64 位下性能更好栈回溯可靠ucrtC 运行时基于 Windows 通用运行时Win10 系统自带rt-v11-rMinGW-w64 runtime 版本和 GCC 13.1 配套的运行时层影响 libstdc 行为x86-64 这节最容易忽略。解压出来gcc.exe是 64 位不代表你后面链的库也是 64 位。第三方库下载时经常同时提供 i686 和 x86_64 两个目录拿错一个就是后面避坑章里那个链接崩溃问题。GCC 13.1.0 是这套工具链的编译器本体版本。GCC 13 系列默认支持-stdc20c23的部分特性也能编。如果你项目里用了 C20 的std::format、std::span那 GCC 11 以下的版本基本没戏这包直接装好就是 GCC 13.1不用再折腾升级。posix 和 win32 是 MinGW-w64 构建时的线程模型选项。posix 版在 Windows 线程之上包了一层 pthread 实现所以std::thread能映射到 pthread 语义上第三方库用std::thread编译时不报错。win32 版不提供 pthread 封装部分依赖 pthread 语义的 C 库会直接编译失败。Qt 生态里很多扩展库也更倾向 posix 版选这个组合基本是当前 64 位 Windows 下的最优解。seh 是异常处理模型。64 位下可选的是 seh 和 sjlj 两种dwarf 是 32 位专用。seh 的栈展开依赖 Windows 原生异常机制性能好调试时栈回溯也准。sjlj 兼容性广但性能差一截没特殊理由不选它。ucrt 对应运行时Win10 和 Win11 系统自带 Universal C Runtime所以这包在主流 Windows 上解压就能跑。注意一点老 Win7 系统需要先装 KB2999226 补丁才有 UCRT 文件后面避坑章会讲。2.2 解压与验证把工具链放到固定位置再配 PATH下载拿到的是 7z 压缩包解压工具有 7-Zip 或者 Bandizip 都行。我一般直接解压到C:\下但这里有个坑解压出来可能是两层目录第一层叫mingw64里面又套一层mingw64。判断标准很简单C:\mingw64\bin\gcc.exe这个路径必须真实存在如果bin不在第一层就把内层目录挪出来。# 解压完成后先看第一层目录是不是 bin ls /c/mingw64/bin | head -30 # 关键是要看到 gcc.exe、g.exe、gdb.exe、mingw32-make.exe # 缺了这几个后面 CMake 和 Qt 都没法干活版本验证这一步别省。刚解压完的编译器是最干净的状态先在这里确认版本串和包名一致回头出问题排查范围就小。cd /c/mingw64/bin ./gcc --version # 第一行应有 gcc (GCC) 13.1.0 字样 ./gcc -v # 注意看 Configured with 那行确认 --with-threadsposix、--enable-seh-exceptions、--enable-ucrt ./g --version # g 版本要和 gcc 对齐 ./mingw32-make --version # GNU Make 4.xx86_64-w64-mingw32 目标gcc -v的 Configured with 行是这个包的真实身份证明。包名写的 posix 和 seh 对不对全看这一行。如果编译出来的程序在别人机器上报异常多半是编译器配置和预期不一致。PATH 配置分临时和永久两种。先做临时验证避免一上来就把用户环境改乱# PowerShell 临时生效只对当前窗口有效 $env:Path C:\mingw64\bin; $env:Path gcc --version # 输出 GCC 13.1.0 即表示当前窗口已经命中这套工具链验证没问题再做永久配置。我用的是用户级 PATH不碰系统级避免影响系统里其他依赖旧版 PATH 的软件[Environment]::SetEnvironmentVariable( Path, C:\mingw64\bin; [Environment]::GetEnvironmentVariable(Path, User), User ) # 只写 User 级不动 Machine 级 # 新开的终端窗口才会生效已经开着的窗口需要手动重载 PATHCMD 里用setx也能配但有个隐患setx会把超过 1024 字符的 PATH 截断。机器上装了一堆软件、PATH 很长的别用这招直接sysdm.cpl图形界面改或者用上面 PowerShell 那套。配置完成后where gcc是个关键检查where gcc # 如果列出多个路径第一个才是实际生效的 gcc # 第二个是 MSYS2 的或旧版 MinGW说明 PATH 顺序没排对最后跑一个最小编译确认整条链路通了printf #include iostream\nint main(){ std::cout ok; }\n hello.cpp g hello.cpp -o hello.exe ./hello.exe # 输出 ok 说明编译器、链接器、运行时都正常这一步值得每次都做装了新环境先跑最小工程别一上来就构建大项目。2.3 多版本管理按目录隔离用 PATH 切换而不是卸载重装工具链版本切换是高频操作。一个老项目用 GCC 11 维护一个新项目要用 GCC 13把旧的卸载掉装新的下次老项目要出包又装回来不对。正确做法是不同版本放不同目录用 PATH 顺序控制生效版本。我一般这样组织目录C:\mingw64-13放这份 13.1.0C:\mingw64-11放旧版本。需要哪个版本就把哪个版本的bin放到 PATH 最前面。PowerShell 里可以写一个简单的切换函数function Use-MinGW($ver) { $env:Path C:\mingw64-$ver\bin; $env:Path gcc --version | Select-Object -First 1 } # 用法Use-MinGW 13 # 把 13 对应目录临时加到当前窗口 PATH 最前面 # 只影响当前终端其他窗口和系统设置不受影响这样不同项目开不同窗口各自用各自的编译器版本互不干扰。比装一个卸一个省心太多出问题切回去也就是一条命令的事。3. CMake 集成用 MinGW Makefiles 生成器把编译流程串起来CMake 和 MinGW 的配合第一道坎就是生成器。CMake 在 Windows 上默认会优先探测 Visual Studio装了 VS 没装 C 工具链时会出现“找到 VS 但找不到编译器”的怪现象。实际上就是 CMake 选了 VS 生成器但 VS 里没有 cl.exe自然配不出来。3.1 CMake 与 MinGW 的配合为什么生成器必须是 MinGW MakefilesMinGW 这套工具链对应的 CMake 生成器是MinGW Makefiles。这个生成器内部调用的是mingw32-make.exe也就是 GNU Make 的 Windows 移植版。注意它和 MSYS2 环境里的make不是同一个东西CMake 的 MinGW Makefiles 生成器认的是 MinGW 自带那个mingw32-make.exe。三种生成器在 Windows 下的区别如下生成器底层构建工具典型场景MinGW Makefilesmingw32-make.exeMinGW 工具链命令行构建Visual StudioMSBuild / cl.exeMSVC 工具链VS IDE 集成Ninjaninja.exe跨平台构建速度最快需单独安装如果机器上同时装了 VS 和 MinGWCMake 默认探测可能会选到 VS 生成器然后配置出一堆看似正常但实际走 MSVC 的构建文件。所以用 MinGW 编译时-G MinGW Makefiles这个参数要写成显式指定不能省。3.2 一个最小 CMake 工程从 CMakeLists 到编译全流程先给一份 CMakeLists.txt。GCC 13.1 默认的 C 标准是gnu17要拉到 C20 需要显式设置cmake_minimum_required(VERSION 3.16) project(mingw_demo CXX) add_executable(demo main.cpp) target_compile_features(demo PRIVATE cxx_std_20) # cxx_std_20 通知 CMake 这个目标需要编译器支持 C20 # GCC 13.1 支持但如果换到老版本编译器会在配置阶段直接报错 set_target_properties(demo PROPERTIES CXX_STANDARD 20 CXX_STANDARD_REQUIRED ON ) # 这是另一种写法等效于对 cxx_std_20 的 meta feature 设置 # STANDARD_REQUIRED ON 表示编译器不支持就报错而不是降级对应的main.cpp就写个能体现 C20 特性的最小代码比如用std::format#include format #include iostream int main() { std::cout std::format(GCC {} bits, sizeof(void*) * 8) std::endl; return 0; }构建命令整段如下mkdir build cd build cmake -G MinGW Makefiles -DCMAKE_BUILD_TYPERelease \ -DCMAKE_C_COMPILERgcc -DCMAKE_CXX_COMPILERg .. # -G 指定生成器为 MinGW Makefiles # -DCMAKE_BUILD_TYPERelease 对应 -O3 优化Debug 则是 -g -O0 # 手动指定 C/C 编译器防止 CMake 探测到 PATH 里其他编译器 mingw32-make -j8 # -j8 是并行编译任务数按 CPU 逻辑核数填8 核机器用 8 # 核数少就 -j4并行任务数超过核数反而拖慢 ./demo.exe # 输出 GCC 64 bits 即整条链路正常较新版本的 CMake 会自动识别 MinGW 编译器前缀但保险起见还是手动指定CMAKE_C_COMPILER和CMAKE_CXX_COMPILER。因为 PATH 里如果还有别的 gccCMake 探错了人后面就是一连串莫名其妙的链接错误。CMakeLists.txt 多起来之后用CMakePresets.json把配置固定下来更省事{ version: 3, configurePresets: [ { name: mingw, generator: MinGW Makefiles, binaryDir: ${sourceDir}/build/mingw, cacheVariables: { CMAKE_C_COMPILER: gcc, CMAKE_CXX_COMPILER: g, CMAKE_BUILD_TYPE: Release } } ] }使用方式就是cmake --preset mingw和cmake --build --preset mingw。presets 文件的优势是把生成器、编译器、构建类型一次性锁死团队其他人 clone 下来直接用同名命令构建不会再因为命令行参数抄漏了导致环境不一致。3.3 运行时 DLL 依赖与静态链接编译过了不代表 exe 能跑MinGW 动态链接出来的 exe并不是单文件可执行。objdump -p看一眼依赖就有数objdump -p demo.exe | grep DLL Name # 输出里应该能看到这三条 # libgcc_s_seh-1.dll # libstdc-6.dll # libwinpthread-1.dll # 这些 DLL 都在 C:\mingw64\bin 下把 exe 拷到别的机器上不带这三个 DLL 就跑不起来。三种解决方式目标机器装同一套 MinGW 并配置 PATH把三个 DLL 拷到 exe 同目录或者做静态链接。静态链接的做法是在 CMakeLists.txt 里追加链接选项target_link_options(demo PRIVATE -static-libgcc -static-libstdc ) # -static-libgcc把 libgcc 静态编入 exe解决 libgcc_s_seh-1.dll 依赖 # -static-libstdc同上解决 libstdc-6.dll # 注意libwinpthread-1.dll 不会因此消失pthread 的静态链接需要额外处理libwinpthread-1.dll是 posix 线程模型引入的。静态引入 pthread 要用-Wl,-Bstatic -lpthread -Wl,-Bdynamic这种组合实际项目里经常触发莫名其妙的链接顺序问题。我一般不跟 pthread 较劲直接带着C:\mingw64\bin目录一起分发省心。反正目标机器上做部署把 MinGW 的 bin 目录加进 PATH 是最不容易翻车的方案。4. 避坑记录五个最容易翻车的 MinGW 使用细节这部分全是实际操作里踩过的按现象到解决的顺序写每条都能单独对上号。4.1 解压后第一层目录是 mingw64 而不是 bin现象按C:\mingw64\bin配好了 PATH执行gcc一直提示“不是内部或外部命令”。原因解压工具把压缩包里的mingw64外层目录也解出来了实际路径变成了C:\mingw64\mingw64\bin。第一层C:\mingw64下根本没有bin。解决解压完先看一眼第一层内容是bin、include、lib这些就直接用如果第一层只有一个mingw64目录把它挪出来让bin出现在C:\mingw64第一层。判断标准就是C:\mingw64\bin\gcc.exe这个路径真实存在。4.2 编译通过运行报缺库文件现象g编译没有报错生成 exe但双击或命令行运行时提示缺少libgcc_s_seh-1.dll或ucrtbase.dll还有更老的机器上报api-ms-win-crt-runtime-l1-1-0.dll缺失。原因缺的 DLL 分两类。libgcc_s_seh-1.dll、libstdc-6.dll是 MinGW 自己的运行时库exe 动态链接了它们而运行环境没把C:\mingw64\bin加进 PATHucrtbase.dll和api-ms-win-crt-*是 Windows 系统组件Win10 以上自带老系统或者精简版系统没有。解决第一类把C:\mingw64\bin加进 PATH或者把缺失的 DLL 直接拷到 exe 同目录或者做静态链接。第二类给目标机器装系统更新补丁或者在工具链选型时改用 msvcrt 版以兼容老系统。标题这个包是 ucrt 版目标机器是 Win10/11 就不会有这问题。4.3 CMake 配置阶段报找不到编译器现象cmake ..执行后报错类似CMAKE_C_COMPILER not set但命令行里gcc --version明明正常输出。原因最常见的是没写-G MinGW MakefilesCMake 默认选了 Visual Studio 生成器然后又找不到 VS 的 cl.exe。还有一种是 PATH 里存在多个 MinGW 或 MSYS2 的 gccCMake 探测到了 MSYS2 的工具链版本或环境不兼容导致配置失败。解决命令补全写完整cmake -G MinGW Makefiles -DCMAKE_C_COMPILERgcc -DCMAKE_CXX_COMPILERg ..同时执行where gcc确认 PATH 第一个命中的就是目标工具链的 gcc。4.4 x64 编译器链了 32 位静态库现象链接时提示cannot find -lxxx或者大量未定义符号偶尔链接能过但运行时随机崩溃。原因工具链是 x86_64但从网上下依赖库时拿的是 i686 版本。静态库的位数跟编译器对不上链接器找得到名字但架构完全错位。解决拉第三方库时先确认压缩包或下载页标注的架构和工具链一致。已经下下来分不清位数的用objdump -f看库文件的 architecture 行objdump -f libfoo.a | grep architecture # i386:x86-64 是 64 位i386 是 32 位 # 发现 32 位库直接换下载源不要尝试混用4.5 异常模型不一致Debug 崩溃 Release 正常现象工程里混入用不同异常模型编译的第三方库Debug 构建偶尔崩溃Release 反而正常崩溃位置每次还不太一样。原因MinGW 的异常处理模型分 seh 和 sjlj32 位下还有 dwarf。同一个程序里出现两种模型栈展开行为不一致异常跨库边界传播时就可能踩坏栈。Debug 构建由于优化级别不同更容易暴露出这类问题。解决第三方库尽量用同一套异常模型重新编译或者下载时盯着版本串里的 seh 字段选。确认当前工具链模型的方法gcc -v 21 | grep Configured with # 看有没有 --enable-seh-exceptions # 有就是 SEH 模型包名里写的就是它5. Qt 与 MSVC 共存工具链匹配和环境变量隔离把这章单独拎出来是因为关键词里两个问题特别集中Qt 装完 MinGW 之后编译器怎么配以及同一台机器上怎么再装一套 MSVC 工具链不打架。5.1 Qt Kit 与 MinGW 版本的匹配逻辑Qt 官方在 Windows 上发布的二进制包分为 MinGW 版和 MSVC 版二者不能混用。下载 Qt 库的时候选择带mingw字样的组件比如 Qt 安装器里常见的“MinGW 13.1 64-bit”它的意思就是这个 Qt 库是用 MinGW 13.1 编译出来的。手上这份离线包的 GCC 版本是 13.1.0和 Qt 官方打包用的工具链大版本一致是最稳的组合。GCC 主版本不一致时Qt 库本身因为是官方二进制一般还能跑但你自己编译的第三方 C 库在std::string、std::vector这些类型上可能出现 ABI 不匹配运行期内存错乱很难查。Qt Creator 里的配置路径是 Tools Options Kits在 Compilers 选项卡里手动添加 C 和 C 编译器C 编译器: C:\mingw64\bin\gcc.exe C 编译器: C:\mingw64\bin\g.exe # 添加后 Qt Creator 会自动识别 ABI 为 x86_64-w64-mingw32 # ABI 识别不出来时检查 PATH 里是否混入了其他编译器CMake 构建 Qt 工程时关键参数是CMAKE_PREFIX_PATH它指向 Qt 库的安装目录cmake -G MinGW Makefiles \ -DCMAKE_PREFIX_PATHC:/Qt/6.5.2/mingw_64 \ -DCMAKE_BUILD_TYPERelease .. # 注意 Qt 路径里反斜杠写成正斜杠避免 CMake 转义问题 # CMAKE_PREFIX_PATH 是 Qt6 找 Qt6Config.cmake 的核心参数 # 路径填错时配置阶段会报 Could not find a package configuration file另外qmake 工程文件.pro构建时要确保用的是 MinGW 版 qmake路径形如C:\Qt\6.5.2\mingw_64\bin\qmake.exe。拿 MSVC 版 qmake 配 MinGW 编译器moc 生成代码会在编译阶段报错且错误信息非常迷惑指向语法层面让人误以为是源码有问题。5.2 MinGW 与 MSVC 共存两套工具链的环境隔离装了 MinGW 之后要装 MSVC 工具链正确姿势是 Visual Studio Installer 里勾选“使用 C 的桌面开发”工作负载或者单独装 Build Tools。装完之后 MSVC 的cl.exe、nmake.exe并不在系统 PATH 里需要通过开发者命令行快捷方式或vcvarsall.bat进入环境。PowerShell 下有微软官方的进入方式Import-Module C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\Tools\Microsoft.VisualStudio.DevShell.dll Enter-VsDevShell -VsInstallPath C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools -SkipAutomaticLocation # 这条命令执行后当前窗口才有 cl.exe 和 nmake.exe # VsInstallPath 按实际安装路径修改Community 版路径对应改 # 环境变量只注入当前窗口不会污染全局 PATH两套工具链共存的要点就是彻底理解 MSVC 的环境进入方式是“窗口级注入”而 MinGW 是“全局 PATH”。二者不是同一个机制不会互相覆盖。编译产物层面也要彻底分开对比项MinGWMSVC编译器入口gcc.exe / g.execl.exe构建工具mingw32-make.exenmake.exe / MSBuild目标文件格式.o.obj调试信息DWARFPDB依赖查看objdump -pdumpbin /dependents所以同一个工程不要试图在一个 build 目录里来回切换工具链。CMake 的 cache 一旦用 MinGW 配置过换成 MSVC 时要么删掉整个 build 目录要么用 CMake 的--fresh参数重新配置。我习惯直接建build-mingw和build-msvc两个目录互不干扰切换成本为零。6. 验证工具链的三条命令版本串、DLL 依赖与实际生效路径工具链装好之后的验证我固定跑三条命令一分钟搞定信息量够用。第一条看编译器身份gcc -v 21 | grep Configured with # 输出里找 --with-threadsposix、--enable-seh-exceptions、--enable-ucrt # 三个参数和包名 x86-64-13.1.0-release-posix-seh-ucrt 一一对应 # 对不上说明 PATH 里生效的不是这份包继续查 where gcc第二条看运行时依赖objdump -p demo.exe | grep DLL Name # 期望是 kernel32.dll、ucrtbase.dll 以及自己项目里的 dll # 如果混入 libgcc_s_seh-1.dll 说明还是动态链接 # 如果需要单文件分发再处理静态链接参数第三条确认 PATH 优先级where gcc where g where mingw32-make # 三条命令的第一项结果必须指向同一个 C:\mingw64\bin # 任何一个指向别的目录说明环境变量顺序有问题这三条命令看起来简单但覆盖了两个最隐蔽的问题PATH 里同时存在多套工具链时实际生效的是哪个以及 exe 的运行时依赖是否和预期一致。换编译器版本时我习惯新建目录而不是覆盖旧的。C:\mingw64-13放 13.1.0旧版本留在C:\mingw64-11切版本就是改一次 PATH 的事。需要两个版本同时用就在不同窗口分别配各自的 PATH。命令行里要精确调用某个版本时用绝对路径最干净C:\mingw64-13\bin\g.exe。从那以后我每次新装工具链或者接手别人的机器都先花一分钟跑完这三条命令确认版本串和 DLL 依赖没有意外再往下走。希望帮到你。本文还有配套的精品资源点击获取