1# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2# file Copyright.txt or https://cmake.org/licensing for details.
3
4#[=======================================================================[.rst:
5FindHDF5
6--------
7
8Find Hierarchical Data Format (HDF5), a library for reading and writing
9self describing array data.
10
11
12This module invokes the ``HDF5`` wrapper compiler that should be installed
13alongside ``HDF5``.  Depending upon the ``HDF5`` Configuration, the wrapper
14compiler is called either ``h5cc`` or ``h5pcc``.  If this succeeds, the module
15will then call the compiler with the show argument to see what flags
16are used when compiling an ``HDF5`` client application.
17
18The module will optionally accept the ``COMPONENTS`` argument.  If no
19``COMPONENTS`` are specified, then the find module will default to finding
20only the ``HDF5`` C library.  If one or more ``COMPONENTS`` are specified, the
21module will attempt to find the language bindings for the specified
22components.  The valid components are ``C``, ``CXX``, ``Fortran``, ``HL``.
23``HL`` refers to the "high-level" HDF5 functions for C and Fortran.
24If the ``COMPONENTS`` argument is not given, the module will
25attempt to find only the C bindings.
26For example, to use Fortran HDF5 and HDF5-HL functions, do:
27``find_package(HDF5 COMPONENTS Fortran HL)``.
28
29This module will read the variable
30``HDF5_USE_STATIC_LIBRARIES`` to determine whether or not to prefer a
31static link to a dynamic link for ``HDF5`` and all of it's dependencies.
32To use this feature, make sure that the ``HDF5_USE_STATIC_LIBRARIES``
33variable is set before the call to find_package.
34
35.. versionadded:: 3.10
36  Support for ``HDF5_USE_STATIC_LIBRARIES`` on Windows.
37
38Both the serial and parallel ``HDF5`` wrappers are considered and the first
39directory to contain either one will be used.  In the event that both appear
40in the same directory the serial version is preferentially selected. This
41behavior can be reversed by setting the variable ``HDF5_PREFER_PARALLEL`` to
42``TRUE``.
43
44In addition to finding the includes and libraries required to compile
45an ``HDF5`` client application, this module also makes an effort to find
46tools that come with the ``HDF5`` distribution that may be useful for
47regression testing.
48
49Result Variables
50^^^^^^^^^^^^^^^^
51
52This module will set the following variables in your project:
53
54``HDF5_FOUND``
55  HDF5 was found on the system
56``HDF5_VERSION``
57  .. versionadded:: 3.3
58    HDF5 library version
59``HDF5_INCLUDE_DIRS``
60  Location of the HDF5 header files
61``HDF5_DEFINITIONS``
62  Required compiler definitions for HDF5
63``HDF5_LIBRARIES``
64  Required libraries for all requested bindings
65``HDF5_HL_LIBRARIES``
66  Required libraries for the HDF5 high level API for all bindings,
67  if the ``HL`` component is enabled
68
69Available components are: ``C`` ``CXX`` ``Fortran`` and ``HL``.
70For each enabled language binding, a corresponding ``HDF5_${LANG}_LIBRARIES``
71variable, and potentially ``HDF5_${LANG}_DEFINITIONS``, will be defined.
72If the ``HL`` component is enabled, then an ``HDF5_${LANG}_HL_LIBRARIES`` will
73also be defined.  With all components enabled, the following variables will be defined:
74
75``HDF5_C_DEFINITIONS``
76  Required compiler definitions for HDF5 C bindings
77``HDF5_CXX_DEFINITIONS``
78  Required compiler definitions for HDF5 C++ bindings
79``HDF5_Fortran_DEFINITIONS``
80  Required compiler definitions for HDF5 Fortran bindings
81``HDF5_C_INCLUDE_DIRS``
82  Required include directories for HDF5 C bindings
83``HDF5_CXX_INCLUDE_DIRS``
84  Required include directories for HDF5 C++ bindings
85``HDF5_Fortran_INCLUDE_DIRS``
86  Required include directories for HDF5 Fortran bindings
87``HDF5_C_LIBRARIES``
88  Required libraries for the HDF5 C bindings
89``HDF5_CXX_LIBRARIES``
90  Required libraries for the HDF5 C++ bindings
91``HDF5_Fortran_LIBRARIES``
92  Required libraries for the HDF5 Fortran bindings
93``HDF5_C_HL_LIBRARIES``
94  Required libraries for the high level C bindings
95``HDF5_CXX_HL_LIBRARIES``
96  Required libraries for the high level C++ bindings
97``HDF5_Fortran_HL_LIBRARIES``
98  Required libraries for the high level Fortran bindings.
99
100``HDF5_IS_PARALLEL``
101  HDF5 library has parallel IO support
102``HDF5_C_COMPILER_EXECUTABLE``
103  path to the HDF5 C wrapper compiler
104``HDF5_CXX_COMPILER_EXECUTABLE``
105  path to the HDF5 C++ wrapper compiler
106``HDF5_Fortran_COMPILER_EXECUTABLE``
107  path to the HDF5 Fortran wrapper compiler
108``HDF5_C_COMPILER_EXECUTABLE_NO_INTERROGATE``
109  path to the primary C compiler which is also the HDF5 wrapper
110``HDF5_CXX_COMPILER_EXECUTABLE_NO_INTERROGATE``
111  path to the primary C++ compiler which is also the HDF5 wrapper
112``HDF5_Fortran_COMPILER_EXECUTABLE_NO_INTERROGATE``
113  path to the primary Fortran compiler which is also the HDF5 wrapper
114``HDF5_DIFF_EXECUTABLE``
115  path to the HDF5 dataset comparison tool
116
117With all components enabled, the following targets will be defined:
118
119``HDF5::HDF5``
120  All detected ``HDF5_LIBRARIES``.
121``hdf5::hdf5``
122  C library.
123``hdf5::hdf5_cpp``
124  C++ library.
125``hdf5::hdf5_fortran``
126  Fortran library.
127``hdf5::hdf5_hl``
128  High-level C library.
129``hdf5::hdf5_hl_cpp``
130  High-level C++ library.
131``hdf5::hdf5_hl_fortran``
132  High-level Fortran library.
133``hdf5::h5diff``
134  ``h5diff`` executable.
135
136Hints
137^^^^^
138
139The following variables can be set to guide the search for HDF5 libraries and includes:
140
141``HDF5_PREFER_PARALLEL``
142  .. versionadded:: 3.4
143
144  set ``true`` to prefer parallel HDF5 (by default, serial is preferred)
145
146``HDF5_FIND_DEBUG``
147  .. versionadded:: 3.9
148
149  Set ``true`` to get extra debugging output.
150
151``HDF5_NO_FIND_PACKAGE_CONFIG_FILE``
152  .. versionadded:: 3.8
153
154  Set ``true`` to skip trying to find ``hdf5-config.cmake``.
155#]=======================================================================]
156
157include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
158include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
159
160# We haven't found HDF5 yet. Clear its state in case it is set in the parent
161# scope somewhere else. We can't rely on it because different components may
162# have been requested for this call.
163set(HDF5_FOUND OFF)
164set(HDF5_LIBRARIES)
165set(HDF5_HL_LIBRARIES)
166
167# List of the valid HDF5 components
168set(HDF5_VALID_LANGUAGE_BINDINGS C CXX Fortran)
169
170# Validate the list of find components.
171if(NOT HDF5_FIND_COMPONENTS)
172  set(HDF5_LANGUAGE_BINDINGS "C")
173else()
174  set(HDF5_LANGUAGE_BINDINGS)
175  # add the extra specified components, ensuring that they are valid.
176  set(HDF5_FIND_HL OFF)
177  foreach(_component IN LISTS HDF5_FIND_COMPONENTS)
178    list(FIND HDF5_VALID_LANGUAGE_BINDINGS ${_component} _component_location)
179    if(NOT _component_location EQUAL -1)
180      list(APPEND HDF5_LANGUAGE_BINDINGS ${_component})
181    elseif(_component STREQUAL "HL")
182      set(HDF5_FIND_HL ON)
183    elseif(_component STREQUAL "Fortran_HL") # only for compatibility
184      list(APPEND HDF5_LANGUAGE_BINDINGS Fortran)
185      set(HDF5_FIND_HL ON)
186      set(HDF5_FIND_REQUIRED_Fortran_HL FALSE)
187      set(HDF5_FIND_REQUIRED_Fortran TRUE)
188      set(HDF5_FIND_REQUIRED_HL TRUE)
189    else()
190      message(FATAL_ERROR "${_component} is not a valid HDF5 component.")
191    endif()
192  endforeach()
193  unset(_component)
194  unset(_component_location)
195  if(NOT HDF5_LANGUAGE_BINDINGS)
196    get_property(_langs GLOBAL PROPERTY ENABLED_LANGUAGES)
197    foreach(_lang IN LISTS _langs)
198      if(_lang MATCHES "^(C|CXX|Fortran)$")
199        list(APPEND HDF5_LANGUAGE_BINDINGS ${_lang})
200      endif()
201    endforeach()
202  endif()
203  list(REMOVE_ITEM HDF5_FIND_COMPONENTS Fortran_HL) # replaced by Fortran and HL
204  list(REMOVE_DUPLICATES HDF5_LANGUAGE_BINDINGS)
205endif()
206
207# Determine whether to search for serial or parallel executable first
208if(HDF5_PREFER_PARALLEL)
209  set(HDF5_C_COMPILER_NAMES h5pcc h5cc)
210  set(HDF5_CXX_COMPILER_NAMES h5pc++ h5c++)
211  set(HDF5_Fortran_COMPILER_NAMES h5pfc h5fc)
212else()
213  set(HDF5_C_COMPILER_NAMES h5cc h5pcc)
214  set(HDF5_CXX_COMPILER_NAMES h5c++ h5pc++)
215  set(HDF5_Fortran_COMPILER_NAMES h5fc h5pfc)
216endif()
217
218# Test first if the current compilers automatically wrap HDF5
219function(_HDF5_test_regular_compiler_C success version is_parallel)
220  set(scratch_directory
221    ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hdf5)
222  if(NOT ${success} OR
223     NOT EXISTS ${scratch_directory}/compiler_has_h5_c)
224    set(test_file ${scratch_directory}/cmake_hdf5_test.c)
225    file(WRITE ${test_file}
226      "#include <hdf5.h>\n"
227      "const char* info_ver = \"INFO\" \":\" H5_VERSION;\n"
228      "#ifdef H5_HAVE_PARALLEL\n"
229      "const char* info_parallel = \"INFO\" \":\" \"PARALLEL\";\n"
230      "#endif\n"
231      "int main(int argc, char **argv) {\n"
232      "  int require = 0;\n"
233      "  require += info_ver[argc];\n"
234      "#ifdef H5_HAVE_PARALLEL\n"
235      "  require += info_parallel[argc];\n"
236      "#endif\n"
237      "  hid_t fid;\n"
238      "  fid = H5Fcreate(\"foo.h5\",H5F_ACC_TRUNC,H5P_DEFAULT,H5P_DEFAULT);\n"
239      "  return 0;\n"
240      "}")
241    try_compile(${success} ${scratch_directory} ${test_file}
242      COPY_FILE ${scratch_directory}/compiler_has_h5_c
243    )
244  endif()
245  if(${success})
246    file(STRINGS ${scratch_directory}/compiler_has_h5_c INFO_STRINGS
247      REGEX "^INFO:"
248    )
249    string(REGEX MATCH "^INFO:([0-9]+\\.[0-9]+\\.[0-9]+)(-patch([0-9]+))?"
250      INFO_VER "${INFO_STRINGS}"
251    )
252    set(${version} ${CMAKE_MATCH_1})
253    if(CMAKE_MATCH_3)
254      set(${version} ${HDF5_C_VERSION}.${CMAKE_MATCH_3})
255    endif()
256    set(${version} ${${version}} PARENT_SCOPE)
257
258    if(INFO_STRINGS MATCHES "INFO:PARALLEL")
259      set(${is_parallel} TRUE PARENT_SCOPE)
260    else()
261      set(${is_parallel} FALSE PARENT_SCOPE)
262    endif()
263  endif()
264endfunction()
265
266function(_HDF5_test_regular_compiler_CXX success version is_parallel)
267  set(scratch_directory ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hdf5)
268  if(NOT ${success} OR
269     NOT EXISTS ${scratch_directory}/compiler_has_h5_cxx)
270    set(test_file ${scratch_directory}/cmake_hdf5_test.cxx)
271    file(WRITE ${test_file}
272      "#include <H5Cpp.h>\n"
273      "#ifndef H5_NO_NAMESPACE\n"
274      "using namespace H5;\n"
275      "#endif\n"
276      "const char* info_ver = \"INFO\" \":\" H5_VERSION;\n"
277      "#ifdef H5_HAVE_PARALLEL\n"
278      "const char* info_parallel = \"INFO\" \":\" \"PARALLEL\";\n"
279      "#endif\n"
280      "int main(int argc, char **argv) {\n"
281      "  int require = 0;\n"
282      "  require += info_ver[argc];\n"
283      "#ifdef H5_HAVE_PARALLEL\n"
284      "  require += info_parallel[argc];\n"
285      "#endif\n"
286      "  H5File file(\"foo.h5\", H5F_ACC_TRUNC);\n"
287      "  return 0;\n"
288      "}")
289    try_compile(${success} ${scratch_directory} ${test_file}
290      COPY_FILE ${scratch_directory}/compiler_has_h5_cxx
291    )
292  endif()
293  if(${success})
294    file(STRINGS ${scratch_directory}/compiler_has_h5_cxx INFO_STRINGS
295      REGEX "^INFO:"
296    )
297    string(REGEX MATCH "^INFO:([0-9]+\\.[0-9]+\\.[0-9]+)(-patch([0-9]+))?"
298      INFO_VER "${INFO_STRINGS}"
299    )
300    set(${version} ${CMAKE_MATCH_1})
301    if(CMAKE_MATCH_3)
302      set(${version} ${HDF5_CXX_VERSION}.${CMAKE_MATCH_3})
303    endif()
304    set(${version} ${${version}} PARENT_SCOPE)
305
306    if(INFO_STRINGS MATCHES "INFO:PARALLEL")
307      set(${is_parallel} TRUE PARENT_SCOPE)
308    else()
309      set(${is_parallel} FALSE PARENT_SCOPE)
310    endif()
311  endif()
312endfunction()
313
314function(_HDF5_test_regular_compiler_Fortran success is_parallel)
315  if(NOT ${success})
316    set(scratch_directory
317      ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hdf5)
318    set(test_file ${scratch_directory}/cmake_hdf5_test.f90)
319    file(WRITE ${test_file}
320      "program hdf5_hello\n"
321      "  use hdf5\n"
322      "  use h5lt\n"
323      "  use h5ds\n"
324      "  integer error\n"
325      "  call h5open_f(error)\n"
326      "  call h5close_f(error)\n"
327      "end\n")
328    try_compile(${success} ${scratch_directory} ${test_file})
329    if(${success})
330      execute_process(COMMAND ${CMAKE_Fortran_COMPILER} -showconfig
331        OUTPUT_VARIABLE config_output
332        ERROR_VARIABLE config_error
333        RESULT_VARIABLE config_result
334        )
335      if(config_output MATCHES "Parallel HDF5: yes")
336        set(${is_parallel} TRUE PARENT_SCOPE)
337      else()
338        set(${is_parallel} FALSE PARENT_SCOPE)
339      endif()
340    endif()
341  endif()
342endfunction()
343
344# Invoke the HDF5 wrapper compiler.  The compiler return value is stored to the
345# return_value argument, the text output is stored to the output variable.
346function( _HDF5_invoke_compiler language output_var return_value_var version_var is_parallel_var)
347  set(is_parallel FALSE)
348  if(HDF5_USE_STATIC_LIBRARIES)
349    set(lib_type_args -noshlib)
350  else()
351    set(lib_type_args -shlib)
352  endif()
353  set(scratch_dir ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hdf5)
354  if("${language}" STREQUAL "C")
355    set(test_file ${scratch_dir}/cmake_hdf5_test.c)
356  elseif("${language}" STREQUAL "CXX")
357    set(test_file ${scratch_dir}/cmake_hdf5_test.cxx)
358  elseif("${language}" STREQUAL "Fortran")
359    set(test_file ${scratch_dir}/cmake_hdf5_test.f90)
360  endif()
361  # Verify that the compiler wrapper can actually compile: sometimes the compiler
362  # wrapper exists, but not the compiler.  E.g. Miniconda / Anaconda Python
363  execute_process(
364    COMMAND ${HDF5_${language}_COMPILER_EXECUTABLE} ${test_file}
365    WORKING_DIRECTORY ${scratch_dir}
366    OUTPUT_VARIABLE output
367    ERROR_VARIABLE output
368    RESULT_VARIABLE return_value
369    )
370  if(return_value AND NOT HDF5_FIND_QUIETLY)
371    message(STATUS
372      "HDF5 ${language} compiler wrapper is unable to compile a minimal HDF5 program.")
373  else()
374    execute_process(
375      COMMAND ${HDF5_${language}_COMPILER_EXECUTABLE} -show ${lib_type_args} ${test_file}
376      WORKING_DIRECTORY ${scratch_dir}
377      OUTPUT_VARIABLE output
378      ERROR_VARIABLE output
379      RESULT_VARIABLE return_value
380      OUTPUT_STRIP_TRAILING_WHITESPACE
381      )
382    if(return_value AND NOT HDF5_FIND_QUIETLY)
383      message(STATUS
384        "Unable to determine HDF5 ${language} flags from HDF5 wrapper.")
385    endif()
386    execute_process(
387      COMMAND ${HDF5_${language}_COMPILER_EXECUTABLE} -showconfig
388      OUTPUT_VARIABLE config_output
389      ERROR_VARIABLE config_output
390      RESULT_VARIABLE return_value
391      OUTPUT_STRIP_TRAILING_WHITESPACE
392      )
393    if(return_value AND NOT HDF5_FIND_QUIETLY)
394      message(STATUS
395        "Unable to determine HDF5 ${language} version_var from HDF5 wrapper.")
396    endif()
397    string(REGEX MATCH "HDF5 Version: ([a-zA-Z0-9\\.\\-]*)" version "${config_output}")
398    if(version)
399      string(REPLACE "HDF5 Version: " "" version "${version}")
400      string(REPLACE "-patch" "." version "${version}")
401    endif()
402    if(config_output MATCHES "Parallel HDF5: yes")
403      set(is_parallel TRUE)
404    endif()
405  endif()
406  foreach(var output return_value version is_parallel)
407    set(${${var}_var} ${${var}} PARENT_SCOPE)
408  endforeach()
409endfunction()
410
411# Parse a compile line for definitions, includes, library paths, and libraries.
412function(_HDF5_parse_compile_line compile_line_var include_paths definitions
413    library_paths libraries libraries_hl)
414
415  separate_arguments(_compile_args NATIVE_COMMAND "${${compile_line_var}}")
416
417  foreach(_arg IN LISTS _compile_args)
418    if("${_arg}" MATCHES "^-I(.*)$")
419      # include directory
420      list(APPEND include_paths "${CMAKE_MATCH_1}")
421    elseif("${_arg}" MATCHES "^-D(.*)$")
422      # compile definition
423      list(APPEND definitions "-D${CMAKE_MATCH_1}")
424    elseif("${_arg}" MATCHES "^-L(.*)$")
425      # library search path
426      list(APPEND library_paths "${CMAKE_MATCH_1}")
427    elseif("${_arg}" MATCHES "^-l(hdf5.*hl.*)$")
428      # library name (hl)
429      list(APPEND libraries_hl "${CMAKE_MATCH_1}")
430    elseif("${_arg}" MATCHES "^-l(.*)$")
431      # library name
432      list(APPEND libraries "${CMAKE_MATCH_1}")
433    elseif("${_arg}" MATCHES "^(.:)?[/\\].*\\.(a|so|dylib|sl|lib)$")
434      # library file
435      if(NOT EXISTS "${_arg}")
436        continue()
437      endif()
438      get_filename_component(_lpath "${_arg}" DIRECTORY)
439      get_filename_component(_lname "${_arg}" NAME_WE)
440      string(REGEX REPLACE "^lib" "" _lname "${_lname}")
441      list(APPEND library_paths "${_lpath}")
442      if(_lname MATCHES "hdf5.*hl")
443        list(APPEND libraries_hl "${_lname}")
444      else()
445        list(APPEND libraries "${_lname}")
446      endif()
447    endif()
448  endforeach()
449  foreach(var include_paths definitions library_paths libraries libraries_hl)
450    set(${${var}_var} ${${var}} PARENT_SCOPE)
451  endforeach()
452endfunction()
453
454# Select a preferred imported configuration from a target
455function(_HDF5_select_imported_config target imported_conf)
456    # We will first assign the value to a local variable _imported_conf, then assign
457    # it to the function argument at the end.
458    get_target_property(_imported_conf ${target} MAP_IMPORTED_CONFIG_${CMAKE_BUILD_TYPE})
459    if (NOT _imported_conf)
460        # Get available imported configurations by examining target properties
461        get_target_property(_imported_conf ${target} IMPORTED_CONFIGURATIONS)
462        if(HDF5_FIND_DEBUG)
463            message(STATUS "Found imported configurations: ${_imported_conf}")
464        endif()
465        # Find the imported configuration that we prefer.
466        # We do this by making list of configurations in order of preference,
467        # starting with ${CMAKE_BUILD_TYPE} and ending with the first imported_conf
468        set(_preferred_confs ${CMAKE_BUILD_TYPE})
469        list(GET _imported_conf 0 _fallback_conf)
470        list(APPEND _preferred_confs RELWITHDEBINFO RELEASE DEBUG ${_fallback_conf})
471        if(HDF5_FIND_DEBUG)
472            message(STATUS "Start search through imported configurations in the following order: ${_preferred_confs}")
473        endif()
474        # Now find the first of these that is present in imported_conf
475        cmake_policy(PUSH)
476        cmake_policy(SET CMP0057 NEW) # support IN_LISTS
477        foreach (_conf IN LISTS _preferred_confs)
478            if (${_conf} IN_LIST _imported_conf)
479               set(_imported_conf ${_conf})
480               break()
481            endif()
482        endforeach()
483        cmake_policy(POP)
484    endif()
485    if(HDF5_FIND_DEBUG)
486        message(STATUS "Selected imported configuration: ${_imported_conf}")
487    endif()
488    # assign value to function argument
489    set(${imported_conf} ${_imported_conf} PARENT_SCOPE)
490endfunction()
491
492
493if(NOT HDF5_ROOT)
494    set(HDF5_ROOT $ENV{HDF5_ROOT})
495endif()
496if(HDF5_ROOT)
497    set(_HDF5_SEARCH_OPTS NO_DEFAULT_PATH)
498else()
499    set(_HDF5_SEARCH_OPTS)
500endif()
501
502# Try to find HDF5 using an installed hdf5-config.cmake
503if(NOT HDF5_FOUND AND NOT HDF5_NO_FIND_PACKAGE_CONFIG_FILE)
504    find_package(HDF5 QUIET NO_MODULE
505      HINTS ${HDF5_ROOT}
506      ${_HDF5_SEARCH_OPTS}
507      )
508    if( HDF5_FOUND)
509        if(HDF5_FIND_DEBUG)
510            message(STATUS "Found HDF5 at ${HDF5_DIR} via NO_MODULE. Now trying to extract locations etc.")
511        endif()
512        set(HDF5_IS_PARALLEL ${HDF5_ENABLE_PARALLEL})
513        set(HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIR})
514        set(HDF5_LIBRARIES)
515        if (NOT TARGET hdf5 AND NOT TARGET hdf5-static AND NOT TARGET hdf5-shared)
516            # Some HDF5 versions (e.g. 1.8.18) used hdf5::hdf5 etc
517            set(_target_prefix "hdf5::")
518        endif()
519        set(HDF5_C_TARGET ${_target_prefix}hdf5)
520        set(HDF5_C_HL_TARGET ${_target_prefix}hdf5_hl)
521        set(HDF5_CXX_TARGET ${_target_prefix}hdf5_cpp)
522        set(HDF5_CXX_HL_TARGET ${_target_prefix}hdf5_hl_cpp)
523        set(HDF5_Fortran_TARGET ${_target_prefix}hdf5_fortran)
524        set(HDF5_Fortran_HL_TARGET ${_target_prefix}hdf5_hl_fortran)
525        set(HDF5_DEFINITIONS "")
526        if(HDF5_USE_STATIC_LIBRARIES)
527            set(_suffix "-static")
528        else()
529            set(_suffix "-shared")
530        endif()
531        foreach(_lang ${HDF5_LANGUAGE_BINDINGS})
532
533            #Older versions of hdf5 don't have a static/shared suffix so
534            #if we detect that occurrence clear the suffix
535            if(_suffix AND NOT TARGET ${HDF5_${_lang}_TARGET}${_suffix})
536              if(NOT TARGET ${HDF5_${_lang}_TARGET})
537                #can't find this component with or without the suffix
538                #so bail out, and let the following locate HDF5
539                set(HDF5_FOUND FALSE)
540                break()
541              endif()
542              set(_suffix "")
543            endif()
544
545            if(HDF5_FIND_DEBUG)
546                message(STATUS "Trying to get properties of target ${HDF5_${_lang}_TARGET}${_suffix}")
547            endif()
548            # Find library for this target. Complicated as on Windows with a DLL, we need to search for the import-lib.
549            _HDF5_select_imported_config(${HDF5_${_lang}_TARGET}${_suffix} _hdf5_imported_conf)
550            get_target_property(_hdf5_lang_location ${HDF5_${_lang}_TARGET}${_suffix} IMPORTED_IMPLIB_${_hdf5_imported_conf} )
551            if (NOT _hdf5_lang_location)
552                # no import lib, just try LOCATION
553                get_target_property(_hdf5_lang_location ${HDF5_${_lang}_TARGET}${_suffix} LOCATION_${_hdf5_imported_conf})
554                if (NOT _hdf5_lang_location)
555                    get_target_property(_hdf5_lang_location ${HDF5_${_lang}_TARGET}${_suffix} LOCATION)
556                endif()
557            endif()
558            if( _hdf5_lang_location )
559                set(HDF5_${_lang}_LIBRARY ${_hdf5_lang_location})
560                list(APPEND HDF5_LIBRARIES ${HDF5_${_lang}_TARGET}${_suffix})
561                set(HDF5_${_lang}_LIBRARIES ${HDF5_${_lang}_TARGET}${_suffix})
562                set(HDF5_${_lang}_FOUND TRUE)
563            endif()
564            if(HDF5_FIND_HL)
565                get_target_property(_hdf5_lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} IMPORTED_IMPLIB_${_hdf5_imported_conf} )
566                if (NOT _hdf5_lang_hl_location)
567                    get_target_property(_hdf5_lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} LOCATION_${_hdf5_imported_conf})
568                    if (NOT _hdf5_hl_lang_location)
569                        get_target_property(_hdf5_hl_lang_location ${HDF5_${_lang}_HL_TARGET}${_suffix} LOCATION)
570                    endif()
571                endif()
572                if( _hdf5_lang_hl_location )
573                    set(HDF5_${_lang}_HL_LIBRARY ${_hdf5_lang_hl_location})
574                    list(APPEND HDF5_HL_LIBRARIES ${HDF5_${_lang}_HL_TARGET}${_suffix})
575                    set(HDF5_${_lang}_HL_LIBRARIES ${HDF5_${_lang}_HL_TARGET}${_suffix})
576                    set(HDF5_HL_FOUND TRUE)
577                endif()
578                unset(_hdf5_lang_hl_location)
579            endif()
580            unset(_hdf5_imported_conf)
581            unset(_hdf5_lang_location)
582        endforeach()
583    endif()
584endif()
585
586if(NOT HDF5_FOUND)
587  set(_HDF5_NEED_TO_SEARCH FALSE)
588  set(HDF5_COMPILER_NO_INTERROGATE TRUE)
589  # Only search for languages we've enabled
590  foreach(_lang IN LISTS HDF5_LANGUAGE_BINDINGS)
591    set(HDF5_${_lang}_LIBRARIES)
592    set(HDF5_${_lang}_HL_LIBRARIES)
593
594    # First check to see if our regular compiler is one of wrappers
595    if(_lang STREQUAL "C")
596      _HDF5_test_regular_compiler_C(
597        HDF5_${_lang}_COMPILER_NO_INTERROGATE
598        HDF5_${_lang}_VERSION
599        HDF5_${_lang}_IS_PARALLEL)
600    elseif(_lang STREQUAL "CXX")
601      _HDF5_test_regular_compiler_CXX(
602        HDF5_${_lang}_COMPILER_NO_INTERROGATE
603        HDF5_${_lang}_VERSION
604        HDF5_${_lang}_IS_PARALLEL)
605    elseif(_lang STREQUAL "Fortran")
606      _HDF5_test_regular_compiler_Fortran(
607        HDF5_${_lang}_COMPILER_NO_INTERROGATE
608        HDF5_${_lang}_IS_PARALLEL)
609    else()
610      continue()
611    endif()
612    if(HDF5_${_lang}_COMPILER_NO_INTERROGATE)
613      if(HDF5_FIND_DEBUG)
614        message(STATUS "HDF5: Using hdf5 compiler wrapper for all ${_lang} compiling")
615      endif()
616      set(HDF5_${_lang}_FOUND TRUE)
617      set(HDF5_${_lang}_COMPILER_EXECUTABLE_NO_INTERROGATE
618          "${CMAKE_${_lang}_COMPILER}"
619          CACHE FILEPATH "HDF5 ${_lang} compiler wrapper")
620      set(HDF5_${_lang}_DEFINITIONS)
621      set(HDF5_${_lang}_INCLUDE_DIRS)
622      set(HDF5_${_lang}_LIBRARIES)
623      set(HDF5_${_lang}_HL_LIBRARIES)
624
625      mark_as_advanced(HDF5_${_lang}_COMPILER_EXECUTABLE_NO_INTERROGATE)
626
627      set(HDF5_${_lang}_FOUND TRUE)
628      set(HDF5_HL_FOUND TRUE)
629    else()
630      set(HDF5_COMPILER_NO_INTERROGATE FALSE)
631      # If this language isn't using the wrapper, then try to seed the
632      # search options with the wrapper
633      find_program(HDF5_${_lang}_COMPILER_EXECUTABLE
634        NAMES ${HDF5_${_lang}_COMPILER_NAMES} NAMES_PER_DIR
635        HINTS ${HDF5_ROOT}
636        PATH_SUFFIXES bin Bin
637        DOC "HDF5 ${_lang} Wrapper compiler.  Used only to detect HDF5 compile flags."
638        ${_HDF5_SEARCH_OPTS}
639      )
640      mark_as_advanced( HDF5_${_lang}_COMPILER_EXECUTABLE )
641      unset(HDF5_${_lang}_COMPILER_NAMES)
642
643      if(HDF5_${_lang}_COMPILER_EXECUTABLE)
644        _HDF5_invoke_compiler(${_lang} HDF5_${_lang}_COMPILE_LINE
645          HDF5_${_lang}_RETURN_VALUE HDF5_${_lang}_VERSION HDF5_${_lang}_IS_PARALLEL)
646        if(HDF5_${_lang}_RETURN_VALUE EQUAL 0)
647          if(HDF5_FIND_DEBUG)
648            message(STATUS "HDF5: Using hdf5 compiler wrapper to determine ${_lang} configuration")
649          endif()
650          _HDF5_parse_compile_line( HDF5_${_lang}_COMPILE_LINE
651            HDF5_${_lang}_INCLUDE_DIRS
652            HDF5_${_lang}_DEFINITIONS
653            HDF5_${_lang}_LIBRARY_DIRS
654            HDF5_${_lang}_LIBRARY_NAMES
655            HDF5_${_lang}_HL_LIBRARY_NAMES
656          )
657          set(HDF5_${_lang}_LIBRARIES)
658
659          foreach(_lib IN LISTS HDF5_${_lang}_LIBRARY_NAMES)
660            set(_HDF5_SEARCH_NAMES_LOCAL)
661            if("x${_lib}" MATCHES "hdf5")
662              # hdf5 library
663              set(_HDF5_SEARCH_OPTS_LOCAL ${_HDF5_SEARCH_OPTS})
664              if(HDF5_USE_STATIC_LIBRARIES)
665                if(WIN32)
666                  set(_HDF5_SEARCH_NAMES_LOCAL lib${_lib})
667                else()
668                  set(_HDF5_SEARCH_NAMES_LOCAL lib${_lib}.a)
669                endif()
670              endif()
671            else()
672              # external library
673              set(_HDF5_SEARCH_OPTS_LOCAL)
674            endif()
675            find_library(HDF5_${_lang}_LIBRARY_${_lib}
676              NAMES ${_HDF5_SEARCH_NAMES_LOCAL} ${_lib} NAMES_PER_DIR
677              HINTS ${HDF5_${_lang}_LIBRARY_DIRS}
678                    ${HDF5_ROOT}
679              ${_HDF5_SEARCH_OPTS_LOCAL}
680              )
681            unset(_HDF5_SEARCH_OPTS_LOCAL)
682            unset(_HDF5_SEARCH_NAMES_LOCAL)
683            if(HDF5_${_lang}_LIBRARY_${_lib})
684              list(APPEND HDF5_${_lang}_LIBRARIES ${HDF5_${_lang}_LIBRARY_${_lib}})
685            else()
686              list(APPEND HDF5_${_lang}_LIBRARIES ${_lib})
687            endif()
688          endforeach()
689          if(HDF5_FIND_HL)
690            set(HDF5_${_lang}_HL_LIBRARIES)
691            foreach(_lib IN LISTS HDF5_${_lang}_HL_LIBRARY_NAMES)
692              set(_HDF5_SEARCH_NAMES_LOCAL)
693              if("x${_lib}" MATCHES "hdf5")
694                # hdf5 library
695                set(_HDF5_SEARCH_OPTS_LOCAL ${_HDF5_SEARCH_OPTS})
696                if(HDF5_USE_STATIC_LIBRARIES)
697                  if(WIN32)
698                    set(_HDF5_SEARCH_NAMES_LOCAL lib${_lib})
699                  else()
700                    set(_HDF5_SEARCH_NAMES_LOCAL lib${_lib}.a)
701                  endif()
702                endif()
703              else()
704                # external library
705                set(_HDF5_SEARCH_OPTS_LOCAL)
706              endif()
707              find_library(HDF5_${_lang}_LIBRARY_${_lib}
708                NAMES ${_HDF5_SEARCH_NAMES_LOCAL} ${_lib} NAMES_PER_DIR
709                HINTS ${HDF5_${_lang}_LIBRARY_DIRS}
710                      ${HDF5_ROOT}
711                ${_HDF5_SEARCH_OPTS_LOCAL}
712                )
713              unset(_HDF5_SEARCH_OPTS_LOCAL)
714              unset(_HDF5_SEARCH_NAMES_LOCAL)
715              if(HDF5_${_lang}_LIBRARY_${_lib})
716                list(APPEND HDF5_${_lang}_HL_LIBRARIES ${HDF5_${_lang}_LIBRARY_${_lib}})
717              else()
718                list(APPEND HDF5_${_lang}_HL_LIBRARIES ${_lib})
719              endif()
720            endforeach()
721            set(HDF5_HL_FOUND TRUE)
722          endif()
723
724          set(HDF5_${_lang}_FOUND TRUE)
725          list(REMOVE_DUPLICATES HDF5_${_lang}_DEFINITIONS)
726          list(REMOVE_DUPLICATES HDF5_${_lang}_INCLUDE_DIRS)
727        else()
728          set(_HDF5_NEED_TO_SEARCH TRUE)
729        endif()
730      else()
731        set(_HDF5_NEED_TO_SEARCH TRUE)
732      endif()
733    endif()
734    if(HDF5_${_lang}_VERSION)
735      if(NOT HDF5_VERSION)
736        set(HDF5_VERSION ${HDF5_${_lang}_VERSION})
737      elseif(NOT HDF5_VERSION VERSION_EQUAL HDF5_${_lang}_VERSION)
738        message(WARNING "HDF5 Version found for language ${_lang}, ${HDF5_${_lang}_VERSION} is different than previously found version ${HDF5_VERSION}")
739      endif()
740    endif()
741    if(DEFINED HDF5_${_lang}_IS_PARALLEL)
742      if(NOT DEFINED HDF5_IS_PARALLEL)
743        set(HDF5_IS_PARALLEL ${HDF5_${_lang}_IS_PARALLEL})
744      elseif(NOT HDF5_IS_PARALLEL AND HDF5_${_lang}_IS_PARALLEL)
745        message(WARNING "HDF5 found for language ${_lang} is parallel but previously found language is not parallel.")
746      elseif(HDF5_IS_PARALLEL AND NOT HDF5_${_lang}_IS_PARALLEL)
747        message(WARNING "HDF5 found for language ${_lang} is not parallel but previously found language is parallel.")
748      endif()
749    endif()
750  endforeach()
751  unset(_lib)
752else()
753  set(_HDF5_NEED_TO_SEARCH TRUE)
754endif()
755
756if(NOT HDF5_FOUND AND HDF5_COMPILER_NO_INTERROGATE)
757  # No arguments necessary, all languages can use the compiler wrappers
758  set(HDF5_FOUND TRUE)
759  set(HDF5_METHOD "Included by compiler wrappers")
760  set(HDF5_REQUIRED_VARS HDF5_METHOD)
761elseif(NOT HDF5_FOUND AND NOT _HDF5_NEED_TO_SEARCH)
762  # Compiler wrappers aren't being used by the build but were found and used
763  # to determine necessary include and library flags
764  set(HDF5_INCLUDE_DIRS)
765  set(HDF5_LIBRARIES)
766  set(HDF5_HL_LIBRARIES)
767  foreach(_lang IN LISTS HDF5_LANGUAGE_BINDINGS)
768    if(HDF5_${_lang}_FOUND)
769      if(NOT HDF5_${_lang}_COMPILER_NO_INTERROGATE)
770        list(APPEND HDF5_DEFINITIONS ${HDF5_${_lang}_DEFINITIONS})
771        list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${_lang}_INCLUDE_DIRS})
772        list(APPEND HDF5_LIBRARIES ${HDF5_${_lang}_LIBRARIES})
773        if(HDF5_FIND_HL)
774          list(APPEND HDF5_HL_LIBRARIES ${HDF5_${_lang}_HL_LIBRARIES})
775        endif()
776      endif()
777    endif()
778  endforeach()
779  list(REMOVE_DUPLICATES HDF5_DEFINITIONS)
780  list(REMOVE_DUPLICATES HDF5_INCLUDE_DIRS)
781  set(HDF5_FOUND TRUE)
782  set(HDF5_REQUIRED_VARS HDF5_LIBRARIES)
783  if(HDF5_FIND_HL)
784    list(APPEND HDF5_REQUIRED_VARS HDF5_HL_LIBRARIES)
785  endif()
786endif()
787
788find_program( HDF5_DIFF_EXECUTABLE
789    NAMES h5diff
790    HINTS ${HDF5_ROOT}
791    PATH_SUFFIXES bin Bin
792    ${_HDF5_SEARCH_OPTS}
793    DOC "HDF5 file differencing tool." )
794mark_as_advanced( HDF5_DIFF_EXECUTABLE )
795
796if( NOT HDF5_FOUND )
797    # seed the initial lists of libraries to find with items we know we need
798    set(HDF5_C_LIBRARY_NAMES          hdf5)
799    set(HDF5_C_HL_LIBRARY_NAMES       hdf5_hl ${HDF5_C_LIBRARY_NAMES} )
800
801    set(HDF5_CXX_LIBRARY_NAMES        hdf5_cpp    ${HDF5_C_LIBRARY_NAMES})
802    set(HDF5_CXX_HL_LIBRARY_NAMES     hdf5_hl_cpp ${HDF5_C_HL_LIBRARY_NAMES} ${HDF5_CXX_LIBRARY_NAMES})
803
804    set(HDF5_Fortran_LIBRARY_NAMES    hdf5_fortran   ${HDF5_C_LIBRARY_NAMES})
805    set(HDF5_Fortran_HL_LIBRARY_NAMES hdf5_hl_fortran hdf5hl_fortran ${HDF5_C_HL_LIBRARY_NAMES} ${HDF5_Fortran_LIBRARY_NAMES})
806
807    # suffixes as seen on Linux, MSYS2, ...
808    set(_lib_suffixes hdf5)
809    if(NOT HDF5_PREFER_PARALLEL)
810      list(APPEND _lib_suffixes hdf5/serial)
811    endif()
812    if(HDF5_USE_STATIC_LIBRARIES)
813      set(_inc_suffixes include/static)
814    else()
815      set(_inc_suffixes include/shared)
816    endif()
817
818    foreach(_lang IN LISTS HDF5_LANGUAGE_BINDINGS)
819        set(HDF5_${_lang}_LIBRARIES)
820        set(HDF5_${_lang}_HL_LIBRARIES)
821
822        # The "main" library.
823        set(_hdf5_main_library "")
824
825        # find the HDF5 libraries
826        foreach(LIB IN LISTS HDF5_${_lang}_LIBRARY_NAMES)
827            if(HDF5_USE_STATIC_LIBRARIES)
828                # According to bug 1643 on the CMake bug tracker, this is the
829                # preferred method for searching for a static library.
830                # See https://gitlab.kitware.com/cmake/cmake/-/issues/1643.  We search
831                # first for the full static library name, but fall back to a
832                # generic search on the name if the static search fails.
833                set( THIS_LIBRARY_SEARCH_DEBUG
834                    lib${LIB}d.a lib${LIB}_debug.a lib${LIB}d lib${LIB}_D lib${LIB}_debug
835                    lib${LIB}d-static.a lib${LIB}_debug-static.a ${LIB}d-static ${LIB}_D-static ${LIB}_debug-static )
836                set( THIS_LIBRARY_SEARCH_RELEASE lib${LIB}.a lib${LIB} lib${LIB}-static.a ${LIB}-static)
837            else()
838                set( THIS_LIBRARY_SEARCH_DEBUG ${LIB}d ${LIB}_D ${LIB}_debug ${LIB}d-shared ${LIB}_D-shared ${LIB}_debug-shared)
839                set( THIS_LIBRARY_SEARCH_RELEASE ${LIB} ${LIB}-shared)
840                if(WIN32)
841                  list(APPEND HDF5_DEFINITIONS "-DH5_BUILT_AS_DYNAMIC_LIB")
842                endif()
843            endif()
844            find_library(HDF5_${LIB}_LIBRARY_DEBUG
845                NAMES ${THIS_LIBRARY_SEARCH_DEBUG}
846                HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib ${_lib_suffixes}
847                ${_HDF5_SEARCH_OPTS}
848            )
849            find_library(HDF5_${LIB}_LIBRARY_RELEASE
850                NAMES ${THIS_LIBRARY_SEARCH_RELEASE}
851                HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib ${_lib_suffixes}
852                ${_HDF5_SEARCH_OPTS}
853            )
854
855            # Set the "main" library if not already set.
856            if (NOT _hdf5_main_library)
857              if (HDF5_${LIB}_LIBRARY_RELEASE)
858                set(_hdf5_main_library "${HDF5_${LIB}_LIBRARY_RELEASE}")
859              elseif (HDF5_${LIB}_LIBRARY_DEBUG)
860                set(_hdf5_main_library "${HDF5_${LIB}_LIBRARY_DEBUG}")
861              endif ()
862            endif ()
863
864            select_library_configurations( HDF5_${LIB} )
865            list(APPEND HDF5_${_lang}_LIBRARIES ${HDF5_${LIB}_LIBRARY})
866        endforeach()
867        if(HDF5_${_lang}_LIBRARIES)
868            set(HDF5_${_lang}_FOUND TRUE)
869        endif()
870
871        # Append the libraries for this language binding to the list of all
872        # required libraries.
873        list(APPEND HDF5_LIBRARIES ${HDF5_${_lang}_LIBRARIES})
874
875        # find the HDF5 include directories
876        set(_hdf5_inc_extra_paths)
877        set(_hdf5_inc_extra_suffixes)
878        if("${_lang}" STREQUAL "Fortran")
879            set(HDF5_INCLUDE_FILENAME hdf5.mod HDF5.mod)
880
881            # Add library-based search paths for Fortran modules.
882            if (NOT _hdf5_main_library STREQUAL "")
883              # gfortran module directory
884              if (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
885                get_filename_component(_hdf5_library_dir "${_hdf5_main_library}" DIRECTORY)
886                list(APPEND _hdf5_inc_extra_paths "${_hdf5_library_dir}")
887                unset(_hdf5_library_dir)
888                list(APPEND _hdf5_inc_extra_suffixes gfortran/modules)
889              endif ()
890            endif ()
891        elseif("${_lang}" STREQUAL "CXX")
892            set(HDF5_INCLUDE_FILENAME H5Cpp.h)
893        else()
894            set(HDF5_INCLUDE_FILENAME hdf5.h)
895        endif()
896
897        unset(_hdf5_main_library)
898
899        find_path(HDF5_${_lang}_INCLUDE_DIR ${HDF5_INCLUDE_FILENAME}
900            HINTS ${HDF5_ROOT}
901            PATHS $ENV{HOME}/.local/include ${_hdf5_inc_extra_paths}
902            PATH_SUFFIXES include Include ${_inc_suffixes} ${_lib_suffixes} ${_hdf5_inc_extra_suffixes}
903            ${_HDF5_SEARCH_OPTS}
904        )
905        mark_as_advanced(HDF5_${_lang}_INCLUDE_DIR)
906        unset(_hdf5_inc_extra_paths)
907        unset(_hdf5_inc_extra_suffixes)
908        # set the _DIRS variable as this is what the user will normally use
909        set(HDF5_${_lang}_INCLUDE_DIRS ${HDF5_${_lang}_INCLUDE_DIR})
910        list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${_lang}_INCLUDE_DIR})
911
912        if(HDF5_FIND_HL)
913            foreach(LIB IN LISTS HDF5_${_lang}_HL_LIBRARY_NAMES)
914                if(HDF5_USE_STATIC_LIBRARIES)
915                    # According to bug 1643 on the CMake bug tracker, this is the
916                    # preferred method for searching for a static library.
917                    # See https://gitlab.kitware.com/cmake/cmake/-/issues/1643.  We search
918                    # first for the full static library name, but fall back to a
919                    # generic search on the name if the static search fails.
920                    set( THIS_LIBRARY_SEARCH_DEBUG
921                        lib${LIB}d.a lib${LIB}_debug.a lib${LIB}d lib${LIB}_D lib${LIB}_debug
922                        lib${LIB}d-static.a lib${LIB}_debug-static.a lib${LIB}d-static lib${LIB}_D-static lib${LIB}_debug-static )
923                    set( THIS_LIBRARY_SEARCH_RELEASE lib${LIB}.a lib${LIB} lib${LIB}-static.a lib${LIB}-static)
924                else()
925                    set( THIS_LIBRARY_SEARCH_DEBUG ${LIB}d ${LIB}_D ${LIB}_debug ${LIB}d-shared ${LIB}_D-shared ${LIB}_debug-shared)
926                    set( THIS_LIBRARY_SEARCH_RELEASE ${LIB} ${LIB}-shared)
927                endif()
928                find_library(HDF5_${LIB}_LIBRARY_DEBUG
929                    NAMES ${THIS_LIBRARY_SEARCH_DEBUG}
930                    HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib ${_lib_suffixes}
931                    ${_HDF5_SEARCH_OPTS}
932                )
933                find_library(HDF5_${LIB}_LIBRARY_RELEASE
934                    NAMES ${THIS_LIBRARY_SEARCH_RELEASE}
935                    HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib ${_lib_suffixes}
936                    ${_HDF5_SEARCH_OPTS}
937                )
938
939                select_library_configurations( HDF5_${LIB} )
940                list(APPEND HDF5_${_lang}_HL_LIBRARIES ${HDF5_${LIB}_LIBRARY})
941            endforeach()
942
943            # Append the libraries for this language binding to the list of all
944            # required libraries.
945            list(APPEND HDF5_HL_LIBRARIES ${HDF5_${_lang}_HL_LIBRARIES})
946        endif()
947    endforeach()
948    if(HDF5_FIND_HL AND HDF5_HL_LIBRARIES)
949        set(HDF5_HL_FOUND TRUE)
950    endif()
951
952    list(REMOVE_DUPLICATES HDF5_DEFINITIONS)
953    list(REMOVE_DUPLICATES HDF5_INCLUDE_DIRS)
954
955    # If the HDF5 include directory was found, open H5pubconf.h to determine if
956    # HDF5 was compiled with parallel IO support
957    set( HDF5_IS_PARALLEL FALSE )
958    set( HDF5_VERSION "" )
959    foreach( _dir IN LISTS HDF5_INCLUDE_DIRS )
960      foreach(_hdr "${_dir}/H5pubconf.h" "${_dir}/H5pubconf-64.h" "${_dir}/H5pubconf-32.h")
961        if( EXISTS "${_hdr}" )
962            file( STRINGS "${_hdr}"
963                HDF5_HAVE_PARALLEL_DEFINE
964                REGEX "HAVE_PARALLEL 1" )
965            if( HDF5_HAVE_PARALLEL_DEFINE )
966                set( HDF5_IS_PARALLEL TRUE )
967            endif()
968            unset(HDF5_HAVE_PARALLEL_DEFINE)
969
970            file( STRINGS "${_hdr}"
971                HDF5_VERSION_DEFINE
972                REGEX "^[ \t]*#[ \t]*define[ \t]+H5_VERSION[ \t]+" )
973            if( "${HDF5_VERSION_DEFINE}" MATCHES
974                "H5_VERSION[ \t]+\"([0-9]+\\.[0-9]+\\.[0-9]+)(-patch([0-9]+))?\"" )
975                set( HDF5_VERSION "${CMAKE_MATCH_1}" )
976                if( CMAKE_MATCH_3 )
977                  set( HDF5_VERSION ${HDF5_VERSION}.${CMAKE_MATCH_3})
978                endif()
979            endif()
980            unset(HDF5_VERSION_DEFINE)
981        endif()
982      endforeach()
983    endforeach()
984    unset(_hdr)
985    unset(_dir)
986    set( HDF5_IS_PARALLEL ${HDF5_IS_PARALLEL} CACHE BOOL
987        "HDF5 library compiled with parallel IO support" )
988    mark_as_advanced( HDF5_IS_PARALLEL )
989
990    set(HDF5_REQUIRED_VARS HDF5_LIBRARIES HDF5_INCLUDE_DIRS)
991    if(HDF5_FIND_HL)
992        list(APPEND HDF5_REQUIRED_VARS HDF5_HL_LIBRARIES)
993    endif()
994endif()
995
996# For backwards compatibility we set HDF5_INCLUDE_DIR to the value of
997# HDF5_INCLUDE_DIRS
998if( HDF5_INCLUDE_DIRS )
999  set( HDF5_INCLUDE_DIR "${HDF5_INCLUDE_DIRS}" )
1000endif()
1001
1002# If HDF5_REQUIRED_VARS is empty at this point, then it's likely that
1003# something external is trying to explicitly pass already found
1004# locations
1005if(NOT HDF5_REQUIRED_VARS)
1006    set(HDF5_REQUIRED_VARS HDF5_LIBRARIES HDF5_INCLUDE_DIRS)
1007endif()
1008
1009find_package_handle_standard_args(HDF5
1010    REQUIRED_VARS ${HDF5_REQUIRED_VARS}
1011    VERSION_VAR   HDF5_VERSION
1012    HANDLE_COMPONENTS
1013)
1014
1015unset(_HDF5_SEARCH_OPTS)
1016
1017if( HDF5_FOUND AND NOT HDF5_DIR)
1018  # hide HDF5_DIR for the non-advanced user to avoid confusion with
1019  # HDF5_DIR-NOT_FOUND while HDF5 was found.
1020  mark_as_advanced(HDF5_DIR)
1021endif()
1022
1023if (HDF5_FOUND)
1024  if (NOT TARGET HDF5::HDF5)
1025    add_library(HDF5::HDF5 INTERFACE IMPORTED)
1026    string(REPLACE "-D" "" _hdf5_definitions "${HDF5_DEFINITIONS}")
1027    set_target_properties(HDF5::HDF5 PROPERTIES
1028      INTERFACE_INCLUDE_DIRECTORIES "${HDF5_INCLUDE_DIRS}"
1029      INTERFACE_COMPILE_DEFINITIONS "${_hdf5_definitions}")
1030    unset(_hdf5_definitions)
1031    target_link_libraries(HDF5::HDF5 INTERFACE ${HDF5_LIBRARIES})
1032  endif ()
1033
1034  foreach (hdf5_lang IN LISTS HDF5_LANGUAGE_BINDINGS)
1035    if (hdf5_lang STREQUAL "C")
1036      set(hdf5_target_name "hdf5")
1037    elseif (hdf5_lang STREQUAL "CXX")
1038      set(hdf5_target_name "hdf5_cpp")
1039    elseif (hdf5_lang STREQUAL "Fortran")
1040      set(hdf5_target_name "hdf5_fortran")
1041    else ()
1042      continue ()
1043    endif ()
1044
1045    if (NOT TARGET "hdf5::${hdf5_target_name}")
1046      if (HDF5_COMPILER_NO_INTERROGATE)
1047        add_library("hdf5::${hdf5_target_name}" INTERFACE IMPORTED)
1048        string(REPLACE "-D" "" _hdf5_definitions "${HDF5_${hdf5_lang}_DEFINITIONS}")
1049        set_target_properties("hdf5::${hdf5_target_name}" PROPERTIES
1050          INTERFACE_INCLUDE_DIRECTORIES "${HDF5_${hdf5_lang}_INCLUDE_DIRS}"
1051          INTERFACE_COMPILE_DEFINITIONS "${_hdf5_definitions}")
1052      else()
1053        if (DEFINED "HDF5_${hdf5_target_name}_LIBRARY")
1054          set(_hdf5_location "${HDF5_${hdf5_target_name}_LIBRARY}")
1055        elseif (DEFINED "HDF5_${hdf5_lang}_LIBRARY")
1056          set(_hdf5_location "${HDF5_${hdf5_lang}_LIBRARY}")
1057        elseif (DEFINED "HDF5_${hdf5_lang}_LIBRARY_${hdf5_target_name}")
1058          set(_hdf5_location "${HDF5_${hdf5_lang}_LIBRARY_${hdf5_target_name}}")
1059        else ()
1060          # Error if we still don't have the location.
1061          message(SEND_ERROR
1062            "HDF5 was found, but a different variable was set which contains "
1063            "the location of the `hdf5::${hdf5_target_name}` library.")
1064        endif ()
1065        add_library("hdf5::${hdf5_target_name}" UNKNOWN IMPORTED)
1066        string(REPLACE "-D" "" _hdf5_definitions "${HDF5_${hdf5_lang}_DEFINITIONS}")
1067        if (NOT HDF5_${hdf5_lang}_INCLUDE_DIRS)
1068         set(HDF5_${hdf5_lang}_INCLUDE_DIRS ${HDF5_INCLUDE_DIRS})
1069        endif ()
1070        set_target_properties("hdf5::${hdf5_target_name}" PROPERTIES
1071          IMPORTED_LOCATION "${_hdf5_location}"
1072          IMPORTED_IMPLIB "${_hdf5_location}"
1073          INTERFACE_INCLUDE_DIRECTORIES "${HDF5_${hdf5_lang}_INCLUDE_DIRS}"
1074          INTERFACE_COMPILE_DEFINITIONS "${_hdf5_definitions}")
1075        if (_hdf5_libtype STREQUAL "SHARED")
1076          set_property(TARGET "hdf5::${hdf5_target_name}" APPEND
1077            PROPERTY
1078              INTERFACE_COMPILE_DEFINITIONS H5_BUILT_AS_DYNAMIC_LIB)
1079        elseif (_hdf5_libtype STREQUAL "STATIC")
1080          set_property(TARGET "hdf5::${hdf5_target_name}" APPEND
1081            PROPERTY
1082              INTERFACE_COMPILE_DEFINITIONS H5_BUILT_AS_STATIC_LIB)
1083        endif ()
1084        unset(_hdf5_definitions)
1085        unset(_hdf5_libtype)
1086        unset(_hdf5_location)
1087      endif ()
1088    endif ()
1089
1090    if (NOT HDF5_FIND_HL)
1091      continue ()
1092    endif ()
1093
1094    set(hdf5_alt_target_name "")
1095    if (hdf5_lang STREQUAL "C")
1096      set(hdf5_target_name "hdf5_hl")
1097    elseif (hdf5_lang STREQUAL "CXX")
1098      set(hdf5_target_name "hdf5_hl_cpp")
1099    elseif (hdf5_lang STREQUAL "Fortran")
1100      set(hdf5_target_name "hdf5_hl_fortran")
1101      set(hdf5_alt_target_name "hdf5hl_fortran")
1102    else ()
1103      continue ()
1104    endif ()
1105
1106    if (NOT TARGET "hdf5::${hdf5_target_name}")
1107      if (HDF5_COMPILER_NO_INTERROGATE)
1108        add_library("hdf5::${hdf5_target_name}" INTERFACE IMPORTED)
1109        string(REPLACE "-D" "" _hdf5_definitions "${HDF5_${hdf5_lang}_HL_DEFINITIONS}")
1110        set_target_properties("hdf5::${hdf5_target_name}" PROPERTIES
1111          INTERFACE_INCLUDE_DIRECTORIES "${HDF5_${hdf5_lang}_HL_INCLUDE_DIRS}"
1112          INTERFACE_COMPILE_DEFINITIONS "${_hdf5_definitions}")
1113      else()
1114        if (DEFINED "HDF5_${hdf5_target_name}_LIBRARY")
1115          set(_hdf5_location "${HDF5_${hdf5_target_name}_LIBRARY}")
1116        elseif (DEFINED "HDF5_${hdf5_lang}_HL_LIBRARY")
1117          set(_hdf5_location "${HDF5_${hdf5_lang}_HL_LIBRARY}")
1118        elseif (DEFINED "HDF5_${hdf5_lang}_LIBRARY_${hdf5_target_name}")
1119          set(_hdf5_location "${HDF5_${hdf5_lang}_LIBRARY_${hdf5_target_name}}")
1120        elseif (hdf5_alt_target_name AND DEFINED "HDF5_${hdf5_lang}_LIBRARY_${hdf5_alt_target_name}")
1121          set(_hdf5_location "${HDF5_${hdf5_lang}_LIBRARY_${hdf5_alt_target_name}}")
1122        else ()
1123          # Error if we still don't have the location.
1124          message(SEND_ERROR
1125            "HDF5 was found, but a different variable was set which contains "
1126            "the location of the `hdf5::${hdf5_target_name}` library.")
1127        endif ()
1128        add_library("hdf5::${hdf5_target_name}" UNKNOWN IMPORTED)
1129        string(REPLACE "-D" "" _hdf5_definitions "${HDF5_${hdf5_lang}_HL_DEFINITIONS}")
1130        set_target_properties("hdf5::${hdf5_target_name}" PROPERTIES
1131          IMPORTED_LOCATION "${_hdf5_location}"
1132          IMPORTED_IMPLIB "${_hdf5_location}"
1133          INTERFACE_INCLUDE_DIRECTORIES "${HDF5_${hdf5_lang}_HL_INCLUDE_DIRS}"
1134          INTERFACE_COMPILE_DEFINITIONS "${_hdf5_definitions}")
1135        if (_hdf5_libtype STREQUAL "SHARED")
1136          set_property(TARGET "hdf5::${hdf5_target_name}" APPEND
1137            PROPERTY
1138              INTERFACE_COMPILE_DEFINITIONS H5_BUILT_AS_DYNAMIC_LIB)
1139        elseif (_hdf5_libtype STREQUAL "STATIC")
1140          set_property(TARGET "hdf5::${hdf5_target_name}" APPEND
1141            PROPERTY
1142              INTERFACE_COMPILE_DEFINITIONS H5_BUILT_AS_STATIC_LIB)
1143        endif ()
1144        unset(_hdf5_definitions)
1145        unset(_hdf5_libtype)
1146        unset(_hdf5_location)
1147      endif ()
1148    endif ()
1149  endforeach ()
1150  unset(hdf5_lang)
1151
1152  if (HDF5_DIFF_EXECUTABLE AND NOT TARGET hdf5::h5diff)
1153    add_executable(hdf5::h5diff IMPORTED)
1154    set_target_properties(hdf5::h5diff PROPERTIES
1155      IMPORTED_LOCATION "${HDF5_DIFF_EXECUTABLE}")
1156  endif ()
1157endif ()
1158
1159if (HDF5_FIND_DEBUG)
1160  message(STATUS "HDF5_DIR: ${HDF5_DIR}")
1161  message(STATUS "HDF5_DEFINITIONS: ${HDF5_DEFINITIONS}")
1162  message(STATUS "HDF5_INCLUDE_DIRS: ${HDF5_INCLUDE_DIRS}")
1163  message(STATUS "HDF5_LIBRARIES: ${HDF5_LIBRARIES}")
1164  message(STATUS "HDF5_HL_LIBRARIES: ${HDF5_HL_LIBRARIES}")
1165  foreach(_lang IN LISTS HDF5_LANGUAGE_BINDINGS)
1166    message(STATUS "HDF5_${_lang}_DEFINITIONS: ${HDF5_${_lang}_DEFINITIONS}")
1167    message(STATUS "HDF5_${_lang}_INCLUDE_DIR: ${HDF5_${_lang}_INCLUDE_DIR}")
1168    message(STATUS "HDF5_${_lang}_INCLUDE_DIRS: ${HDF5_${_lang}_INCLUDE_DIRS}")
1169    message(STATUS "HDF5_${_lang}_LIBRARY: ${HDF5_${_lang}_LIBRARY}")
1170    message(STATUS "HDF5_${_lang}_LIBRARIES: ${HDF5_${_lang}_LIBRARIES}")
1171    message(STATUS "HDF5_${_lang}_HL_LIBRARY: ${HDF5_${_lang}_HL_LIBRARY}")
1172    message(STATUS "HDF5_${_lang}_HL_LIBRARIES: ${HDF5_${_lang}_HL_LIBRARIES}")
1173  endforeach()
1174  message(STATUS "Defined targets (if any):")
1175  foreach(_lang IN  ITEMS "" "_cpp" "_fortran")
1176    foreach(_hl IN  ITEMS "" "_hl")
1177      foreach(_prefix IN ITEMS "hdf5::" "")
1178        foreach(_suffix IN ITEMS "-static" "-shared" "")
1179          set (_target ${_prefix}hdf5${_hl}${_lang}${_suffix})
1180          if (TARGET  ${_target})
1181            message(STATUS "... ${_target}")
1182          else()
1183            #message(STATUS "... ${_target} does not exist")
1184          endif()
1185        endforeach()
1186      endforeach()
1187    endforeach()
1188  endforeach()
1189endif()
1190unset(_lang)
1191unset(_HDF5_NEED_TO_SEARCH)
1192