将串行 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 一起使用的主要内容,如果未能解决你的问题,请参考以下文章
将 aws-iot-device-sdk-cpp-v2 与 CMake 一起使用
在 Visual Studio 上的 C++ 项目中将 NetCDF(通过 vcpkg 安装)与 CMake 一起使用时未解析的外部符号