【问题标题】:Link error due to HDF5 compatibility issue using CMake由于使用 CMake 的 HDF5 兼容性问题导致的链接错误
【发布时间】:2018-03-03 12:14:33
【问题描述】:

快速提问:如何编写 CMakeLists.txt 以避免下面描述的 HDF5 链接问题?

我正在使用 HDF5 库 (1.10.1) 制作 C++ 项目,
我通过源代码文件 tarball 和 CMake 安装的。
(安装在/usr/local/
我还使用 CMake 为我的项目配置构建环境。
(CentOS 7 上的 CMake 3.8.1、g++ 5.3.1)

最近由于链接错误,我的应用程序无法编译。
(下面附上错误日志)
发现在我的一位同事更新服务器和一些软件包期间也安装了 HDF5 1.8.12。
这些库文件位于/usr/lib64/
所以,我认为,

  • 从 1.10.1 引用的包含文件
  • 链接时从 1.8.12 引用库
  • 出现兼容性问题(即这些 API 未在 HDF5 1.8.12 中定义),导致链接错误
    (我查找了 HDF5 C++ API 参考,它看起来是真的)

那么,我应该如何编写/修复 CMakeLists.txt 以避免此类链接错误?
即在这种情况下如何正确链接 HDF5 1.10.1?


编辑: 添加了有关 CMakeLists.txt 的更多详细信息
以下是我项目的 CMakeLists.txt 的一些详细信息:

cmake_minimum_required(VERSION 3.8.1)

# Reference: https://github.com/dmonopoly/gtest-cmake-example/blob/master/CMakeLists.txt

project (adl-boilerplate)

enable_language(CXX)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost 1.64.0 COMPONENTS program_options)

option(ENABLE_HDF5 "Enable HDF5 support" ON)
if(ENABLE_HDF5)
    set(HDF5_ROOT /usr/local/hdf5/)
    find_package(HDF5 "1.10.1" REQUIRED)
    if(HDF5_FOUND)
        include_directories(${HDF5_INCLUDE_DIR})
        set(_hdf5_libs hdf5 hdf5_cpp hdf5_hl hdf5_hl_cpp)
        message(STATUS "HDF5 root: ${HDF5_ROOT}")
        message(STATUS "HDF5 version: ${HDF5_VERSION}")
        message(STATUS "HDF5 include dir: ${HDF5_INCLUDE_DIRS}")
        message(STATUS "HDF5 CXX lib: ${HDF5_LIBRARIES}")
        message(STATUS "CMake library path: " ${CMAKE_LIBRARY_PATH})
    else()
        # Download HDF5 library and define hdf5_local
        # ...
    endif()
endif()

# Get includes/srcs
file(GLOB_RECURSE adl-boilerplate_SOURCES "src/*.cpp")
file(GLOB_RECURSE adl-boilerplate_HEADERS "src/*.h")

set(adl-boilerplate_INCLUDE_DIRS "include")
include_directories(${adl-boilerplate_INCLUDE_DIRS})

if(ENABLE_HDF5)
    add_executable(
    runner
    ${adl-boilerplate_SOURCES}
    )
    target_link_libraries(
        runner
        ${_hdf5_libs}
        )
endif()

if(Boost_FOUND)
    include_directories(${Boost_INCLUDE_DIRS})
    target_link_libraries(runner ${Boost_LIBRARIES})
endif()

这是我执行make时的错误日志

