☰
MinGW-w64 13.1.0离线安装包:Windows C/C++编译环境搭建指南
2026/10/16 3:17:48 网站建设 项目流程

简介:MinGW 64 位最新版离线安装包面向 Windows 开发者,内置 GCC 13.1.0 稳定版,定位为软件/插件类工具资源。包体采用 x86-64 架构,基于 POSIX 线程模型,启用 SEH 结构化异常处理与 UCRT 统一 C 运行时,可在 64 位系统中直接编译原生 C/C++ 程序;离线安装方式省去联网交互,适合无稳定网络或需快速复现环境的使用场景。压缩包共 18725 个文件,约 68.89MB,除编译器、链接器与可执行程序外,还包含 2441 个头文件、957 个静态库文件、990 个 Python 脚本及 3971 个说明文档,便于查阅版本特性与库调用细节。对追求最新语言标准、需要稳定高效构建链的开发者而言,解压后即可快速搭建本地编译环境,gcc、g++ 等工具可直接调用,也可作为长期保留的离线工具链备份。目前已有 1647 人学习下载。

1. 为什么要把 MinGW-w64 13.1.0 装成离线包:一件事省掉后续所有折腾

拿到这个压缩包的人,多半之前被在线安装器折腾过。我见过不少同事,装 MinGW 装到一半网络断掉,第二天重新来过,更别提在线安装器动不动就卡在某个组件的下载进度条上。你要的不过是一个能用的 gcc/g++ 编译器,放在 Windows 上把 C/C++ 源码编译成 exe,但选择哪个版本、哪种线程模型、哪种异常处理、哪套运行时,直接决定你后面调试和发布时少踩多少坑。

这份 x86-64-13.1.0-release-posix-seh-ucrt-rt-v11-r 离线包,把 GCC 13.1.0 的 64 位工具链完整打好了。它面向的是这一类人:用 Windows 做 C/C++ 开发,想要最新编译器特性、想要标准线程支持、想要免安装直接解压即用,又不想被在线安装器反复折磨。新手能靠它把第一个程序跑起来,熟手能把它当作可靠的工具链底座,省去和网络、环境变量、运行时依赖作斗争的时间。下面从选型逻辑开始,一步步把安装、编译、排错和进阶用法都过一遍。

2. 看懂版本字符串:x86-64、posix、seh、ucrt、rt-v11 分别决定了什么

2.1 从一串字符里读出工具链的全部性格

版本字符串里的每一项都不是随手写的。x86-64指目标架构是 64 位 x86,生成的 exe 跑在 64 位 Windows 上,不能用这个工具链编出 32 位程序;13.1.0是 GCC 版本号,属于 GCC 13 系列的第一个次版本,C++23 的不少特性在这个版本里已经可用;posix是线程模型——这是最容易影响代码行为的一项;seh是异常处理模型;ucrt是 C 运行时;rt-v11-r指 runtime 版本号为 v11,对应 winpthreads 等运行时组件。把这串字符逐项拆开,你才清楚自己拿到的是怎样一套编译器。

对于大多数从 Windows 出发做 C/C++ 开发的人来说,选型最容易交学费的地方就在posix、seh、ucrt这三项。选对了,std::thread、std::mutex、结构化异常处理都能正常工作;选错了,编译出来的程序不是缺 dll 就是崩溃方式诡异。

2.2 posix 线程模型:让 std::thread 真正可用

GCC 在 Windows 上常见两种线程模型:win32和posix。win32 模型内部调用 Windows 线程 API,行为最接近纯 Windows 风格,但代价是不支持 C++11 标准线程库——你用std::thread编译会直接报错。posix 模型则基于 winpthreads 库把 POSIX 线程语义映射到 Windows 上,std::thread、std::async、std::future都能正常使用。

如果你写的是现代 C++,大量依赖标准库的并发设施,posix 模型就是刚需。即便你当前项目没用到线程,后续接第三方库时,很多库的 CMake 检测也会因为线程模型不匹配而失败。这个离线包选的就是 posix,意味着你在代码里写std::thread t([]{})不会碰壁。

2.3 seh 异常模型:64 位下的唯一合理选择

64 位 Windows 上,异常处理模型只有两个选项在实战中常见:seh和dwarf。seh 使用 Windows 原生的结构化异常处理机制,与系统深度集成,调试器能正确识别异常,混合编译、跨语言调用时兼容性更好。dwarf 是基于调试信息的异常处理,在某些嵌入式场景下有用,但在 Windows 64 位上,与系统级 API 交互时容易出现“异常无法跨模块传播”的问题。

