我想在带有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不会自动告诉我/这样做。
我错过了什么吗?设置HDF5_IS_PARALLEL
时,CMake FindHDF5模块是否有缺陷?是否需要我手动链接到MPI?我现在怎么可能需要将 MY 应用程序链接到MPI?
我做了一些检查:
-lmpi
mpicxx -show
显示了不同的输出:新的包含-lmpi_cxx
,旧的不包含。h5c++ -show
似乎是相同的(当然还有其他一些路径)答案 0 :(得分:0)
TL&DR:当HDF_IS_PARALLEL
为true时,即使不使用MPI,也需要链接到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中删除了MPI,但看起来仍然可选),而旧版本则没有。
由于C头仅具有声明,因此引用不位于源中,但是C ++绑定具有定义。这导致引用降落在目标文件中,并且以后在链接期间无法解析。
我发现的所有内容都是“并行HDF5 IO需要MPI”,但与CMake无关。 https://www.hdfgroup.org/HDF5/release/cmakebuild.html对此也很稀疏,没有提到HDF5_IS_PARALLEL
(他们确实提到他们没有提供该find模块)。
鉴于此,我最终添加了一个接口目标,从hdf5设置了包含和库,检查HDF_IS_PARALLEL
并将mpi包含和库添加到该目标。