diff --git a/CMake/SiloFindHDF5.cmake b/CMake/SiloFindHDF5.cmake index c2806447..3e2a3b85 100644 --- a/CMake/SiloFindHDF5.cmake +++ b/CMake/SiloFindHDF5.cmake @@ -62,8 +62,47 @@ if(DEFINED SILO_HDF5_DIR AND EXISTS ${SILO_HDF5_DIR}) set(HDF5_ROOT ${SILO_HDF5_DIR}) endif() +function(_silo_hdf5_detect_zlib_support_from_header out_var) + set(_header_candidates) + foreach(_include_dir ${HDF5_INCLUDE_DIRS} ${HDF5_INCLUDE_DIR}) + if(_include_dir) + list(APPEND _header_candidates + "${_include_dir}/H5pubconf.h" + "${_include_dir}/hdf5/H5pubconf.h") + endif() + endforeach() + list(REMOVE_DUPLICATES _header_candidates) + + foreach(_header IN LISTS _header_candidates) + if(EXISTS "${_header}") + file(STRINGS "${_header}" _zlib_markers + REGEX "^#define H5_HAVE_FILTER_DEFLATE 1$|^#define H5_HAVE_ZLIB_H 1$") + if(_zlib_markers) + set(${out_var} TRUE PARENT_SCOPE) + return() + endif() + endif() + endforeach() + + set(${out_var} FALSE PARENT_SCOPE) +endfunction() + find_package(HDF5) +# Prefer the concrete imported HDF5 C library targets before HDF5::HDF5. +# CMake's FindHDF5 module may synthesize HDF5::HDF5 with a flattened raw +# libhdf5.a link interface even when the upstream package also exports +# hdf5-static/hdf5-shared with the full transitive dependency set. +unset(HDF5_C_TARGET) +set(HDF5_HAS_IMPORTED_C_TARGET FALSE) +foreach(_hdf5_c_target hdf5-shared hdf5-static hdf5::hdf5-shared hdf5::hdf5-static hdf5::hdf5 HDF5::HDF5) + if(TARGET ${_hdf5_c_target}) + set(HDF5_C_TARGET ${_hdf5_c_target}) + set(HDF5_HAS_IMPORTED_C_TARGET TRUE) + break() + endif() +endforeach() + if(NOT HDF5_FOUND) include(FindPackageHandleStandardArgs) @@ -86,6 +125,7 @@ if(NOT HDF5_FOUND) set_target_properties(HDF5::HDF5 PROPERTIES IMPORTED_LOCATION "${HDF5_LIBRARY}" INTERFACE_INCLUDE_DIRECTORIES "${HDF5_INCLUDE_DIR}") + set(HDF5_C_TARGET HDF5::HDF5) endif() endif() @@ -95,16 +135,21 @@ if(HDF5_FOUND) set(HAVE_HDF5_H 1) set(HAVE_HDF5_DRIVER 1) set(HAVE_LIBHDF5 1) + set(HDF5_PROVIDES_ZLIB_SUPPORT FALSE) + + if(DEFINED HDF5_ENABLE_Z_LIB_SUPPORT) + set(HDF5_PROVIDES_ZLIB_SUPPORT ${HDF5_ENABLE_Z_LIB_SUPPORT}) + elseif(NOT HDF5_HAS_IMPORTED_C_TARGET) + _silo_hdf5_detect_zlib_support_from_header(HDF5_PROVIDES_ZLIB_SUPPORT) + endif() # On Windows need to have hdf5's dll installed with browser/silex # in order for the executables to work if(WIN32) - - get_target_property(HDF5_DLL ${HDF5_C_LIBRARIES} IMPORTED_LOCATION_RELEASE) - - # DLL may also be needed by testing infrastructure - get_target_property(HDF5_DLL ${HDF5_C_LIBRARIES} IMPORTED_LOCATION_RELEASE ) + if(HDF5_C_TARGET) + get_target_property(HDF5_DLL ${HDF5_C_TARGET} IMPORTED_LOCATION_RELEASE) + endif() if(HDF5_DLL AND (SILO_ENABLE_SILEX OR SILO_ENABLE_BROWSER)) install(FILES ${HDF5_DLL} DESTINATION ${CMAKE_INSTALL_BINDIR} PERMISSIONS OWNER_READ OWNER_WRITE @@ -120,4 +165,3 @@ if(HDF5_FOUND) else() message(FATAL_ERROR "An explicit request for HDF5 was made but HDF5 was not found. You may want to try setting SILO_HDF5_DIR") endif() - diff --git a/CMakeLists.txt b/CMakeLists.txt index cb5756ca..9fd66ae6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -241,14 +241,32 @@ if(SILO_ENABLE_HDF5) endif() ## -# Zlib needed for hzip (non-BSD) -# On Windows, if HDF5 was built with zlib support, need to find the zlib package -# so that the correct path to the dll can be found and copied to the necessary places +# Zlib needed for hzip (non-BSD) and for HDF5 builds that use deflate. +# When HDF5 is not discovered with a complete imported target, SiloFindHDF5 +# determines HDF5_PROVIDES_ZLIB_SUPPORT from HDF5's installed metadata. ## -if(SILO_ENABLE_HZIP OR (WIN32 AND HDF5_PROVIDES_ZLIB_SUPPORT)) +if(SILO_ENABLE_HZIP OR HDF5_PROVIDES_ZLIB_SUPPORT) include(SiloFindZlib) endif() +function(silo_target_link_hdf5 target_name) + if(SILO_ENABLE_HDF5 AND HDF5_FOUND) + if(HDF5_C_TARGET) + target_link_libraries(${target_name} ${HDF5_C_TARGET}) + else() + target_link_libraries(${target_name} ${HDF5_C_LIBRARIES}) + if(HDF5_PROVIDES_ZLIB_SUPPORT AND ZLIB_FOUND) + if(TARGET ZLIB::ZLIB) + target_link_libraries(${target_name} ZLIB::ZLIB) + elseif(ZLIB_LIBRARY) + target_link_libraries(${target_name} ${ZLIB_LIBRARY}) + endif() + endif() + endif() + target_include_directories(${target_name} PRIVATE ${HDF5_INCLUDE_DIRS}) + endif() +endfunction() + ## # szip if HDF5 was built with szip support on Windows (needed to find dll's) ## @@ -734,8 +752,7 @@ if(SILO_ENABLE_HDF5 AND HDF5_FOUND) # with HDF5, will use $ in place of plain 'silo' # when telling broswer and silex to link with silo set_target_properties(silo PROPERTIES OUTPUT_NAME siloh5) - target_link_libraries(silo ${HDF5_C_LIBRARIES}) - target_include_directories(silo PRIVATE ${HDF5_INCLUDE_DIRS}) + silo_target_link_hdf5(silo) endif() if(SILO_ENABLE_JSON AND JSONC_FOUND) diff --git a/tests/CMake/SiloTestFunctions.cmake b/tests/CMake/SiloTestFunctions.cmake index 86529b04..c59239f6 100644 --- a/tests/CMake/SiloTestFunctions.cmake +++ b/tests/CMake/SiloTestFunctions.cmake @@ -114,12 +114,10 @@ function(silo_add_test) set_target_properties(${sat_NAME} PROPERTIES FOLDER testing/tests) if(SILO_ENABLE_HDF5 AND HDF5_FOUND) - target_link_libraries(${sat_NAME} ${HDF5_C_LIBRARIES}) - target_include_directories(${sat_NAME} PRIVATE ${HDF5_INCLUDE_DIRS}) + silo_target_link_hdf5(${sat_NAME}) endif() if(WIN32) target_compile_definitions(${sat_NAME} PRIVATE PDB_LITE) endif() endfunction() - diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d4e48f4e..00512726 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -437,8 +437,7 @@ foreach(src IN LISTS C_TEST_SOURCES CXX_TEST_SOURCES F_TEST_SOURCES) endif() if(SILO_ENABLE_HDF5 AND HDF5_FOUND) - target_link_libraries(${base} ${HDF5_C_LIBRARIES}) - target_include_directories(${base} PRIVATE ${HDF5_INCLUDE_DIRS}) + silo_target_link_hdf5(${base}) endif() if(SILO_ENABLE_JSON AND JSONC_FOUND) diff --git a/tools/browser/CMakeLists.txt b/tools/browser/CMakeLists.txt index b4a76772..5bc384a2 100644 --- a/tools/browser/CMakeLists.txt +++ b/tools/browser/CMakeLists.txt @@ -98,7 +98,7 @@ endif() target_link_libraries(browser ${CMAKE_DL_LIBS}) if(SILO_ENABLE_HDF5 AND HDF5_FOUND) - target_link_libraries(browser ${HDF5_C_LIBRARIES}) + silo_target_link_hdf5(browser) endif() if(SILO_BUILD_FOR_ASAN) @@ -123,4 +123,3 @@ if(NOT WIN32) WORLD_READ WORLD_EXECUTE) endif() -