这个包选 seh 是对的。我在 64 位环境下没见过谁因为用 seh 后悔,反而见过用 dwarf 的人折腾半天,最后发现是第三方库内部用 seh 抛异常,dwarf 模型接不住。需要明确的是,seh是 64 位下的默认事实标准,不是可选项里的妥协。

2.4 ucrt 运行时:和系统更新节奏保持一致

ucrt指 Universal C Runtime,Windows 10 及以上系统自带,安全更新跟着系统推送走。对比旧的msvcrt(老式 C 运行时,停留在上世纪),ucrt 支持完整的 C99/C11 函数,snprintf、strtoull这些函数都有正确实现。你编出来的 exe 只要运行在 Windows 10+ 上,一般不需要额外携带运行时 dll。

需要注意,如果程序要部署到 Windows 7 这类老系统上,ucrt 可能需要单独安装系统补丁,但这属于个别场景。对于主流开发目标系统,ucrt 是省心选项——不用像以前那样为运行时版本焦头烂额。

2.5 rt-v11-r 的实践含义

rt-v11-r中的 runtime 指向 winpthreads 等运行时组件的版本。不同 runtime 版本的 winpthreads 在互斥量实现、条件变量性能上有差异。v11 这个版本经过多轮迭代,稳定性是足够高的。实战中你不需要记住 v11 的具体更新日志,只需要知道这是配套打包好的运行时版本,和 GCC 13.1.0 的 posix 模型是匹配关系。

我一般建议用户直接使用发布者打包好的这个组合,不要在同一个工具链里混搭不同 runtime。混搭容易出现libwinpthread-1.dll版本号对不上、编译出的程序到别的机器上缺 dll 的连锁问题。

3. 部署与配置:把离线包变成随时可用的编译器

3.1 解压后必须完成的目录整理

离线包下载后是一个压缩文件,第一步是解压到你希望长期驻留的位置。不要解压到桌面临时文件夹,也不要解压后随意移动目录,因为后续的 PATH 配置会绑定这个路径。我之前见过有人解压到C:\Users\临时目录\Downloads\xxx,清理磁盘时顺手删掉,再写代码时 gcc 突然没反应了。

推荐结构是把解压后的根目录放在一个没有空格、没有中文的路径下。例如:

C:\mingw64\ ├── bin\ ├── include\ ├── lib\ ├── libexec\ ├── share\ └── x86_64-w64-mingw32\

为什么强调路径里别有空格和中文,因为很多 C/C++ 构建脚本(Makefile、CMake)对路径中的空格处理有历史遗留问题,哪怕现在多数工具能处理,也不值得为这点事冒险。解压完成后,先看一眼bin目录里有没有gcc.exe、g++.exe、mingw32-make.exe,这是最基本的完整性自检。

3.2 环境变量 PATH 配置:两种方式

PATH 配置有两种常见做法,推荐优先使用用户级别环境变量,避免影响到系统全局配置。从控制面板进入“高级系统设置 → 环境变量”,在用户变量里找到或新建Path,追加一行:

C:\mingw64\bin

还有一种方式是命令行里临时设置,适合不想动全局环境的场景:

set PATH=C:\mingw64\bin;%PATH%

但这条命令只对当前终端窗口生效,关掉重开就没了。所以我建议直接配用户变量,一劳永逸。配置完 PATH 后,新开的终端才会刷新变量,已经开着的终端窗口里直接输出gcc --version往往看到的还是旧内容。

验证配置是否生效:

gcc --version

正常应该看到 gcc (GCC) 13.1.0 的版本信息输出。如果提示“不是内部或外部命令”,优先检查 PATH 里追加的路径是否指向了真正的bin目录,以及是否忘记重开终端。

3.3 确认编译器自洽性

安装完第一件事,除了看版本号,还可以做一次烟雾测试,确认编译、链接、运行整条链路通畅。在任意目录新建一个文本文件:

#include <stdio.h> int main(void) { printf("mingw64 toolchain works\n"); return 0; }

编译运行:

gcc hello.c -o hello.exe hello.exe

如果控制台输出mingw64 toolchain works,说明工具链可用。这里有一个容易被忽略的细节:如果你在 Windows 自带终端里运行hello.exe,程序会正常输出;如果你在 PowerShell 里运行,可能需要加上.\hello.exe的前缀,因为 PowerShell 默认不执行当前目录下的裸命令。

4. 编译一个真实项目:多文件、Makefile 与第三方库的接入方式

4.1 从单文件到多文件项目的编译命令变化

实际项目几乎不会只有一个 C 文件。假定手头有一个模拟项目,目录结构长这样:

project_sim\ ├── main.c ├── utils.c ├── utils.h └── Makefile

