CMake/Modules/FindHDF5.cmake

870 lines
35 KiB
CMake

# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#.rst:
# FindHDF5
# --------
#
# Find HDF5, a library for reading and writing self describing array data.
#
#
#
# This module invokes the HDF5 wrapper compiler that should be installed
# alongside HDF5. Depending upon the HDF5 Configuration, the wrapper
# compiler is called either h5cc or h5pcc. If this succeeds, the module
# will then call the compiler with the -show argument to see what flags
# are used when compiling an HDF5 client application.
#
# The module will optionally accept the COMPONENTS argument. If no
# COMPONENTS are specified, then the find module will default to finding
# only the HDF5 C library. If one or more COMPONENTS are specified, the
# module will attempt to find the language bindings for the specified
# components. The only valid components are C, CXX, Fortran, HL, and
# Fortran_HL. If the COMPONENTS argument is not given, the module will
# attempt to find only the C bindings.
#
# On UNIX systems, this module will read the variable
# HDF5_USE_STATIC_LIBRARIES to determine whether or not to prefer a
# static link to a dynamic link for HDF5 and all of it's dependencies.
# To use this feature, make sure that the HDF5_USE_STATIC_LIBRARIES
# variable is set before the call to find_package.
#
# To provide the module with a hint about where to find your HDF5
# installation, you can set the environment variable HDF5_ROOT. The
# Find module will then look in this path when searching for HDF5
# executables, paths, and libraries.
#
# Both the serial and parallel HDF5 wrappers are considered and the first
# directory to contain either one will be used. In the event that both appear
# in the same directory the serial version is preferentially selected. This
# behavior can be reversed by setting the variable HDF5_PREFER_PARALLEL to
# true.
#
# In addition to finding the includes and libraries required to compile
# an HDF5 client application, this module also makes an effort to find
# tools that come with the HDF5 distribution that may be useful for
# regression testing.
#
# This module will define the following variables:
#
# ::
#
# HDF5_FOUND - true if HDF5 was found on the system
# HDF5_VERSION - HDF5 version in format Major.Minor.Release
# HDF5_INCLUDE_DIRS - Location of the hdf5 includes
# HDF5_INCLUDE_DIR - Location of the hdf5 includes (deprecated)
# HDF5_DEFINITIONS - Required compiler definitions for HDF5
# HDF5_LIBRARIES - Required libraries for all requested bindings
# HDF5_HL_LIBRARIES - Required libraries for the HDF5 high level API for all
# bindings, if the HL component is enabled
#
# Available components are: C CXX Fortran and HL. For each enabled language
# binding, a corresponding HDF5_${LANG}_LIBRARIES variable, and potentially
# HDF5_${LANG}_DEFINITIONS, will be defined.
# If the HL component is enabled, then an HDF5_${LANG}_HL_LIBRARIES will
# also be defined. With all components enabled, the following variables will be defined:
#
# ::
#
# HDF5_C_DEFINITIONS -- Required compiler definitions for HDF5 C bindings
# HDF5_CXX_DEFINITIONS -- Required compiler definitions for HDF5 C++ bindings
# HDF5_Fortran_DEFINITIONS -- Required compiler definitions for HDF5 Fortran bindings
# HDF5_C_INCLUDE_DIRS -- Required include directories for HDF5 C bindings
# HDF5_CXX_INCLUDE_DIRS -- Required include directories for HDF5 C++ bindings
# HDF5_Fortran_INCLUDE_DIRS -- Required include directories for HDF5 Fortran bindings
# HDF5_C_LIBRARIES - Required libraries for the HDF5 C bindings
# HDF5_CXX_LIBRARIES - Required libraries for the HDF5 C++ bindings
# HDF5_Fortran_LIBRARIES - Required libraries for the HDF5 Fortran bindings
# HDF5_C_HL_LIBRARIES - Required libraries for the high level C bindings
# HDF5_CXX_HL_LIBRARIES - Required libraries for the high level C++ bindings
# HDF5_Fortran_HL_LIBRARIES - Required libraries for the high level Fortran
# bindings.
#
# HDF5_IS_PARALLEL - Whether or not HDF5 was found with parallel IO support
# HDF5_C_COMPILER_EXECUTABLE - the path to the HDF5 C wrapper compiler
# HDF5_CXX_COMPILER_EXECUTABLE - the path to the HDF5 C++ wrapper compiler
# HDF5_Fortran_COMPILER_EXECUTABLE - the path to the HDF5 Fortran wrapper compiler
# HDF5_C_COMPILER_EXECUTABLE_NO_INTERROGATE - path to the primary C compiler
# which is also the HDF5 wrapper
# HDF5_CXX_COMPILER_EXECUTABLE_NO_INTERROGATE - path to the primary C++
# compiler which is also
# the HDF5 wrapper
# HDF5_Fortran_COMPILER_EXECUTABLE_NO_INTERROGATE - path to the primary
# Fortran compiler which
# is also the HDF5 wrapper
# HDF5_DIFF_EXECUTABLE - the path to the HDF5 dataset comparison tool
#
# The following variable can be set to guide the search for HDF5 libraries and includes:
#
# ``HDF5_ROOT``
# Specify the path to the HDF5 installation to use.
#
# ``HDF5_FIND_DEBUG``
# Set to a true value to get some extra debugging output.
#
# ``HDF5_NO_FIND_PACKAGE_CONFIG_FILE``
# Set to a true value to skip trying to find ``hdf5-config.cmake``.
# This module is maintained by Will Dicharry <wdicharry@stellarscience.com>.
include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
# List of the valid HDF5 components
set(HDF5_VALID_LANGUAGE_BINDINGS C CXX Fortran)
# Validate the list of find components.
if(NOT HDF5_FIND_COMPONENTS)
set(HDF5_LANGUAGE_BINDINGS "C")
else()
set(HDF5_LANGUAGE_BINDINGS)
# add the extra specified components, ensuring that they are valid.
set(FIND_HL OFF)
foreach(component IN LISTS HDF5_FIND_COMPONENTS)
list(FIND HDF5_VALID_LANGUAGE_BINDINGS ${component} component_location)
if(NOT component_location EQUAL -1)
list(APPEND HDF5_LANGUAGE_BINDINGS ${component})
elseif(component STREQUAL "HL")
set(FIND_HL ON)
elseif(component STREQUAL "Fortran_HL") # only for compatibility
list(APPEND HDF5_LANGUAGE_BINDINGS Fortran)
set(FIND_HL ON)
set(HDF5_FIND_REQUIRED_Fortran_HL False)
set(HDF5_FIND_REQUIRED_Fortran True)
set(HDF5_FIND_REQUIRED_HL True)
else()
message(FATAL_ERROR "${component} is not a valid HDF5 component.")
endif()
endforeach()
if(NOT HDF5_LANGUAGE_BINDINGS)
get_property(__langs GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach(__lang IN LISTS __langs)
if(__lang MATCHES "^(C|CXX|Fortran)$")
list(APPEND HDF5_LANGUAGE_BINDINGS ${__lang})
endif()
endforeach()
endif()
list(REMOVE_ITEM HDF5_FIND_COMPONENTS Fortran_HL) # replaced by Fortran and HL
list(REMOVE_DUPLICATES HDF5_LANGUAGE_BINDINGS)
endif()
# Determine whether to search for serial or parallel executable first
if(HDF5_PREFER_PARALLEL)
set(HDF5_C_COMPILER_NAMES h5pcc h5cc)
set(HDF5_CXX_COMPILER_NAMES h5pc++ h5c++)
set(HDF5_Fortran_COMPILER_NAMES h5pfc h5fc)
else()
set(HDF5_C_COMPILER_NAMES h5cc h5pcc)
set(HDF5_CXX_COMPILER_NAMES h5c++ h5pc++)
set(HDF5_Fortran_COMPILER_NAMES h5fc h5pfc)
endif()
# We may have picked up some duplicates in various lists during the above
# process for the language bindings (both the C and C++ bindings depend on
# libz for example). Remove the duplicates. It appears that the default
# CMake behavior is to remove duplicates from the end of a list. However,
# for link lines, this is incorrect since unresolved symbols are searched
# for down the link line. Therefore, we reverse the list, remove the
# duplicates, and then reverse it again to get the duplicates removed from
# the beginning.
macro(_HDF5_remove_duplicates_from_beginning _list_name)
if(${_list_name})
list(REVERSE ${_list_name})
list(REMOVE_DUPLICATES ${_list_name})
list(REVERSE ${_list_name})
endif()
endmacro()
# Test first if the current compilers automatically wrap HDF5
function(_HDF5_test_regular_compiler_C success version is_parallel)
set(scratch_directory
${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hdf5)
if(NOT ${success} OR
NOT EXISTS ${scratch_directory}/compiler_has_h5_c)
set(test_file ${scratch_directory}/cmake_hdf5_test.c)
file(WRITE ${test_file}
"#include <hdf5.h>\n"
"#include <hdf5_hl.h>\n"
"int main(void) {\n"
" char const* info_ver = \"INFO\" \":\" H5_VERSION;\n"
" hid_t fid;\n"
" fid = H5Fcreate(\"foo.h5\",H5F_ACC_TRUNC,H5P_DEFAULT,H5P_DEFAULT);\n"
" return 0;\n"
"}")
try_compile(${success} ${scratch_directory} ${test_file}
COPY_FILE ${scratch_directory}/compiler_has_h5_c
)
endif()
if(${success})
file(STRINGS ${scratch_directory}/compiler_has_h5_c INFO_VER
REGEX "^INFO:([0-9]+\\.[0-9]+\\.[0-9]+)(-patch([0-9]+))?"
)
string(REGEX MATCH "^INFO:([0-9]+\\.[0-9]+\\.[0-9]+)(-patch([0-9]+))?"
INFO_VER "${INFO_VER}"
)
set(${version} ${CMAKE_MATCH_1})
if(CMAKE_MATCH_3)
set(${version} ${HDF5_CXX_VERSION}.${CMAKE_MATCH_3})
endif()
set(${version} ${${version}} PARENT_SCOPE)
execute_process(COMMAND ${CMAKE_C_COMPILER} -showconfig
OUTPUT_VARIABLE config_output
ERROR_VARIABLE config_error
RESULT_VARIABLE config_result
)
if(config_output MATCHES "Parallel HDF5: yes")
set(${is_parallel} TRUE PARENT_SCOPE)
else()
set(${is_parallel} FALSE PARENT_SCOPE)
endif()
endif()
endfunction()
function(_HDF5_test_regular_compiler_CXX success version is_parallel)
set(scratch_directory ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hdf5)
if(NOT ${success} OR
NOT EXISTS ${scratch_directory}/compiler_has_h5_cxx)
set(test_file ${scratch_directory}/cmake_hdf5_test.cxx)
file(WRITE ${test_file}
"#include <H5Cpp.h>\n"
"#ifndef H5_NO_NAMESPACE\n"
"using namespace H5;\n"
"#endif\n"
"int main(int argc, char **argv) {\n"
" char const* info_ver = \"INFO\" \":\" H5_VERSION;\n"
" H5File file(\"foo.h5\", H5F_ACC_TRUNC);\n"
" return 0;\n"
"}")
try_compile(${success} ${scratch_directory} ${test_file}
COPY_FILE ${scratch_directory}/compiler_has_h5_cxx
)
endif()
if(${success})
file(STRINGS ${scratch_directory}/compiler_has_h5_cxx INFO_VER
REGEX "^INFO:([0-9]+\\.[0-9]+\\.[0-9]+)(-patch([0-9]+))?"
)
string(REGEX MATCH "^INFO:([0-9]+\\.[0-9]+\\.[0-9]+)(-patch([0-9]+))?"
INFO_VER "${INFO_VER}"
)
set(${version} ${CMAKE_MATCH_1})
if(CMAKE_MATCH_3)
set(${version} ${HDF5_CXX_VERSION}.${CMAKE_MATCH_3})
endif()
set(${version} ${${version}} PARENT_SCOPE)
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -showconfig
OUTPUT_VARIABLE config_output
ERROR_VARIABLE config_error
RESULT_VARIABLE config_result
)
if(config_output MATCHES "Parallel HDF5: yes")
set(${is_parallel} TRUE PARENT_SCOPE)
else()
set(${is_parallel} FALSE PARENT_SCOPE)
endif()
endif()
endfunction()
function(_HDF5_test_regular_compiler_Fortran success is_parallel)
if(NOT ${success})
set(scratch_directory
${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hdf5)
set(test_file ${scratch_directory}/cmake_hdf5_test.f90)
file(WRITE ${test_file}
"program hdf5_hello\n"
" use hdf5\n"
" use h5lt\n"
" use h5ds\n"
" integer error\n"
" call h5open_f(error)\n"
" call h5close_f(error)\n"
"end\n")
try_compile(${success} ${scratch_directory} ${test_file})
if(${success})
execute_process(COMMAND ${CMAKE_Fortran_COMPILER} -showconfig
OUTPUT_VARIABLE config_output
ERROR_VARIABLE config_error
RESULT_VARIABLE config_result
)
if(config_output MATCHES "Parallel HDF5: yes")
set(${is_parallel} TRUE PARENT_SCOPE)
else()
set(${is_parallel} FALSE PARENT_SCOPE)
endif()
endif()
endif()
endfunction()
# Invoke the HDF5 wrapper compiler. The compiler return value is stored to the
# return_value argument, the text output is stored to the output variable.
macro( _HDF5_invoke_compiler language output return_value version is_parallel)
set(${version})
if(HDF5_USE_STATIC_LIBRARIES)
set(lib_type_args -noshlib)
else()
set(lib_type_args -shlib)
endif()
set(scratch_dir ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hdf5)
if("${language}" STREQUAL "C")
set(test_file ${scratch_dir}/cmake_hdf5_test.c)
elseif("${language}" STREQUAL "CXX")
set(test_file ${scratch_dir}/cmake_hdf5_test.cxx)
elseif("${language}" STREQUAL "Fortran")
set(test_file ${scratch_dir}/cmake_hdf5_test.f90)
endif()
exec_program( ${HDF5_${language}_COMPILER_EXECUTABLE}
ARGS -show ${lib_type_args} ${test_file}
OUTPUT_VARIABLE ${output}
RETURN_VALUE ${return_value}
)
if(NOT ${${return_value}} EQUAL 0)
message(STATUS
"Unable to determine HDF5 ${language} flags from HDF5 wrapper.")
endif()
exec_program( ${HDF5_${language}_COMPILER_EXECUTABLE}
ARGS -showconfig
OUTPUT_VARIABLE config_output
RETURN_VALUE config_return
)
if(NOT ${return_value} EQUAL 0)
message( STATUS
"Unable to determine HDF5 ${language} version from HDF5 wrapper.")
endif()
string(REGEX MATCH "HDF5 Version: ([a-zA-Z0-9\\.\\-]*)" version_match "${config_output}")
if(version_match)
string(REPLACE "HDF5 Version: " "" ${version} "${version_match}")
string(REPLACE "-patch" "." ${version} "${${version}}")
endif()
if(config_output MATCHES "Parallel HDF5: yes")
set(${is_parallel} TRUE)
else()
set(${is_parallel} FALSE)
endif()
endmacro()
# Parse a compile line for definitions, includes, library paths, and libraries.
macro( _HDF5_parse_compile_line
compile_line_var
include_paths
definitions
library_paths
libraries
libraries_hl)
if(UNIX)
separate_arguments(_HDF5_COMPILE_ARGS UNIX_COMMAND "${${compile_line_var}}")
else()
separate_arguments(_HDF5_COMPILE_ARGS WINDOWS_COMMAND "${${compile_line_var}}")
endif()
foreach(arg IN LISTS _HDF5_COMPILE_ARGS)
if("${arg}" MATCHES "^-I(.*)$")
# include directory
list(APPEND ${include_paths} "${CMAKE_MATCH_1}")
elseif("${arg}" MATCHES "^-D(.*)$")
# compile definition
list(APPEND ${definitions} "-D${CMAKE_MATCH_1}")
elseif("${arg}" MATCHES "^-L(.*)$")
# library search path
list(APPEND ${library_paths} "${CMAKE_MATCH_1}")
elseif("${arg}" MATCHES "^-l(hdf5.*hl.*)$")
# library name (hl)
list(APPEND ${libraries_hl} "${CMAKE_MATCH_1}")
elseif("${arg}" MATCHES "^-l(.*)$")
# library name
list(APPEND ${libraries} "${CMAKE_MATCH_1}")
elseif("${arg}" MATCHES "^(.:)?[/\\].*\\.(a|so|dylib|sl|lib)$")
# library file
if(NOT EXISTS "${arg}")
continue()
endif()
get_filename_component(_HDF5_LPATH "${arg}" DIRECTORY)
get_filename_component(_HDF5_LNAME "${arg}" NAME_WE)
string(REGEX REPLACE "^lib" "" _HDF5_LNAME "${_HDF5_LNAME}")
list(APPEND ${library_paths} "${_HDF5_LPATH}")
if(_HDF5_LNAME MATCHES "hdf5.*hl")
list(APPEND ${libraries_hl} "${_HDF5_LNAME}")
else()
list(APPEND ${libraries} "${_HDF5_LNAME}")
endif()
endif()
endforeach()
endmacro()
if(NOT HDF5_ROOT)
set(HDF5_ROOT $ENV{HDF5_ROOT})
endif()
if(HDF5_ROOT)
set(_HDF5_SEARCH_OPTS NO_DEFAULT_PATH)
else()
set(_HDF5_SEARCH_OPTS)
endif()
# Try to find HDF5 using an installed hdf5-config.cmake
if(NOT HDF5_FOUND AND NOT HDF5_NO_FIND_PACKAGE_CONFIG_FILE)
find_package(HDF5 QUIET NO_MODULE
HINTS ${HDF5_ROOT}
${_HDF5_SEARCH_OPTS}
)
if( HDF5_FOUND)
if(HDF5_FIND_DEBUG)
message(STATUS "Found HDF5 at ${HDF5_DIR} via NO_MODULE. Now trying to extract locations etc.")
endif()
set(HDF5_IS_PARALLEL ${HDF5_ENABLE_PARALLEL})
set(HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIR})
set(HDF5_LIBRARIES)
if (NOT TARGET hdf5 AND NOT TARGET hdf5-static AND NOT TARGET hdf5-shared)
# Some HDF5 versions (e.g. 1.8.18) used hdf5::hdf5 etc
set(_target_prefix "hdf5::")
endif()
set(HDF5_C_TARGET ${_target_prefix}hdf5)
set(HDF5_C_HL_TARGET ${_target_prefix}hdf5_hl)
set(HDF5_CXX_TARGET ${_target_prefix}hdf5_cpp)
set(HDF5_CXX_HL_TARGET ${_target_prefix}hdf5_hl_cpp)
set(HDF5_Fortran_TARGET ${_target_prefix}hdf5_fortran)
set(HDF5_Fortran_HL_TARGET ${_target_prefix}hdf5_hl_fortran)
set(HDF5_DEFINITIONS "")
if(HDF5_USE_STATIC_LIBRARIES)
set(_suffix "-static")
else()
set(_suffix "-shared")
endif()
foreach(_lang ${HDF5_LANGUAGE_BINDINGS})
#Older versions of hdf5 don't have a static/shared suffix so
#if we detect that occurrence clear the suffix
if(_suffix AND NOT TARGET ${HDF5_${_lang}_TARGET}${_suffix})
if(NOT TARGET ${HDF5_${_lang}_TARGET})
#cant find this component with or without the suffix
#so bail out, and let the following locate HDF5
set(HDF5_FOUND FALSE)
break()
endif()
set(_suffix "")
endif()
if(HDF5_FIND_DEBUG)
message(STATUS "Trying to get properties of target ${HDF5_${_lang}_TARGET}${_suffix}")
endif()
# Find library for this target. Complicated as on Windows with a DLL, we need to search for the import-lib.
get_target_property(_imported_conf ${HDF5_${_lang}_TARGET}${_suffix} IMPORTED_CONFIGURATIONS)
get_target_property(_lang_location ${HDF5_${_lang}_TARGET}${_suffix} IMPORTED_IMPLIB_${_imported_conf} )
if (NOT _lang_location)
# no import lib, just try LOCATION
get_target_property(_lang_location ${HDF5_${_lang}_TARGET}${_suffix} LOCATION)
endif()
if( _lang_location )
set(HDF5_${_lang}_LIBRARY ${_lang_location})
list(APPEND HDF5_LIBRARIES ${HDF5_${_lang}_TARGET}${_suffix})
set(HDF5_${_lang}_LIBRARIES ${HDF5_${_lang}_TARGET}${_suffix})
set(HDF5_${_lang}_FOUND True)
endif()
if(FIND_HL)
get_target_property(__lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} IMPORTED_IMPLIB_${_imported_conf} )
if (NOT _lang_hl_location)
get_target_property(_lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} LOCATION)
endif()
if( _lang_hl_location )
set(HDF5_${_lang}_HL_LIBRARY ${_lang_hl_location})
list(APPEND HDF5_HL_LIBRARIES ${HDF5_${_lang}_TARGET}${_suffix})
set(HDF5_${_lang}_HL_LIBRARIES ${HDF5_${_lang}_TARGET}${_suffix})
set(HDF5_HL_FOUND True)
endif()
endif()
endforeach()
endif()
endif()
if(NOT HDF5_FOUND)
set(_HDF5_NEED_TO_SEARCH False)
set(HDF5_COMPILER_NO_INTERROGATE True)
# Only search for languages we've enabled
foreach(__lang IN LISTS HDF5_LANGUAGE_BINDINGS)
# First check to see if our regular compiler is one of wrappers
if(__lang STREQUAL "C")
_HDF5_test_regular_compiler_C(
HDF5_${__lang}_COMPILER_NO_INTERROGATE
HDF5_${__lang}_VERSION
HDF5_${__lang}_IS_PARALLEL)
elseif(__lang STREQUAL "CXX")
_HDF5_test_regular_compiler_CXX(
HDF5_${__lang}_COMPILER_NO_INTERROGATE
HDF5_${__lang}_VERSION
HDF5_${__lang}_IS_PARALLEL)
elseif(__lang STREQUAL "Fortran")
_HDF5_test_regular_compiler_Fortran(
HDF5_${__lang}_COMPILER_NO_INTERROGATE
HDF5_${__lang}_IS_PARALLEL)
else()
continue()
endif()
if(HDF5_${__lang}_COMPILER_NO_INTERROGATE)
message(STATUS "HDF5: Using hdf5 compiler wrapper for all ${__lang} compiling")
set(HDF5_${__lang}_FOUND True)
set(HDF5_${__lang}_COMPILER_EXECUTABLE_NO_INTERROGATE
"${CMAKE_${__lang}_COMPILER}"
CACHE FILEPATH "HDF5 ${__lang} compiler wrapper")
set(HDF5_${__lang}_DEFINITIONS)
set(HDF5_${__lang}_INCLUDE_DIRS)
set(HDF5_${__lang}_LIBRARIES)
set(HDF5_${__lang}_HL_LIBRARIES)
mark_as_advanced(HDF5_${__lang}_COMPILER_EXECUTABLE_NO_INTERROGATE)
set(HDF5_${__lang}_FOUND True)
set(HDF5_HL_FOUND True)
else()
set(HDF5_COMPILER_NO_INTERROGATE False)
# If this language isn't using the wrapper, then try to seed the
# search options with the wrapper
find_program(HDF5_${__lang}_COMPILER_EXECUTABLE
NAMES ${HDF5_${__lang}_COMPILER_NAMES} NAMES_PER_DIR
HINTS ${HDF5_ROOT}
PATH_SUFFIXES bin Bin
DOC "HDF5 ${__lang} Wrapper compiler. Used only to detect HDF5 compile flags."
${_HDF5_SEARCH_OPTS}
)
mark_as_advanced( HDF5_${__lang}_COMPILER_EXECUTABLE )
unset(HDF5_${__lang}_COMPILER_NAMES)
if(HDF5_${__lang}_COMPILER_EXECUTABLE)
_HDF5_invoke_compiler(${__lang} HDF5_${__lang}_COMPILE_LINE
HDF5_${__lang}_RETURN_VALUE HDF5_${__lang}_VERSION HDF5_${__lang}_IS_PARALLEL)
if(HDF5_${__lang}_RETURN_VALUE EQUAL 0)
message(STATUS "HDF5: Using hdf5 compiler wrapper to determine ${__lang} configuration")
_HDF5_parse_compile_line( HDF5_${__lang}_COMPILE_LINE
HDF5_${__lang}_INCLUDE_DIRS
HDF5_${__lang}_DEFINITIONS
HDF5_${__lang}_LIBRARY_DIRS
HDF5_${__lang}_LIBRARY_NAMES
HDF5_${__lang}_HL_LIBRARY_NAMES
)
set(HDF5_${__lang}_LIBRARIES)
foreach(L IN LISTS HDF5_${__lang}_LIBRARY_NAMES)
set(_HDF5_SEARCH_NAMES_LOCAL)
if("x${L}" MATCHES "hdf5")
# hdf5 library
set(_HDF5_SEARCH_OPTS_LOCAL ${_HDF5_SEARCH_OPTS})
if(UNIX AND HDF5_USE_STATIC_LIBRARIES)
set(_HDF5_SEARCH_NAMES_LOCAL lib${L}.a)
endif()
else()
# external library
set(_HDF5_SEARCH_OPTS_LOCAL)
endif()
find_library(HDF5_${__lang}_LIBRARY_${L}
NAMES ${_HDF5_SEARCH_NAMES_LOCAL} ${L} NAMES_PER_DIR
HINTS ${HDF5_${__lang}_LIBRARY_DIRS}
${HDF5_ROOT}
${_HDF5_SEARCH_OPTS_LOCAL}
)
unset(_HDF5_SEARCH_OPTS_LOCAL)
unset(_HDF5_SEARCH_NAMES_LOCAL)
if(HDF5_${__lang}_LIBRARY_${L})
list(APPEND HDF5_${__lang}_LIBRARIES ${HDF5_${__lang}_LIBRARY_${L}})
else()
list(APPEND HDF5_${__lang}_LIBRARIES ${L})
endif()
endforeach()
if(FIND_HL)
set(HDF5_${__lang}_HL_LIBRARIES)
foreach(L IN LISTS HDF5_${__lang}_HL_LIBRARY_NAMES)
set(_HDF5_SEARCH_NAMES_LOCAL)
if("x${L}" MATCHES "hdf5")
# hdf5 library
set(_HDF5_SEARCH_OPTS_LOCAL ${_HDF5_SEARCH_OPTS})
if(UNIX AND HDF5_USE_STATIC_LIBRARIES)
set(_HDF5_SEARCH_NAMES_LOCAL lib${L}.a)
endif()
else()
# external library
set(_HDF5_SEARCH_OPTS_LOCAL)
endif()
find_library(HDF5_${__lang}_LIBRARY_${L}
NAMES ${_HDF5_SEARCH_NAMES_LOCAL} ${L} NAMES_PER_DIR
HINTS ${HDF5_${__lang}_LIBRARY_DIRS}
${HDF5_ROOT}
${_HDF5_SEARCH_OPTS_LOCAL}
)
unset(_HDF5_SEARCH_OPTS_LOCAL)
unset(_HDF5_SEARCH_NAMES_LOCAL)
if(HDF5_${__lang}_LIBRARY_${L})
list(APPEND HDF5_${__lang}_HL_LIBRARIES ${HDF5_${__lang}_LIBRARY_${L}})
else()
list(APPEND HDF5_${__lang}_HL_LIBRARIES ${L})
endif()
endforeach()
set(HDF5_HL_FOUND True)
endif()
set(HDF5_${__lang}_FOUND True)
_HDF5_remove_duplicates_from_beginning(HDF5_${__lang}_DEFINITIONS)
_HDF5_remove_duplicates_from_beginning(HDF5_${__lang}_INCLUDE_DIRS)
_HDF5_remove_duplicates_from_beginning(HDF5_${__lang}_LIBRARIES)
_HDF5_remove_duplicates_from_beginning(HDF5_${__lang}_HL_LIBRARIES)
else()
set(_HDF5_NEED_TO_SEARCH True)
endif()
else()
set(_HDF5_NEED_TO_SEARCH True)
endif()
endif()
if(HDF5_${__lang}_VERSION)
if(NOT HDF5_VERSION)
set(HDF5_VERSION ${HDF5_${__lang}_VERSION})
elseif(NOT HDF5_VERSION VERSION_EQUAL HDF5_${__lang}_VERSION)
message(WARNING "HDF5 Version found for language ${__lang}, ${HDF5_${__lang}_VERSION} is different than previously found version ${HDF5_VERSION}")
endif()
endif()
if(DEFINED HDF5_${__lang}_IS_PARALLEL)
if(NOT DEFINED HDF5_IS_PARALLEL)
set(HDF5_IS_PARALLEL ${HDF5_${__lang}_IS_PARALLEL})
elseif(NOT HDF5_IS_PARALLEL AND HDF5_${__lang}_IS_PARALLEL)
message(WARNING "HDF5 found for language ${__lang} is parallel but previously found language is not parallel.")
elseif(HDF5_IS_PARALLEL AND NOT HDF5_${__lang}_IS_PARALLEL)
message(WARNING "HDF5 found for language ${__lang} is not parallel but previously found language is parallel.")
endif()
endif()
endforeach()
else()
set(_HDF5_NEED_TO_SEARCH True)
endif()
if(NOT HDF5_FOUND AND HDF5_COMPILER_NO_INTERROGATE)
# No arguments necessary, all languages can use the compiler wrappers
set(HDF5_FOUND True)
set(HDF5_METHOD "Included by compiler wrappers")
set(HDF5_REQUIRED_VARS HDF5_METHOD)
elseif(NOT HDF5_FOUND AND NOT _HDF5_NEED_TO_SEARCH)
# Compiler wrappers aren't being used by the build but were found and used
# to determine necessary include and library flags
set(HDF5_INCLUDE_DIRS)
set(HDF5_LIBRARIES)
set(HDF5_HL_LIBRARIES)
foreach(__lang IN LISTS HDF5_LANGUAGE_BINDINGS)
if(HDF5_${__lang}_FOUND)
if(NOT HDF5_${__lang}_COMPILER_NO_INTERROGATE)
list(APPEND HDF5_DEFINITIONS ${HDF5_${__lang}_DEFINITIONS})
list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${__lang}_INCLUDE_DIRS})
list(APPEND HDF5_LIBRARIES ${HDF5_${__lang}_LIBRARIES})
if(FIND_HL)
list(APPEND HDF5_HL_LIBRARIES ${HDF5_${__lang}_HL_LIBRARIES})
endif()
endif()
endif()
endforeach()
_HDF5_remove_duplicates_from_beginning(HDF5_DEFINITIONS)
_HDF5_remove_duplicates_from_beginning(HDF5_INCLUDE_DIRS)
_HDF5_remove_duplicates_from_beginning(HDF5_LIBRARIES)
_HDF5_remove_duplicates_from_beginning(HDF5_HL_LIBRARIES)
set(HDF5_FOUND True)
set(HDF5_REQUIRED_VARS HDF5_LIBRARIES)
if(FIND_HL)
list(APPEND HDF5_REQUIRED_VARS HDF5_HL_LIBRARIES)
endif()
endif()
find_program( HDF5_DIFF_EXECUTABLE
NAMES h5diff
HINTS ${HDF5_ROOT}
PATH_SUFFIXES bin Bin
${_HDF5_SEARCH_OPTS}
DOC "HDF5 file differencing tool." )
mark_as_advanced( HDF5_DIFF_EXECUTABLE )
if( NOT HDF5_FOUND )
# seed the initial lists of libraries to find with items we know we need
set(HDF5_C_LIBRARY_NAMES hdf5)
set(HDF5_C_HL_LIBRARY_NAMES hdf5_hl)
set(HDF5_CXX_LIBRARY_NAMES hdf5_cpp ${HDF5_C_LIBRARY_NAMES})
set(HDF5_CXX_HL_LIBRARY_NAMES hdf5_hl_cpp ${HDF5_C_HL_LIBRARY_NAMES} ${HDF5_CXX_LIBRARY_NAMES})
set(HDF5_Fortran_LIBRARY_NAMES hdf5_fortran ${HDF5_C_LIBRARY_NAMES})
set(HDF5_Fortran_HL_LIBRARY_NAMES hdf5hl_fortran ${HDF5_C_HL_LIBRARY_NAMES} ${HDF5_Fortran_LIBRARY_NAMES})
foreach(__lang IN LISTS HDF5_LANGUAGE_BINDINGS)
# find the HDF5 include directories
if("${__lang}" STREQUAL "Fortran")
set(HDF5_INCLUDE_FILENAME hdf5.mod)
elseif("${__lang}" STREQUAL "CXX")
set(HDF5_INCLUDE_FILENAME H5Cpp.h)
else()
set(HDF5_INCLUDE_FILENAME hdf5.h)
endif()
find_path(HDF5_${__lang}_INCLUDE_DIR ${HDF5_INCLUDE_FILENAME}
HINTS ${HDF5_ROOT}
PATHS $ENV{HOME}/.local/include
PATH_SUFFIXES include Include
${_HDF5_SEARCH_OPTS}
)
mark_as_advanced(HDF5_${__lang}_INCLUDE_DIR)
# set the _DIRS variable as this is what the user will normally use
set(HDF5_${__lang}_INCLUDE_DIRS ${HDF5_${__lang}_INCLUDE_DIR})
list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${__lang}_INCLUDE_DIR})
# find the HDF5 libraries
foreach(LIB IN LISTS HDF5_${__lang}_LIBRARY_NAMES)
if(UNIX AND HDF5_USE_STATIC_LIBRARIES)
# According to bug 1643 on the CMake bug tracker, this is the
# preferred method for searching for a static library.
# See https://gitlab.kitware.com/cmake/cmake/issues/1643. We search
# first for the full static library name, but fall back to a
# generic search on the name if the static search fails.
set( THIS_LIBRARY_SEARCH_DEBUG
lib${LIB}d.a lib${LIB}_debug.a ${LIB}d ${LIB}_debug
lib${LIB}d-static.a lib${LIB}_debug-static.a ${LIB}d-static ${LIB}_debug-static )
set( THIS_LIBRARY_SEARCH_RELEASE lib${LIB}.a ${LIB} lib${LIB}-static.a ${LIB}-static)
else()
set( THIS_LIBRARY_SEARCH_DEBUG ${LIB}d ${LIB}_debug ${LIB}d-shared ${LIB}_debug-shared)
set( THIS_LIBRARY_SEARCH_RELEASE ${LIB} ${LIB}-shared)
endif()
find_library(HDF5_${LIB}_LIBRARY_DEBUG
NAMES ${THIS_LIBRARY_SEARCH_DEBUG}
HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib
${_HDF5_SEARCH_OPTS}
)
find_library( HDF5_${LIB}_LIBRARY_RELEASE
NAMES ${THIS_LIBRARY_SEARCH_RELEASE}
HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib
${_HDF5_SEARCH_OPTS}
)
select_library_configurations( HDF5_${LIB} )
list(APPEND HDF5_${__lang}_LIBRARIES ${HDF5_${LIB}_LIBRARY})
endforeach()
if(HDF5_${__lang}_LIBRARIES)
set(HDF5_${__lang}_FOUND True)
endif()
# Append the libraries for this language binding to the list of all
# required libraries.
list(APPEND HDF5_LIBRARIES ${HDF5_${__lang}_LIBRARIES})
if(FIND_HL)
foreach(LIB IN LISTS HDF5_${__lang}_HL_LIBRARY_NAMES)
if(UNIX AND HDF5_USE_STATIC_LIBRARIES)
# According to bug 1643 on the CMake bug tracker, this is the
# preferred method for searching for a static library.
# See https://gitlab.kitware.com/cmake/cmake/issues/1643. We search
# first for the full static library name, but fall back to a
# generic search on the name if the static search fails.
set( THIS_LIBRARY_SEARCH_DEBUG
lib${LIB}d.a lib${LIB}_debug.a ${LIB}d ${LIB}_debug
lib${LIB}d-static.a lib${LIB}_debug-static.a ${LIB}d-static ${LIB}_debug-static )
set( THIS_LIBRARY_SEARCH_RELEASE lib${LIB}.a ${LIB} lib${LIB}-static.a ${LIB}-static)
else()
set( THIS_LIBRARY_SEARCH_DEBUG ${LIB}d ${LIB}_debug ${LIB}d-shared ${LIB}_debug-shared)
set( THIS_LIBRARY_SEARCH_RELEASE ${LIB} ${LIB}-shared)
endif()
find_library(HDF5_${LIB}_LIBRARY_DEBUG
NAMES ${THIS_LIBRARY_SEARCH_DEBUG}
HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib
${_HDF5_SEARCH_OPTS}
)
find_library( HDF5_${LIB}_LIBRARY_RELEASE
NAMES ${THIS_LIBRARY_SEARCH_RELEASE}
HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib
${_HDF5_SEARCH_OPTS}
)
select_library_configurations( HDF5_${LIB} )
list(APPEND HDF5_${__lang}_HL_LIBRARIES ${HDF5_${LIB}_LIBRARY})
endforeach()
# Append the libraries for this language binding to the list of all
# required libraries.
list(APPEND HDF5_HL_LIBRARIES ${HDF5_${__lang}_HL_LIBRARIES})
endif()
endforeach()
if(FIND_HL AND HDF5_HL_LIBRARIES)
set(HDF5_HL_FOUND True)
endif()
_HDF5_remove_duplicates_from_beginning(HDF5_INCLUDE_DIRS)
_HDF5_remove_duplicates_from_beginning(HDF5_LIBRARIES)
_HDF5_remove_duplicates_from_beginning(HDF5_HL_LIBRARIES)
# If the HDF5 include directory was found, open H5pubconf.h to determine if
# HDF5 was compiled with parallel IO support
set( HDF5_IS_PARALLEL FALSE )
set( HDF5_VERSION "" )
foreach( _dir IN LISTS HDF5_INCLUDE_DIRS )
foreach(_hdr "${_dir}/H5pubconf.h" "${_dir}/H5pubconf-64.h" "${_dir}/H5pubconf-32.h")
if( EXISTS "${_hdr}" )
file( STRINGS "${_hdr}"
HDF5_HAVE_PARALLEL_DEFINE
REGEX "HAVE_PARALLEL 1" )
if( HDF5_HAVE_PARALLEL_DEFINE )
set( HDF5_IS_PARALLEL TRUE )
endif()
unset(HDF5_HAVE_PARALLEL_DEFINE)
file( STRINGS "${_hdr}"
HDF5_VERSION_DEFINE
REGEX "^[ \t]*#[ \t]*define[ \t]+H5_VERSION[ \t]+" )
if( "${HDF5_VERSION_DEFINE}" MATCHES
"H5_VERSION[ \t]+\"([0-9]+\\.[0-9]+\\.[0-9]+)(-patch([0-9]+))?\"" )
set( HDF5_VERSION "${CMAKE_MATCH_1}" )
if( CMAKE_MATCH_3 )
set( HDF5_VERSION ${HDF5_VERSION}.${CMAKE_MATCH_3})
endif()
endif()
unset(HDF5_VERSION_DEFINE)
endif()
endforeach()
endforeach()
set( HDF5_IS_PARALLEL ${HDF5_IS_PARALLEL} CACHE BOOL
"HDF5 library compiled with parallel IO support" )
mark_as_advanced( HDF5_IS_PARALLEL )
set(HDF5_REQUIRED_VARS HDF5_LIBRARIES HDF5_INCLUDE_DIRS)
if(FIND_HL)
list(APPEND HDF5_REQUIRED_VARS HDF5_HL_LIBRARIES)
endif()
endif()
# For backwards compatibility we set HDF5_INCLUDE_DIR to the value of
# HDF5_INCLUDE_DIRS
if( HDF5_INCLUDE_DIRS )
set( HDF5_INCLUDE_DIR "${HDF5_INCLUDE_DIRS}" )
endif()
# If HDF5_REQUIRED_VARS is empty at this point, then it's likely that
# something external is trying to explicitly pass already found
# locations
if(NOT HDF5_REQUIRED_VARS)
set(HDF5_REQUIRED_VARS HDF5_LIBRARIES HDF5_INCLUDE_DIRS)
endif()
find_package_handle_standard_args(HDF5
REQUIRED_VARS ${HDF5_REQUIRED_VARS}
VERSION_VAR HDF5_VERSION
HANDLE_COMPONENTS
)
unset(_HDF5_SEARCH_OPTS)
if( HDF5_FOUND AND NOT HDF5_DIR)
# hide HDF5_DIR for the non-advanced user to avoid confusion with
# HDF5_DIR-NOT_FOUND while HDF5 was found.
mark_as_advanced(HDF5_DIR)
endif()
if (HDF5_FIND_DEBUG)
message(STATUS "HDF5_DIR: ${HDF5_DIR}")
message(STATUS "HDF5_DEFINITIONS: ${HDF5_DEFINITIONS}")
message(STATUS "HDF5_INCLUDE_DIRS: ${HDF5_INCLUDE_DIRS}")
message(STATUS "HDF5_LIBRARIES: ${HDF5_LIBRARIES}")
foreach(__lang IN LISTS HDF5_LANGUAGE_BINDINGS)
message(STATUS "HDF5_${__lang}_DEFINITIONS: ${HDF5_${__lang}_DEFINITIONS}")
message(STATUS "HDF5_${__lang}_INCLUDE_DIR: ${HDF5_${__lang}_INCLUDE_DIR}")
message(STATUS "HDF5_${__lang}_INCLUDE_DIRS: ${HDF5_${__lang}_INCLUDE_DIRS}")
message(STATUS "HDF5_${__lang}_LIBRARY: ${HDF5_${__lang}_LIBRARY}")
message(STATUS "HDF5_${__lang}_LIBRARIES: ${HDF5_${__lang}_LIBRARIES}")
endforeach()
endif()