2 # Once done this will define
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)
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
17 # Setting these changes the behavior of the search
18 # PETSC_DIR - directory in which PETSc resides
19 # PETSC_ARCH - build architecture
21 # Redistribution and use is allowed according to the terms of the BSD license.
22 # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
25 set(PETSC_VALID_COMPONENTS
29 if(NOT PETSc_FIND_COMPONENTS)
30 set(PETSC_LANGUAGE_BINDINGS "C")
32 # Right now, this is designed for compatability with the --with-clanguage option, so
33 # only allow one item in the components list.
34 list(LENGTH ${PETSc_FIND_COMPONENTS} components_length)
35 if(${components_length} GREATER 1)
36 message(FATAL_ERROR "Only one component for PETSc is allowed to be specified")
38 # This is a stub for allowing multiple components should that time ever come. Perhaps
39 # to also test Fortran bindings?
40 foreach(component ${PETSc_FIND_COMPONENTS})
41 list(FIND PETSC_VALID_COMPONENTS ${component} component_location)
42 if(${component_location} EQUAL -1)
43 message(FATAL_ERROR "\"${component}\" is not a valid PETSc component.")
45 list(APPEND PETSC_LANGUAGE_BINDINGS ${component})
50 function (petsc_get_version)
51 if (EXISTS "${PETSC_DIR}/petscversion.h" OR EXISTS "${PETSC_DIR}/include/petscversion.h" OR EXISTS "${PETSC_DIR}/${PETSC_ARCH}/include/petscversion.h")
52 if (EXISTS "${PETSC_DIR}/include/petscversion.h")
53 file (STRINGS "${PETSC_DIR}/include/petscversion.h" vstrings REGEX "#define PETSC_VERSION_(RELEASE|MAJOR|MINOR|SUBMINOR|PATCH) ")
54 elseif( EXISTS "${PETSC_DIR}/${PETSC_ARCH}/include/petscversion.h" )
55 file (STRINGS "${PETSC_DIR}/${PETSC_ARCH}/include/petscversion.h" vstrings REGEX "#define PETSC_VERSION_(RELEASE|MAJOR|MINOR|SUBMINOR|PATCH) ")
57 file (STRINGS "${PETSC_DIR}/petscversion.h" vstrings REGEX "#define PETSC_VERSION_(RELEASE|MAJOR|MINOR|SUBMINOR|PATCH) ")
59 foreach (line ${vstrings})
60 string (REGEX REPLACE " +" ";" fields ${line}) # break line into three fields (the first is always "#define")
61 list (GET fields 1 var)
62 list (GET fields 2 val)
63 set (${var} ${val} PARENT_SCOPE)
64 set (${var} ${val}) # Also in local scope so we have access below
67 if (PETSC_VERSION_RELEASE)
68 set (PETSC_VERSION "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}p${PETSC_VERSION_PATCH}" PARENT_SCOPE)
70 # make dev version compare higher than any patch level of a released version
71 set (PETSC_VERSION "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}.99" PARENT_SCOPE)
74 message (SEND_ERROR "PETSC_DIR can not be used, file ${PETSC_DIR}/include/petscversion.h does not exist")
78 find_path (PETSC_DIR include/petsc.h
84 /usr/lib/petscdir/3.7.6 /usr/lib/petscdir/3.7
85 /usr/lib/petscdir/3.6.2 /usr/lib/petscdir/3.6
86 /usr/lib/petscdir/3.5.1 /usr/lib/petscdir/3.5
87 /usr/lib/petscdir/3.4.2 /usr/lib/petscdir/3.4
88 /usr/lib/petscdir/3.3 /usr/lib/petscdir/3.2 /usr/lib/petscdir/3.1
89 /usr/lib/petscdir/3.0.0 /usr/lib/petscdir/2.3.3 /usr/lib/petscdir/2.3.2
93 DOC "PETSc Directory")
95 find_program (MAKE_EXECUTABLE NAMES make gmake)
97 if (PETSC_DIR AND NOT PETSC_ARCH)
99 $ENV{PETSC_ARCH} # If set, use environment variable first
100 linux-gnu-c-debug linux-gnu-c-opt # Debian defaults (petsc compilation)
101 x86_64-linux-gnu-real i686-linux-gnu-real # Debian defaults (petsc system installation)
102 arch-linux2-c-opt or arch-linux2-c-debug # RedHat defaults (petsc compilation)
103 x86_64-redhat-linux-gnu i686-redhat-linux-gnu # RedHat defaults (petsc apt installation)
104 x86_64-unknown-linux-gnu i386-unknown-linux-gnu)
105 set (petscconf "NOTFOUND" CACHE FILEPATH "Cleared" FORCE)
106 foreach (arch ${_petsc_arches})
108 find_path (petscconf petscconf.h
110 PATH_SUFFIXES ${arch}/include bmake/${arch}
113 set (PETSC_ARCH "${arch}" CACHE STRING "PETSc build architecture")
115 endif (NOT PETSC_ARCH)
117 set (petscconf "NOTFOUND" CACHE INTERNAL "Scratch variable" FORCE)
118 endif (PETSC_DIR AND NOT PETSC_ARCH)
120 set (petsc_slaves LIBRARIES_SYS LIBRARIES_VEC LIBRARIES_MAT LIBRARIES_DM LIBRARIES_KSP LIBRARIES_SNES LIBRARIES_TS
121 INCLUDE_DIR INCLUDE_CONF)
122 include (FindPackageMultipass)
123 find_package_multipass (PETSc petsc_config_current
125 DEPENDENTS INCLUDES LIBRARIES COMPILER MPIEXEC ${petsc_slaves})
127 # Determine whether the PETSc layout is old-style (through 2.3.3) or
128 # new-style (>= 3.0.0)
129 if (EXISTS "${PETSC_DIR}/${PETSC_ARCH}/lib/petsc/conf/petscvariables") # > 3.5
130 set (petsc_conf_rules "${PETSC_DIR}/lib/petsc/conf/rules")
131 set (petsc_conf_variables "${PETSC_DIR}/lib/petsc/conf/variables")
132 elseif (EXISTS "${PETSC_DIR}/${PETSC_ARCH}/include/petscconf.h") # > 2.3.3
133 set (petsc_conf_rules "${PETSC_DIR}/conf/rules")
134 set (petsc_conf_variables "${PETSC_DIR}/conf/variables")
135 elseif (EXISTS "${PETSC_DIR}/bmake/${PETSC_ARCH}/petscconf.h") # <= 2.3.3
136 set (petsc_conf_rules "${PETSC_DIR}/bmake/common/rules")
137 set (petsc_conf_variables "${PETSC_DIR}/bmake/common/variables")
139 message (SEND_ERROR "The pair PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} do not specify a valid PETSc installation")
142 if (petsc_conf_rules AND petsc_conf_variables AND NOT petsc_config_current)
145 # Put variables into environment since they are needed to get
146 # configuration (petscvariables) in the PETSc makefile
147 set (ENV{PETSC_DIR} "${PETSC_DIR}")
148 set (ENV{PETSC_ARCH} "${PETSC_ARCH}")
150 # A temporary makefile to probe the PETSc configuration
151 set (petsc_config_makefile "${PROJECT_BINARY_DIR}/Makefile.petsc")
152 file (WRITE "${petsc_config_makefile}"
153 "## This file was autogenerated by FindPETSc.cmake
154 # PETSC_DIR = ${PETSC_DIR}
155 # PETSC_ARCH = ${PETSC_ARCH}
156 include ${petsc_conf_rules}
157 include ${petsc_conf_variables}
159 \t-@echo -n \${\${VARIABLE}}
162 macro (PETSC_GET_VARIABLE name var)
163 set (${var} "NOTFOUND" CACHE INTERNAL "Cleared" FORCE)
164 execute_process (COMMAND ${MAKE_EXECUTABLE} --no-print-directory -f ${petsc_config_makefile} show VARIABLE=${name}
165 OUTPUT_VARIABLE ${var}
166 RESULT_VARIABLE petsc_return)
167 endmacro (PETSC_GET_VARIABLE)
168 petsc_get_variable (PETSC_LIB_DIR petsc_lib_dir)
169 petsc_get_variable (PETSC_EXTERNAL_LIB_BASIC petsc_libs_external)
170 petsc_get_variable (PETSC_CCPPFLAGS petsc_cpp_line)
171 petsc_get_variable (PETSC_INCLUDE petsc_include)
172 petsc_get_variable (PCC petsc_cc)
173 petsc_get_variable (PCC_FLAGS petsc_cc_flags)
174 petsc_get_variable (MPIEXEC petsc_mpiexec)
175 # We are done with the temporary Makefile, calling PETSC_GET_VARIABLE after this point is invalid!
176 file (REMOVE ${petsc_config_makefile})
178 include (ResolveCompilerPaths)
179 # Extract include paths and libraries from compile command line
180 resolve_includes (petsc_includes_all "${petsc_cpp_line}")
182 #on windows we need to make sure we're linking against the right
185 if (petsc_cc_flags MATCHES "-MT")
188 CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
189 CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
190 CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
191 CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
192 if(${flag_var} MATCHES "/MD")
194 endif(${flag_var} MATCHES "/MD")
196 if(${using_md} MATCHES "True")
197 message(WARNING "PETSc was built with /MT, but /MD is currently set.
198 See http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F")
199 endif(${using_md} MATCHES "True")
200 endif (petsc_cc_flags MATCHES "-MT")
203 include (CorrectWindowsPaths)
204 convert_cygwin_path(petsc_lib_dir)
205 message (STATUS "petsc_lib_dir ${petsc_lib_dir}")
207 macro (PETSC_FIND_LIBRARY suffix name)
208 set (PETSC_LIBRARY_${suffix} "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) # Clear any stale value, if we got here, we need to find it again
210 set (libname lib${name}) #windows expects "libfoo", linux expects "foo"
212 set (libname ${name})
214 find_library (PETSC_LIBRARY_${suffix} NAMES ${libname} HINTS ${petsc_lib_dir} NO_DEFAULT_PATH)
215 set (PETSC_LIBRARIES_${suffix} "${PETSC_LIBRARY_${suffix}}")
216 mark_as_advanced (PETSC_LIBRARY_${suffix})
217 endmacro (PETSC_FIND_LIBRARY suffix name)
219 # Look for petscvec first, if it doesn't exist, we must be using single-library
220 petsc_find_library (VEC petscvec)
221 if (PETSC_LIBRARY_VEC)
222 petsc_find_library (SYS "petscsys;petsc") # libpetscsys is called libpetsc prior to 3.1 (when single-library was introduced)
223 petsc_find_library (MAT petscmat)
224 petsc_find_library (DM petscdm)
225 petsc_find_library (KSP petscksp)
226 petsc_find_library (SNES petscsnes)
227 petsc_find_library (TS petscts)
228 macro (PETSC_JOIN libs deps)
229 list (APPEND PETSC_LIBRARIES_${libs} ${PETSC_LIBRARIES_${deps}})
230 endmacro (PETSC_JOIN libs deps)
235 petsc_join (SNES KSP)
239 set (PETSC_LIBRARY_VEC "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) # There is no libpetscvec
240 petsc_find_library (SINGLE petsc) #check existence of libpetsc.so
241 if (NOT PETSC_LIBRARY_SINGLE)
242 petsc_find_library (SINGLE petsc_real) #check existence of libpetsc_real.so
244 if (NOT PETSC_LIBRARY_SINGLE)
245 petsc_find_library (SINGLE petsc_complex) #check existence of libpetsc_complex.so
247 foreach (pkg SYS VEC MAT DM KSP SNES TS ALL)
248 set (PETSC_LIBRARIES_${pkg} "${PETSC_LIBRARY_SINGLE}")
251 if (PETSC_LIBRARY_TS)
252 message (STATUS "Recognized PETSc install with separate libraries for each package")
254 message (STATUS "Recognized PETSc install with single library for all packages")
257 include(Check${PETSC_LANGUAGE_BINDINGS}SourceRuns)
258 macro (PETSC_TEST_RUNS includes libraries runs)
259 if(${PETSC_LANGUAGE_BINDINGS} STREQUAL "C")
260 set(_PETSC_ERR_FUNC "CHKERRQ(ierr)")
261 elseif(${PETSC_LANGUAGE_BINDINGS} STREQUAL "CXX")
262 set(_PETSC_ERR_FUNC "CHKERRXX(ierr)")
264 if (PETSC_VERSION VERSION_GREATER 3.1)
265 set (_PETSC_TSDestroy "TSDestroy(&ts)")
267 set (_PETSC_TSDestroy "TSDestroy(ts)")
270 set(_PETSC_TEST_SOURCE "
271 static const char help[] = \"PETSc test program.\";
273 int main(int argc,char *argv[]) {
277 ierr = PetscInitialize(&argc,&argv,0,help);${_PETSC_ERR_FUNC};
278 ierr = TSCreate(PETSC_COMM_WORLD,&ts);${_PETSC_ERR_FUNC};
279 ierr = TSSetFromOptions(ts);${_PETSC_ERR_FUNC};
280 ierr = ${_PETSC_TSDestroy};${_PETSC_ERR_FUNC};
281 ierr = PetscFinalize();${_PETSC_ERR_FUNC};
285 multipass_source_runs ("${includes}" "${libraries}" "${_PETSC_TEST_SOURCE}" ${runs} "${PETSC_LANGUAGE_BINDINGS}")
287 set (PETSC_EXECUTABLE_RUNS "YES" CACHE BOOL
288 "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)
290 endmacro (PETSC_TEST_RUNS)
293 find_path (PETSC_INCLUDE_DIR petscts.h HINTS "${PETSC_DIR}" PATH_SUFFIXES include NO_DEFAULT_PATH)
294 find_path (PETSC_INCLUDE_CONF petscconf.h HINTS "${PETSC_DIR}" PATH_SUFFIXES "${PETSC_ARCH}/include" "bmake/${PETSC_ARCH}" NO_DEFAULT_PATH)
295 mark_as_advanced (PETSC_INCLUDE_DIR PETSC_INCLUDE_CONF)
296 set (petsc_includes_minimal ${PETSC_INCLUDE_CONF} ${PETSC_INCLUDE_DIR})
298 petsc_test_runs ("${petsc_includes_minimal}" "${PETSC_LIBRARIES_TS}" petsc_works_minimal)
299 if (petsc_works_minimal)
300 message (STATUS "Minimal PETSc includes and libraries work. This probably means we are building with shared libs.")
301 set (petsc_includes_needed "${petsc_includes_minimal}")
302 else (petsc_works_minimal) # Minimal includes fail, see if just adding full includes fixes it
303 petsc_test_runs ("${petsc_includes_all}" "${PETSC_LIBRARIES_TS}" petsc_works_allincludes)
304 if (petsc_works_allincludes) # It does, we just need all the includes (
305 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).")
306 set (petsc_includes_needed ${petsc_includes_all})
307 else (petsc_works_allincludes) # We are going to need to link the external libs explicitly
308 resolve_libraries (petsc_libraries_external "${petsc_libs_external}")
309 foreach (pkg SYS VEC MAT DM KSP SNES TS ALL)
310 list (APPEND PETSC_LIBRARIES_${pkg} ${petsc_libraries_external})
312 petsc_test_runs ("${petsc_includes_minimal}" "${PETSC_LIBRARIES_TS}" petsc_works_alllibraries)
313 if (petsc_works_alllibraries)
314 message (STATUS "PETSc only need minimal includes, but requires explicit linking to all dependencies. This is expected when PETSc is built with static libraries.")
315 set (petsc_includes_needed ${petsc_includes_minimal})
316 else (petsc_works_alllibraries)
317 # It looks like we really need everything, should have listened to Matt
318 set (petsc_includes_needed ${petsc_includes_all})
319 petsc_test_runs ("${petsc_includes_all}" "${PETSC_LIBRARIES_TS}" petsc_works_all)
320 if (petsc_works_all) # We fail anyways
321 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.")
322 else (petsc_works_all) # We fail anyways
323 message (STATUS "PETSc could not be used, maybe the install is broken.")
324 endif (petsc_works_all)
325 endif (petsc_works_alllibraries)
326 endif (petsc_works_allincludes)
327 endif (petsc_works_minimal)
329 # We do an out-of-source build so __FILE__ will be an absolute path, hence __INSDIR__ is superfluous
330 if (${PETSC_VERSION} VERSION_LESS 3.1)
331 set (PETSC_DEFINITIONS "-D__SDIR__=\"\"" CACHE STRING "PETSc definitions" FORCE)
333 set (PETSC_DEFINITIONS "-D__INSDIR__=" CACHE STRING "PETSc definitions" FORCE)
335 # Sometimes this can be used to assist FindMPI.cmake
336 set (PETSC_MPIEXEC ${petsc_mpiexec} CACHE FILEPATH "Executable for running PETSc MPI programs" FORCE)
337 set (PETSC_INCLUDES ${petsc_includes_needed} CACHE STRING "PETSc include path" FORCE)
338 set (PETSC_LIBRARIES ${PETSC_LIBRARIES_ALL} CACHE STRING "PETSc libraries" FORCE)
339 set (PETSC_COMPILER ${petsc_cc} CACHE FILEPATH "PETSc compiler" FORCE)
340 # Note that we have forced values for all these choices. If you
341 # change these, you are telling the system to trust you that they
342 # work. It is likely that you will end up with a broken build.
343 mark_as_advanced (PETSC_INCLUDES PETSC_LIBRARIES PETSC_COMPILER PETSC_DEFINITIONS PETSC_MPIEXEC PETSC_EXECUTABLE_RUNS)
346 include (FindPackageHandleStandardArgs)
347 find_package_handle_standard_args (PETSc
348 "PETSc could not be found. Be sure to set PETSC_DIR and PETSC_ARCH."
349 PETSC_INCLUDES PETSC_LIBRARIES PETSC_EXECUTABLE_RUNS)