单文件时代的编译命令gcc main.c -o app.exe在多文件场景下需要扩展。最笨但最直观的做法是把所有源文件一次性交给 gcc:

gcc main.c utils.c -o app.exe

这种做法的优点是简单,缺点是每次都要重新编译所有文件,项目大了以后速度没法接受。稍微好一点的思路是分开编译再链接:

gcc -c main.c -o main.o gcc -c utils.c -o utils.o gcc main.o utils.o -o app.exe

-c参数只编译不链接,产出目标文件.o,最后再统一链接。这种方式为增量编译打下基础,你在改了main.c后只要重新编译main.o、再链接即可,utils.o不用动。

4.2 用 mingw32-make 管理构建流程

mingw32-make 是 MinGW-w64 自带的 make 工具,对应原生 Linux 的 make。写一个最基础的 Makefile:

CC = gcc CFLAGS = -Wall -O2 -std=c11 OBJS = main.o utils.o TARGET = app.exe $(TARGET): $(OBJS) $(CC) $(OBJS) -o $(TARGET) main.o: main.c utils.h $(CC) $(CFLAGS) -c main.c -o main.o utils.o: utils.c utils.h $(CC) $(CFLAGS) -c utils.c -o utils.o clean: del *.o *.exe

执行:

mingw32-make

注意 Makefile 中缩进必须用 Tab 字符,不能用空格代替——这是 make 历史遗留的坑,换了空格就报 “missing separator” 错误。target一节里的命令,clean用的del是 Windows 命令,因为 mingw32-make 在 Windows 上执行的是 cmd 命令,不是 Linux 的rm。

4.3 接入第三方库:以静态库为例

假定你拿到一个第三方库libfoo.a和头文件foo.h,存放在third_party/目录下。编译时要用两个参数:-I指定头文件搜索路径,-L指定库文件搜索路径,-l指定库名。

gcc main.c -I./third_party -L./third_party -lfoo -o app.exe

-lfoo让链接器去找libfoo.a(静态库)或libfoo.dll.a(动态库的导入库)。这里最容易搞错的是库文件名前缀:Windows 上静态库常叫libfoo.a,而 Linux 上叫libfoo.a也有,但动态链接库在 MinGW 下往往是libfoo.dll.a配合foo.dll使用。如果你看到的是foo.lib这种 MSVC 风格的库文件,那是给微软编译器用的,MinGW 不能直接链接,这里的库兼容问题后面专门说。

参数位置也有讲究:-lfoo必须放在源文件或目标文件之后,链接器按从左到右的顺序解析符号依赖。把-lfoo放到main.c前面,可能报一堆 undefined reference,这是新手最容易视觉性忽略的点。

5. 避坑与常见问题排查:这些坑我前后踩了三次

5.1 现象:gcc 命令可用,但系统里存在多个 MinGW 版本

A同学因为项目需要装了两个 MinGW-w64 解压包,一个在C:\mingw64,一个在D:\tools\mingw64,PATH 里两个路径都加了。结果终端里gcc --version显示的版本忽旧忽新,编译行为不一致,某个支持 C++17 特性换一台机器就编译不过。

原因:PATH 中靠前的bin目录会被优先搜索,两个 MinGW 都被搜索到,谁在前面谁生效。

解决:保留一个就行。打开“环境变量”,把多余的那个 MinGW 的路径从 PATH 里移除。用命令行确认当前生效的 gcc 位置:

where gcc

只看到一个路径是健康的。看到多个路径,就按上面方法清理。

5.2 现象:程序在开发机跑得好好的,拷到别的 Windows 机器上提示缺 dll

这个场景太常见了。开发机上编译完 exe,打包发给同事,对方双击后报“无法启动此程序,因为计算机中丢失 libstdc++-6.dll”。查原因前先别急着骂系统,用工具看一眼 exe 依赖了什么:

objdump -p app.exe | grep "DLL Name"

如果看到libstdc++-6.dll、libgcc_s_seh-1.dll、libwinpthread-1.dll,说明你的程序依赖了 MinGW 运行时动态库。

解决:发布到没有 MinGW 环境的机器时,把这些 dll 一并拷到 exe 同目录,或者用静态链接规避。静态链接的具体做法在下一章展开,但至少要分清:开发机上程序能跑不代表依赖都在,这是 MinGW 动态运行时模式下的天然行为,不是安装包的缺陷。

5.3 现象:链接时报 undefined reference to__imp_...或一堆看不懂的符号

链接第三方库时报错信息里出现__imp_前缀,通常是动态库导入方式不匹配。__imp_前缀表示符号来自 DLL 的导入表,静态库里的符号一般不会有这个前缀。上面提到的 MSVC 生成的.lib文件给 MinGW 链接时,也会出现类似问题。

