windows中使用MSYS2作为编译链工具注意事项

一、抛弃vcpkg选择MSYS2的原因

本来,我的初衷是在项目中使用grpc和protobuf来实现不同工控机间的通信,但是新版grpc和protobuf的编译过于困难(编译时间长、依赖复杂以及github时常连接失败),让我不得不去寻找一个简便的方法使用该库。在尝试了vcpkg后,我实在受不了那龟速的下载速度以及杂乱的编译流程,便转而将目光投向了MSYS2上,在折腾了一天后,便有了这篇文章。

二、MSYS2安装使用grpc

使用下列命令安装:

# 查询包
pacman -Ss grpc

# 安装
pacman -S mingw-w64-ucrt-x86_64-grpc

关于 utrc64版本与 mingw64版本的区别(来自DeepSeek):

MSYS2 提供了多种工具链环境,其中 UCRT64MINGW64 是最常用的两种。它们的核心区别在于底层使用的 C 运行时库(C Runtime Library)目标系统兼容性 。以下是关键区别对比:


1. 运行时库(核心区别)

特性MINGW64UCRT64
C 运行时库 (CRT)传统 msvcrt.dll(旧版 Windows 兼容)现代 ucrtbase.dll(Windows 10+ 标准)
C++ 标准库libstdc++-6.dll(GCC)libstdc++-6.dll(GCC)
来源MinGW-w64 项目微软官方 Universal CRT

2. 系统兼容性

特性MINGW64UCRT64
最低 Windows 版本Windows XPWindows 10
旧系统兼容性✅ 支持旧系统(如 Win7)❌ 仅 Win10+(需手动安装 UCRT 补丁)
新系统优化基础兼容✅ 原生支持 Win10/11 新特性

3. 工具链特性

特性MINGW64UCRT64
C11/C17 标准支持部分支持(旧 CRT 限制)✅ 完整支持
Unicode 处理依赖 libiconv✅ 原生 UTF-8 支持(无转换开销)
路径分隔符/(Unix 风格)“(Windows 风格)
环境变量继承 MSYS2 环境更接近原生 Windows

4. 使用场景推荐

场景推荐工具链原因
兼容旧版 Windows✅ MINGW64无需额外运行时,支持 Win7/XP
Win10/11 开发✅ UCRT64原生支持新 API,更好的性能
跨平台项目移植✅ MINGW64路径/行为更接近 Unix,减少移植成本
依赖现代 C 特性✅ UCRT64完整支持 C11/C17 标准

5. 实际使用差异示例

编译命令对比

# MINGW64 编译(传统路径)

g++ -o app.exe app.cpp -I/mingw64/include -L/mingw64/lib

# UCRT64 编译(Windows 风格路径)

g++ -o app.exe app.cpp -IC:/msys64/ucrt64/include -LC:/msys64/ucrt64/lib

运行时依赖

  • MINGW64 程序:需 libgcc_s_seh-1.dll+ libstdc++-6.dll+ libwinpthread-1.dll
  • UCRT64 程序:需 ucrtbase.dll+ libstdc++-6.dll+ libgcc_s_seh-1.dll

总结​ 选 ​MINGW64​ 如果:

  • 需要兼容 Windows 7/8 或旧系统
  • 项目依赖传统 MinGW 库

选 ​UCRT64​ 如果:

  • 仅面向 Windows 10/11
  • 需要完整 C11/C17 支持
  • 追求更好的性能和现代 API

⚠️ ​重要提示​:避免混合使用两种环境编译的库!同一项目的所有依赖必须使用同一工具链编译,否则会出现 clock_gettime64等符号冲突错误。

三、在clion中使用MSYS2

首先添加工具链:

1758393499912

然后修改cmake的工具链,并添加cmake选项,将CMAKE_PREFIX_PATH定位到utrc所在目录:

1758393698071

做完上述步骤后就可以使用了。

注意事项

在cmake中,如果使用了find_package(gRPC REQUIRED),不要在前面再次find_package(Protobuf REQUIRED),否则会报错:

CMake Error at D:/Environment/MSYS2/ucrt64/lib/cmake/protobuf/protobuf-targets.cmake:42 (message):
  Some (but not all) targets in this export set were already defined.

  Targets Defined: protobuf::libprotobuf-lite, protobuf::libprotobuf,
  protobuf::libprotoc, protobuf::protoc

  Targets not yet defined: protobuf::libupb, protobuf::protoc-gen-upb,
  protobuf::protoc-gen-upbdefs

这是由于包重定义,导致冲突:grpc的包会自动寻找protobuf,如果在之前就包含protobuf包,会出现版本不匹配的问题。

四、在vs中使用MSYS2

vs中配置cmake项目使用MSYS2的方法是需要额外配置一个文件,具体如下:

在vs中新建一个cmake项目,结构如下:

1758394348012

要使用MSYS2,需要修改CMakePresets.json文件:

{
  "version": 3,
  "configurePresets": [
    {
      "name": "MSYS2-UCRT64-Base",
      "hidden": true,
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/out/build/${presetName}",
      "installDir": "${sourceDir}/out/install/${presetName}",
      "cacheVariables": {
        "CMAKE_C_COMPILER": "D:/Environment/MSYS2/ucrt64/bin/gcc.exe",
        "CMAKE_CXX_COMPILER": "D:/Environment/MSYS2/ucrt64/bin/g++.exe",
        "CMAKE_MAKE_PROGRAM": "D:/Environment/MSYS2/ucrt64/bin/ninja.exe",
        "CMAKE_RC_COMPILER": "D:/Environment/MSYS2/ucrt64/bin/windres.exe"
      },
      "environment": {
        "PATH": "D:/Environment/MSYS2/ucrt64/bin;%PATH%"
      },
      "condition": {
        "type": "equals",
        "lhs": "${hostSystemName}",
        "rhs": "Windows"
      }
    },
    {
      "name": "ucrt64-debug",
      "displayName": "UCRT64 Debug",
      "inherits": "MSYS2-UCRT64-Base",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Debug",
        "CMAKE_C_FLAGS": "-g",
        "CMAKE_CXX_FLAGS": "-g"
      }
    },
    {
      "name": "ucrt64-release",
      "displayName": "UCRT64 Release",
      "inherits": "MSYS2-UCRT64-Base",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release",
        "CMAKE_C_FLAGS": "-O3",
        "CMAKE_CXX_FLAGS": "-O3"
      }
    }
  ],
  "buildPresets": [
    {
      "name": "ucrt64-debug",
      "configurePreset": "ucrt64-debug",
      "displayName": "Build UCRT64 Debug"
    },
    {
      "name": "ucrt64-release",
      "configurePreset": "ucrt64-release",
      "displayName": "Build UCRT64 Release"
    }
  ]
}

然后就可以使用了。