/
SetupHDF5.cmake
289 lines (250 loc) · 10.4 KB
/
SetupHDF5.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# Copyright (c) Lawrence Livermore National Security, LLC and other Conduit
# Project developers. See top-level LICENSE AND COPYRIGHT files for dates and
# other details. No copyright assignment is required to contribute to Conduit.
#
# Setup HDF5
#
# first Check for HDF5_DIR
if(NOT HDF5_DIR)
MESSAGE(FATAL_ERROR "HDF5 support needs explicit HDF5_DIR")
endif()
# find the absolute path w/ symlinks resolved of the passed HDF5_DIR,
# since sanity checks later need to compare against the real path
get_filename_component(HDF5_DIR_REAL "${HDF5_DIR}" REALPATH)
message(STATUS "Looking for HDF5 at: " ${HDF5_DIR_REAL})
# CMake's FindHDF5 module uses the HDF5_ROOT env var
set(HDF5_ROOT ${HDF5_DIR_REAL})
if(NOT WIN32)
# use HDF5_ROOT env var for FindHDF5 with older versions of cmake
if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
set(ENV{HDF5_ROOT} ${HDF5_ROOT}/bin)
endif()
endif()
# Use CMake's FindHDF5 module to locate hdf5 and setup hdf5
find_package(HDF5 REQUIRED)
# FindHDF5/find_package sets HDF5_DIR to it's installed CMake info if it exists
# we want to keep HDF5_DIR as the root dir of the install to be
# consistent with other packages
# find the absolute path w/ symlinks resolved of the passed HDF5_DIR,
# since sanity checks later need to compare against the real path
get_filename_component(HDF5_DIR_REAL "${HDF5_ROOT}" REALPATH)
set(HDF5_DIR ${HDF5_DIR_REAL} CACHE PATH "" FORCE)
message(STATUS "HDF5_DIR_REAL=${HDF5_DIR_REAL}")
#
# Sanity check to alert us if some how we found an hdf5 instance
# in an unexpected location.
#
message(STATUS "Checking that found HDF5_INCLUDE_DIRS are in HDF5_DIR")
#
# HDF5_INCLUDE_DIRS may also include paths to external lib headers
# (such as szip), so we check that *at least one* of the includes
# listed in HDF5_INCLUDE_DIRS exists in the HDF5_DIR specified.
#
# HDF5_INCLUDE_DIR is deprecated, but there are still some cases
# where HDF5_INCLUDE_DIR is set, but HDF5_INCLUDE_DIRS is not
if(NOT HDF5_INCLUDE_DIRS)
if(HDF5_INCLUDE_DIR)
set(HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIR})
else()
message(FATAL_ERROR "FindHDF5 did not provide HDF5_INCLUDE_DIRS or HDF5_INCLUDE_DIR.")
endif()
endif()
if(NOT HDF5_LIBRARIES)
message(FATAL_ERROR "FindHDF5 did not provide HDF5_LIBRARIES.")
endif()
message(STATUS "HDF5_INCLUDE_DIRS=${HDF5_INCLUDE_DIRS}")
set(check_hdf5_inc_dir_ok 0)
foreach(IDIR ${HDF5_INCLUDE_DIRS})
# get real path of the include dir
# w/ abs and symlinks resolved
get_filename_component(IDIR_REAL "${IDIR}" REALPATH)
# check if idir_real is a substring of hdf5_dir
if("${IDIR_REAL}" MATCHES "${HDF5_DIR}")
message(STATUS " ${IDIR_REAL} includes HDF5_DIR (${HDF5_DIR})")
set(check_hdf5_inc_dir_ok 1)
endif()
if("${IDIR_REAL}" MATCHES "${HDF5_REAL_DIR}")
message(STATUS " ${IDIR_REAL} includes HDF5_REAL_DIR (${HDF5_REAL_DIR})")
set(check_hdf5_inc_dir_ok 1)
endif()
endforeach()
if(NOT check_hdf5_inc_dir_ok)
message(FATAL_ERROR " ${HDF5_INCLUDE_DIRS} does not include HDF5_DIR")
endif()
#
# filter HDF5_LIBRARIES to remove hdf5_hl if it exists
# we don't use hdf5_hl, but if we link with it will become
# a transitive dependency
#
set(HDF5_HL_LIB FALSE)
foreach(LIB ${HDF5_LIBRARIES})
if("${LIB}" MATCHES "hdf5_hl")
set(HDF5_HL_LIB ${LIB})
endif()
endforeach()
if(HDF5_HL_LIB)
message(STATUS "Removing hdf5_hl from HDF5_LIBRARIES")
list(REMOVE_ITEM HDF5_LIBRARIES ${HDF5_HL_LIB})
endif()
##########################################################
# Use libhdf5.settings or h5cc to capture transitive hdf5
# deps (mainly zlib) for downstream static builds using
# config.mk
##########################################################
message(STATUS "Attempting to find libhdf5.settings in HDF5_REAL_DIR...")
find_file(HDF5_SETTINGS_FILE
NAMES libhdf5.settings
PATHS ${HDF5_DIR}
PATH_SUFFIXES lib share/cmake/hdf5
NO_DEFAULT_PATH
NO_CMAKE_ENVIRONMENT_PATH
NO_CMAKE_PATH
NO_SYSTEM_ENVIRONMENT_PATH
NO_CMAKE_SYSTEM_PATH)
if(EXISTS ${HDF5_SETTINGS_FILE})
message(STATUS "Found HDF5 settings file: ${HDF5_SETTINGS_FILE}")
#Output by HDF5 CMake build system
message(STATUS "Reading 'HDF5_SETTINGS_FILE' to determine hdf5 config settings")
file(READ ${HDF5_SETTINGS_FILE} _HDF5_CC_CONFIG_VALUE)
else()
message(STATUS "Unable to find libhdf5.settings, defaulting to h5cc output")
#Run HDF5_C_COMPILER_EXECUTABLE -showconfig
message(STATUS "Using 'h5cc -showconfig' to determine hdf5 config settings")
execute_process(COMMAND "${HDF5_C_COMPILER_EXECUTABLE}" "-showconfig"
RESULT_VARIABLE _HDF5_CC_CONFIG_SUCCESS
OUTPUT_VARIABLE _HDF5_CC_CONFIG_VALUE
ERROR_VARIABLE _HDF5_CC_CONFIG_ERROR_VALUE
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(_HDF5_CC_CONFIG_SUCCESS MATCHES 0)
#h5cc ran ok
message(STATUS "SUCCESS: h5cc -showconfig")
else()
# use warning b/c fatal error is to heavy handed
message(WARNING "h5cc -showconfig failed, config.mk may not correclty report HDF5 details.")
endif()
endif()
#######
# parse include flags (key = AM_CPPFLAGS)
#######
string(REGEX MATCHALL "AM_CPPFLAGS: .+\n" hdf5_tpl_inc_flags "${_HDF5_CC_CONFIG_VALUE}")
# strip prefix
string(REGEX REPLACE "AM_CPPFLAGS: " "" hdf5_tpl_inc_flags "${hdf5_tpl_inc_flags}")
# strip after
string(FIND "${hdf5_tpl_inc_flags}" "\n" hdf5_tpl_inc_flags_end_pos)
string(SUBSTRING "${hdf5_tpl_inc_flags}" 0 "${hdf5_tpl_inc_flags_end_pos}" hdf5_tpl_inc_flags)
# only do final strip if not empty
if("${hdf5_tpl_inc_flags}")
string(STRIP "${hdf5_tpl_inc_flags}" hdf5_tpl_inc_flags)
endif()
#######
# parse -L flags (key = AM_LDFLAGS)
#######
string(REGEX MATCHALL "AM_LDFLAGS: .+\n" hdf5_tpl_lnk_flags "${_HDF5_CC_CONFIG_VALUE}")
# strip prefix
string(REGEX REPLACE "AM_LDFLAGS: " "" hdf5_tpl_lnk_flags "${hdf5_tpl_lnk_flags}")
# strip after
string(FIND "${hdf5_tpl_lnk_flags}" "\n" hdf5_tpl_lnk_flags_end_pos)
string(SUBSTRING "${hdf5_tpl_lnk_flags}" 0 "${hdf5_tpl_lnk_flags_end_pos}" hdf5_tpl_lnk_flags)
# only do final strip if not empty
if("${hdf5_tpl_lnk_flags}")
string(STRIP "${hdf5_tpl_lnk_flags}" hdf5_tpl_lnk_flags)
endif()
#######
# parse -l flags (key = Extra libraries)
#######
string(REGEX MATCHALL "Extra libraries: .+\n" hdf5_tpl_lnk_libs "${_HDF5_CC_CONFIG_VALUE}")
# strip prefix
string(REGEX REPLACE "Extra libraries: " "" hdf5_tpl_lnk_libs "${hdf5_tpl_lnk_libs}")
# strip after
string(FIND "${hdf5_tpl_lnk_libs}" "\n" hdf5_tpl_lnk_libs_end_pos)
string(SUBSTRING "${hdf5_tpl_lnk_libs}" 0 "${hdf5_tpl_lnk_libs_end_pos}" hdf5_tpl_lnk_libs)
# When hdf5 is built with cmake, the h5settings file may list
# these libs as a cmake list (separated by semi colons)
#
# if hdf5_tpl_lnk_libs_len greater than 1 -- we have a semi colon case
list(LENGTH hdf5_tpl_lnk_libs hdf5_tpl_lnk_libs_len)
# only do final strip if not empty
if("${hdf5_tpl_lnk_libs}")
# and not already a list
if(hdf5_tpl_lnk_libs_len EQUAL 1)
string(STRIP "${hdf5_tpl_lnk_libs}" hdf5_tpl_lnk_libs)
endif()
endif()
# get a cmake list of these libs if don't already have one by
# splitting the link libs string
if(hdf5_tpl_lnk_libs_len EQUAL 1)
# ** Note **
# The NATIVE_COMMAND arg to separate_arguments() was added in CMake 3.9
# instead use strategy that allows older versions of CMake:
# an if to select WINDOWS_COMMAND or UNIX_COMMAND arg
if(WIN32)
separate_arguments(_temp_link_libs WINDOWS_COMMAND "${hdf5_tpl_lnk_libs}")
else()
separate_arguments(_temp_link_libs UNIX_COMMAND "${hdf5_tpl_lnk_libs}")
endif()
endif()
# add -l to any libraries that are just their names (like "m" instead of "-lm")
set(_fixed_link_libs)
foreach(lib ${_temp_link_libs})
if(NOT "${lib}" MATCHES ^[-/])
# lib doesn't start with '-' (-l) or '/' ()
set(_fixed_link_libs "${_fixed_link_libs} -l${lib}")
else()
set(_fixed_link_libs "${_fixed_link_libs} ${lib}")
endif()
endforeach()
set(hdf5_tpl_lnk_libs "${_fixed_link_libs}")
# append hdf5_tpl_lnk_libs to hdf5_tpl_lnk_flags
set(hdf5_tpl_lnk_flags "${hdf5_tpl_lnk_flags} ${hdf5_tpl_lnk_libs}")
#
# these will be used in Conduit's config.mk
#
set(CONDUIT_HDF5_TPL_INC_FLAGS ${hdf5_tpl_inc_flags})
set(CONDUIT_HDF5_TPL_LIB_FLAGS ${hdf5_tpl_lnk_flags})
#
# Display main hdf5 cmake vars
#
message(STATUS "HDF5 Include Dirs: ${HDF5_INCLUDE_DIRS}")
message(STATUS "HDF5 Libraries: ${HDF5_LIBRARIES}")
message(STATUS "HDF5 Definitions: ${HDF5_DEFINITIONS}")
message(STATUS "HDF5 is parallel: ${HDF5_IS_PARALLEL}")
# if hdf5 was built with mpi support, we have to propgate
# that regardless of conduit's use of MPI
if(HDF5_IS_PARALLEL)
if(NOT MPI_FOUND)
MESSAGE(FATAL_ERROR "Cannot link non-mpi aware conduit (MPI_FOUND == FALSE) "
"against HDF5 built with MPI support (HDF5_IS_PARALLEL == TRUE). "
"Please enable conduit's MPI support (ENABLE_MPI == ON, etc) or "
"build against a non-mpi HDF5 library.")
endif()
endif()
#############
# Note: MPI libraries and include dirs are not propgated for the config.mk case
#############
message(STATUS "HDF5 Thirdparty Include Flags: ${hdf5_tpl_inc_flags}")
message(STATUS "HDF5 Thirdparty Link Flags: ${hdf5_tpl_lnk_flags}")
# if newer style hdf5 imported targets exist, use these
if(TARGET hdf5::hdf5-shared AND BUILD_SHARED_LIBS)
# reg shared ver of imported lib target
message(STATUS "HDF5 using hdf5::hdf5-shared target")
blt_register_library(NAME hdf5
LIBRARIES hdf5::hdf5-shared)
elseif(TARGET hdf5::hdf5-static)
# reg static ver of imported lib target
message(STATUS "HDF5 using hdf5::hdf5-static target")
blt_register_library(NAME hdf5
LIBRARIES hdf5::hdf5-static)
elseif(TARGET hdf5)
# legacy hdf5 CMake build system support creates an hdf5 target we use directly
message(STATUS "HDF5 using hdf5 target")
else()
# reg includes and libs with blt
message(STATUS "HDF5 using HDF5_DEFINITIONS + HDF5_INCLUDE_DIRS + HDF5_LIBRARIES")
message(STATUS "HDF5_DEFINITIONS: ${HDF5_DEFINITIONS}")
message(STATUS "HDF5_INCLUDE_DIRS: ${HDF5_INCLUDE_DIRS}")
message(STATUS "HDF5_LIBRARIES: ${HDF5_LIBRARIES}")
blt_register_library(NAME hdf5
DEFINES ${HDF5_DEFINITIONS}
INCLUDES ${HDF5_INCLUDE_DIRS}
LIBRARIES ${HDF5_LIBRARIES})
endif()