将串行 HDF5 C++ 与 CMake 结合使用

Using serial HDF5 C++ with CMake

我想在使用 CMake 构建的项目中使用 HDF5 C++ 绑定。所以我照常做:

find_package (HDF5 REQUIRED COMPONENTS CXX)
target_link_libraries(foo PUBLIC ${HDF5_LIBRARIES})
target_include_directories(foo PUBLIC ${HDF5_INCLUDE_DIRS})

这在我们的集群 (HPC) 升级之前一直有效。 现在我在 linking:

期间遇到错误
function MPI::Win::Set_name(char const*): error: undefined reference to 'MPI_Win_set_name'
function MPI::Win::Set_attr(int, void const*): error: undefined reference to 'MPI_Win_set_attr'

虽然 HDF5 的版本没有改变,但新版本似乎需要 linking 反对 CMake 不会自动告诉 me/does 的 MPI。

我错过了什么吗? CMake FindHDF5 模块是否存在缺陷,或者我是否需要在设置 HDF5_IS_PARALLEL 时手动针对 MPI link?怎么可能,我现在需要 link MY 针对 mpi 的应用程序?

我做了一些检查:

TL&DR:当 HDF_IS_PARALLEL 为真时,即使不使用它,也需要 link 对抗 MPI。
HDF5 编译器包装器调用 MPI 编译器包装器,它会自动添加该包装器,但 CMake 模块不遵循此路径。进一步阅读我如何发现可能有助于解决类似问题的内容。

我通过将调用的编译器命令隔离到最低限度找到了解决方案。使用 grep 我在 cpp 源文件的 object 文件中找到了对 MPI_* 的引用。这消除了与库 linked 相关的可能性,因此只有包含的差异是可能的。我将新旧 HDF5 包含目录与 diff -qr 进行了比较,发现它们是相同的。
确定它是 headers 我检查了预处理文件 (g++ -E)。经过一些额外的步骤后,我将新旧系统与 vimdiff 进行了比较(替换的 header 包括从旧系统更改为新系统以将混乱降至最低的路径)搜索 mpi 我发现唯一的区别是包含 mpi_cxx。这是由 mpi.h 完成的,从预处理的输出中也很容易看到。
检查两个系统上的 MPI 安装确认,新的是用 mpi_cxx 支持构建的(MPI 的 C++ 绑定在 MPI2 中添加并在 MPI3 中删除,但看起来仍然可选)和旧的没有。

由于 C headers 只有声明,源代码中没有引用,但 C++ 绑定有定义。这导致引用落在 object 文件中,后来在 linking 期间无法解析。

四处搜索,我发现 "Parallel HDF5 IO requires MPI" 但与 CMake 无关。 https://www.hdfgroup.org/HDF5/release/cmakebuild.html 对此也很少提及,没有提及 HDF5_IS_PARALLEL(他们确实提到他们不提供该查找模块)。

鉴于此,我最终添加了一个接口目标,从 hdf5 设置包含和库,检查 HDF_IS_PARALLEL 并将 mpi 包含和库添加到该目标。