链接静态 HDF5 Fortran 库

Posted

技术标签:

【中文标题】链接静态 HDF5 Fortran 库【英文标题】:Linking Static HDF5 Fortran Library 【发布时间】:2016-05-20 02:18:43 【问题描述】:

所以我有一个小型 Fortran 库,它为 HDF5 Fortran 调用提供了一些包装器。我还有一个小测试,它调用库中定义的接口。我知道问题在于我链接 HDF5 的方式。我检查了我的 HDF5 版本(特别是 1.8.15-patch1),确保它全部正确安装到我的机器上,并且我的机器上没有替代版本。我正在使用设置为 gcc-5、g++-5 和 gfortran-5 的编译器构建这两个项目。

我正在使用 CMake 3.2.2 生成 makefile。

项目的布局是这样的:

CMakeLists.txt
test
 |_____ CMakeLists.txt
 |_____ dump_test.f90
src
 |_____ data
         |_____ CMakeLists.txt
         |_____ dump_data.f90
 |_____ <other libraries>

在主 CMakeLists.txt 中,我有

project(testlibs)

ENABLE_LANGUAGE(Fortran)

SET(HDF5_USE_STATIC_LIBRARIES ON)
find_package(HDF5 COMPONENTS C CXX Fortran REQUIRED)

SET(CMAKE_Fortran_FLAGS_DEBUG "-g -O0 -DDEBUG")

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY $CMAKE_BINARY_DIR/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY $CMAKE_BINARY_DIR/lib)
set(CMAKE_INSTALL_RPATH $CMAKE_INSTALL_PREFIX/lib)

add_subdirectory($CMAKE_CURRENT_LIST_DIR/src/data)
add_subdirectory($CMAKE_CURRENT_LIST_DIR/tests)

在数据库CMakeLists.txt中,我有

include_directories($HDF5_INCLUDE_DIRS)
add_library(dumpData STATIC $CMAKE_CURRENT_LIST_DIR/dump_data.f90)
target_link_libraries(dumpData hdf5 hdf5_fortran )
install(TARGETS dumpData DESTINATION $CMAKE_INSTALL_RPATH)

在测试CMakeLists.txt中,我有

include_directories($HDF5_INCLUDE_DIRS)
include_directories("$PROJECT_BINARY_DIR/src/data")
add_executable(dumptest EXCLUDE_FROM_ALL dump_test.f90)
target_link_libraries(dumptest dumpData)

我也看到了将库与 dl 链接的建议,但这似乎没有任何影响。

我在构建库时没有收到任何错误,但是在构建示例时,我得到了一堆未定义的引用

