1

Question fast: How do I write CMakeLists.txt to avoid HDF5 linking issue described below?

I am making a C++ project using HDF5 library(1.10.1),
which I had installed via source code file tarball and CMake.
(installed in /usr/local/)
Also I use CMake to configure build environment for my project.
(CMake 3.8.1, g++ 5.3.1 on CentOS 7)

Recently my application fails to compile due to link error.
(attached error logs below)
Found out HDF5 1.8.12 was also installed during one of my colleague had updated server and some packages.
These library files are in /usr/lib64/.
So, I think,

  • Include files are referenced from 1.10.1
  • Libraries are referenced from 1.8.12 when linking
  • Compatibility issues risen(i.e. these APIs are not defined in HDF5 1.8.12), causes link error
    (I looked up HDF5 C++ API reference, and it looks true)

So, How should I write/fix CMakeLists.txt to avoid such linking error?
i.e. how do I properly link HDF5 1.10.1 in this case?


EDIT: added more details around CMakeLists.txt
Here are some details on CMakeLists.txt of my project:

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()

and here are error logs when I execute 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

2 Answers 2

3

Using find_package implies that your code will use variables defined by it in both in include_directories and target_link_libraries.

According to FindHDF5 docs, proper usage for your case would be:

# 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.
)
Sign up to request clarification or add additional context in comments.

3 Comments

I still havn't supressed the error. :-( Just before target_link_libraries I added message(STATUS "HDF5_LIBRARIES: ${HDF5_LIBRARIES}") and nothing shows up in $HDF5_LIBRARIES position. What should I investigate?
I added more details on current CMakeLists.txt
Weird, variable HDF5_LIBRARIES is one of required for HDF5 package. The variable's emptiness should be treated by CMake as "package not found". BTW, are you sure that find_package(HDF5) has actually found the package? It should be reflected in the CMake messages during configuration.
1

The cmake "finder" for HDF5 can be influenced by the environment variable HDF5_ROOT to determine the HDF5 installation to use, in the case of multiple installations.

  1. Make a new build directory to remove any cached setting

  2. Define HDF5_ROOT

    export HDF5_ROOT=/usr/local
    

(or export HDF5_ROOT=/usr/local/hdf5-1.10.1 if HDF5 is in a subdirectory).

  1. Run cmake again

It is very important to make a new build or remove cached settings, else the setting will not be picked up.

If this does not work, I'd advise to have the /usr install of HDF removed.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.