简介:MinGW for Win64 是面向 Windows 64 位平台的 GCC 编译器工具链资源,适合希望在本地编写、编译 C++ 程序的开发者与编程学习者,尤其适合不依赖大型 IDE、偏好命令行操作的人群。压缩包为 zip 格式,整体约 156.05MB,内含 TDM-GCC-64 分支,集成 64 位 GCC 工具链,支持 C++11、C++14、C++17 标准及部分 C++20 特性。资源涵盖 GCC 编译器、libstdc++ 标准库、Binutils 链接与汇编工具、Make 自动化构建工具,以及开发所需的头文件和静态、动态库,可满足从源码编译到可执行程序生成的完整流程。借助它,读者能快速搭建轻量级本地 C++ 开发环境,通过命令行理解编译与调试过程,并利用 64 位编译优势提升程序运行效率。目前已有 115 人学习下载,适合需要稳定 GCC 支持、追求轻量高效开发体验的 C++ 学习者与开发者参考使用。
1. MinGW for Win64:为什么你编译的 exe 在别人机器上跑不起来
你在自己电脑上用 MinGW for Win64 编译出一个 exe,双击运行一切正常,发给同事却弹窗报错「缺少 libgcc_s_seh-1.dll」或者「找不到 libstdc++-6.dll」。这不是代码写错了,而是 MinGW 在 Win64 下的动态链接模型和运行库分发方式没搞对。MinGW for Win64 指的是在 64 位 Windows 上使用 GCC 工具链进行原生编译的整套方案,核心产物是 PE32+ 格式的 exe 和 dll,不依赖任何中间虚拟机。它解决的是「不想装 Visual Studio、又想用 GCC 生态写 Windows 原生程序」这个需求,适合做命令行工具、嵌入式上位机、Qt 桌面应用以及需要跨平台编译的 C/C++ 项目。很多人第一次接触 MinGW 是从 mingw 官网下载开始的,但下载哪个包、选什么线程模型、怎么配 CMake,每一步都有分叉。
2. MinGW-w64 工具链选型:从 mingw 官网下载到第一次编译通过
2.1 为什么是 MinGW-w64 而不是老 MinGW
老 MinGW 项目在 64 位支持上长期停滞,MinGW-w64 是社区分叉出来专门解决 Win64 目标的工具链。它同时支持 32 位和 64 位目标,头文件覆盖更完整的 Windows API,对 SEH(结构化异常处理)和 DWARF 调试信息的支持也更靠谱。你在网上搜 mingw 下载,排在前面的基本都是 MinGW-w64 的衍生发行版,而不是原始 MinGW。选型时第一个要确认的就是目标架构:x86_64 对应 64 位 Windows,i686 对应 32 位。如果你只做 Win64,直接锁定 x86_64 即可,不要装 i686 版本,否则后面链接系统库时会遇到架构不匹配的报错。
第二个要确认的是线程模型。MinGW-w64 提供 win32 和 posix 两种线程实现。win32 线程模型直接用 Windows 原生线程 API,不依赖额外运行库,编译出的程序体积小、启动快;posix 线程模型通过一层封装提供 pthread 接口,如果你用的第三方库依赖 pthread,就必须选 posix。常见做法是:纯 Windows 原生开发选 win32,需要跨平台移植或依赖 pthread 的选 posix。这个选择在安装后不能轻易切换,装错了只能重装。
第三个是异常处理模型。64 位下只有 SEH 可用,32 位下才有 SJLJ 和 DWARF 之分。所以只要你做 Win64,异常模型基本没有选择余地,SEH 是唯一正确选项。如果你看到某个发行版在 64 位下还提供 SJLJ,那说明它的打包方式比较老,不建议用。
2.2 安装方式:安装器、压缩包与包管理器
MinGW-w64 本身不提供官方安装器,你下载到的都是第三方打包。常见的有 MSYS2 的 pacman 包管理、w64devkit 的单文件压缩包、以及 SourceForge 上的独立构建。我一般推荐两条路:一是用 MSYS2,二是用 w64devkit。MSYS2 的好处是包管理方便,后续装 CMake、Ninja、pkg-config 都是一条命令;w64devkit 的好处是解压即用,不污染系统环境,适合放在 U 盘里随身带。
用 MSYS2 安装 MinGW-w64 的命令如下:
# 更新 MSYS2 基础包 pacman -Syu # 安装 64 位 MinGW-w64 工具链 pacman -S mingw-w64-x86_64-gcc # 安装配套构建工具 pacman -S mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-make # 安装调试器 pacman -S mingw-w64-x86_64-gdb这几条命令的逻辑是:先滚动更新 MSYS2 自身,再从 mingw64 仓库拉取针对 x86_64-w64-mingw32 目标编译好的工具链。注意包名前缀mingw-w64-x86_64-不能省,它决定了你装的是 64 位目标工具链而不是 MSYS 环境下的本地工具。装完后需要把C:\msys64\mingw64\bin加入系统 PATH,而不是C:\msys64\usr\bin。这两个目录混了是新手最常见的翻车点:usr\bin下的是 MSYS 环境工具,编译出来的是依赖 msys-2.0.dll 的程序,拿到没装 MSYS2 的机器上直接跑不了。
用 w64devkit 的话更简单,下载压缩包解压到任意目录,把bin目录加入 PATH 即可。验证安装是否成功:
gcc --version g++ --version where gccwhere gcc的输出应该指向你刚加入 PATH 的那个目录。如果指向了别的路径,说明系统里存在多个 GCC,优先级冲突了,需要调整 PATH 顺序。
2.3 第一个可执行文件:编译、链接与运行库模式
装好之后先写一个最小程序验证工具链:
// hello.c #include <stdio.h> int main(void) { printf("MinGW-w64 Win64 build OK\n"); return 0; }编译命令:
# 动态链接方式,默认行为 gcc hello.c -o hello.exe # 静态链接 libgcc 和 libstdc++ gcc hello.c -o hello_static.exe -static-libgcc -static # 查看依赖的 DLL objdump -p hello.exe | findstr "DLL Name"第一条命令生成动态链接版本,exe 体积小,但依赖 libgcc_s_seh-1.dll 等运行库。第二条命令加上-static-libgcc -static后,运行库被静态编入 exe,体积变大但可以独立分发。第三条命令用 objdump 查看 PE 导入表,能直观看到这个 exe 到底依赖哪些 DLL。参数说明:-static-libgcc只静态链接 GCC 运行库,-static会尝试静态链接所有可用的库,包括 libstdc++ 和 winpthread。如果你用了 posix 线程模型又加了-static,pthread 相关代码也会被静态链入。
提示:不要用
-static去链接系统 DLL 如 kernel32、user32,这些永远走动态链接,静态链接选项对它们无效。
3. 用 CMake 驱动 MinGW for Win64:从工具链文件到可分发产物
3.1 工具链文件怎么写才不翻车
CMake 默认在 Windows 上会去找 Visual Studio 或 MSVC 的编译器,你要让它用 MinGW-w64,最干净的方式是写一个工具链文件,而不是靠命令行传一堆变量。工具链文件在CMAKE_TOOLCHAIN_FILE指定,CMake 在配置阶段最开始就会读取它。
# mingw-w64-x86_64.cmake set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_SYSTEM_PROCESSOR x86_64) # 指定交叉编译器前缀,如果是原生编译可以省略前缀 set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) # 指定目标环境根目录,防止 CMake 误用宿主机的库 set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)这个文件的逻辑是:先声明目标系统是 Windows、处理器是 x86_64,然后指定 C/C++/资源编译器。CMAKE_FIND_ROOT_PATH告诉 CMake 去哪里找目标平台的库和头文件,后面三个 MODE 变量控制查找策略——程序在宿主机找,库和头文件只在目标根目录找。如果你在 MSYS2 环境里做原生编译,编译器名可以写成gcc和g++,不需要前缀;如果你在 Linux 上交叉编译到 Win64,前缀就必须写全。
配置和构建命令:
cmake -B build -G Ninja \ -DCMAKE_TOOLCHAIN_FILE=mingw-w64-x86_64.cmake \ -DCMAKE_BUILD_TYPE=Release cmake --build build-G Ninja指定用 Ninja 作为生成器,比 MinGW Makefiles 快不少。-DCMAKE_BUILD_TYPE=Release开启优化并去掉调试符号。如果你不指定构建类型,CMake 默认是空配置,优化等级为-O0,产物性能会差很多。
3.2 让产物可分发:静态链接与 DLL 依赖收集
CMake 项目里控制静态链接,不要在每个 target 上手动加 flag,而是用全局变量或 target 属性:
# 方式一:全局设置,影响所有 target set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++") # 方式二:针对单个 target add_executable(myapp main.cpp) target_link_options(myapp PRIVATE -static-libgcc -static-libstdc++)方式一适合整个项目统一策略,方式二适合只有部分 target 需要独立分发。注意-static-libstdc++和-static的区别:前者只静态链接 C++ 标准库,后者会尝试静态链接所有库。如果你的项目依赖了第三方动态库,用-static可能导致链接失败或行为异常,这时候应该只静态链接 GCC 运行库,第三方库单独处理。
构建完成后,用objdump或ntldd检查依赖:
# 列出所有导入的 DLL objdump -p build/myapp.exe | findstr "DLL Name" # 如果有 ntldd 工具,直接看依赖树 ntldd -R build/myapp.exe如果输出里还有libgcc_s_seh-1.dll、libstdc++-6.dll、libwinpthread-1.dll,说明静态链接没生效。检查你的链接选项是否加在了正确的 target 上,以及是否被后面的选项覆盖了。CMake 里链接选项的顺序很重要,后面的会覆盖前面的同名选项。
3.3 和 MSVC 产物的互操作边界
msvc 和 mingw 区别是热搜里的高频问题。两者编译出的 C++ 产物在二进制层面不兼容:异常处理机制不同、名称修饰规则不同、标准库 ABI 不同。这意味着你不能在一个 MSVC 编译的 exe 里直接链接 MinGW 编译的 C++ 静态库,反之亦然。但纯 C 接口是可以互操作的,因为 C 没有名称修饰和异常传播问题。
如果你必须混用,常见做法是:把 MinGW 侧的功能封装成纯 C 接口的动态库,导出extern "C"函数,MSVC 侧通过LoadLibrary+GetProcAddress动态加载,或者用导入库链接。不要试图直接链接 C++ 符号,那是一条血泪之路。另外,MinGW 和 MSVC 对struct默认对齐、wchar_t大小(MinGW 默认 2 字节,MSVC 也是 2 字节,但某些编译选项下会变)的处理需要逐一确认,跨边界传递结构体时最好用固定宽度的整型和显式 packing。
4. 避坑与排查:MinGW for Win64 最常见的五类翻车
4.1 编译通过但运行报缺少 DLL
现象:exe 在开发机运行正常,复制到其他机器提示缺少libgcc_s_seh-1.dll或libstdc++-6.dll。
原因:默认动态链接 GCC 运行库,而这些 DLL 不在目标机器的 PATH 里。
解决:编译时加-static-libgcc -static-libstdc++,或者把对应的 DLL 和 exe 放在同一目录。用objdump -p确认依赖列表,逐个核对。如果用了 posix 线程模型,还要处理libwinpthread-1.dll。
4.2 PATH 里混入了 MSYS 的 usr/bin
现象:编译成功,但生成的 exe 依赖msys-2.0.dll,在没装 MSYS2 的机器上无法运行。
原因:PATH 中C:\msys64\usr\bin排在C:\msys64\mingw64\bin前面,gcc解析到了 MSYS 环境下的版本。
解决:调整 PATH 顺序,确保mingw64\bin在前。用where gcc确认实际调用的编译器路径。更彻底的做法是不要在系统 PATH 里加usr\bin,只在 MSYS2 终端里用。
4.3 CMake 找到了错误的编译器
现象:cmake -B build后生成的构建系统用的是 MSVC 或 clang,不是 MinGW-w64。
原因:没有指定工具链文件,CMake 按默认优先级选了 Visual Studio 生成器。
解决:显式传-DCMAKE_TOOLCHAIN_FILE=mingw-w64-x86_64.cmake,并且清理 build 目录重新配置。CMake 会缓存编译器路径,改工具链文件后必须删掉CMakeCache.txt或整个 build 目录。
4.4 静态链接后程序体积暴涨或链接失败
现象:加了-static后 exe 从几百 KB 变成十几 MB,或者链接阶段报未定义符号。
原因:-static会尝试静态链接所有库,包括一些只提供动态版本的第三方库,导致链接失败;体积暴涨是因为把整个 libstdc++ 和 libgcc 都链进去了。
解决:优先用-static-libgcc -static-libstdc++而不是-static。如果第三方库只有动态版本,就让它保持动态,只静态链接 GCC 运行库。体积敏感的场景可以加-Os优化体积,或者用strip去掉符号表。
4.5 调试信息格式不匹配导致 GDB 无法断点
现象:GDB 加载 exe 后能运行,但断点设不上,或者堆栈信息乱码。
原因:编译时没有加-g,或者调试信息格式和 GDB 期望的不一致。MinGW-w64 在 64 位下默认用 DWARF 调试信息,但某些发行版可能配置成了别的格式。
解决:编译时显式加-g -gdwarf-4,确保调试信息格式明确。CMake 里设置CMAKE_BUILD_TYPE=Debug或RelWithDebInfo。如果还是不行,检查 GDB 版本是否和 GCC 版本匹配,老版本 GDB 读新格式 DWARF 会出问题。
5. 进阶技巧:用 MinGW for Win64 做 Qt 与第三方库的交叉构建
5.1 Qt 项目用 MinGW 工具链的配置要点
Qt 官方为 Windows 提供的预编译包分 MSVC 和 MinGW 两个版本,你下载的 Qt 版本必须和工具链匹配。如果你用 MinGW-w64 8.1.0,就下载对应 MinGW 8.1.0 的 Qt 包,版本号对不上会在链接阶段报 ABI 不兼容。CMake 里配置 Qt 项目时,CMAKE_PREFIX_PATH指向 Qt 安装目录下的lib/cmake父目录:
cmake -B build -G Ninja \ -DCMAKE_TOOLCHAIN_FILE=mingw-w64-x86_64.cmake \ -DCMAKE_PREFIX_PATH=C:/Qt/6.5.0/mingw_64 \ -DCMAKE_BUILD_TYPE=ReleaseCMAKE_PREFIX_PATH告诉 CMake 去哪里找 Qt 的配置文件。路径里的mingw_64是 Qt 为 MinGW 64 位准备的目录,不要指向msvc2019_64。构建完成后,Qt 的 DLL 需要手动复制到 exe 同目录,或者用windeployqt工具自动收集:
windeployqt --release --no-translations build/myapp.exe--release指定收集 Release 版 DLL,--no-translations跳过翻译文件。这个命令会把 Qt 核心 DLL、平台插件、样式插件都复制到 exe 旁边,生成一个可直接分发的目录。
5.2 第三方库的交叉编译与 pkg-config 配置
很多第三方库不提供 MinGW 预编译包,需要自己编译。以 zlib 为例,用 MinGW-w64 编译静态库:
# 在 MSYS2 MINGW64 终端中 cd zlib-1.3 make -f win32/Makefile.gcc \ PREFIX=x86_64-w64-mingw32- \ BINARY_PATH=/mingw64/bin \ INCLUDE_PATH=/mingw64/include \ LIBRARY_PATH=/mingw64/lib \ install参数说明:PREFIX指定交叉编译器前缀,BINARY_PATH、INCLUDE_PATH、LIBRARY_PATH分别指定安装位置。装完后在 CMake 里用find_package(ZLIB REQUIRED)就能找到。如果库没有提供 CMake 配置文件,可以用pkg-config:
# 设置 pkg-config 搜索路径 export PKG_CONFIG_PATH=/mingw64/lib/pkgconfig:$PKG_CONFIG_PATH # 查询编译和链接选项 pkg-config --cflags --libs zlibCMake 里用PkgConfig模块:
find_package(PkgConfig REQUIRED) pkg_check_modules(ZLIB REQUIRED zlib) target_include_directories(myapp PRIVATE ${ZLIB_INCLUDE_DIRS}) target_link_libraries(myapp PRIVATE ${ZLIB_LIBRARIES})这套流程的关键是确保PKG_CONFIG_PATH指向 MinGW-w64 的 pkgconfig 目录,而不是 MSYS 的。路径混了会拿到错误的编译选项,链接阶段报架构不匹配。
5.3 验证产物可移植性的检查清单
在把 exe 发给别人之前,我习惯做三个检查。第一,用objdump -p列出所有 DLL 依赖,确认没有 MSYS 相关 DLL。第二,在一台没装 MinGW 和 MSYS2 的干净 Windows 虚拟机上双击运行,确认不报缺库。第三,如果用了 Qt,用windeployqt收集依赖后,把整个目录复制到干净机器上再测一次。这三个检查能拦住九成以上的分发翻车。
还有一个容易被忽略的点:Windows 的 UCRT 和 MSVCRT 运行库差异。MinGW-w64 可以链接到msvcrt.dll(老式)或ucrtbase.dll(现代)。如果你的目标机器是 Windows 10 及以上,建议用 UCRT 版本的工具链,对 C99/C11 的支持更完整。检查方法是在 MSYS2 里看包名,mingw-w64-x86_64-gcc默认链接 MSVCRT,mingw-w64-ucrt-x86_64-gcc链接 UCRT。两者不能混用,选定了就统一到底。
我自己的习惯是:项目一开始就锁定 UCRT + posix 线程 + SEH 异常这个组合,工具链文件里写死,CI 里用同一套环境构建。这样从开发到分发,运行库依赖始终一致,不会出现「我机器上好好的」这种玄学问题。希望帮到你。
本文还有配套的精品资源,点击获取