将串行 HDF5 C++ 与 CMake 一起使用

Posted

技术标签:

【中文标题】将串行 HDF5 C++ 与 CMake 一起使用【英文标题】:Using serial HDF5 C++ with CMake 【发布时间】:2019-01-04 18:14:36 【问题描述】:

我想在使用 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) 升级之前一直有效。 现在我在链接过程中遇到错误:

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 的版本没有改变,但新版本似乎需要链接 MPI,而 CMake 不会告诉我/自动执行。

我错过了什么吗? CMake FindHDF5 模块是否存在缺陷,或者在设置HDF5_IS_PARALLEL 时我是否需要手动链接 MPI?我现在需要将 MY 应用程序与 mpi 关联起来,这怎么可能?

我做了一些检查:

两个 hdf5 库上的 ldd 显示 libmpi 我的应用在任一系统上都没有 -lmpi 两者均使用 HDF5 1.10.1,均针对 OpenMPI 2.1.2 和 GCC 6.4.0 构建 mpicxx -show 显示不同的输出:新的包含-lmpi_cxx,旧的没有。 h5c++ -show 似乎是一样的(当然还有其他路径)

【问题讨论】:

【参考方案1】:

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

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

由于 C 头文件只有声明,因此源代码中没有引用,但 C++ 绑定有定义。这导致引用落在目标文件中,后来在链接期间无法解析。

搜索所有我发现的是“并行 HDF5 IO 需要 MPI”,但与 CMake 无关。 https://www.hdfgroup.org/HDF5/release/cmakebuild.html 对此也很少提及,也没有提到 HDF5_IS_PARALLEL(他们确实提到他们不提供那个 find 模块)。

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

【讨论】:

以上是关于将串行 HDF5 C++ 与 CMake 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

将 CMake 与同一语言的多个编译器一起使用

将 it++ 与 cmake ( QT ) 一起使用

将 aws-iot-device-sdk-cpp-v2 与 CMake 一起使用

使用 g++ 时 HDF5 的未定义符号

在 Visual Studio 上的 C++ 项目中将 NetCDF(通过 vcpkg 安装)与 CMake 一起使用时未解析的外部符号

如何在 Visual Studio 2017、C++、CMake 中使用数据断点?