# - FindHDF5.cmake # # The FindHDF5 module with the CMake distribution will not work if # the HDF5 compilers are not installed or if more the one hdf5 is on the # system. The search logic also depends on an environment variable # HDF5_ROOT. This module removes both requirements and insteead relies on the # libhdf5.settings file found in the library installation directory # # This module will ONLY work for HDF5 configured through the GNU # autoconf script configure. When built through CMake, the *config.cmake # files should be used. # # # Based on version from MSTK which has the following: # ACKNOWLEDGEMENT: # This file has been adapted from the build system of the Amanzi project # under the DOE/ASCEM code project. It is used here based on the BSD open # source licensing of the Amanzi code base. Many thanks to the Amanzi build # system developers # # @HEADER # ************************************************************************ # # TriBITS: Tribal Build, Integrate, and Test System # Copyright 2016, 2021, 2022 Sandia Corporation # # Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, # the U.S. Government retains certain rights in this software. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # 3. Neither the name of the Corporation nor the names of the # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # ************************************************************************ # @HEADER# # CMake includes include(FindPackageHandleStandardArgs) include(AddImportedLibrary) # ---------------------------------------------------------------------------- # # Functions/Macros # # macro(_hdf5_boolean_convert _var) string(TOUPPER ${${_var}} _var_UC) if(_var_UC) set(${_var} TRUE) else() set(${_var} FALSE) endif() endmacro() function(_hdf5_chomp_string old_str new_str_var) string(REGEX REPLACE "[\t\r\n]" " " _tmp "${old_str}") #string(REGEX REPLACE " " "S" _tmp "${_tmp}") string(REGEX REPLACE "^ +" "" _tmp "${_tmp}") string(REGEX REPLACE " +$" "" _tmp "${_tmp}") set(${new_str_var} ${_tmp} PARENT_SCOPE) endfunction() function(_hdf5_parse_settings_file _file _key _value) set(_tmp ${_value}-NOTFOUND) file(STRINGS ${_file} _output REGEX "^[ \t]*${_key}:|^${_key}") if(_output) # _hdf5_chomp_string will remove all tabs, newlines and returns # It also removes leading and trailing whitespace _hdf5_chomp_string(${_output} _output) # Remove the key signature string(REGEX REPLACE "${_key}:" "" _output "${_output}") # CHOMP again to remove leading and trailing whitespace if (_output) _hdf5_chomp_string(${_output} _output) endif() # Entry is non-empty if ANY non-space character is left if ( "${_output}" MATCHES "[^ ]" ) set(_tmp ${_output}) endif() endif() set(${_value} ${_tmp} PARENT_SCOPE) endfunction() function(_hdf5_define_version _file _var) set(_search_key "HDF5 Version") _hdf5_parse_settings_file(${_file} ${_search_key} _tmp) set(${_var} ${_tmp} PARENT_SCOPE) endfunction() function(_hdf5_define_parallel_build _file _var) set(_search_key "Parallel HDF5") _hdf5_parse_settings_file(${_file} ${_search_key} _tmp) _hdf5_boolean_convert(_tmp) set(${_var} ${_tmp} PARENT_SCOPE) endfunction() function(_hdf5_extra_library_dirs _file _var) # Settings file has several locations to list LDFLAGS # We'll pick them all and sort out later. set(_search_ldflags_keys "AM_LDFLAGS;H5_LDFLAGS;LDFLAGS;Extra libraries") set(_ldflags "") foreach ( _key ${_search_ldflags_keys}) _hdf5_parse_settings_file(${_file} ${_key} _tmp) if ( _tmp ) set(_ldflags "${_ldflags} ${_tmp}") endif() endforeach() # Now match all the -L flags string(REGEX MATCHALL "-L([^\" ]+|\"[^\"]+\")" _lib_path_flags ${_ldflags}) # Loop through each set(_directories) foreach(_dir ${_lib_path_flags}) string(REGEX REPLACE "^-L" "" _dir ${_dir}) string(REGEX REPLACE "//" "/" _dir ${_dir}) list(APPEND _directories ${_dir}) endforeach() if(_directories) list(REMOVE_DUPLICATES _directories) endif() set(${_var} ${_directories} PARENT_SCOPE) endfunction() function(_hdf5_library_path _file _var) # Settings file has several locations to list LDFLAGS # We'll pick them all and sort out later. set(_search_key "Installation point") _hdf5_parse_settings_file(${_file} ${_search_key} _tmp) set(${_var} ${_tmp} PARENT_SCOPE) endfunction() function(_hdf5_extra_libraries _file _var) # Find all the extra libraries defined in the file set(_search_key "Extra libraries") set(_libraries) _hdf5_parse_settings_file(${_file} ${_search_key} _library_flags) string( REGEX MATCHALL "[, ]-l([^\", ]+)|^-l([^\", ]+)" _library_name_flags ${_library_flags}) foreach ( _lib ${_library_name_flags} ) _hdf5_chomp_string(${_lib} _lib_chomp) string( REGEX REPLACE "^[,]-l|^-l" "" _lib_chomp ${_lib_chomp}) list(APPEND _libraries ${_lib_chomp}) endforeach() # Grab all the extra library paths to build a search list _hdf5_extra_library_dirs(${_file} _search_list) # Loop through each library # (1) find_library with the search list for hints # (2) Add library name if find succeeds, otherwise # add the name to the list. set(_return_list) foreach( _lib ${_libraries}) # Search with hints set(_lib_name _lib_name-NOTFOUND) find_library(_lib_name NAMES ${_lib} HINTS ${_search_list} ) # Search without hints if the first search fails if ( NOT _lib_name ) find_library(_lib_name NAMES ${_lib}) endif() # Add the full library name if either find succeeded # otherwise add the library name. if(_lib_name) list(APPEND _return_list ${_lib_name}) else() list(APPEND _return_list ${_lib}) endif() endforeach() set(${_var} ${_return_list} PARENT_SCOPE) endfunction() function(_hdf5_extra_include_dirs _file _var) # Settings file has several locations to list LDFLAGS # We'll pick them all and sort out later. # Keys in the file changed around version 1.8.3 set(_search_cflags_keys "CFLAGS;H5_CFLAGS;AM_CFLAGS;CPPFLAGS;H5_CPPFLAGS;AM_CPPFLAGS") if ( HDF5_VERSION_STRING ) if ( "${HDF5_VERSION_STRING}" VERSION_LESS "1.8.3") set(_search_cflags_keys "CFLAGS/H5_CFLAGS;AM_CFLAGS;CPPFLAGS/H5_CPPFLAGS;AM_CPPFLAGS") endif() endif() set(_cflags "") foreach ( _key ${_search_cflags_keys}) _hdf5_parse_settings_file(${_file} ${_key} _tmp) if ( _tmp ) set(_cflags "${_cflags} ${_tmp}") endif() endforeach() # Now match all the -I flags if (${_cflags}) string(REGEX MATCHALL "-I([^\" ]+|\"[^\"]+\")" _inc_path_flags ${_cflags}) # Loop through each set(_directories) foreach(_dir ${_inc_path_flags}) string(REGEX REPLACE "^-I" "" _dir ${_dir}) string(REGEX REPLACE "//" "/" _dir ${_dir}) list(APPEND _directories ${_dir}) endforeach() endif() if(_directories) list(REMOVE_DUPLICATES _directories) endif() set(${_var} ${_directories} PARENT_SCOPE) endfunction() # # End Functions/Macros # ---------------------------------------------------------------------------- # # ------------------------------------ # # Initialize search paths and criteria # # ------------------------------------ # # If HDF5_ROOT was defined in the environment, use it. # Definition from the command line will take precedence. if (NOT HDF5_ROOT AND NOT $ENV{HDF5_ROOT} STREQUAL "") set(HDF5_ROOT $ENV{HDF5_ROOT}) endif() # HDF5_DIR is DEPRECATED WARN THE USER if it is set if (NOT HDF5_ROOT AND HDF5_DIR ) message(WARNING "The configuration parameter HDF5_DIR is deprecated." " Please use HDF5_ROOT instead to define the HDF5 installation") set(HDF5_ROOT ${HDF5_DIR}) endif() # Add the usual paths for searching using the HDF5_ROOT variable if (HDF5_ROOT) list(APPEND _hdf5_INCLUDE_SEARCH_DIRS ${HDF5_ROOT}/include ${HDF5_ROOT}/include/hdf5/serial ${HDF5_ROOT} ) list(APPEND _hdf5_LIBRARY_SEARCH_DIRS ${HDF5_ROOT}/lib ${HDF5_ROOT} ) list(APPEND _hdf5_BINARY_SEARCH_DIRS ${HDF5_ROOT}/bin ${HDF5_ROOT} ) endif() # Restrict the search to HDF5_ROOT if user does not want other # directories searched. if ( HDF5_NO_SYSTEM_PATHS ) set(_hdf5_FIND_OPTIONS NO_CMAKE_SYSTEM_PATH) endif() # A list of valid components set(HDF5_VALID_COMPONENTS HL C) # A list of requested components, invalid components are ignored. if ( NOT HDF5_FIND_COMPONENTS ) set(HDF5_SEARCH_COMPONENTS "C") else() foreach ( component ${HDF5_FIND_COMPONENTS} ) list(FIND HDF5_VALID_COMPONENTS ${component} component_idx) if ( ${component_idx} EQUAL -1 ) message(SEND_ERROR "${component} is not a valid HDF5 component") else() list(APPEND HDF5_SEARCH_COMPONENTS ${component}) endif() endforeach() endif() # ------------------------------------ # # Perform CMake Search # # ------------------------------------ # if ( HDF5_INCLUDE_DIRS AND HDF5_LIBRARIES ) # Do nothing if the user has defined these on the command line else() # --- Target names used in both the CMake configure files # and here to create targets set( HDF5_C_TARGET hdf5 ) set( HDF5_HL_TARGET hdf5_hl ) # ------------------------------------------------------ # # Search Logic # (1) Look for a CMake configuration file(s) # (2) If the above fails, search by name the include and # library files. # Step one will be bypassed if HDF5_NO_HDF5_CMAKE is set # --- Search for a CMake Configuration if ( NOT HDF5_NO_HDF5_CMAKE ) # Call find package only looking for CMake config files if (WIN32) find_package(HDF5 HINTS ${HDF5_ROOT}/lib/cmake QUIET NO_MODULE) else() find_package(HDF5 HINTS ${HDF5_ROOT}/cmake/hdf5 QUIET NO_MODULE) endif() # If located a HDF5 configuration file if (HDF5_FOUND) message(STATUS "Found HDF5 CMake configuration file ( directory ${HDF5_CONFIG} )") # Want consistency between this module and the CMake file set(HDF5_VERSION ${HDF5_VERSION_STRING}) set(HDF5_IS_PARALLEL ${HDF5_ENABLE_PARALLEL}) set(HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIR}) # Define HDF5_C_LIBRARIES to contain hdf5 and hdf5_hl C libraries set(HDF5_C_LIBRARIES ${HDF5_HL_LIBRARY} ${HDF5_CLIBRARY}) if (HDF5_IS_PARALLEL) find_package(MPI) if (MPI_C_FOUND) set(HDF5_LIBRARIES ${HDF5_LIBRARIES} ${MPI_C_LIBRARIES}) endif() endif() set(HDF5_C_LIBRARIES "${HDF5_LIBRARIES}") endif() endif() # --- If HDF5 is NOT found search for the settings file installed with the libraries # Will allow the user to define the HDF5_SETTINGS_FILE before attempting a search. if ( NOT HDF5_FOUND AND ( NOT HDF5_SETTINGS_FILE ) ) find_file(HDF5_SETTINGS_FILE NAMES libhdf5.settings HINTS ${_hdf5_LIBRARY_SEARCH_DIRS} ${_hdf5_FIND_OPTIONS}) endif() # --- Now search by file name. HDF5_INCLUDE_DIRS and HD5_LIBRARIES will # not be set if the CMake configuration search was successful. # --- Search for the include files if ( NOT HDF5_INCLUDE_DIRS ) find_path(HDF5_INCLUDE_DIR NAMES hdf5.h PATHS ${_hdf5_INCLUDE_SEARCH_DIRS} ${_hdf5_FIND_OPTIONS} ) if ( NOT HDF5_INCLUDE_DIR ) message(FATAL_ERROR "Failed to locate HDF5 include file") endif() # Check the settings file for other include directories if ( HDF5_SETTINGS_FILE ) _hdf5_extra_include_dirs(${HDF5_SETTINGS_FILE} extra_inc_dirs) endif() # Build HDF5_INCLUDE_DIRS set(HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIR} ${extra_inc_dirs}) list(REMOVE_DUPLICATES HDF5_INCLUDE_DIRS) endif() # Search for the libraries if (HDF5_SETTINGS_FILE) _hdf5_library_path(${HDF5_SETTINGS_FILE} _hdf5_path) set(_hdf5_LIBRARY_SEARCH_DIRS ${_hdf5_path}/lib) endif() if ( NOT HDF5_LIBRARIES ) # --- Search for the C library find_library(_HDF5_C_LIBRARY NAMES hdf5 hdf5_serial HINTS ${_hdf5_LIBRARY_SEARCH_DIRS} ${_hdf5_FIND_OPTIONS} ) # Since all other libraries need this core library, throw a # fatal error her if it is not found. if ( NOT _HDF5_C_LIBRARY ) message(FATAL_ERROR "Could not locate the C HDF5 library") endif() # Define the target for the C library if (HDF5_SETTINGS_FILE) _hdf5_extra_libraries(${HDF5_SETTINGS_FILE} HDF5_LINK_LIBRARIES) endif() # Search for the high-level (HL) library find_library(_HDF5_HL_LIBRARY NAMES hdf5_hl hdf5_serial_hl HINTS ${_hdf5_LIBRARY_SEARCH_DIRS} ${_hdf5_FIND_OPTIONS}) # --- Create the imported targets for each of the components found # and update HDF5_LIBRARIES. # HL Library if ( _HDF5_HL_LIBRARY ) add_imported_library(${HDF5_HL_TARGET} LOCATION ${_HDF5_HL_LIBRARY} LINK_LANGUAGES "C" LINK_INTERFACE_LIBRARIES "${HDF5_C_TARGET}") set(HDF5_HL_LIBRARY ${HDF5_HL_TARGET}) endif() add_imported_library(${HDF5_C_TARGET} LOCATION ${_HDF5_C_LIBRARY} LINK_LANGUAGES "C" LINK_INTERFACE_LIBRARIES "${HDF5_LINK_LIBRARIES}") set(HDF5_C_LIBRARY ${HDF5_C_TARGET}) # --- Search for the other possible component libraries # Define the HDF5__LIBRARY to point to the target foreach ( _component ${HDF5_VALID_COMPONENTS} ) if ( TARGET ${HDF5_${_component}_TARGET} ) set(HDF5_${_component}_LIBRARY ${HDF5_${_component}_TARGET}) endif() endforeach() # Define the HDF5_LIBRARIES variable set(HDF5_LIBRARY_TARGETS ${HDF5_HL_LIBRARY} ${HDF5_C_LIBRARY}) # Define the HDF5_C_LIBRARIES variable set(HDF5_C_LIBRARIES ${HDF5_HL_LIBRARY} ${HDF5_C_LIBRARY}) # HDF5 and extra libraries listed as full paths rather than # libraries for the purposes of exporting set(HDF5_LIBRARIES) if ( TARGET ${HDF5_HL_TARGET} ) list(APPEND HDF5_LIBRARIES ${_HDF5_HL_LIBRARY}) endif() if ( TARGET ${HDF5_C_TARGET} ) list(APPEND HDF5_LIBRARIES ${_HDF5_C_LIBRARY}) endif() list(APPEND HDF5_LIBRARIES ${HDF5_LINK_LIBRARIES}) endif() endif() set(HDF5_LIBRARIES_EXPORT ${HDF5_LIBRARIES}) # --- Define the version string from the settings file if not already set if ( NOT HDF5_VERSION AND HDF5_SETTINGS_FILE ) _hdf5_define_version(${HDF5_SETTINGS_FILE} HDF5_VERSION) endif() if ( NOT HDF5_VERSION ) SET(HDF5_VERSION "Unknown") endif() # --- Define HDF5_IS_PARALLEL from the settings file if not already set if ( NOT HDF5_IS_PARALLEL AND HDF5_SETTINGS_FILE ) _hdf5_define_parallel_build(${HDF5_SETTINGS_FILE} HDF5_IS_PARALLEL) endif() # --- Search for HDF5 tools set(_hdf5_TOOLS h52gif h5copy h5debug h5diff h5dump h5import h5jam h5ls h5mkgrp h5stat) set(HDF5_TOOLS_FOUND) foreach( tool ${_hdf5_TOOLS}) string(TOUPPER "${tool}" tool_uc) set(_hdf5_VAR_NAME HDF5_${tool_uc}_BINARY) find_program(${_hdf5_VAR_NAME} ${tool} HINTS ${_hdf5_BINARY_SEARCH_DIRS} ${_hdf5_FIND_OPTIONS}) if (${_hdf5_VAR_NAME}) list(APPEND HDF5_TOOLS_FOUND ${tool}) endif() endforeach() # --- Set the variables HDF5__FOUND FLAGS foreach ( _component ${HDF5_VALID_COMPONENTS} ) if( HDF5_${_component}_LIBRARY ) set(HDF5_${_component}_FOUND TRUE) else() set(HDF5_${_component}_FOUND FALSE) endif() endforeach() # --- Provide a summary of what the module found if ( NOT HDF5_FIND_QUIETLY ) # Create a not found list message(STATUS "HDF5 Version: ${HDF5_VERSION}") message(STATUS "\tHDF5_INCLUDE_DIRS =${HDF5_INCLUDE_DIRS}") message(STATUS "\tHDF5_LIBRARY_TARGETS =${HDF5_LIBRARY_TARGETS}") message(STATUS "\tHDF5_LIBRARIES =${HDF5_LIBRARIES}") message(STATUS "\tHDF5_LIBRARIES_EXPORT =${HDF5_LIBRARIES_EXPORT}") message(STATUS "\tHDF5_LINK_LIBRARIES =${HDF5_LINK_LIBRARIES}") message(STATUS "\tHDF5_IS_PARALLEL =${HDF5_IS_PARALLEL}") message(STATUS "Found the following HDF5 component libraries") set(HDF5_COMPONENTS_NOTFOUND) foreach (_component ${HDF5_VALID_COMPONENTS} ) if ( HDF5_${_component}_FOUND ) #message(STATUS "\t HDF5_${_component}_LIBRARY\t\t=${HDF5_${_component}_LIBRARY}") message(STATUS "\t${HDF5_${_component}_LIBRARY}") else() list(APPEND HDF5_COMPONENTS_NOTFOUND ${_component}) endif() endforeach() if ( HDF5_COMPONENTS_NOTFOUND ) message(STATUS "\tHDF5 Components not found: ${HDF5_COMPONENTS_NOTFOUND}") endif() message(STATUS "\tHDF5_TOOLS_FOUND: ${HDF5_TOOLS_FOUND}") endif() # For compatability with TriBITS: set(TPL_HDF5_LIBRARY_DIRS ${_hdf5_LIBRARY_SEARCH_DIRS}) set(TPL_HDF5_LIBRARIES ${HDF5_LIBRARIES}) set(TPL_HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIRS}) find_package_handle_standard_args( HDF5 DEFAULT_MESSAGE HDF5_INCLUDE_DIRS HDF5_LIBRARIES HDF5_VERSION)