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.12.4 /usr/lib/petscdir/3.12 #Ubuntu 20.04
85 /usr/lib/petscdir/3.7.6 /usr/lib/petscdir/3.7 #Ubuntu 18.04
86 /usr/lib/petscdir/3.6.2 /usr/lib/petscdir/3.6 #Ubuntu 16.04
87 /usr/lib/petscdir/3.5.1 /usr/lib/petscdir/3.5
88 /usr/lib/petscdir/3.4.2 /usr/lib/petscdir/3.4
89 /usr/lib/petscdir/3.3 /usr/lib/petscdir/3.2 /usr/lib/petscdir/3.1
90 /usr/lib/petscdir/3.0.0 /usr/lib/petscdir/2.3.3 /usr/lib/petscdir/2.3.2
94 DOC "PETSc Directory")
96 find_program (MAKE_EXECUTABLE NAMES make gmake)
98 if (PETSC_DIR AND NOT PETSC_ARCH)
100 $ENV{PETSC_ARCH} # If set, use environment variable first
101 linux-gnu-c-debug linux-gnu-c-opt # old Debian defaults (petsc compilation)
102 arch-linux-c-opt or arch-linux-c-debug # new Debian defaults (petsc compilation)
103 x86_64-linux-gnu-real i686-linux-gnu-real # Debian defaults (petsc system installation)
104 arch-linux2-c-opt or arch-linux2-c-debug # old RedHat defaults (petsc compilation)
105 x86_64-redhat-linux-gnu i686-redhat-linux-gnu # RedHat defaults (petsc apt installation)
106 x86_64-unknown-linux-gnu i386-unknown-linux-gnu)
107 set (petscconf "NOTFOUND" CACHE FILEPATH "Cleared" FORCE)
108 foreach (arch ${_petsc_arches})
110 find_path (petscconf petscconf.h
112 PATH_SUFFIXES ${arch}/include bmake/${arch}
115 set (PETSC_ARCH "${arch}" CACHE STRING "PETSc build architecture")
117 endif (NOT PETSC_ARCH)
119 set (petscconf "NOTFOUND" CACHE INTERNAL "Scratch variable" FORCE)
120 endif (PETSC_DIR AND NOT PETSC_ARCH)
122 set (petsc_slaves LIBRARIES_SYS LIBRARIES_VEC LIBRARIES_MAT LIBRARIES_DM LIBRARIES_KSP LIBRARIES_SNES LIBRARIES_TS
123 INCLUDE_DIR INCLUDE_CONF)
124 include (FindPackageMultipass)
125 find_package_multipass (PETSc petsc_config_current
127 DEPENDENTS INCLUDES LIBRARIES COMPILER MPIEXEC ${petsc_slaves})
129 # Determine whether the PETSc layout is old-style (through 2.3.3) or
130 # new-style (>= 3.0.0)
131 if (EXISTS "${PETSC_DIR}/${PETSC_ARCH}/lib/petsc/conf/petscvariables") # > 3.5
132 set (petsc_conf_rules "${PETSC_DIR}/lib/petsc/conf/rules")
133 set (petsc_conf_variables "${PETSC_DIR}/lib/petsc/conf/variables")
134 elseif (EXISTS "${PETSC_DIR}/${PETSC_ARCH}/include/petscconf.h") # > 2.3.3
135 set (petsc_conf_rules "${PETSC_DIR}/conf/rules")
136 set (petsc_conf_variables "${PETSC_DIR}/conf/variables")
137 elseif (EXISTS "${PETSC_DIR}/bmake/${PETSC_ARCH}/petscconf.h") # <= 2.3.3
138 set (petsc_conf_rules "${PETSC_DIR}/bmake/common/rules")
139 set (petsc_conf_variables "${PETSC_DIR}/bmake/common/variables")
141 message (SEND_ERROR "The pair PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} do not specify a valid PETSc installation")
144 if (petsc_conf_rules AND petsc_conf_variables AND NOT petsc_config_current)
147 # Put variables into environment since they are needed to get
148 # configuration (petscvariables) in the PETSc makefile
149 set (ENV{PETSC_DIR} "${PETSC_DIR}")
150 set (ENV{PETSC_ARCH} "${PETSC_ARCH}")
152 # A temporary makefile to probe the PETSc configuration
153 set (petsc_config_makefile "${PROJECT_BINARY_DIR}/Makefile.petsc")
154 file (WRITE "${petsc_config_makefile}"
155 "## This file was autogenerated by FindPETSc.cmake
156 # PETSC_DIR = ${PETSC_DIR}
157 # PETSC_ARCH = ${PETSC_ARCH}
158 include ${petsc_conf_rules}
159 include ${petsc_conf_variables}
161 \t-@echo -n \${\${VARIABLE}}
164 macro (PETSC_GET_VARIABLE name var)
165 set (${var} "NOTFOUND" CACHE INTERNAL "Cleared" FORCE)
166 execute_process (COMMAND ${MAKE_EXECUTABLE} --no-print-directory -f ${petsc_config_makefile} show VARIABLE=${name}
167 OUTPUT_VARIABLE ${var}
168 RESULT_VARIABLE petsc_return)
169 endmacro (PETSC_GET_VARIABLE)
170 petsc_get_variable (PETSC_LIB_DIR petsc_lib_dir)
171 petsc_get_variable (PETSC_EXTERNAL_LIB_BASIC petsc_libs_external)
172 petsc_get_variable (PETSC_CCPPFLAGS petsc_cpp_line)
173 petsc_get_variable (PETSC_INCLUDE petsc_include)
174 petsc_get_variable (PCC petsc_cc)
175 petsc_get_variable (PCC_FLAGS petsc_cc_flags)
176 petsc_get_variable (MPIEXEC petsc_mpiexec)
177 # We are done with the temporary Makefile, calling PETSC_GET_VARIABLE after this point is invalid!
178 file (REMOVE ${petsc_config_makefile})
180 include (ResolveCompilerPaths)
181 # Extract include paths and libraries from compile command line
182 resolve_includes (petsc_includes_all "${petsc_cpp_line}")
184 #on windows we need to make sure we're linking against the right
187 if (petsc_cc_flags MATCHES "-MT")
190 CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
191 CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
192 CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
193 CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
194 if(${flag_var} MATCHES "/MD")
196 endif(${flag_var} MATCHES "/MD")
198 if(${using_md} MATCHES "True")
199 message(WARNING "PETSc was built with /MT, but /MD is currently set.
200 See http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F")
201 endif(${using_md} MATCHES "True")
202 endif (petsc_cc_flags MATCHES "-MT")
205 include (CorrectWindowsPaths)
206 convert_cygwin_path(petsc_lib_dir)
207 message (STATUS "petsc_lib_dir ${petsc_lib_dir}")
209 macro (PETSC_FIND_LIBRARY suffix name)
210 set (PETSC_LIBRARY_${suffix} "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) # Clear any stale value, if we got here, we need to find it again
212 set (libname lib${name}) #windows expects "libfoo", linux expects "foo"
214 set (libname ${name})
216 find_library (PETSC_LIBRARY_${suffix} NAMES ${libname} HINTS ${petsc_lib_dir} NO_DEFAULT_PATH)
217 set (PETSC_LIBRARIES_${suffix} "${PETSC_LIBRARY_${suffix}}")
218 mark_as_advanced (PETSC_LIBRARY_${suffix})
219 endmacro (PETSC_FIND_LIBRARY suffix name)
221 # Look for petscvec first, if it doesn't exist, we must be using single-library
222 petsc_find_library (VEC petscvec)
223 if (PETSC_LIBRARY_VEC)
224 petsc_find_library (SYS "petscsys;petsc") # libpetscsys is called libpetsc prior to 3.1 (when single-library was introduced)
225 petsc_find_library (MAT petscmat)
226 petsc_find_library (DM petscdm)
227 petsc_find_library (KSP petscksp)
228 petsc_find_library (SNES petscsnes)
229 petsc_find_library (TS petscts)
230 macro (PETSC_JOIN libs deps)
231 list (APPEND PETSC_LIBRARIES_${libs} ${PETSC_LIBRARIES_${deps}})
232 endmacro (PETSC_JOIN libs deps)
237 petsc_join (SNES KSP)
241 set (PETSC_LIBRARY_VEC "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) # There is no libpetscvec
242 petsc_find_library (SINGLE petsc) #check existence of libpetsc.so
243 if (NOT PETSC_LIBRARY_SINGLE)
244 petsc_find_library (SINGLE petsc_real) #check existence of libpetsc_real.so
246 if (NOT PETSC_LIBRARY_SINGLE)
247 petsc_find_library (SINGLE petsc_complex) #check existence of libpetsc_complex.so
249 foreach (pkg SYS VEC MAT DM KSP SNES TS ALL)
250 set (PETSC_LIBRARIES_${pkg} "${PETSC_LIBRARY_SINGLE}")
253 if (PETSC_LIBRARY_TS)
254 message (STATUS "Recognized PETSc install with separate libraries for each package")
256 message (STATUS "Recognized PETSc install with single library for all packages")
259 include(Check${PETSC_LANGUAGE_BINDINGS}SourceRuns)
260 macro (PETSC_TEST_RUNS includes libraries runs)
261 if(${PETSC_LANGUAGE_BINDINGS} STREQUAL "C")
262 set(_PETSC_ERR_FUNC "CHKERRQ(ierr)")
263 elseif(${PETSC_LANGUAGE_BINDINGS} STREQUAL "CXX")
264 set(_PETSC_ERR_FUNC "CHKERRXX(ierr)")
266 if (PETSC_VERSION VERSION_GREATER 3.1)
267 set (_PETSC_TSDestroy "TSDestroy(&ts)")
269 set (_PETSC_TSDestroy "TSDestroy(ts)")
272 set(_PETSC_TEST_SOURCE "
273 static const char help[] = \"PETSc test program.\";
275 int main(int argc,char *argv[]) {
280 ierr = PetscInitialize(&argc,&argv,0,help);${_PETSC_ERR_FUNC};
281 ierr = TSCreate(PETSC_COMM_WORLD,&ts);${_PETSC_ERR_FUNC};
282 ierr = TSSetFromOptions(ts);${_PETSC_ERR_FUNC};
283 ierr = ${_PETSC_TSDestroy};${_PETSC_ERR_FUNC};
284 ierr = PetscFinalize();${_PETSC_ERR_FUNC};
289 multipass_source_runs ("${includes}" "${libraries}" "${_PETSC_TEST_SOURCE}" ${runs} "${PETSC_LANGUAGE_BINDINGS}")
291 set (PETSC_EXECUTABLE_RUNS "YES" CACHE BOOL
292 "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)
294 endmacro (PETSC_TEST_RUNS)
297 find_path (PETSC_INCLUDE_DIR petscts.h HINTS "${PETSC_DIR}" PATH_SUFFIXES include NO_DEFAULT_PATH)
298 find_path (PETSC_INCLUDE_CONF petscconf.h HINTS "${PETSC_DIR}" PATH_SUFFIXES "${PETSC_ARCH}/include" "bmake/${PETSC_ARCH}" NO_DEFAULT_PATH)
299 mark_as_advanced (PETSC_INCLUDE_DIR PETSC_INCLUDE_CONF)
300 set (petsc_includes_minimal ${PETSC_INCLUDE_CONF} ${PETSC_INCLUDE_DIR})
302 petsc_test_runs ("${petsc_includes_minimal}" "${PETSC_LIBRARIES_TS}" petsc_works_minimal)
303 if (petsc_works_minimal)
304 message (STATUS "Minimal PETSc includes and libraries work. This probably means we are building with shared libs.")
305 set (petsc_includes_needed "${petsc_includes_minimal}")
306 else (petsc_works_minimal) # Minimal includes fail, see if just adding full includes fixes it
307 petsc_test_runs ("${petsc_includes_all}" "${PETSC_LIBRARIES_TS}" petsc_works_allincludes)
308 if (petsc_works_allincludes) # It does, we just need all the includes (
309 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).")
310 set (petsc_includes_needed ${petsc_includes_all})
311 else (petsc_works_allincludes) # We are going to need to link the external libs explicitly
312 resolve_libraries (petsc_libraries_external "${petsc_libs_external}")
313 foreach (pkg SYS VEC MAT DM KSP SNES TS ALL)
314 list (APPEND PETSC_LIBRARIES_${pkg} ${petsc_libraries_external})
316 petsc_test_runs ("${petsc_includes_minimal}" "${PETSC_LIBRARIES_TS}" petsc_works_alllibraries)
317 if (petsc_works_alllibraries)
318 message (STATUS "PETSc only need minimal includes, but requires explicit linking to all dependencies. This is expected when PETSc is built with static libraries.")
319 set (petsc_includes_needed ${petsc_includes_minimal})
320 else (petsc_works_alllibraries)
321 # It looks like we really need everything, should have listened to Matt
322 set (petsc_includes_needed ${petsc_includes_all})
323 petsc_test_runs ("${petsc_includes_all}" "${PETSC_LIBRARIES_TS}" petsc_works_all)
324 if (petsc_works_all) # We fail anyways
325 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.")
326 else (petsc_works_all) # We fail anyways
327 message (STATUS "PETSc could not be used, maybe the install is broken.")
328 endif (petsc_works_all)
329 endif (petsc_works_alllibraries)
330 endif (petsc_works_allincludes)
331 endif (petsc_works_minimal)
333 # We do an out-of-source build so __FILE__ will be an absolute path, hence __INSDIR__ is superfluous
334 if (${PETSC_VERSION} VERSION_LESS 3.1)
335 set (PETSC_DEFINITIONS "-D__SDIR__=\"\"" CACHE STRING "PETSc definitions" FORCE)
337 set (PETSC_DEFINITIONS "-D__INSDIR__=" CACHE STRING "PETSc definitions" FORCE)
339 # Sometimes this can be used to assist FindMPI.cmake
340 set (PETSC_MPIEXEC ${petsc_mpiexec} CACHE FILEPATH "Executable for running PETSc MPI programs" FORCE)
341 set (PETSC_INCLUDES ${petsc_includes_needed} CACHE STRING "PETSc include path" FORCE)
342 set (PETSC_LIBRARIES ${PETSC_LIBRARIES_ALL} CACHE STRING "PETSc libraries" FORCE)
343 set (PETSC_COMPILER ${petsc_cc} CACHE FILEPATH "PETSc compiler" FORCE)
344 # Note that we have forced values for all these choices. If you
345 # change these, you are telling the system to trust you that they
346 # work. It is likely that you will end up with a broken build.
347 mark_as_advanced (PETSC_INCLUDES PETSC_LIBRARIES PETSC_COMPILER PETSC_DEFINITIONS PETSC_MPIEXEC PETSC_EXECUTABLE_RUNS)
350 include (FindPackageHandleStandardArgs)
351 find_package_handle_standard_args (PETSc
352 "PETSc could not be found. Be sure to set PETSC_DIR and PETSC_ARCH."
353 PETSC_INCLUDES PETSC_LIBRARIES PETSC_EXECUTABLE_RUNS)