1# Project uclales
2# http://gitorious.org/uclales
3# License: Academic Free License v3.0
4#
5# - Find NETCDF, a library for reading and writing self describing array data.
6#
7# This module invokes the NETCDF wrapper compiler that should be installed
8# alongside NETCDF.  Depending upon the NETCDF Configuration, the wrapper compiler
9# is called either h5cc or h5pcc.  If this succeeds, the module will then call
10# the compiler with the -show argument to see what flags are used when compiling
11# an NETCDF client application.
12#
13# The module will optionally accept the COMPONENTS argument.  If no COMPONENTS
14# are specified, then the find module will default to finding only the NETCDF C
15# library.  If one or more COMPONENTS are specified, the module will attempt to
16# find the language bindings for the specified components.  Currently, the only
17# valid components are C, CXX, FORTRAN and F90.
18#
19# On UNIX systems, this module will read the variable NETCDF_USE_STATIC_LIBRARIES
20# to determine whether or not to prefer a static link to a dynamic link for NETCDF
21# and all of it's dependencies.  To use this feature, make sure that the
22# NETCDF_USE_STATIC_LIBRARIES variable is set before the call to find_package.
23#
24# To provide the module with a hint about where to find your NETCDF installation,
25# set the CMake or environment variable NETCDF_ROOT, NETCDF_DIR, NETCDF_PATH or
26# NETCDF4_DIR. The Find module will then look in this path when searching for
27# NETCDF executables, paths, and libraries.
28#
29# In addition to finding the includes and libraries required to compile an NETCDF
30# client application, this module also makes an effort to find tools that come
31# with the NETCDF distribution that may be useful for regression testing.
32#
33# This module will define the following variables:
34#  NETCDF_INCLUDE_DIRS - Location of the NETCDF includes
35#  NETCDF_INCLUDE_DIR - Location of the NETCDF includes (deprecated)
36#  NETCDF_DEFINITIONS - Required compiler definitions for NETCDF
37#  NETCDF_C_LIBRARIES - Required libraries for the NETCDF C bindings.
38#  NETCDF_CXX_LIBRARIES - Required libraries for the NETCDF C++ bindings
39#  NETCDF_FORTRAN_LIBRARIES - Required libraries for the NETCDF FORTRAN bindings
40#  NETCDF_F90_LIBRARIES - Required libraries for the NETCDF FORTRAN 90 bindings
41#  NETCDF_LIBRARIES - Required libraries for all requested bindings
42#  NETCDF_FOUND - true if NETCDF was found on the system
43#  NETCDF_LIBRARY_DIRS - the full set of library directories
44#  NETCDF_IS_PARALLEL - Whether or not NETCDF was found with parallel IO support
45#  NETCDF_CONFIG_EXECUTABLE - the path to the NC-CONFIG tool
46
47#=============================================================================
48# Copyright 2009 Kitware, Inc.
49#
50# Distributed under the OSI-approved BSD License (the "License");
51# see accompanying file Copyright.txt for details.
52#
53# This software is distributed WITHOUT ANY WARRANTY; without even the
54# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
55# See the License for more information.
56#=============================================================================
57# (To distribute this file outside of CMake, substitute the full
58#  License text for the above reference.)
59
60# This module is maintained by Thijs Heus <thijs.heus@zmaw.de>.
61
62include(SelectLibraryConfigurations)
63include(FindPackageHandleStandardArgs)
64
65# List of the valid NETCDF components
66set( NETCDF_VALID_COMPONENTS
67    FORTRAN
68    F90
69    CXX
70    C
71)
72
73# Invoke the NETCDF wrapper compiler.  The compiler return value is stored to the
74# return_value argument, the text output is stored to the output variable.
75macro( _NETCDF_CONFIG flag output return_value )
76    if( NETCDF_CONFIG_EXECUTABLE )
77        exec_program( ${NETCDF_CONFIG_EXECUTABLE}
78            ARGS ${flag}
79            OUTPUT_VARIABLE ${output}
80            RETURN_VALUE ${return_value}
81        )
82        if( ${${return_value}} EQUAL 0 )
83            # do nothing
84        else()
85            message( STATUS
86              "Unable to determine ${flag} from NC-CONFIG." )
87        endif()
88    endif()
89endmacro()
90#
91# try to find the NETCDF wrapper compilers
92find_program( NETCDF_CONFIG_EXECUTABLE
93    NAMES nc-config
94    HINTS ${NETCDF_ROOT} ${NETCDF_DIR} ${NETCDF_PATH} ${NETCDF4_DIR}
95          ENV NETCDF_ROOT ENV NETCDF_DIR ENV NETCDF_PATH ENV NETCDF4_DIR
96    PATH_SUFFIXES bin Bin
97    DOC "NETCDF CONFIG PROGRAM.  Used only to detect NETCDF compile flags." )
98mark_as_advanced( NETCDF_CONFIG_EXECUTABLE )
99ecbuild_debug("FindNetCDF4: nc-config executable = ${NETCDF_CONFIG_EXECUTABLE}")
100
101set(output "no")
102_NETCDF_CONFIG (--has-hdf5 output return)
103set(HAS_HDF5 FALSE)
104
105if(${output} STREQUAL yes)
106  set(HAS_HDF5 TRUE)
107  set(HDF5_FIND_QUIETLY ${NETCDF_FIND_QUIETLY})
108  set(HDF5_FIND_REQUIRED ${NETCDF_FIND_REQUIRED})
109  find_package(HDF5)
110#        list( APPEND NETCDF_LIBRARIES_DEBUG
111#            ${HDF5_LIBRARIES_DEBUG} )
112#        list( APPEND NETCDF_LIBRARIES_RELEASE
113#            ${HDF5_LIBRARIES_RELEASE} )
114  set (NETCDF_IS_PARALLEL ${HDF5_IS_PARALLEL})
115endif()
116_NETCDF_CONFIG (--has-pnetcdf output return)
117if(${output} STREQUAL yes)
118  set (NETCDF_IS_PARALLEL TRUE)
119else()
120#   set(NETCDF_IS_PARALLEL FALSE)
121endif()
122set( NETCDF_IS_PARALLEL TRUE CACHE BOOL
123    "NETCDF library compiled with parallel IO support" )
124
125
126if( NETCDF_INCLUDE_DIRS AND NETCDF_LIBRARIES )
127    # Do nothing: we already have NETCDF_INCLUDE_PATH and NETCDF_LIBRARIES in the
128    # cache, it would be a shame to override them
129else()
130    if( NOT NETCDF_FIND_COMPONENTS )
131        set( NETCDF_LANGUAGE_BINDINGS "C" )
132    else()
133        # add the extra specified components, ensuring that they are valid.
134        foreach( component ${NETCDF_FIND_COMPONENTS} )
135            list( FIND NETCDF_VALID_COMPONENTS ${component} component_location )
136            if( ${component_location} EQUAL -1 )
137                message( FATAL_ERROR
138                    "\"${component}\" is not a valid NETCDF component." )
139            else()
140                list( APPEND NETCDF_LANGUAGE_BINDINGS ${component} )
141            endif()
142        endforeach()
143    endif()
144
145    # seed the initial lists of libraries to find with items we know we need
146    set( NETCDF_C_INCLUDE_NAMES netcdf.h )
147    set( NETCDF_CXX_INCLUDE_NAMES netcdfcpp.h ${NETCDF_C_INCLUDE_NAMES} )
148    set( NETCDF_FORTRAN_INCLUDE_NAMES ${NETCDF_C_INCLUDE_NAMES} )
149    set( NETCDF_F90_INCLUDE_NAMES netcdf.mod typesizes.mod ${NETCDF_C_INCLUDE_NAMES} )
150
151    set( NETCDF_C_LIBRARY_NAMES netcdf)
152    set( NETCDF_CXX_LIBRARY_NAMES netcdf_c++ netcdf_c++4 ${NETCDF_C_LIBRARY_NAMES} )
153    set( NETCDF_FORTRAN_LIBRARY_NAMES netcdff ${NETCDF_C_LIBRARY_NAMES})
154    set( NETCDF_F90_LIBRARY_NAMES ${NETCDF_FORTRAN_LIBRARY_NAMES} )
155
156    set( NETCDF_REQUIRED netcdf.h netcdfcpp.h netcdf.mod typesizes.mod netcdf netcdff netcdf_c++ netcdf_c++4)
157
158    foreach( LANGUAGE ${NETCDF_LANGUAGE_BINDINGS} )
159        ecbuild_debug("FindNetCDF4: looking for ${LANGUAGE} language bindings")
160
161        set( NETCDF_${LANGUAGE}_FOUND 1 ) # disable this in following if necessary
162
163        # find the NETCDF includes
164        foreach( INC ${NETCDF_${LANGUAGE}_INCLUDE_NAMES} )
165          #ecbuild_debug( "FindNetCDF4: looking for include file ${INC}")
166
167          find_path( NETCDF_${INC}_INCLUDE_DIR ${INC}
168              HINTS ${NETCDF_${LANGUAGE}_INCLUDE_FLAGS}
169                    ${NETCDF_ROOT} ${NETCDF_DIR} ${NETCDF_PATH} ${NETCDF4_DIR}
170                    ENV NETCDF_ROOT ENV NETCDF_DIR ENV NETCDF_PATH ENV NETCDF4_DIR
171              PATH_SUFFIXES
172                  include
173                  Include
174          )
175          if( NOT NETCDF_${INC}_INCLUDE_DIR )
176            #ecbuild_debug( "FindNetCDF4: ${INC} not found" )
177            GET_FILENAME_COMPONENT( _basename ${INC} NAME_WE )
178            GET_FILENAME_COMPONENT( _ext ${INC} EXT )
179            string( TOUPPER ${_basename} _BASENAME )
180            set( INC_MOD "${_BASENAME}${_ext}")
181            #ecbuild_debug( "FindNetCDF4:     try ${INC_MOD}" )
182            find_path( NETCDF_${INC}_INCLUDE_DIR ${INC_MOD}
183              HINTS ${NETCDF_${LANGUAGE}_INCLUDE_FLAGS}
184                    ${NETCDF_ROOT} ${NETCDF_DIR} ${NETCDF_PATH} ${NETCDF4_DIR}
185                    ENV NETCDF_ROOT ENV NETCDF_DIR ENV NETCDF_PATH ENV NETCDF4_DIR
186              PATH_SUFFIXES
187                  include
188                  Include
189            )
190          endif()
191
192          mark_as_advanced( NETCDF_${INC}_INCLUDE_DIR )
193          #ecbuild_debug_var( NETCDF_${INC}_INCLUDE_DIR)
194          if (NETCDF_${INC}_INCLUDE_DIR)
195            list( APPEND NETCDF_INCLUDE_DIRS ${NETCDF_${INC}_INCLUDE_DIR} )
196          else()
197            list( FIND NETCDF_REQUIRED ${INC} location )
198            if( ${location} GREATER -1 )
199              if(NETCDF_FIND_REQUIRED)
200                ecbuild_error( "\"${INC}\" is not found for NetCDF component ${LANGUAGE}" )
201              elseif( NOT NETCDF_FIND_QUIETLY )
202                message( STATUS "\"${INC}\" is not found for NetCDF component ${LANGUAGE}" )
203              endif()
204              set( NETCDF_${LANGUAGE}_FOUND 0 )
205            endif()
206          endif()
207        endforeach()
208        # find the NETCDF libraries
209        foreach( LIB ${NETCDF_${LANGUAGE}_LIBRARY_NAMES} )
210            if( UNIX AND NETCDF_USE_STATIC_LIBRARIES )
211                # According to bug 1643 on the CMake bug tracker, this is the
212                # preferred method for searching for a static library.
213                # See http://www.cmake.org/Bug/view.php?id=1643.  We search
214                # first for the full static library name, but fall back to a
215                # generic search on the name if the static search fails.
216                set( THIS_LIBRARY_SEARCH_DEBUG lib${LIB}d.a ${LIB}d )
217                set( THIS_LIBRARY_SEARCH_RELEASE lib${LIB}.a ${LIB} )
218            else()
219                set( THIS_LIBRARY_SEARCH_DEBUG ${LIB}d )
220                set( THIS_LIBRARY_SEARCH_RELEASE ${LIB} )
221            endif()
222            find_library( NETCDF_${LIB}_LIBRARY_DEBUG
223                NAMES ${THIS_LIBRARY_SEARCH_DEBUG}
224                HINTS ${NETCDF_${LANGUAGE}_LIBRARY_DIRS}
225                      ${NETCDF_ROOT} ${NETCDF_DIR} ${NETCDF_PATH} ${NETCDF4_DIR}
226                      ENV NETCDF_ROOT ENV NETCDF_DIR ENV NETCDF_PATH ENV NETCDF4_DIR
227                PATH_SUFFIXES lib64 Lib64 lib Lib)
228            find_library( NETCDF_${LIB}_LIBRARY_RELEASE
229                NAMES ${THIS_LIBRARY_SEARCH_RELEASE}
230                HINTS ${NETCDF_${LANGUAGE}_LIBRARY_DIRS}
231                      ${NETCDF_ROOT} ${NETCDF_DIR} ${NETCDF_PATH} ${NETCDF4_DIR}
232                      ENV NETCDF_ROOT ENV NETCDF_DIR ENV NETCDF_PATH ENV NETCDF4_DIR
233                PATH_SUFFIXES lib64 Lib64 lib Lib )
234            select_library_configurations( NETCDF_${LIB} )
235            # even though we adjusted the individual library names in
236            # select_library_configurations, we still need to distinguish
237            # between debug and release variants because NETCDF_LIBRARIES will
238            # need to specify different lists for debug and optimized builds.
239            # We can't just use the NETCDF_${LIB}_LIBRARY variable (which was set
240            # up by the selection macro above) because it may specify debug and
241            # optimized variants for a particular library, but a list of
242            # libraries is allowed to specify debug and optimized only once.
243          if (NETCDF_${LIB}_LIBRARY_RELEASE)
244            list( APPEND NETCDF_LIBRARIES_RELEASE ${NETCDF_${LIB}_LIBRARY_RELEASE} )
245            list( APPEND NETCDF_${LANGUAGE}_LIBRARIES_RELEASE ${NETCDF_${LIB}_LIBRARY_RELEASE} )
246          endif()
247          if (NETCDF_${LIB}_LIBRARY_DEBUG)
248            list( APPEND NETCDF_LIBRARIES_DEBUG ${NETCDF_${LIB}_LIBRARY_DEBUG} )
249            list( APPEND NETCDF_${LANGUAGE}_LIBRARIES_DEBUG ${NETCDF_${LIB}_LIBRARY_DEBUG} )
250          endif()
251          if (NETCDF_${LIB}_LIBRARY_RELEASE OR NETCDF_${LIB}_LIBRARY_DEBUG )
252          else()
253            list( FIND NETCDF_REQUIRED ${LIB} location )
254            if( ${location} EQUAL -1 )
255            else()
256              if(NETCDF_FIND_REQUIRED)
257                message( SEND_ERROR "\"${LIB}\" is not found for NetCDF component ${LANGUAGE}." )
258              elseif( NOT NETCDF_FIND_QUIETLY )
259                message( STATUS "\"${LIB}\" is not found for NetCDF component ${LANGUAGE}." )
260              else()
261                set( NETCDF_${LANGUAGE}_FOUND 0 )
262              endif()
263           endif()
264          endif()
265        endforeach()
266        list( APPEND NETCDF_LIBRARY_DIRS ${NETCDF_${LANGUAGE}_LIBRARY_DIRS} )
267
268        # Append the libraries for this language binding to the list of all
269        # required libraries.
270
271        if( NETCDF_${LANGUAGE}_FOUND )
272            ecbuild_debug( "FindNetCDF4: ${LANGUAGE} language bindings found" )
273            if( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE )
274                list( APPEND NETCDF_${LANGUAGE}_LIBRARIES
275                    debug ${NETCDF_${LANGUAGE}_LIBRARIES_DEBUG}
276                    optimized ${NETCDF_${LANGUAGE}_LIBRARIES_RELEASE} )
277            else()
278                list( APPEND NETCDF_${LANGUAGE}_LIBRARIES
279                    ${NETCDF_${LANGUAGE}_LIBRARIES_RELEASE} )
280            endif()
281        endif()
282        # ecbuild_debug_var( NETCDF_${LANGUAGE}_LIBRARIES )
283        list( APPEND NETCDF_FOUND_REQUIRED_VARS NETCDF_${LANGUAGE}_FOUND )
284    endforeach()
285
286    # We may have picked up some duplicates in various lists during the above
287    # process for the language bindings (both the C and C++ bindings depend on
288    # libz for example).  Remove the duplicates.
289    if( NETCDF_INCLUDE_DIRS )
290        list( REMOVE_DUPLICATES NETCDF_INCLUDE_DIRS )
291    endif()
292    if( NETCDF_LIBRARIES_DEBUG )
293        list( REMOVE_DUPLICATES NETCDF_LIBRARIES_DEBUG )
294    endif()
295    if( NETCDF_LIBRARIES_RELEASE )
296        list( REMOVE_DUPLICATES NETCDF_LIBRARIES_RELEASE )
297    endif()
298    if( NETCDF_LIBRARY_DIRS )
299        list( REMOVE_DUPLICATES NETCDF_LIBRARY_DIRS )
300    endif()
301
302    # Construct the complete list of NETCDF libraries with debug and optimized
303    # variants when the generator supports them.
304    if( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE )
305        if( NOT NETCDF_LIBRARIES_DEBUG )
306          set( NETCDF_LIBRARIES_DEBUG ${NETCDF_LIBRARIES_RELEASE} )
307        endif()
308        set( NETCDF_LIBRARIES
309            debug ${NETCDF_LIBRARIES_DEBUG}
310            optimized ${NETCDF_LIBRARIES_RELEASE} )
311    else()
312        set( NETCDF_LIBRARIES ${NETCDF_LIBRARIES_RELEASE} )
313    endif()
314endif()
315
316set( NETCDF4_FIND_QUIETLY ${NETCDF_FIND_QUIETLY} )
317set( NETCDF4_FIND_REQUIRED ${NETCDF_FIND_REQUIRED} )
318# handle the QUIET and REQUIRED arguments and set NETCDF4_FOUND to TRUE
319# if all listed variables are valid
320# Note: capitalisation of the package name must be the same as in the file name
321find_package_handle_standard_args( NetCDF4 DEFAULT_MSG
322    ${NETCDF_FOUND_REQUIRED_VARS}
323    NETCDF_LIBRARIES
324    NETCDF_INCLUDE_DIRS
325)
326
327mark_as_advanced(
328    NETCDF_INCLUDE_DIRS
329    NETCDF_LIBRARIES
330    NETCDF_LIBRARY_DIRS
331)
332
333set( NETCDF_FOUND  ${NETCDF4_FOUND} )
334set( NetCDF_FOUND  ${NETCDF4_FOUND} )
335set( NetCDF4_FOUND ${NETCDF4_FOUND} )
336
337# For backwards compatibility we set NETCDF_INCLUDE_DIR to the value of
338# NETCDF_INCLUDE_DIRS
339set( NETCDF_INCLUDE_DIR "${NETCDF_INCLUDE_DIRS}" )
340
341