Imported Upstream version 2.8.11.2
[platform/upstream/cmake.git] / Modules / FindHDF5.cmake
1 # - Find HDF5, a library for reading and writing self describing array data.
2 #
3 # This module invokes the HDF5 wrapper compiler that should be installed
4 # alongside HDF5.  Depending upon the HDF5 Configuration, the wrapper compiler
5 # is called either h5cc or h5pcc.  If this succeeds, the module will then call
6 # the compiler with the -show argument to see what flags are used when compiling
7 # an HDF5 client application.
8 #
9 # The module will optionally accept the COMPONENTS argument.  If no COMPONENTS
10 # are specified, then the find module will default to finding only the HDF5 C
11 # library.  If one or more COMPONENTS are specified, the module will attempt to
12 # find the language bindings for the specified components.  The only valid
13 # components are C, CXX, Fortran, HL, and Fortran_HL.  If the COMPONENTS
14 # argument is not given, the module will attempt to find only the C bindings.
15 #
16 # On UNIX systems, this module will read the variable HDF5_USE_STATIC_LIBRARIES
17 # to determine whether or not to prefer a static link to a dynamic link for HDF5
18 # and all of it's dependencies.  To use this feature, make sure that the
19 # HDF5_USE_STATIC_LIBRARIES variable is set before the call to find_package.
20 #
21 # To provide the module with a hint about where to find your HDF5 installation,
22 # you can set the environment variable HDF5_ROOT.  The Find module will then
23 # look in this path when searching for HDF5 executables, paths, and libraries.
24 #
25 # In addition to finding the includes and libraries required to compile an HDF5
26 # client application, this module also makes an effort to find tools that come
27 # with the HDF5 distribution that may be useful for regression testing.
28 #
29 # This module will define the following variables:
30 #  HDF5_INCLUDE_DIRS - Location of the hdf5 includes
31 #  HDF5_INCLUDE_DIR - Location of the hdf5 includes (deprecated)
32 #  HDF5_DEFINITIONS - Required compiler definitions for HDF5
33 #  HDF5_C_LIBRARIES - Required libraries for the HDF5 C bindings.
34 #  HDF5_CXX_LIBRARIES - Required libraries for the HDF5 C++ bindings
35 #  HDF5_Fortran_LIBRARIES - Required libraries for the HDF5 Fortran bindings
36 #  HDF5_HL_LIBRARIES - Required libraries for the HDF5 high level API
37 #  HDF5_Fortran_HL_LIBRARIES - Required libraries for the high level Fortran
38 #                              bindings.
39 #  HDF5_LIBRARIES - Required libraries for all requested bindings
40 #  HDF5_FOUND - true if HDF5 was found on the system
41 #  HDF5_LIBRARY_DIRS - the full set of library directories
42 #  HDF5_IS_PARALLEL - Whether or not HDF5 was found with parallel IO support
43 #  HDF5_C_COMPILER_EXECUTABLE - the path to the HDF5 C wrapper compiler
44 #  HDF5_CXX_COMPILER_EXECUTABLE - the path to the HDF5 C++ wrapper compiler
45 #  HDF5_Fortran_COMPILER_EXECUTABLE - the path to the HDF5 Fortran wrapper compiler
46 #  HDF5_DIFF_EXECUTABLE - the path to the HDF5 dataset comparison tool
47
48 #=============================================================================
49 # Copyright 2009 Kitware, Inc.
50 #
51 # Distributed under the OSI-approved BSD License (the "License");
52 # see accompanying file Copyright.txt for details.
53 #
54 # This software is distributed WITHOUT ANY WARRANTY; without even the
55 # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
56 # See the License for more information.
57 #=============================================================================
58 # (To distribute this file outside of CMake, substitute the full
59 #  License text for the above reference.)
60
61 # This module is maintained by Will Dicharry <wdicharry@stellarscience.com>.
62
63 include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
64 include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
65
66 # List of the valid HDF5 components
67 set( HDF5_VALID_COMPONENTS
68     C
69     CXX
70     Fortran
71     HL
72     Fortran_HL
73 )
74
75 # Validate the list of find components.
76 if( NOT HDF5_FIND_COMPONENTS )
77     set( HDF5_LANGUAGE_BINDINGS "C" )
78 else()
79     # add the extra specified components, ensuring that they are valid.
80     foreach( component ${HDF5_FIND_COMPONENTS} )
81         list( FIND HDF5_VALID_COMPONENTS ${component} component_location )
82         if( ${component_location} EQUAL -1 )
83             message( FATAL_ERROR
84                 "\"${component}\" is not a valid HDF5 component." )
85         else()
86             list( APPEND HDF5_LANGUAGE_BINDINGS ${component} )
87         endif()
88     endforeach()
89 endif()
90
91 # try to find the HDF5 wrapper compilers
92 find_program( HDF5_C_COMPILER_EXECUTABLE
93     NAMES h5cc h5pcc
94     HINTS ENV HDF5_ROOT
95     PATH_SUFFIXES bin Bin
96     DOC "HDF5 Wrapper compiler.  Used only to detect HDF5 compile flags." )
97 mark_as_advanced( HDF5_C_COMPILER_EXECUTABLE )
98
99 find_program( HDF5_CXX_COMPILER_EXECUTABLE
100     NAMES h5c++ h5pc++
101     HINTS ENV HDF5_ROOT
102     PATH_SUFFIXES bin Bin
103     DOC "HDF5 C++ Wrapper compiler.  Used only to detect HDF5 compile flags." )
104 mark_as_advanced( HDF5_CXX_COMPILER_EXECUTABLE )
105
106 find_program( HDF5_Fortran_COMPILER_EXECUTABLE
107     NAMES h5fc h5pfc
108     HINTS ENV HDF5_ROOT
109     PATH_SUFFIXES bin Bin
110     DOC "HDF5 Fortran Wrapper compiler.  Used only to detect HDF5 compile flags." )
111 mark_as_advanced( HDF5_Fortran_COMPILER_EXECUTABLE )
112
113 find_program( HDF5_DIFF_EXECUTABLE
114     NAMES h5diff
115     HINTS ENV HDF5_ROOT
116     PATH_SUFFIXES bin Bin
117     DOC "HDF5 file differencing tool." )
118 mark_as_advanced( HDF5_DIFF_EXECUTABLE )
119
120 # Invoke the HDF5 wrapper compiler.  The compiler return value is stored to the
121 # return_value argument, the text output is stored to the output variable.
122 macro( _HDF5_invoke_compiler language output return_value )
123     if( HDF5_${language}_COMPILER_EXECUTABLE )
124         exec_program( ${HDF5_${language}_COMPILER_EXECUTABLE}
125             ARGS -show
126             OUTPUT_VARIABLE ${output}
127             RETURN_VALUE ${return_value}
128         )
129         if( ${${return_value}} EQUAL 0 )
130             # do nothing
131         else()
132             message( STATUS
133               "Unable to determine HDF5 ${language} flags from HDF5 wrapper." )
134         endif()
135     endif()
136 endmacro()
137
138 # Parse a compile line for definitions, includes, library paths, and libraries.
139 macro( _HDF5_parse_compile_line
140     compile_line_var
141     include_paths
142     definitions
143     library_paths
144     libraries )
145
146     # Match the include paths
147     string( REGEX MATCHALL "-I([^\" ]+)" include_path_flags
148         "${${compile_line_var}}"
149     )
150     foreach( IPATH ${include_path_flags} )
151         string( REGEX REPLACE "^-I" "" IPATH ${IPATH} )
152         string( REGEX REPLACE "//" "/" IPATH ${IPATH} )
153         list( APPEND ${include_paths} ${IPATH} )
154     endforeach()
155
156     # Match the definitions
157     string( REGEX MATCHALL "-D[^ ]*" definition_flags "${${compile_line_var}}" )
158     foreach( DEF ${definition_flags} )
159         list( APPEND ${definitions} ${DEF} )
160     endforeach()
161
162     # Match the library paths
163     string( REGEX MATCHALL "-L([^\" ]+|\"[^\"]+\")" library_path_flags
164         "${${compile_line_var}}"
165     )
166
167     foreach( LPATH ${library_path_flags} )
168         string( REGEX REPLACE "^-L" "" LPATH ${LPATH} )
169         string( REGEX REPLACE "//" "/" LPATH ${LPATH} )
170         list( APPEND ${library_paths} ${LPATH} )
171     endforeach()
172
173     # now search for the library names specified in the compile line (match -l...)
174     # match only -l's preceded by a space or comma
175     # this is to exclude directory names like xxx-linux/
176     string( REGEX MATCHALL "[, ]-l([^\", ]+)" library_name_flags
177         "${${compile_line_var}}" )
178     # strip the -l from all of the library flags and add to the search list
179     foreach( LIB ${library_name_flags} )
180         string( REGEX REPLACE "^[, ]-l" "" LIB ${LIB} )
181         list( APPEND ${libraries} ${LIB} )
182     endforeach()
183 endmacro()
184
185 # Try to find HDF5 using an installed hdf5-config.cmake
186 if( NOT HDF5_FOUND )
187     find_package( HDF5 QUIET NO_MODULE )
188     if( HDF5_FOUND )
189         set( HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIR} )
190         set( HDF5_LIBRARIES )
191         set( HDF5_C_TARGET hdf5 )
192         set( HDF5_CXX_TARGET hdf5_cpp )
193         set( HDF5_HL_TARGET hdf5_hl )
194         set( HDF5_Fortran_TARGET hdf5_fortran )
195         set( HDF5_Fortran_HL_TARGET hdf5_hl_fortran )
196         foreach( _component ${HDF5_LANGUAGE_BINDINGS} )
197             list( FIND HDF5_VALID_COMPONENTS ${_component} _component_location )
198             get_target_property( _comp_location ${HDF5_${_component}_TARGET} LOCATION )
199             if( _comp_location )
200                 set( HDF5_${_component}_LIBRARY ${_comp_location} CACHE PATH
201                     "HDF5 ${_component} library" )
202                 mark_as_advanced( HDF5_${_component}_LIBRARY )
203                 list( APPEND HDF5_LIBRARIES ${HDF5_${_component}_LIBRARY} )
204             endif()
205         endforeach()
206     endif()
207 endif()
208
209 if( NOT HDF5_FOUND )
210     _HDF5_invoke_compiler( C HDF5_C_COMPILE_LINE HDF5_C_RETURN_VALUE )
211     _HDF5_invoke_compiler( CXX HDF5_CXX_COMPILE_LINE HDF5_CXX_RETURN_VALUE )
212     _HDF5_invoke_compiler( Fortran HDF5_Fortran_COMPILE_LINE HDF5_Fortran_RETURN_VALUE )
213
214     # seed the initial lists of libraries to find with items we know we need
215     set( HDF5_C_LIBRARY_NAMES_INIT hdf5 )
216     set( HDF5_HL_LIBRARY_NAMES_INIT hdf5_hl ${HDF5_C_LIBRARY_NAMES_INIT} )
217     set( HDF5_CXX_LIBRARY_NAMES_INIT hdf5_cpp ${HDF5_C_LIBRARY_NAMES_INIT} )
218     set( HDF5_Fortran_LIBRARY_NAMES_INIT hdf5_fortran
219         ${HDF5_C_LIBRARY_NAMES_INIT} )
220     set( HDF5_Fortran_HL_LIBRARY_NAMES_INIT hdf5hl_fortran
221         ${HDF5_Fortran_LIBRARY_NAMES_INIT} )
222
223     foreach( LANGUAGE ${HDF5_LANGUAGE_BINDINGS} )
224         if( HDF5_${LANGUAGE}_COMPILE_LINE )
225             _HDF5_parse_compile_line( HDF5_${LANGUAGE}_COMPILE_LINE
226                 HDF5_${LANGUAGE}_INCLUDE_FLAGS
227                 HDF5_${LANGUAGE}_DEFINITIONS
228                 HDF5_${LANGUAGE}_LIBRARY_DIRS
229                 HDF5_${LANGUAGE}_LIBRARY_NAMES
230             )
231
232             # take a guess that the includes may be in the 'include' sibling
233             # directory of a library directory.
234             foreach( dir ${HDF5_${LANGUAGE}_LIBRARY_DIRS} )
235                 list( APPEND HDF5_${LANGUAGE}_INCLUDE_FLAGS ${dir}/../include )
236             endforeach()
237         endif()
238
239         # set the definitions for the language bindings.
240         list( APPEND HDF5_DEFINITIONS ${HDF5_${LANGUAGE}_DEFINITIONS} )
241
242         # find the HDF5 include directories
243         if(${LANGUAGE} MATCHES "Fortran.*")
244             set(HDF5_INCLUDE_FILENAME hdf5.mod)
245         else()
246             set(HDF5_INCLUDE_FILENAME hdf5.h)
247         endif()
248
249         find_path( HDF5_${LANGUAGE}_INCLUDE_DIR ${HDF5_INCLUDE_FILENAME}
250             HINTS
251                 ${HDF5_${LANGUAGE}_INCLUDE_FLAGS}
252                 ENV
253                     HDF5_ROOT
254             PATHS
255                 $ENV{HOME}/.local/include
256             PATH_SUFFIXES
257                 include
258                 Include
259         )
260         mark_as_advanced( HDF5_${LANGUAGE}_INCLUDE_DIR )
261         list( APPEND HDF5_INCLUDE_DIRS ${HDF5_${LANGUAGE}_INCLUDE_DIR} )
262
263         set( HDF5_${LANGUAGE}_LIBRARY_NAMES
264             ${HDF5_${LANGUAGE}_LIBRARY_NAMES_INIT}
265             ${HDF5_${LANGUAGE}_LIBRARY_NAMES} )
266
267         # find the HDF5 libraries
268         foreach( LIB ${HDF5_${LANGUAGE}_LIBRARY_NAMES} )
269             if( UNIX AND HDF5_USE_STATIC_LIBRARIES )
270                 # According to bug 1643 on the CMake bug tracker, this is the
271                 # preferred method for searching for a static library.
272                 # See http://www.cmake.org/Bug/view.php?id=1643.  We search
273                 # first for the full static library name, but fall back to a
274                 # generic search on the name if the static search fails.
275                 set( THIS_LIBRARY_SEARCH_DEBUG lib${LIB}d.a ${LIB}d )
276                 set( THIS_LIBRARY_SEARCH_RELEASE lib${LIB}.a ${LIB} )
277             else()
278                 set( THIS_LIBRARY_SEARCH_DEBUG ${LIB}d )
279                 set( THIS_LIBRARY_SEARCH_RELEASE ${LIB} )
280             endif()
281             find_library( HDF5_${LIB}_LIBRARY_DEBUG
282                 NAMES ${THIS_LIBRARY_SEARCH_DEBUG}
283                 HINTS ${HDF5_${LANGUAGE}_LIBRARY_DIRS}
284                 ENV HDF5_ROOT
285                 PATH_SUFFIXES lib Lib )
286             find_library( HDF5_${LIB}_LIBRARY_RELEASE
287                 NAMES ${THIS_LIBRARY_SEARCH_RELEASE}
288                 HINTS ${HDF5_${LANGUAGE}_LIBRARY_DIRS}
289                 ENV HDF5_ROOT
290                 PATH_SUFFIXES lib Lib )
291             select_library_configurations( HDF5_${LIB} )
292             # even though we adjusted the individual library names in
293             # select_library_configurations, we still need to distinguish
294             # between debug and release variants because HDF5_LIBRARIES will
295             # need to specify different lists for debug and optimized builds.
296             # We can't just use the HDF5_${LIB}_LIBRARY variable (which was set
297             # up by the selection macro above) because it may specify debug and
298             # optimized variants for a particular library, but a list of
299             # libraries is allowed to specify debug and optimized only once.
300             list( APPEND HDF5_${LANGUAGE}_LIBRARIES_DEBUG
301                 ${HDF5_${LIB}_LIBRARY_DEBUG} )
302             list( APPEND HDF5_${LANGUAGE}_LIBRARIES_RELEASE
303                 ${HDF5_${LIB}_LIBRARY_RELEASE} )
304         endforeach()
305         list( APPEND HDF5_LIBRARY_DIRS ${HDF5_${LANGUAGE}_LIBRARY_DIRS} )
306
307         # Append the libraries for this language binding to the list of all
308         # required libraries.
309         list( APPEND HDF5_LIBRARIES_DEBUG
310             ${HDF5_${LANGUAGE}_LIBRARIES_DEBUG} )
311         list( APPEND HDF5_LIBRARIES_RELEASE
312             ${HDF5_${LANGUAGE}_LIBRARIES_RELEASE} )
313     endforeach()
314
315     # We may have picked up some duplicates in various lists during the above
316     # process for the language bindings (both the C and C++ bindings depend on
317     # libz for example).  Remove the duplicates. It appears that the default
318     # CMake behavior is to remove duplicates from the end of a list. However,
319     # for link lines, this is incorrect since unresolved symbols are searched
320     # for down the link line. Therefore, we reverse the list, remove the
321     # duplicates, and then reverse it again to get the duplicates removed from
322     # the beginning.
323     macro( _remove_duplicates_from_beginning _list_name )
324         list( REVERSE ${_list_name} )
325         list( REMOVE_DUPLICATES ${_list_name} )
326         list( REVERSE ${_list_name} )
327     endmacro()
328
329     if( HDF5_INCLUDE_DIRS )
330         _remove_duplicates_from_beginning( HDF5_INCLUDE_DIRS )
331     endif()
332     if( HDF5_LIBRARIES_DEBUG )
333         _remove_duplicates_from_beginning( HDF5_LIBRARIES_DEBUG )
334     endif()
335     if( HDF5_LIBRARIES_RELEASE )
336         _remove_duplicates_from_beginning( HDF5_LIBRARIES_RELEASE )
337     endif()
338     if( HDF5_LIBRARY_DIRS )
339         _remove_duplicates_from_beginning( HDF5_LIBRARY_DIRS )
340     endif()
341
342     # Construct the complete list of HDF5 libraries with debug and optimized
343     # variants when the generator supports them.
344     if( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE )
345         set( HDF5_LIBRARIES )
346         foreach( _lib ${HDF5_LIBRARIES_DEBUG} )
347             list( APPEND HDF5_LIBRARIES debug ${_lib} )
348         endforeach()
349         foreach( _lib ${HDF5_LIBRARIES_RELEASE} )
350             list( APPEND HDF5_LIBRARIES optimized ${_lib} )
351         endforeach()
352     else()
353         set( HDF5_LIBRARIES ${HDF5_LIBRARIES_RELEASE} )
354     endif()
355
356     # If the HDF5 include directory was found, open H5pubconf.h to determine if
357     # HDF5 was compiled with parallel IO support
358     set( HDF5_IS_PARALLEL FALSE )
359     foreach( _dir IN LISTS HDF5_INCLUDE_DIRS )
360         if( EXISTS "${_dir}/H5pubconf.h" )
361             file( STRINGS "${_dir}/H5pubconf.h"
362                 HDF5_HAVE_PARALLEL_DEFINE
363                 REGEX "HAVE_PARALLEL 1" )
364             if( HDF5_HAVE_PARALLEL_DEFINE )
365                 set( HDF5_IS_PARALLEL TRUE )
366             endif()
367         endif()
368     endforeach()
369     set( HDF5_IS_PARALLEL ${HDF5_IS_PARALLEL} CACHE BOOL
370         "HDF5 library compiled with parallel IO support" )
371     mark_as_advanced( HDF5_IS_PARALLEL )
372
373     # For backwards compatibility we set HDF5_INCLUDE_DIR to the value of
374     # HDF5_INCLUDE_DIRS
375     if( HDF5_INCLUDE_DIRS )
376         set( HDF5_INCLUDE_DIR "${HDF5_INCLUDE_DIRS}" )
377     endif()
378
379 endif()
380
381 find_package_handle_standard_args( HDF5 DEFAULT_MSG
382     HDF5_LIBRARIES
383     HDF5_INCLUDE_DIRS
384 )
385