tFindPETSc.cmake - pism - [fork] customized build of PISM, the parallel ice sheet model (tillflux branch)
 (HTM) git clone git://src.adamsgaard.dk/pism
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
       tFindPETSc.cmake (15924B)
       ---
            1 # - Try to find PETSc
            2 # Once done this will define
            3 #
            4 #  PETSC_FOUND        - system has PETSc
            5 #  PETSC_INCLUDES     - the PETSc include directories
            6 #  PETSC_LIBRARIES    - Link these to use PETSc
            7 #  PETSC_COMPILER     - Compiler used by PETSc, helpful to find a compatible MPI
            8 #  PETSC_DEFINITIONS  - Compiler switches for using PETSc
            9 #  PETSC_MPIEXEC      - Executable for running MPI programs
           10 #  PETSC_VERSION      - Version string (MAJOR.MINOR.SUBMINOR)
           11 #
           12 #  Usage:
           13 #  find_package(PETSc COMPONENTS CXX)  - required if build --with-clanguage=C++ --with-c-support=0
           14 #  find_package(PETSc COMPONENTS C)    - standard behavior of checking build using a C compiler
           15 #  find_package(PETSc)                 - same as above
           16 #
           17 # Setting these changes the behavior of the search
           18 #  PETSC_DIR - directory in which PETSc resides
           19 #  PETSC_ARCH - build architecture
           20 #
           21 # Redistribution and use is allowed according to the terms of the BSD license.
           22 # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
           23 #
           24 
           25 cmake_policy(VERSION 3.3)
           26 
           27 set(PETSC_VALID_COMPONENTS
           28   C
           29   CXX)
           30 
           31 if(NOT PETSc_FIND_COMPONENTS)
           32   get_property (_enabled_langs GLOBAL PROPERTY ENABLED_LANGUAGES)
           33   if ("C" IN_LIST _enabled_langs)
           34     set(PETSC_LANGUAGE_BINDINGS "C")
           35   else ()
           36     set(PETSC_LANGUAGE_BINDINGS "CXX")
           37   endif ()
           38 else()
           39   # Right now, this is designed for compatability with the --with-clanguage option, so
           40   # only allow one item in the components list.
           41   list(LENGTH ${PETSc_FIND_COMPONENTS} components_length)
           42   if(${components_length} GREATER 1)
           43     message(FATAL_ERROR "Only one component for PETSc is allowed to be specified")
           44   endif()
           45   # This is a stub for allowing multiple components should that time ever come. Perhaps
           46   # to also test Fortran bindings?
           47   foreach(component ${PETSc_FIND_COMPONENTS})
           48     list(FIND PETSC_VALID_COMPONENTS ${component} component_location)
           49     if(${component_location} EQUAL -1)
           50       message(FATAL_ERROR "\"${component}\" is not a valid PETSc component.")
           51     else()
           52       list(APPEND PETSC_LANGUAGE_BINDINGS ${component})
           53     endif()
           54   endforeach()
           55 endif()
           56 
           57 function (petsc_get_version)
           58   if (EXISTS "${PETSC_DIR}/include/petscversion.h")
           59     file (STRINGS "${PETSC_DIR}/include/petscversion.h" vstrings REGEX "#define PETSC_VERSION_(RELEASE|MAJOR|MINOR|SUBMINOR|PATCH) ")
           60     foreach (line ${vstrings})
           61       string (REGEX REPLACE " +" ";" fields ${line}) # break line into three fields (the first is always "#define")
           62       list (GET fields 1 var)
           63       list (GET fields 2 val)
           64       set (${var} ${val} PARENT_SCOPE)
           65       set (${var} ${val})         # Also in local scope so we have access below
           66     endforeach ()
           67     if (PETSC_VERSION_RELEASE)
           68       if ($(PETSC_VERSION_PATCH) GREATER 0)
           69         set (PETSC_VERSION "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}p${PETSC_VERSION_PATCH}" CACHE INTERNAL "PETSc version")
           70       else ()
           71         set (PETSC_VERSION "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}" CACHE INTERNAL "PETSc version")
           72       endif ()
           73     else ()
           74       # make dev version compare higher than any patch level of a released version
           75       set (PETSC_VERSION "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}.99" CACHE INTERNAL "PETSc version")
           76     endif ()
           77   else ()
           78     message (SEND_ERROR "PETSC_DIR can not be used, ${PETSC_DIR}/include/petscversion.h does not exist")
           79   endif ()
           80 endfunction ()
           81 
           82 # Debian uses versioned paths e.g /usr/lib/petscdir/3.5/
           83 file (GLOB DEB_PATHS "/usr/lib/petscdir/*")
           84 
           85 find_path (PETSC_DIR include/petsc.h
           86   HINTS ENV PETSC_DIR
           87   PATHS
           88   /usr/lib/petsc
           89   # Debian paths
           90   ${DEB_PATHS}
           91   # Arch Linux path
           92   /opt/petsc/linux-c-opt
           93   # MacPorts path
           94   /opt/local/lib/petsc
           95   $ENV{HOME}/petsc
           96   DOC "PETSc Directory")
           97 
           98 find_program (MAKE_EXECUTABLE NAMES make gmake)
           99 
          100 if (PETSC_DIR AND NOT PETSC_ARCH)
          101   set (_petsc_arches
          102     $ENV{PETSC_ARCH}                   # If set, use environment variable first
          103     ""
          104     linux-gnu-c-debug linux-gnu-c-opt  # Debian defaults
          105     x86_64-unknown-linux-gnu i386-unknown-linux-gnu)
          106   set (petscconf "NOTFOUND" CACHE FILEPATH "Cleared" FORCE)
          107   foreach (arch ${_petsc_arches})
          108     if (NOT PETSC_ARCH)
          109       find_path (petscconf petscconf.h
          110         HINTS ${PETSC_DIR}
          111         PATH_SUFFIXES ${arch}/include bmake/${arch}
          112         NO_DEFAULT_PATH)
          113       if (petscconf)
          114         set (PETSC_ARCH "${arch}" CACHE STRING "PETSc build architecture")
          115       endif (petscconf)
          116     endif (NOT PETSC_ARCH)
          117   endforeach (arch)
          118   set (petscconf "NOTFOUND" CACHE INTERNAL "Scratch variable" FORCE)
          119 endif (PETSC_DIR AND NOT PETSC_ARCH)
          120 
          121 set (petsc_slaves LIBRARIES_SYS LIBRARIES_VEC LIBRARIES_MAT LIBRARIES_DM LIBRARIES_KSP LIBRARIES_SNES LIBRARIES_TS
          122   INCLUDE_DIR INCLUDE_CONF)
          123 include (FindPackageMultipass)
          124 find_package_multipass (PETSc petsc_config_current
          125   STATES DIR ARCH
          126   DEPENDENTS INCLUDES LIBRARIES COMPILER MPIEXEC ${petsc_slaves})
          127 
          128 # Determine whether the PETSc layout is old-style (through 2.3.3) or
          129 # new-style (>= 3.0.0)
          130 if (EXISTS "${PETSC_DIR}/${PETSC_ARCH}/lib/petsc/conf/petscvariables") # > 3.5
          131   set (petsc_conf_rules "${PETSC_DIR}/lib/petsc/conf/rules")
          132   set (petsc_conf_variables "${PETSC_DIR}/lib/petsc/conf/variables")
          133 elseif (EXISTS "${PETSC_DIR}/${PETSC_ARCH}/include/petscconf.h")   # > 2.3.3
          134   set (petsc_conf_rules "${PETSC_DIR}/conf/rules")
          135   set (petsc_conf_variables "${PETSC_DIR}/conf/variables")
          136 elseif (EXISTS "${PETSC_DIR}/bmake/${PETSC_ARCH}/petscconf.h") # <= 2.3.3
          137   set (petsc_conf_rules "${PETSC_DIR}/bmake/common/rules")
          138   set (petsc_conf_variables "${PETSC_DIR}/bmake/common/variables")
          139 elseif (PETSC_DIR)
          140   message (SEND_ERROR "The pair PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} do not specify a valid PETSc installation")
          141 endif ()
          142 
          143 if (petsc_conf_rules AND petsc_conf_variables AND NOT petsc_config_current)
          144   petsc_get_version()
          145 
          146   # Put variables into environment since they are needed to get
          147   # configuration (petscvariables) in the PETSc makefile
          148   set (ENV{PETSC_DIR} "${PETSC_DIR}")
          149   set (ENV{PETSC_ARCH} "${PETSC_ARCH}")
          150 
          151   # A temporary makefile to probe the PETSc configuration
          152   set (petsc_config_makefile "${PROJECT_BINARY_DIR}/Makefile.petsc")
          153   file (WRITE "${petsc_config_makefile}"
          154 "## This file was autogenerated by FindPETSc.cmake
          155 # PETSC_DIR  = ${PETSC_DIR}
          156 # PETSC_ARCH = ${PETSC_ARCH}
          157 include ${petsc_conf_rules}
          158 include ${petsc_conf_variables}
          159 show :
          160 \t-@echo -n \${\${VARIABLE}}
          161 ")
          162 
          163   macro (PETSC_GET_VARIABLE name var)
          164     set (${var} "NOTFOUND" CACHE INTERNAL "Cleared" FORCE)
          165     execute_process (COMMAND ${MAKE_EXECUTABLE} --no-print-directory -f ${petsc_config_makefile} show VARIABLE=${name}
          166       OUTPUT_VARIABLE ${var}
          167       RESULT_VARIABLE petsc_return)
          168   endmacro (PETSC_GET_VARIABLE)
          169   petsc_get_variable (PETSC_LIB_DIR            petsc_lib_dir)
          170   petsc_get_variable (PETSC_EXTERNAL_LIB_BASIC petsc_libs_external)
          171   petsc_get_variable (PETSC_CCPPFLAGS          petsc_cpp_line)
          172   petsc_get_variable (PETSC_INCLUDE            petsc_include)
          173   petsc_get_variable (PCC                      petsc_cc)
          174   petsc_get_variable (PCC_FLAGS                petsc_cc_flags)
          175   petsc_get_variable (MPIEXEC                  petsc_mpiexec)
          176   # We are done with the temporary Makefile, calling PETSC_GET_VARIABLE after this point is invalid!
          177   file (REMOVE ${petsc_config_makefile})
          178 
          179   include (ResolveCompilerPaths)
          180   # Extract include paths and libraries from compile command line
          181   resolve_includes (petsc_includes_all "${petsc_cpp_line}")
          182 
          183   #on windows we need to make sure we're linking against the right
          184   #runtime library
          185   if (WIN32)
          186     if (petsc_cc_flags MATCHES "-MT")
          187       set(using_md False)
          188       foreach(flag_var
          189           CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
          190           CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
          191           CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
          192           CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
          193         if(${flag_var} MATCHES "/MD")
          194           set(using_md True)
          195         endif(${flag_var} MATCHES "/MD")
          196       endforeach(flag_var)
          197       if(${using_md} MATCHES "True")
          198         message(WARNING "PETSc was built with /MT, but /MD is currently set.
          199  See http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F")
          200       endif(${using_md} MATCHES "True")
          201     endif (petsc_cc_flags MATCHES "-MT")
          202   endif (WIN32)
          203 
          204   include (CorrectWindowsPaths)
          205   convert_cygwin_path(petsc_lib_dir)
          206   message (STATUS "petsc_lib_dir ${petsc_lib_dir}")
          207 
          208   macro (PETSC_FIND_LIBRARY suffix name)
          209     set (PETSC_LIBRARY_${suffix} "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) # Clear any stale value, if we got here, we need to find it again
          210     if (WIN32)
          211       set (libname lib${name}) #windows expects "libfoo", linux expects "foo"
          212     else (WIN32)
          213       set (libname ${name})
          214     endif (WIN32)
          215     find_library (PETSC_LIBRARY_${suffix} NAMES ${libname} HINTS ${petsc_lib_dir} NO_DEFAULT_PATH)
          216     set (PETSC_LIBRARIES_${suffix} "${PETSC_LIBRARY_${suffix}}")
          217     mark_as_advanced (PETSC_LIBRARY_${suffix})
          218   endmacro (PETSC_FIND_LIBRARY suffix name)
          219 
          220   # Look for petscvec first, if it doesn't exist, we must be using single-library
          221   petsc_find_library (VEC petscvec)
          222   if (PETSC_LIBRARY_VEC)
          223     petsc_find_library (SYS  "petscsys;petsc") # libpetscsys is called libpetsc prior to 3.1 (when single-library was introduced)
          224     petsc_find_library (MAT  petscmat)
          225     petsc_find_library (DM   petscdm)
          226     petsc_find_library (KSP  petscksp)
          227     petsc_find_library (SNES petscsnes)
          228     petsc_find_library (TS   petscts)
          229     macro (PETSC_JOIN libs deps)
          230       list (APPEND PETSC_LIBRARIES_${libs} ${PETSC_LIBRARIES_${deps}})
          231     endmacro (PETSC_JOIN libs deps)
          232     petsc_join (VEC  SYS)
          233     petsc_join (MAT  VEC)
          234     petsc_join (DM   MAT)
          235     petsc_join (KSP  DM)
          236     petsc_join (SNES KSP)
          237     petsc_join (TS   SNES)
          238     petsc_join (ALL  TS)
          239   else ()
          240     set (PETSC_LIBRARY_VEC "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) # There is no libpetscvec
          241     petsc_find_library (SINGLE petsc)
          242     # Debian 9/Ubuntu 16.04 uses _real and _complex extensions when using libraries in /usr/lib/petsc.
          243     if (NOT PETSC_LIBRARY_SINGLE)
          244       petsc_find_library (SINGLE petsc_real)
          245     endif()
          246     if (NOT PETSC_LIBRARY_SINGLE)
          247       petsc_find_library (SINGLE petsc_complex)
          248     endif()
          249     foreach (pkg SYS VEC MAT DM KSP SNES TS ALL)
          250       set (PETSC_LIBRARIES_${pkg} "${PETSC_LIBRARY_SINGLE}")
          251     endforeach ()
          252   endif ()
          253   if (PETSC_LIBRARY_TS)
          254     message (STATUS "Recognized PETSc install with separate libraries for each package")
          255   else ()
          256     message (STATUS "Recognized PETSc install with single library for all packages")
          257   endif ()
          258 
          259   include(Check${PETSC_LANGUAGE_BINDINGS}SourceRuns)
          260   macro (PETSC_TEST_RUNS includes libraries runs)
          261     if (PETSC_VERSION VERSION_GREATER 3.1)
          262       set (_PETSC_TSDestroy "TSDestroy(&ts)")
          263     else ()
          264       set (_PETSC_TSDestroy "TSDestroy(ts)")
          265     endif ()
          266 
          267     set(_PETSC_TEST_SOURCE "
          268 static const char help[] = \"PETSc test program.\";
          269 #include <petscts.h>
          270 int main(int argc,char *argv[]) {
          271   PetscErrorCode ierr;
          272   TS ts;
          273 
          274   ierr = PetscInitialize(&argc,&argv,0,help);CHKERRQ(ierr);
          275   ierr = TSCreate(PETSC_COMM_WORLD,&ts);CHKERRQ(ierr);
          276   ierr = TSSetFromOptions(ts);CHKERRQ(ierr);
          277   ierr = ${_PETSC_TSDestroy};CHKERRQ(ierr);
          278   ierr = PetscFinalize();CHKERRQ(ierr);
          279   return 0;
          280 }
          281 ")
          282     multipass_source_runs ("${includes}" "${libraries}" "${_PETSC_TEST_SOURCE}" ${runs} "${PETSC_LANGUAGE_BINDINGS}")
          283     if (${${runs}})
          284       set (PETSC_EXECUTABLE_RUNS "YES" CACHE BOOL
          285         "Can the system successfully run a PETSc executable?  This variable can be manually set to \"YES\" to force CMake to accept a given PETSc configuration, but this will almost always result in a broken build.  If you change PETSC_DIR, PETSC_ARCH, or PETSC_CURRENT you would have to reset this variable." FORCE)
          286     endif (${${runs}})
          287   endmacro (PETSC_TEST_RUNS)
          288 
          289 
          290   find_path (PETSC_INCLUDE_DIR petscts.h HINTS "${PETSC_DIR}" PATH_SUFFIXES include NO_DEFAULT_PATH)
          291   find_path (PETSC_INCLUDE_CONF petscconf.h HINTS "${PETSC_DIR}" PATH_SUFFIXES "${PETSC_ARCH}/include" "bmake/${PETSC_ARCH}" NO_DEFAULT_PATH)
          292   mark_as_advanced (PETSC_INCLUDE_DIR PETSC_INCLUDE_CONF)
          293   set (petsc_includes_minimal ${PETSC_INCLUDE_CONF} ${PETSC_INCLUDE_DIR})
          294 
          295   petsc_test_runs ("${petsc_includes_minimal}" "${PETSC_LIBRARIES_TS}" petsc_works_minimal)
          296   if (petsc_works_minimal)
          297     message (STATUS "Minimal PETSc includes and libraries work.  This probably means we are building with shared libs.")
          298     set (petsc_includes_needed "${petsc_includes_minimal}")
          299   else (petsc_works_minimal)     # Minimal includes fail, see if just adding full includes fixes it
          300     petsc_test_runs ("${petsc_includes_all}" "${PETSC_LIBRARIES_TS}" petsc_works_allincludes)
          301     if (petsc_works_allincludes) # It does, we just need all the includes (
          302       message (STATUS "PETSc requires extra include paths, but links correctly with only interface libraries.  This is an unexpected configuration (but it seems to work fine).")
          303       set (petsc_includes_needed ${petsc_includes_all})
          304     else (petsc_works_allincludes) # We are going to need to link the external libs explicitly
          305       resolve_libraries (petsc_libraries_external "${petsc_libs_external}")
          306       foreach (pkg SYS VEC MAT DM KSP SNES TS ALL)
          307         list (APPEND PETSC_LIBRARIES_${pkg}  ${petsc_libraries_external})
          308       endforeach (pkg)
          309       petsc_test_runs ("${petsc_includes_minimal}" "${PETSC_LIBRARIES_TS}" petsc_works_alllibraries)
          310       if (petsc_works_alllibraries)
          311          message (STATUS "PETSc only need minimal includes, but requires explicit linking to all dependencies.  This is expected when PETSc is built with static libraries.")
          312         set (petsc_includes_needed ${petsc_includes_minimal})
          313       else (petsc_works_alllibraries)
          314         # It looks like we really need everything, should have listened to Matt
          315         set (petsc_includes_needed ${petsc_includes_all})
          316         petsc_test_runs ("${petsc_includes_all}" "${PETSC_LIBRARIES_TS}" petsc_works_all)
          317         if (petsc_works_all) # We fail anyways
          318           message (STATUS "PETSc requires extra include paths and explicit linking to all dependencies.  This probably means you have static libraries and something unexpected in PETSc headers.")
          319         else (petsc_works_all) # We fail anyways
          320           message (STATUS "PETSc could not be used, maybe the install is broken.")
          321         endif (petsc_works_all)
          322       endif (petsc_works_alllibraries)
          323     endif (petsc_works_allincludes)
          324   endif (petsc_works_minimal)
          325 
          326   # We do an out-of-source build so __FILE__ will be an absolute path, hence __INSDIR__ is superfluous
          327   if (${PETSC_VERSION} VERSION_LESS 3.1)
          328     set (PETSC_DEFINITIONS "-D__SDIR__=\"\"" CACHE STRING "PETSc definitions" FORCE)
          329   else ()
          330     set (PETSC_DEFINITIONS "-D__INSDIR__=" CACHE STRING "PETSc definitions" FORCE)
          331   endif ()
          332   # Sometimes this can be used to assist FindMPI.cmake
          333   set (PETSC_MPIEXEC ${petsc_mpiexec} CACHE FILEPATH "Executable for running PETSc MPI programs" FORCE)
          334   set (PETSC_INCLUDES ${petsc_includes_needed} CACHE STRING "PETSc include path" FORCE)
          335   set (PETSC_LIBRARIES ${PETSC_LIBRARIES_ALL} CACHE STRING "PETSc libraries" FORCE)
          336   set (PETSC_COMPILER ${petsc_cc} CACHE FILEPATH "PETSc compiler" FORCE)
          337   # Note that we have forced values for all these choices.  If you
          338   # change these, you are telling the system to trust you that they
          339   # work.  It is likely that you will end up with a broken build.
          340   mark_as_advanced (PETSC_INCLUDES PETSC_LIBRARIES PETSC_COMPILER PETSC_DEFINITIONS PETSC_MPIEXEC PETSC_EXECUTABLE_RUNS)
          341 endif ()
          342 
          343 include (FindPackageHandleStandardArgs)
          344 find_package_handle_standard_args (PETSc
          345   REQUIRED_VARS PETSC_INCLUDES PETSC_LIBRARIES PETSC_EXECUTABLE_RUNS
          346   VERSION_VAR PETSC_VERSION
          347   FAIL_MESSAGE "PETSc could not be found.  Be sure to set PETSC_DIR and PETSC_ARCH.")