原因:MinGW 和 MSVC 的库格式不同,ABI 也不同。MSVC 的.lib是为微软链接器设计的,MinGW 的链接器不认识。更隐蔽的情况是同一个第三方库提供了 MinGW 版本和 MSVC 版本,你错拿了 MSVC 版本。

解决:优先找libfoo.dll.a或libfoo.a这种 MinGW 风格的文件。没有就自己想办法编译第三方库的源码。作为一个更省事的方案,尽量选择头文件库(header-only)或用 CMake 重新构建第三方库。

5.4 现象:std::thread 编译报错,提示 thread is not a member of std

新手常见误配之一,编译器报这个错十有八九是安装时选了 win32 线程模型,而不是 posix。选 win32 模型时,GCC 直接不提供标准 C++11 线程库的实现。

解决:本离线包是 posix 线程模型,安装这种版本就不会触发此问题。但如果之前装过别的版本,先确认当前生效版本是不是 posix。命令行执行:

gcc -v

看输出中Thread model一行,如果写着posix则正常,如果是win32,要么换到 posix 版本,要么在配置 Makefile 或 CMake 时接受只有 win32 线程 API 可用的事实。这类问题只会出现在系统里存在多个版本混用时。

5.5 现象:编译简单程序没问题,一碰 C++ 标准新特性就报语法错误

比如#include <expected>在新标准里明明该有的,编译器却说不认识。用 GCC 13.1.0 时,C++23 的新特性并非全部默认开启,需要显式指定标准版本。

解决:编译命令加参数:

g++ -std=c++20 main.cpp -o app.exe g++ -std=c++23 main.cpp -o app.exe

-std=c++23能启用大多数已在 GCC 13.1.0 中完成的 C++23 特性。注意 GNU 扩展版本-std=gnu++23会额外打开 GNU 扩展,如果你需要严格遵循标准,用-std=c++23。

6. 让编译产物更干净:静态链接与发布目录的最小化

6.1 静态链接的完整命令与取舍

上一章提到 dll 依赖的问题,这里给出可用的静态链接方案。编译时加上两个静态参数:

gcc main.c utils.c -o app.exe -static -static-libgcc -static-libstdc++

-static尽最大可能静态链接,-static-libgcc强制静态链接 libgcc,-static-libstdc++强制静态链接 C++ 标准库。需要强调的是,-static并不能保证所有依赖都变成静态,例如某些系统库仍可能动态链接,但在 MinGW-w64 场景下,这套组合足以消除libstdc++-6.dll、libgcc_s_seh-1.dll、libwinpthread-1.dll这几个最常见的外部依赖。

静态链接的代价是 exe 体积变大,一个 Hello World 可能从几十 KB 涨到 2 MB 左右。对发布到客户机器上的场景来说,用体积换稳定性是完全值得的。

6.2 验证发布目录是否自洽

静态链接完成后,再来一次依赖检查:

objdump -p app.exe | grep "DLL Name"

理想情况下只剩系统自带的KERNEL32.dll、msvcrt.dll(或ucrtbase.dll,取决于系统)这类 Windows 系统 dll。看到输出里已经没有了libwinpthread-1.dll,就可以放心地把 exe 单独拷出去跑了。这里有个容易误判的点:即使构建机上的 objdump 展示的依赖里有ucrtbase.dll,Windows 10/11 自带的 UCRT 会兜底,一般情况下不会缺。部署到 Windows 7 这种老系统时需要另外判断 UCRT 是否安装了系统补丁,但那是另一码事了。

6.3 日常开发里验证工具链完备性的习惯

最后说一个我后来养成的工作习惯。每次拿到新版本的 MinGW-w64,不管是不是这套离线包,我都会写一个故意使用并发和异常特性的最小程序来验证工具链自洽:

#include <thread> #include <iostream> int main() { std::thread t([](int x) { std::cout << "thread " << x << std::endl; }, 42); t.join(); return 0; }

编译并运行:

g++ -std=c++17 -pthread check.cpp -o check.exe check.exe

-pthread这个参数在 Linux 上需要,在部分 MinGW-w64 配置下不强制,但加上它不会出错。如果这段代码能编译、运行、正常退出,说明 posix 线程模型、运行时、异常处理都处于正常工作状态。从那以后我每次换工具链版本,都强制走一遍这套验证流程再加新项目,这十分钟省下的排查时间远比投入多。希望这篇拆解帮你在 MinGW-w64 的选型、部署和排查上少走弯路,一次把工具链立稳,后面写代码才痛快。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询