[100%] Linking CXX executable runner
CMakeFiles/runner.dir/src/GociHdf5Handler.cpp.o: In function 
'CGociHdf5Handler::OpenRrs(CGociHdf5Handler::AvailableRrs)':
GociHdf5Handler.cpp:(.text+0x166b): undefined reference to 
`H5::H5Location::openDataSet(std::string const&) const'
GociHdf5Handler.cpp:(.text+0x18ad): undefined reference to 
`H5::H5Object::attrExists(std::string const&) const'
GociHdf5Handler.cpp:(.text+0x18e1): undefined reference to 
`H5::H5Object::openAttribute(std::string const&) const'
CMakeFiles/runner.dir/src/GociHdf5Handler.cpp.o: In function 
`CGociHdf5Handler::OpenFlags()':
GociHdf5Handler.cpp:(.text+0x1c72): undefined reference to 
`H5::H5Location::openDataSet(std::string const&) const'
CMakeFiles/runner.dir/src/GociHdf5Handler.cpp.o: In function 
`CGociHdf5Handler::WriteOutput(std::unique_ptr<float [], 
std::default_delete<float []> >, std::string)':
GociHdf5Handler.cpp:(.text+0x20af): undefined reference to 
`H5::H5Location::createGroup(char const*, unsigned long) const'
GociHdf5Handler.cpp:(.text+0x20cc): undefined reference to 
`H5::H5Location::createGroup(char const*, unsigned long) const'
GociHdf5Handler.cpp:(.text+0x20e9): undefined reference to 
`H5::H5Location::createGroup(char const*, unsigned long) const'
GociHdf5Handler.cpp:(.text+0x2109): undefined reference to 
`H5::H5Location::createGroup(char const*, unsigned long) const'
GociHdf5Handler.cpp:(.text+0x2179): undefined reference to 
`H5::H5Location::createDataSet(std::string const&, H5::DataType const&, 
H5::DataSpace const&, H5::DSetCreatPropList const&) const'
GociHdf5Handler.cpp:(.text+0x2229): undefined reference to 
`H5::H5Object::createAttribute(std::string const&, H5::DataType const&, 
H5::DataSpace const&, H5::PropList const&) const'
collect2: error: ld returned 1 exit status
make[2]: *** [runner] 오류 1
make[1]: *** [CMakeFiles/runner.dir/all] 오류 2
make: *** [all] 오류 2

【问题讨论】:

    标签: c++ cmake centos7 hdf5


    【解决方案1】:

    使用find_package 意味着您的代码将在include_directoriestarget_link_librariesboth 中使用由它定义的变量。

    根据FindHDF5 docs,您的情况的正确用法是:

    # Explicitely list required HDF5 components
    find_package(HDF5 COMPONENTS CXX HL)
    
    include_directories(${HDF5_INCLUDE_DIRS})
    target_link_libraries(
        runner
        ${HDF5_LIBRARIES} # This should list all libraries.
    )
    

    【讨论】:

    • 我仍然没有抑制错误。 :-( 就在target_link_libraries 之前,我添加了message(STATUS "HDF5_LIBRARIES: ${HDF5_LIBRARIES}") 并且在$HDF5_LIBRARIES 位置没有显示任何内容。我应该调查什么?
    • 我添加了有关当前 CMakeLists.txt 的更多详细信息
    • 奇怪,变量 HDF5_LIBRARIESrequired for HDF5 package 之一。 CMake 应将变量的空性视为“未找到包”。顺便说一句,你确定find_package(HDF5) 真的找到了这个包吗?它应该在配置期间反映在 CMake 消息中。
    【解决方案2】:

    HDF5 的 cmake "finder" 可以受环境变量 HDF5_ROOT 的影响来确定要使用的 HDF5 安装,在多个安装的情况下。

    1. 创建一个新的构建目录以删除所有缓存设置

    2. 定义HDF5_ROOT

      export HDF5_ROOT=/usr/local
      

    (如果 HDF5 在子目录中,则为 export HDF5_ROOT=/usr/local/hdf5-1.10.1)。

    1. 再次运行 cmake

    重新构建或删除缓存设置非常重要,否则设置将不会被拾取。

    如果这不起作用,我建议删除 HDF 的 /usr 安装。

    【讨论】:

      猜你喜欢
      • 2018-03-04
      • 1970-01-01
      • 2021-05-24
      • 2012-12-26
      • 1970-01-01
      • 2019-03-27
      • 1970-01-01
      • 1970-01-01
      • 2015-01-14
      相关资源
      最近更新 更多