2013-05-15 03:24:52 -05:00
|
|
|
# - Find Tim Davis' SuiteSparse collection of sparse matrix libraries
|
|
|
|
#
|
|
|
|
# Synopsis:
|
|
|
|
# find_package (SuiteSparse COMPONENTS <list-of-components>)
|
|
|
|
#
|
|
|
|
# Components are:
|
|
|
|
# amd Approximate Minimum Degree ordering
|
|
|
|
# camd Constrained Approximate Minimum Degree ordering
|
|
|
|
# colamd COLumn Approximate Minimum Degree ordering
|
|
|
|
# ccolamd Constrained COLumn Approximate Minimum Degree ordering
|
|
|
|
# cholmod Supernodal sparse Cholesky factorization and update
|
|
|
|
# umfpack Unsymmetric MultiFrontal sparse LU factorization
|
|
|
|
#
|
|
|
|
# The following variables will be set:
|
|
|
|
#
|
|
|
|
# SuiteSparse_FOUND True if all dependencies are satisfied
|
|
|
|
# SuiteSparse_Xxx_FOUND True if module Xxx is found
|
|
|
|
# HAVE_SUITESPARSE_Xxx_H Binary value indicating presence of header
|
|
|
|
# SuiteSparse_INCLUDE_DIRS Paths containing the SuiteSparse header files
|
|
|
|
# SuiteSparse_LIBRARIES Name of the libraries which must be linked
|
|
|
|
# SuiteSparse_DEFINITIONS Defines that must be passed to the compiler
|
|
|
|
# SuiteSparse_LINKER_FLAGS Options that must be passed when linking
|
|
|
|
#
|
|
|
|
# See <http://www.cise.ufl.edu/research/sparse/SuiteSparse>.
|
|
|
|
|
|
|
|
# Copyright (C) 2012 Uni Research AS
|
|
|
|
# This file is licensed under the GNU General Public License v3.0
|
|
|
|
|
|
|
|
function (try_compile_umfpack varname)
|
|
|
|
include (CMakePushCheckState)
|
|
|
|
include (CheckCSourceCompiles)
|
|
|
|
cmake_push_check_state ()
|
|
|
|
set (CMAKE_REQUIRED_INCLUDES ${UMFPACK_INCLUDE_DIRS})
|
|
|
|
set (CMAKE_REQUIRED_LIBRARIES ${UMFPACK_LIBRARY} ${ARGN} ${SuiteSparse_EXTRA_LIBS})
|
|
|
|
check_c_source_compiles (
|
|
|
|
"#include <umfpack.h>
|
|
|
|
int main (void) {
|
|
|
|
void *Symbolic, *Numeric;
|
|
|
|
double Info[UMFPACK_INFO], Control[UMFPACK_CONTROL];
|
|
|
|
umfpack_dl_defaults(Control);
|
|
|
|
umfpack_dl_symbolic(0, 0, 0, 0, 0,
|
|
|
|
&Symbolic, Control, Info);
|
|
|
|
umfpack_dl_numeric (0, 0, 0,
|
|
|
|
Symbolic, &Numeric, Control, Info);
|
|
|
|
umfpack_dl_free_symbolic(&Symbolic);
|
|
|
|
umfpack_dl_solve(UMFPACK_A, 0, 0, 0, 0, 0,
|
|
|
|
Numeric, Control, Info);
|
|
|
|
umfpack_dl_free_numeric(&Numeric);
|
|
|
|
umfpack_timer ();
|
|
|
|
return 0;
|
|
|
|
}" ${varname})
|
|
|
|
cmake_pop_check_state ()
|
|
|
|
set (${varname} "${${varname}}" PARENT_SCOPE)
|
|
|
|
endfunction (try_compile_umfpack varname)
|
|
|
|
|
|
|
|
# variables to pass on to other packages
|
|
|
|
if (FIND_QUIETLY)
|
|
|
|
set (SuiteSparse_QUIET "QUIET")
|
|
|
|
else (FIND_QUIETLY)
|
|
|
|
set (SuiteSparse_QUIET "")
|
|
|
|
endif (FIND_QUIETLY)
|
|
|
|
|
|
|
|
# we need to link to BLAS and LAPACK
|
|
|
|
if (NOT BLAS_FOUND)
|
|
|
|
find_package (BLAS ${SuiteSparse_QUIET} REQUIRED)
|
|
|
|
endif (NOT BLAS_FOUND)
|
|
|
|
if (NOT LAPACK_FOUND)
|
|
|
|
find_package (LAPACK ${SuiteSparse_QUIET} REQUIRED)
|
|
|
|
endif (NOT LAPACK_FOUND)
|
|
|
|
|
|
|
|
# we also need the math part of the runtime library
|
|
|
|
find_library (MATH_LIBRARY NAMES "m")
|
|
|
|
set (SuiteSparse_EXTRA_LIBS ${LAPACK_LIBRARIES} ${BLAS_LIBRARIES} ${MATH_LIBRARY})
|
|
|
|
|
|
|
|
# search paths for the library outside of standard system paths. these are the
|
|
|
|
# paths in which the package managers on various distros put the files
|
|
|
|
list (APPEND SuiteSparse_SEARCH_PATH "/usr") # Linux
|
|
|
|
list (APPEND SuiteSparse_SEARCH_PATH "/opt/local") # MacOS X
|
|
|
|
|
|
|
|
# if we don't get any further clues about where to look, then start
|
|
|
|
# roaming around the system
|
|
|
|
set (_no_default_path "")
|
|
|
|
|
|
|
|
# pick up paths from the environment if specified there; these replace the
|
|
|
|
# pre-defined paths so that we don't accidentially pick up old stuff
|
|
|
|
if (NOT $ENV{SuiteSparse_DIR} STREQUAL "")
|
|
|
|
set (SuiteSparse_SEARCH_PATH "$ENV{SuiteSparse_DIR}")
|
|
|
|
set (_no_default_path "NO_DEFAULT_PATH")
|
|
|
|
endif (NOT $ENV{SuiteSparse_DIR} STREQUAL "")
|
2013-09-12 02:36:19 -05:00
|
|
|
if (SuiteSparse_DIR)
|
2013-05-15 03:24:52 -05:00
|
|
|
set (SuiteSparse_SEARCH_PATH "${SuiteSparse_DIR}")
|
|
|
|
set (_no_default_path "NO_DEFAULT_PATH")
|
2013-09-12 02:36:19 -05:00
|
|
|
endif (SuiteSparse_DIR)
|
2013-05-15 03:24:52 -05:00
|
|
|
# CMake uses _DIR suffix as default for config-mode files; it is unlikely
|
|
|
|
# that we are building SuiteSparse ourselves; use _ROOT suffix to specify
|
|
|
|
# location to pre-canned binaries
|
|
|
|
if (NOT $ENV{SuiteSparse_ROOT} STREQUAL "")
|
|
|
|
set (SuiteSparse_SEARCH_PATH "$ENV{SuiteSparse_ROOT}")
|
|
|
|
set (_no_default_path "NO_DEFAULT_PATH")
|
|
|
|
endif (NOT $ENV{SuiteSparse_ROOT} STREQUAL "")
|
2013-09-12 02:36:19 -05:00
|
|
|
if (SuiteSparse_ROOT)
|
2013-05-15 03:24:52 -05:00
|
|
|
set (SuiteSparse_SEARCH_PATH "${SuiteSparse_ROOT}")
|
|
|
|
set (_no_default_path "NO_DEFAULT_PATH")
|
2013-09-12 02:36:19 -05:00
|
|
|
endif (SuiteSparse_ROOT)
|
2013-05-15 03:24:52 -05:00
|
|
|
|
|
|
|
# transitive closure of dependencies; after this SuiteSparse_MODULES is the
|
|
|
|
# full list of modules that must be found to satisfy the user's link demands
|
|
|
|
set (SuiteSparse_MODULES ${SuiteSparse_FIND_COMPONENTS})
|
|
|
|
list (FIND SuiteSparse_MODULES "umfpack" UMFPACK_DESIRED)
|
|
|
|
if (NOT UMFPACK_DESIRED EQUAL -1)
|
|
|
|
list (APPEND SuiteSparse_MODULES amd cholmod)
|
|
|
|
endif (NOT UMFPACK_DESIRED EQUAL -1)
|
|
|
|
list (FIND SuiteSparse_MODULES "cholmod" CHOLMOD_DESIRED)
|
|
|
|
if (NOT CHOLMOD_DESIRED EQUAL -1)
|
|
|
|
list (APPEND SuiteSparse_MODULES amd camd colamd)
|
|
|
|
endif (NOT CHOLMOD_DESIRED EQUAL -1)
|
|
|
|
if (SuiteSparse_MODULES)
|
|
|
|
list (REMOVE_DUPLICATES SuiteSparse_MODULES)
|
|
|
|
endif (SuiteSparse_MODULES)
|
|
|
|
|
|
|
|
# if someone else already have found all the packages for us, then don't do anything
|
|
|
|
set (SuiteSparse_EVERYTHING_FOUND TRUE)
|
|
|
|
foreach (module IN LISTS SuiteSparse_MODULES)
|
|
|
|
string (TOUPPER ${module} MODULE)
|
|
|
|
if (NOT SuiteSparse_${MODULE}_FOUND)
|
|
|
|
set (SuiteSparse_EVERYTHING_FOUND FALSE)
|
|
|
|
break ()
|
|
|
|
endif (NOT SuiteSparse_${MODULE}_FOUND)
|
|
|
|
endforeach (module)
|
|
|
|
if (SuiteSparse_EVERYTHING_FOUND)
|
|
|
|
return ()
|
|
|
|
endif (SuiteSparse_EVERYTHING_FOUND)
|
|
|
|
|
|
|
|
# only search in architecture-relevant directory
|
|
|
|
if (CMAKE_SIZEOF_VOID_P)
|
|
|
|
math (EXPR _BITS "8 * ${CMAKE_SIZEOF_VOID_P}")
|
|
|
|
endif (CMAKE_SIZEOF_VOID_P)
|
|
|
|
|
|
|
|
# if SuiteSparse >= 4.0 we must also link with libsuitesparseconfig
|
|
|
|
# assume that this is the case if we find the library; otherwise just
|
|
|
|
# ignore it (older versions don't have a file named like this)
|
|
|
|
find_library (config_LIBRARY
|
|
|
|
NAMES suitesparseconfig
|
|
|
|
PATHS ${SuiteSparse_SEARCH_PATH}
|
|
|
|
PATH_SUFFIXES ".libs" "lib" "lib${_BITS}" "lib/${CMAKE_LIBRARY_ARCHITECTURE}" "lib/ufsparse"
|
|
|
|
${_no_default_path}
|
|
|
|
)
|
|
|
|
if (config_LIBRARY)
|
|
|
|
list (APPEND SuiteSparse_EXTRA_LIBS ${config_LIBRARY})
|
|
|
|
# POSIX.1-2001 REALTIME portion require us to link this library too for
|
|
|
|
# clock_gettime() which is used by suitesparseconfig
|
|
|
|
if ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
|
|
|
|
list (APPEND SuiteSparse_EXTRA_LIBS "-lrt")
|
|
|
|
endif ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
|
|
|
|
endif (config_LIBRARY)
|
|
|
|
|
|
|
|
# search filesystem for each of the module individually
|
|
|
|
foreach (module IN LISTS SuiteSparse_MODULES)
|
|
|
|
string (TOUPPER ${module} MODULE)
|
|
|
|
# search for files which implements this module
|
|
|
|
find_path (${MODULE}_INCLUDE_DIR
|
|
|
|
NAMES ${module}.h
|
|
|
|
PATHS ${SuiteSparse_SEARCH_PATH}
|
2013-08-26 02:55:13 -05:00
|
|
|
PATH_SUFFIXES "include" "include/suitesparse" "include/ufsparse" "${MODULE}/Include"
|
2013-05-15 03:24:52 -05:00
|
|
|
${_no_default_path}
|
|
|
|
)
|
|
|
|
find_library (${MODULE}_LIBRARY
|
|
|
|
NAMES ${module}
|
|
|
|
PATHS ${SuiteSparse_SEARCH_PATH}
|
2013-08-26 02:55:13 -05:00
|
|
|
PATH_SUFFIXES "lib/.libs" "lib" "lib${_BITS}" "lib/${CMAKE_LIBRARY_ARCHITECTURE}" "lib/ufsparse" "${MODULE}/Lib"
|
2013-05-15 03:24:52 -05:00
|
|
|
${_no_default_path}
|
|
|
|
)
|
|
|
|
# start out by including the module itself; other dependencies will be added later
|
|
|
|
set (${MODULE}_INCLUDE_DIRS ${${MODULE}_INCLUDE_DIR})
|
|
|
|
set (${MODULE}_LIBRARIES ${${MODULE}_LIBRARY})
|
|
|
|
endforeach (module)
|
|
|
|
|
|
|
|
# insert any inter-modular dependencies here
|
|
|
|
if (CHOLMOD_LIBRARY)
|
|
|
|
list (APPEND CHOLMOD_LIBRARIES ${AMD_LIBRARIES} ${COLAMD_LIBRARIES})
|
|
|
|
# optional libraries; don't insert any -NOT_FOUND paths
|
|
|
|
if (CAMD_LIBRARY)
|
|
|
|
list (APPEND CHOLMOD_LIBRARIES ${CAMD_LIBRARIES})
|
|
|
|
endif (CAMD_LIBRARY)
|
|
|
|
if (CCOLAMD_LIBRARY)
|
|
|
|
list (APPEND CHOLMOD_LIBRARIES ${CCOLAMD_LIBRARIES})
|
|
|
|
endif (CCOLAMD_LIBRARY)
|
|
|
|
list (REVERSE CHOLMOD_LIBRARIES)
|
|
|
|
# always remove the *first* library from the list
|
|
|
|
list (REMOVE_DUPLICATES CHOLMOD_LIBRARIES)
|
|
|
|
list (REVERSE CHOLMOD_LIBRARIES)
|
|
|
|
endif (CHOLMOD_LIBRARY)
|
|
|
|
if (UMFPACK_LIBRARY)
|
|
|
|
set (UMFPACK_EXTRA_LIBS)
|
|
|
|
# test if umfpack is usable with only amd and not cholmod
|
|
|
|
try_compile_umfpack (HAVE_UMFPACK_WITHOUT_CHOLMOD ${AMD_LIBRARIES})
|
|
|
|
if (HAVE_UMFPACK_WITHOUT_CHOLMOD)
|
|
|
|
list (APPEND UMFPACK_EXTRA_LIBS ${AMD_LIBRARIES})
|
|
|
|
else (HAVE_UMFPACK_WITHOUT_CHOLMOD)
|
|
|
|
if (CHOLMOD_LIBRARIES)
|
|
|
|
try_compile_umfpack (HAVE_UMFPACK_WITH_CHOLMOD ${CHOLMOD_LIBRARIES})
|
|
|
|
if (HAVE_UMFPACK_WITH_CHOLMOD)
|
|
|
|
list (APPEND UMFPACK_EXTRA_LIBS ${CHOLMOD_LIBRARIES})
|
|
|
|
else (HAVE_UMFPACK_WITH_CHOLMOD)
|
|
|
|
set (UMFPACK_EXTRA_LIBS "-NOTFOUND")
|
|
|
|
endif (HAVE_UMFPACK_WITH_CHOLMOD)
|
|
|
|
else (CHOLMOD_LIBRARIES)
|
|
|
|
# if we don't have cholmod, then we certainly cannot have umfpack with cholmod
|
|
|
|
set (UMFPACK_EXTRA_LIBS "-NOTFOUND")
|
|
|
|
endif (CHOLMOD_LIBRARIES)
|
|
|
|
endif (HAVE_UMFPACK_WITHOUT_CHOLMOD)
|
|
|
|
# test if umfpack is underlinked (CentOS 5.9), i.e. doesn't specify
|
|
|
|
# that it depends on amd. in that case, force amd to be linked
|
|
|
|
if (UMFPACK_EXTRA_LIBS AND (CMAKE_CXX_PLATFORM_ID STREQUAL "Linux") AND CMAKE_COMPILER_IS_GNUCC)
|
|
|
|
try_compile_umfpack (HAVE_UMFPACK_NOT_UNDERLINKED "-Wl,--as-needed" ${UMFPACK_EXTRA_LIBS})
|
|
|
|
if (NOT HAVE_UMFPACK_NOT_UNDERLINKED)
|
|
|
|
list (APPEND UMFPACK_LINKER_FLAGS "-Wl,--no-as-needed")
|
|
|
|
endif (NOT HAVE_UMFPACK_NOT_UNDERLINKED)
|
|
|
|
endif (UMFPACK_EXTRA_LIBS AND (CMAKE_CXX_PLATFORM_ID STREQUAL "Linux") AND CMAKE_COMPILER_IS_GNUCC)
|
|
|
|
list (APPEND UMFPACK_LIBRARIES ${UMFPACK_EXTRA_LIBS})
|
|
|
|
list (REVERSE UMFPACK_LIBRARIES)
|
|
|
|
list (REMOVE_DUPLICATES UMFPACK_LIBRARIES)
|
|
|
|
list (REVERSE UMFPACK_LIBRARIES)
|
|
|
|
endif (UMFPACK_LIBRARY)
|
|
|
|
|
|
|
|
# don't reset these sets; if two packages request SuiteSparse with
|
|
|
|
# different modules, we want the sets to be merged
|
|
|
|
#set (SuiteSparse_LIBRARIES "")
|
|
|
|
#set (SuiteSparse_INCLUDE_DIRS "")
|
|
|
|
|
|
|
|
# determine which modules were found based on whether all dependencies
|
|
|
|
# were satisfied; create a list of ALL modules (specified) that was found
|
|
|
|
# (to be included in one swoop in CMakeLists.txt)
|
|
|
|
set (SuiteSparse_FOUND TRUE)
|
|
|
|
foreach (module IN LISTS SuiteSparse_FIND_COMPONENTS)
|
|
|
|
string (TOUPPER ${module} MODULE)
|
|
|
|
set (SuiteSparse_${MODULE}_FOUND TRUE)
|
|
|
|
foreach (file IN LISTS ${MODULE}_INCLUDE_DIRS ${MODULE}_LIBRARIES)
|
|
|
|
if (NOT EXISTS ${file})
|
|
|
|
set (SuiteSparse_${MODULE}_FOUND FALSE)
|
|
|
|
endif (NOT EXISTS ${file})
|
|
|
|
endforeach (file)
|
|
|
|
if (NOT SuiteSparse_${MODULE}_FOUND)
|
|
|
|
set (SuiteSparse_FOUND FALSE)
|
|
|
|
# use empty string instead of zero, so it can be tested with #ifdef
|
|
|
|
# as well as #if in the source code
|
|
|
|
set (HAVE_SUITESPARSE_${MODULE}_H "" CACHE INT "Is ${module} header present?")
|
|
|
|
else (NOT SuiteSparse_${MODULE}_FOUND)
|
|
|
|
set (HAVE_SUITESPARSE_${MODULE}_H 1 CACHE INT "Is ${module} header present?")
|
|
|
|
list (APPEND SuiteSparse_LIBRARIES "${${MODULE}_LIBRARIES}")
|
|
|
|
list (APPEND SuiteSparse_LINKER_FLAGS "${${MODULE}_LINKER_FLAGS}")
|
|
|
|
list (APPEND SuiteSparse_INCLUDE_DIRS "${${MODULE}_INCLUDE_DIRS}")
|
|
|
|
endif (NOT SuiteSparse_${MODULE}_FOUND)
|
|
|
|
mark_as_advanced (HAVE_SUITESPARSE_${MODULE}_H)
|
|
|
|
mark_as_advanced (${MODULE}_INCLUDE_DIR)
|
|
|
|
mark_as_advanced (${MODULE}_LIBRARY)
|
|
|
|
endforeach (module)
|
|
|
|
|
|
|
|
if (SuiteSparse_INCLUDE_DIRS)
|
|
|
|
list (REMOVE_DUPLICATES SuiteSparse_INCLUDE_DIRS)
|
|
|
|
endif (SuiteSparse_INCLUDE_DIRS)
|
|
|
|
if (SuiteSparse_LIBRARIES)
|
|
|
|
list (REVERSE SuiteSparse_LIBRARIES)
|
|
|
|
list (REMOVE_DUPLICATES SuiteSparse_LIBRARIES)
|
|
|
|
list (REVERSE SuiteSparse_LIBRARIES)
|
|
|
|
endif (SuiteSparse_LIBRARIES)
|
|
|
|
|
|
|
|
# print a message to indicate status of this package
|
|
|
|
include (FindPackageHandleStandardArgs)
|
|
|
|
find_package_handle_standard_args (SuiteSparse
|
|
|
|
DEFAULT_MSG
|
|
|
|
SuiteSparse_LIBRARIES
|
|
|
|
SuiteSparse_INCLUDE_DIRS
|
|
|
|
)
|
|
|
|
|
|
|
|
# add these after checking to not pollute the message output (checking for
|
|
|
|
# BLAS and LAPACK is REQUIRED so if they are not found, we'll have failed
|
|
|
|
# already; suitesparseconfig is "optional" anyway)
|
|
|
|
list (APPEND SuiteSparse_LIBRARIES ${SuiteSparse_EXTRA_LIBS})
|