//usr/local/lib/libhdf5_fortran.a(H5_ff.f90.o): In function `__h5lib_MOD_h5dont_atexit_f':
H5_ff.f90:(.text+0xed): undefined reference to `h5dont_atexit_c_'
//usr/local/lib/libhdf5_fortran.a(H5_ff.f90.o): In function `__h5lib_MOD_h5garbage_collect_f':
H5_ff.f90:(.text+0x109): undefined reference to `h5garbage_collect_c_'
//usr/local/lib/libhdf5_fortran.a(H5_ff.f90.o): In function `__h5lib_MOD_h5check_version_f':
H5_ff.f90:(.text+0x143): undefined reference to `h5check_version_c_'
//usr/local/lib/libhdf5_fortran.a(H5_ff.f90.o): In function `__h5lib_MOD_h5get_libversion_f':
H5_ff.f90:(.text+0x17d): undefined reference to `h5get_libversion_c_'
//usr/local/lib/libhdf5_fortran.a(H5_ff.f90.o): In function `__h5lib_MOD_h5close_f':
H5_ff.f90:(.text+0x1cc): undefined reference to `h5close_types_c_'
//usr/local/lib/libhdf5_fortran.a(H5_ff.f90.o): In function `__h5lib_MOD_h5open_f':
H5_ff.f90:(.text+0x20a): undefined reference to `h5init_types_c_'
H5_ff.f90:(.text+0x2ba): undefined reference to `h5init_flags_c_'
H5_ff.f90:(.text+0x2d0): undefined reference to `h5init1_flags_c_'

我的 CMake 文件中是否缺少某些内容?我知道这是 HDF5 Fortran 函数无法找到底层 C 函数的问题。

【问题讨论】:

我不是 CMake 用户,但看起来您对 hdfhdf5_fortran 库的顺序错误。我很确定hdf5_fortran 应该是第一个 我最初有这个,但为了让它工作,我把它们换了。无论顺序如何,问题仍然存在。不过还是谢谢你的建议。 你想看看链接器试图做什么。看看链接是如何完成的。尝试使用/usr/bin/h5fc -noshlib ... 直接编译,看看有什么区别。 谢谢!这帮助我找到了问题。我没有链接 hdf5_f90cstub 库,这就是为什么它从 Fortran 文件中获得对 C 函数的未定义引用的原因。这将链接行更改为:target_link_libraries(dumpData hdf5_fortran hdf5_f90cstub hdf5 dl)。再次感谢! 【参考方案1】:

我正在做类似的事情,并且有相同的错误消息(请参阅下面的小摘录)。我在主文件夹中有一个 CMakeLists.txt,其中 add_subdirectory( src ) 用于构建我用于多个可执行程序的静态和共享库,add_subdirectory( apps ) 用于构建和链接可执行程序。以下是错误消息的示例:

Faults/src/HDMod.f90:90: undefined reference to `__h5global_MOD_h5f_acc_trunc_f'
Faults/src/HDMod.f90:90: undefined reference to `__h5f_MOD_h5fcreate_f'
Faults/src/HDMod.f90:90: undefined reference to `__h5global_MOD_h5f_acc_rdwr_f'
Faults/src/HDMod.f90:90: undefined reference to `__h5f_MOD_h5fopen_f'
../lib/libFaultsStatic.a(HDMod.f90.o): In function `__hdmod_MOD_hd_open':

主要的 CMakeLists.txt 有这些行(仅摘录,因为还有更多行未显示):

cmake_minimum_required (VERSION 3.12 FATAL_ERROR)
project( Faults_Project Fortran C )
set( HDF5_USE_STATIC_LIBRARIES ON )
find_package( MPI REQUIRED )
find_package( HDF5 COMPONENTS C Fortran REQUIRED )
include_directories( SYSTEM $HDF5_INCLUDE_DIRS )
set( CMAKE_Fortran_FLAGS "$CMAKE_Fortran_FLAGS $OpenMP_Fortran_FLAGS" )
add_subdirectory( src )
add_subdirectory( apps )

src 文件夹的 CmakeLists.txt 从源中生成静态库和共享库:

add_library( FaultsShared SHARED $Faults_Src_Code )
set_target_properties( FaultsShared PROPERTIES LINKER_LANGUAGE Fortran )
set_target_properties( FaultsShared PROPERTIES LINK_FLAGS "$MPI_LINK_FLAGS" )
set_target_properties( FaultsShared PROPERTIES Fortran_FORMAT "FREE" )
install( TARGETS FaultsShared RUNTIME DESTINATION ../bin/ LIBRARY DESTINATION ../lib/ ARCHIVE DESTINATION ../lib/ )

STATIC 库也是如此。然后在 apps 文件夹的 CMakeLists.txt 中:

add_executable( artsRun artsRun.f90 )
target_link_libraries( artsRun FaultsStatic $HDF5_Fortran_LIBRARIES )

对于其他可执行程序,依此类推。诀窍是将$HDF5_Fortran_LIBRARIES 包含在target_link_libraries 行中。

我只是在这里发布这个问题,因为看起来很多人都看过这个问题,并且在 3 年后没有发布任何答案。希望这可以帮助其他寻找相同事物的人。

【讨论】:

很好的解决方案。我在我的 Fortran + PETSc + HDF5 CMake 项目中使用了它,它适用于 gfortran 10

以上是关于链接静态 HDF5 Fortran 库的主要内容,如果未能解决你的问题,请参考以下文章

如何编译C/Fortran动态/静态链接库

CMake:将Fortran与静态C库链接失败

HDF5 库无法使用 -mcmodel=large 进行编译

HDF5作为Windows下的动态链接库Qt/C++

如何将静态库添加到 VS 2015 Fortran 项目?

HDF5 用于使用 fortran 编写的数据文件