MSYS2 MinGW下CMake多次运行才找到MPI库的问题求助
问题描述
在Windows 10的MSYS2 MinGW 64-bit环境中编译Elmer FEM(提交版本:8bff09ddc7a0da78b6ba17b19a9afebe2c7824d7)时,出现异常:CMake前几次运行均无法找到MPI库,但无需修改命令或环境,多次运行后最终成功。
操作步骤
git clone https://github.com/ElmerCSC/elmerfem git checkout 8bff09ddc7a0da78b6ba17b19a9afebe2c7824d7 cd elmerfem mkdir build cd build
使用的CMake命令
cmake -DMPI_C_LIBRARIES=/mingw64/lib/libmsmpi.dll.a -DMPI_CXX_LIBRARIES=/mingw64/lib/libmsmpi.dll.a -DMPI_Fortran_LIBRARIES=/mingw64/lib/libmsmpi.dll.a ..
报错现象
- 第一次运行报错:
CMake Error at cmake/Modules/FindPackageHandleStandardArgs.cmake:108 (message): Could NOT find MPI_C (missing: MPI_C_LIBRARIES)
- 第二次运行(无任何修改)报错:
CMake Error at cmake/Modules/FindPackageHandleStandardArgs.cmake:108 (message): Could NOT find MPI_CXX (missing: MPI_CXX_LIBRARIES)
- 第三次运行报错:
CMake Error at cmake/Modules/FindPackageHandleStandardArgs.cmake:108 (message): Could NOT find MPI_Fortran (missing: MPI_Fortran_LIBRARIES)
- 第四次运行无错误,成功完成配置。
每次运行都会多找到一个MPI组件(C→CXX→Fortran),直到第四次才成功。删除build目录重新操作,该现象会重复出现。
环境信息
- Windows 10
- MSYS2 MinGW 64-bit
- CMake 3.26.4
- GCC 14.1.0
- Elmer FEM 提交版本:
8bff09ddc7a0da78b6ba17b19a9afebe2c7824d7
疑问
- 该现象的原因是什么?
- 如何修改使CMake第一次运行就成功?
- 这是CMake、Elmer FEM构建系统还是我的环境配置的问题?
- Elmer FEM的FindMPI.cmake应该能自动找到
libmsmpi.dll.a,为何会失败?
解答
1. 现象原因
这是CMake的FindMPI模块多语言组件查找时的缓存机制导致的问题。首次运行CMake时,虽手动指定了各语言的MPI库路径,但FindMPI处理C组件时,可能因缓存未初始化、组件依赖顺序或MinGW环境下的路径解析延迟,无法正确识别指定库;第二次运行时C组件缓存已生成,转而在CXX组件上出现同样的缓存初始化问题;第三次处理Fortran组件,直到第四次所有组件缓存都已正确加载,才能完成全部查找。
另外,MinGW环境下libmsmpi.dll.a是导入库,FindMPI默认优先查找静态库或完整MPI工具链(含头文件、编译器包装器),仅指定库路径不足以让模块一次性完成所有组件的验证,需要多次运行逐步填充缓存。
2. 让CMake第一次运行成功的方法
有几种可行方案:
- 指定完整MPI工具链路径:除库文件外,补充指定MPI头文件目录和编译器包装器:
cmake -DMPI_C_COMPILER=/mingw64/bin/mpicc.exe -DMPI_CXX_COMPILER=/mingw64/bin/mpicxx.exe -DMPI_Fortran_COMPILER=/mingw64/bin/mpif90.exe -DMPI_C_INCLUDE_DIRS=/mingw64/include -DMPI_CXX_INCLUDE_DIRS=/mingw64/include -DMPI_Fortran_INCLUDE_DIRS=/mingw64/include -DMPI_C_LIBRARIES=/mingw64/lib/libmsmpi.dll.a -DMPI_CXX_LIBRARIES=/mingw64/lib/libmsmpi.dll.a -DMPI_Fortran_LIBRARIES=/mingw64/lib/libmsmpi.dll.a .. - 用
MPI_ROOT统一指定MPI根目录:让FindMPI自动从根目录查找所有组件:cmake -DMPI_ROOT=/mingw64 .. - 提前设置环境变量:运行CMake前,将MPI相关路径加入环境变量:
export PATH=/mingw64/bin:$PATH export CPATH=/mingw64/include:$CPATH export LIBRARY_PATH=/mingw64/lib:$LIBRARY_PATH cmake ..
3. 问题归属
这是CMake的FindMPI模块与MinGW环境交互的兼容性问题,Elmer FEM构建系统未针对MinGW环境的MPI查找做特殊优化,但核心原因是CMake缓存机制在多语言组件查找时的延迟。你的环境配置本身无错误,只是缺少让FindMPI一次性完成所有组件验证的必要信息。
4. 为何FindMPI无法自动找到libmsmpi.dll.a
FindMPI默认查找逻辑偏向OpenMPI、MPICH等标准MPI实现的目录布局,而libmsmpi.dll.a是Microsoft MPI的MinGW适配版本,未被纳入模块默认搜索优先级;此外,仅存在库文件不足以让FindMPI确认MPI可用,还需要对应头文件、编译器包装器(mpicc/mpicxx/mpif90)等配套文件,若这些文件路径未被CMake识别,模块会判定MPI未找到。
内容的提问来源于stack exchange,提问作者Foad S. Farimani

