Making all config options in CMake & SuiteSparse cleanup. - Also marking all library and include directories found via find_library/path advanced (not directly visible in CMake GUI unless toggled to show advanced options). - Updating documentation to reflect SuiteSparse requirements on Ubuntu and ability to control build options in CMake GUI. - Splitting out all SuiteSparse related find_XX directives into a FindSuiteSparse script. Change-Id: I0d69e02392ec547a7c365ba3e06f2ebc61cacf16
diff --git a/CMakeLists.txt b/CMakeLists.txt index ff1726e..a77f8c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -63,6 +63,9 @@ ENDIF (NOT EXISTS ${LOCAL_GIT_DIRECTORY}/hooks/commit-msg) ENDIF (EXISTS ${LOCAL_GIT_DIRECTORY}) +# Make CMake aware of the cmake folder for local FindXXX scripts. +SET (CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") + SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) @@ -83,8 +86,10 @@ ENABLE_TESTING() -OPTION(MINIGLOG "Use a stripped down version of glog" OFF) +OPTION(MINIGLOG "Use a stripped down version of glog." OFF) OPTION(GFLAGS "Enable Google Flags." ON) +OPTION(SUITESPARSE "Enable SuiteSparse." ON) +OPTION(CXSPARSE "Enable CXSparse." ON) # Template specializations for the Schur complement based solvers. If # compile time, binary size or compiler performance is an issue, you # may consider disabling this. @@ -107,49 +112,41 @@ OPTION(BUILD_DOCUMENTATION "Build User's Guide (html)" OFF) OPTION(BUILD_EXAMPLES "Build examples" ON) OPTION(BUILD_SHARED_LIBS "Build Ceres as a shared library." OFF) -IF (BUILD_SHARED_LIBS) - MESSAGE("-- Building as a shared library.") -ELSE (BUILD_SHARED_LIBS) - MESSAGE("-- Building as a static library.") -ENDIF (BUILD_SHARED_LIBS) # Default locations to search for on various platforms. # Libraries LIST(APPEND CMAKE_LIBRARY_PATH /opt/local/lib) -LIST(APPEND CMAKE_LIBRARY_PATH /opt/local/lib/ufsparse) # Mac OS X LIST(APPEND CMAKE_LIBRARY_PATH /usr/lib) LIST(APPEND CMAKE_LIBRARY_PATH /usr/lib/atlas) -LIST(APPEND CMAKE_LIBRARY_PATH /usr/lib/suitesparse) # Ubuntu LIST(APPEND CMAKE_LIBRARY_PATH /usr/lib64/atlas) LIST(APPEND CMAKE_LIBRARY_PATH /usr/local/homebrew/lib) # Mac OS X LIST(APPEND CMAKE_LIBRARY_PATH /usr/local/lib) -LIST(APPEND CMAKE_LIBRARY_PATH /usr/local/lib/suitesparse) # Headers LIST(APPEND CMAKE_INCLUDE_PATH /opt/local/include) -LIST(APPEND CMAKE_INCLUDE_PATH /opt/local/include/ufsparse) # Mac OS X -LIST(APPEND CMAKE_INCLUDE_PATH /opt/local/var/macports/software/eigen3/opt/local/include/eigen3) # Mac OS X +LIST(APPEND CMAKE_INCLUDE_PATH /opt/local/var/macports/software/eigen3) # Mac OS X +LIST(APPEND CMAKE_INCLUDE_PATH /opt/local/include/eigen3) # Mac OS X LIST(APPEND CMAKE_INCLUDE_PATH /usr/include) LIST(APPEND CMAKE_INCLUDE_PATH /usr/include/eigen3) # Ubuntu 10.04's default location. -LIST(APPEND CMAKE_INCLUDE_PATH /usr/include/suitesparse) # Ubuntu LIST(APPEND CMAKE_INCLUDE_PATH /usr/local/homebrew/include) # Mac OS X LIST(APPEND CMAKE_INCLUDE_PATH /usr/local/homebrew/include/eigen3) # Mac OS X LIST(APPEND CMAKE_INCLUDE_PATH /usr/local/include) LIST(APPEND CMAKE_INCLUDE_PATH /usr/local/include/eigen3) -LIST(APPEND CMAKE_INCLUDE_PATH /usr/local/include/suitesparse) -# Eigen +# Eigen. FIND_PATH(EIGEN_INCLUDE NAMES Eigen/Core) IF (NOT EXISTS ${EIGEN_INCLUDE}) MESSAGE(FATAL_ERROR "Can't find Eigen. Try passing -DEIGEN_INCLUDE=...") ELSE (NOT EXISTS ${EIGEN_INCLUDE}) MESSAGE("-- Found Eigen 3.x: ${EIGEN_INCLUDE}") ENDIF (NOT EXISTS ${EIGEN_INCLUDE}) +MARK_AS_ADVANCED(EIGEN_INCLUDE) +# BLAS & LAPACK. SET(BLAS_AND_LAPACK_FOUND TRUE) IF ((NOT DEFINED LAPACK) OR (DEFINED LAPACK AND LAPACK)) - FIND_PACKAGE(LAPACK) + FIND_PACKAGE(LAPACK QUIET) IF (LAPACK_FOUND) MESSAGE("-- Found LAPACK library: ${LAPACK_LIBRARIES}") ELSE (LAPACK_FOUND) @@ -157,14 +154,13 @@ SET(BLAS_AND_LAPACK_FOUND FALSE) ENDIF (LAPACK_FOUND) - FIND_PACKAGE(BLAS) + FIND_PACKAGE(BLAS QUIET) IF (BLAS_FOUND) MESSAGE("-- Found BLAS library: ${BLAS_LIBRARIES}") ELSE (BLAS_FOUND) MESSAGE("-- Did not find BLAS library") SET(BLAS_AND_BLAS_FOUND FALSE) ENDIF (BLAS_FOUND) - ELSE ((NOT DEFINED LAPACK) OR (DEFINED LAPACK AND LAPACK)) SET(BLAS_AND_LAPACK_FOUND FALSE) ENDIF ((NOT DEFINED LAPACK) OR (DEFINED LAPACK AND LAPACK)) @@ -173,273 +169,85 @@ ADD_DEFINITIONS(-DCERES_NO_LAPACK) ENDIF (NOT BLAS_AND_LAPACK_FOUND) -IF ((NOT DEFINED SUITESPARSE) OR (DEFINED SUITESPARSE AND SUITESPARSE)) -# Check for SuiteSparse dependencies +# SuiteSparse. +IF (SUITESPARSE) + # By default, if SuiteSparse and all dependencies are found, Ceres is + # built with SuiteSparse support. -SET(AMD_FOUND TRUE) -FIND_LIBRARY(AMD_LIB NAMES amd) -IF (EXISTS ${AMD_LIB}) - MESSAGE("-- Found AMD library: ${AMD_LIB}") -ELSE (EXISTS ${AMD_LIB}) - MESSAGE("-- Did not find AMD library") - SET(AMD_FOUND FALSE) -ENDIF (EXISTS ${AMD_LIB}) - -FIND_PATH(AMD_INCLUDE NAMES amd.h) -IF (EXISTS ${AMD_INCLUDE}) - MESSAGE("-- Found AMD header in: ${AMD_INCLUDE}") -ELSE (EXISTS ${AMD_INCLUDE}) - MESSAGE("-- Did not find AMD header") - SET(AMD_FOUND FALSE) -ENDIF (EXISTS ${AMD_INCLUDE}) - -SET(CAMD_FOUND TRUE) -FIND_LIBRARY(CAMD_LIB NAMES camd) -IF (EXISTS ${CAMD_LIB}) - MESSAGE("-- Found CAMD library: ${CAMD_LIB}") -ELSE (EXISTS ${CAMD_LIB}) - MESSAGE("-- Did not find CAMD library") - SET(CAMD_FOUND FALSE) -ENDIF (EXISTS ${CAMD_LIB}) - -FIND_PATH(CAMD_INCLUDE NAMES camd.h) -IF (EXISTS ${CAMD_INCLUDE}) - MESSAGE("-- Found CAMD header in: ${CAMD_INCLUDE}") -ELSE (EXISTS ${CAMD_INCLUDE}) - MESSAGE("-- Did not find CAMD header") - SET(CAMD_FOUND FALSE) -ENDIF (EXISTS ${CAMD_INCLUDE}) - -SET(COLAMD_FOUND TRUE) -FIND_LIBRARY(COLAMD_LIB NAMES colamd) -IF (EXISTS ${COLAMD_LIB}) - MESSAGE("-- Found COLAMD library: ${COLAMD_LIB}") -ELSE (EXISTS ${COLAMD_LIB}) - MESSAGE("-- Did not find COLAMD library") - SET(COLAMD_FOUND FALSE) -ENDIF (EXISTS ${COLAMD_LIB}) - -FIND_PATH(COLAMD_INCLUDE NAMES colamd.h) -IF (EXISTS ${COLAMD_INCLUDE}) - MESSAGE("-- Found COLAMD header in: ${COLAMD_INCLUDE}") -ELSE (EXISTS ${COLAMD_INCLUDE}) - MESSAGE("-- Did not find COLAMD header") - SET(COLAMD_FOUND FALSE) -ENDIF (EXISTS ${COLAMD_INCLUDE}) - -SET(CCOLAMD_FOUND TRUE) -FIND_LIBRARY(CCOLAMD_LIB NAMES ccolamd) -IF (EXISTS ${CCOLAMD_LIB}) - MESSAGE("-- Found CCOLAMD library: ${CCOLAMD_LIB}") -ELSE (EXISTS ${CCOLAMD_LIB}) - MESSAGE("-- Did not find CCOLAMD library") - SET(CCOLAMD_FOUND FALSE) -ENDIF (EXISTS ${CCOLAMD_LIB}) - -FIND_PATH(CCOLAMD_INCLUDE NAMES ccolamd.h) -IF (EXISTS ${CCOLAMD_INCLUDE}) - MESSAGE("-- Found CCOLAMD header in: ${CCOLAMD_INCLUDE}") -ELSE (EXISTS ${CCOLAMD_INCLUDE}) - MESSAGE("-- Did not find CCOLAMD header") - SET(CCOLAMD_FOUND FALSE) -ENDIF (EXISTS ${CCOLAMD_INCLUDE}) - -SET(CHOLMOD_FOUND TRUE) -FIND_LIBRARY(CHOLMOD_LIB NAMES cholmod) -IF (EXISTS ${CHOLMOD_LIB}) - MESSAGE("-- Found CHOLMOD library: ${CHOLMOD_LIB}") -ELSE (EXISTS ${CHOLMOD_LIB}) - MESSAGE("-- Did not find CHOLMOD library") - SET(CHOLMOD_FOUND FALSE) -ENDIF (EXISTS ${CHOLMOD_LIB}) - -FIND_PATH(CHOLMOD_INCLUDE NAMES cholmod.h) -IF (EXISTS ${CHOLMOD_INCLUDE}) - MESSAGE("-- Found CHOLMOD header in: ${CHOLMOD_INCLUDE}") -ELSE (EXISTS ${CHOLMOD_INCLUDE}) - MESSAGE("-- Did not find CHOLMOD header") - SET(CHOLMOD_FOUND FALSE) -ENDIF (EXISTS ${CHOLMOD_INCLUDE}) - -SET(SUITESPARSEQR_FOUND TRUE) -FIND_LIBRARY(SUITESPARSEQR_LIB NAMES spqr) -IF (EXISTS ${SUITESPARSEQR_LIB}) - MESSAGE("-- Found SUITESPARSEQR library: ${SUITESPARSEQR_LIB}") -ELSE (EXISTS ${SUITESPARSEQR_LIB}) - MESSAGE("-- Did not find SUITESPARSEQR library") - SET(SUITESPARSEQR_FOUND FALSE) -ENDIF (EXISTS ${SUITESPARSEQR_LIB}) - -FIND_PATH(SUITESPARSEQR_INCLUDE NAMES SuiteSparseQR.hpp) -IF (EXISTS ${SUITESPARSEQR_INCLUDE}) - MESSAGE("-- Found SUITESPARSEQR header in: ${SUITESPARSEQR_INCLUDE}") -ELSE (EXISTS ${SUITESPARSEQR_INCLUDE}) - MESSAGE("-- Did not find SUITESPARSEQR header") - SET(SUITESPARSEQR_FOUND FALSE) -ENDIF (EXISTS ${SUITESPARSEQR_INCLUDE}) - -# If SuiteSparse version is >= 4 then SuiteSparse_config is required. -# For SuiteSparse 3, UFconfig.h is required. -SET(SUITESPARSE_CONFIG_FOUND TRUE) -SET(UFCONFIG_FOUND TRUE) - -FIND_LIBRARY(SUITESPARSE_CONFIG_LIB NAMES suitesparseconfig) -IF (EXISTS ${SUITESPARSE_CONFIG_LIB}) - MESSAGE("-- Found SuiteSparse_config library: ${SUITESPARSE_CONFIG_LIB}") -ELSE (EXISTS ${SUITESPARSE_CONFIG_LIB}) - MESSAGE("-- Did not find SuiteSparse_config library") -ENDIF (EXISTS ${SUITESPARSE_CONFIG_LIB}) - -FIND_PATH(SUITESPARSE_CONFIG_INCLUDE NAMES SuiteSparse_config.h) -IF (EXISTS ${SUITESPARSE_CONFIG_INCLUDE}) - MESSAGE("-- Found SuiteSparse_config header in: ${SUITESPARSE_CONFIG_INCLUDE}") - SET(UFCONFIG_FOUND FALSE) -ELSE (EXISTS ${SUITESPARSE_CONFIG_INCLUDE}) - MESSAGE("-- Did not find SuiteSparse_config header") -ENDIF (EXISTS ${SUITESPARSE_CONFIG_INCLUDE}) - -IF (EXISTS ${SUITESPARSE_CONFIG_LIB} AND - EXISTS ${SUITESPARSE_CONFIG_INCLUDE}) - # SuiteSparse_config (SuiteSparse version >= 4) requires librt library for - # timing by default when compiled on Linux or Unix, but not on OSX (which - # does not have librt). - IF (CMAKE_SYSTEM_NAME MATCHES "Linux" OR UNIX AND NOT APPLE) - FIND_LIBRARY(LIBRT_LIB NAMES rt) - IF (LIBRT_LIB) - MESSAGE("-- Adding librt: ${LIBRT_LIB} to SuiteSparse_config libraries.") - ELSE (LIBRT_LIB) - MESSAGE("-- Could not find librt, but found SuiteSparse_config, " - "assuming that SuiteSparse was compiled without timing.") - ENDIF (LIBRT_LIB) - LIST(APPEND SUITESPARSE_CONFIG_LIB ${LIBRT_LIB}) - ENDIF (CMAKE_SYSTEM_NAME MATCHES "Linux" OR UNIX AND NOT APPLE) -ELSE (EXISTS ${SUITESPARSE_CONFIG_LIB} AND - EXISTS ${SUITESPARSE_CONFIG_INCLUDE}) - SET(SUITESPARSE_CONFIG_FOUND FALSE) - FIND_PATH(UFCONFIG_INCLUDE NAMES UFconfig.h) - IF (EXISTS ${UFCONFIG_INCLUDE}) - MESSAGE("-- Found UFconfig header in: ${UFCONFIG_INCLUDE}") - ELSE (EXISTS ${UFCONFIG_INCLUDE}) - MESSAGE("-- Did not find UFconfig header") - SET(UFCONFIG_FOUND FALSE) - ENDIF (EXISTS ${UFCONFIG_INCLUDE}) -ENDIF (EXISTS ${SUITESPARSE_CONFIG_LIB} AND - EXISTS ${SUITESPARSE_CONFIG_INCLUDE}) - -FIND_LIBRARY(METIS_LIB NAMES metis) -IF (EXISTS ${METIS_LIB}) - MESSAGE("-- Found METIS library: ${METIS_LIB}") -ELSE (EXISTS ${METIS_LIB}) - MESSAGE("-- Did not find METIS library") -ENDIF (EXISTS ${METIS_LIB}) - -# SuiteSparseQR may be compiled with Intel Threading Building Blocks. -SET(TBB_FOUND TRUE) -FIND_LIBRARY(TBB_LIB NAMES tbb) -IF (EXISTS ${TBB_LIB}) - MESSAGE("-- Found TBB library: ${TBB_LIB}") -ELSE (EXISTS ${TBB_LIB}) - MESSAGE("-- Did not find TBB library") - SET(TBB_FOUND FALSE) -ENDIF (EXISTS ${TBB_LIB}) - -IF (TBB_FOUND) - FIND_LIBRARY(TBB_MALLOC_LIB NAMES tbbmalloc) - IF (EXISTS ${TBB_MALLOC_LIB}) - MESSAGE("-- Found TBB Malloc library: ${TBB_MALLOC_LIB}") - ELSE (EXISTS ${TBB_MALLOC_LIB}) - MESSAGE("-- Did not find TBB Malloc library") - SET(TBB_FOUND FALSE) - ENDIF (EXISTS ${TBB_MALLOC_LIB}) -ENDIF (TBB_FOUND) - -# We don't use SET(SUITESPARSE_FOUND ${AMD_FOUND} ...) in order to be -# able to check whether SuiteSparse is available without expanding -# SUITESPARSE_FOUND with ${}. This means further checks could be: -# -# IF (SUITESPARSE_FOUND) -# -# and not: -# -# IF (${SUITESPARSE_FOUND}) -# -IF (${AMD_FOUND} AND - ${CAMD_FOUND} AND - ${COLAMD_FOUND} AND - ${CCOLAMD_FOUND} AND - ${CHOLMOD_FOUND} AND - (${SUITESPARSE_CONFIG_FOUND} OR ${UFCONFIG_FOUND}) AND - ${BLAS_AND_LAPACK_FOUND}) - SET(SUITESPARSE_FOUND TRUE) -ELSE () - SET(SUITESPARSE_FOUND FALSE) -ENDIF () - -ENDIF ((NOT DEFINED SUITESPARSE) OR (DEFINED SUITESPARSE AND SUITESPARSE)) -# By default, if all of SuiteSparse's dependencies are found, Ceres is -# built with SuiteSparse support. -DSUITESPARSE=ON/OFF can be used to -# enable/disable SuiteSparse explicitly. -IF (DEFINED SUITESPARSE) - IF (SUITESPARSE) - IF (NOT SUITESPARSE_FOUND) - MESSAGE(FATAL_ERROR "One or more of SuiteSparse's dependencies was not found") - ENDIF (NOT SUITESPARSE_FOUND) - ELSE (SUITESPARSE) - ADD_DEFINITIONS(-DCERES_NO_SUITESPARSE) - ENDIF (SUITESPARSE) -ELSE (DEFINED SUITESPARSE) + # Check for SuiteSparse and dependencies. + FIND_PACKAGE(SuiteSparse QUIET) IF (SUITESPARSE_FOUND) - MESSAGE("-- Found all SuiteSparse dependencies. Building with SuiteSparse") - SET(SUITESPARSE ON) + # On Ubuntu the system install of SuiteSparse (v3.4.0) up to at least + # Ubuntu 13.10 cannot be used to link shared libraries. + IF (BUILD_SHARED_LIBS AND + SUITESPARSE_IS_BROKEN_SHARED_LINKING_UBUNTU_SYSTEM_VERSION) + MESSAGE(FATAL_ERROR "You are attempting to build Ceres as a shared " + "library on Ubuntu using a system package install of SuiteSparse " + "3.4.0. This package is broken and does not support the " + "construction of shared libraries (you can still build Ceres as " + "a static library), see: http://homes.cs.washington.edu/~sagarwal" + "/ceres-solver/dev/building.html for more information.") + ENDIF (BUILD_SHARED_LIBS AND + SUITESPARSE_IS_BROKEN_SHARED_LINKING_UBUNTU_SYSTEM_VERSION) + + # By default, if all of SuiteSparse's dependencies are found, Ceres is + # built with SuiteSparse support. + MESSAGE("-- Found all SuiteSparse dependencies. Building with SuiteSparse.") ELSE (SUITESPARSE_FOUND) - MESSAGE("-- Did not find all SuiteSparse dependencies. Building without SuiteSparse") - SET(SUITESPARSE OFF) + # Disable use of SuiteSparse if it cannot be found and continue. + MESSAGE("-- Did not find all SuiteSparse dependencies, disabling " + "SuiteSparse support.") + # Retain the help string associated with the SUITESPARSE option + # when updating it to disable use of SuiteSparse. + GET_PROPERTY(HELP_STRING CACHE SUITESPARSE PROPERTY HELPSTRING) + SET(SUITESPARSE OFF CACHE BOOL "${HELP_STRING}" FORCE) ADD_DEFINITIONS(-DCERES_NO_SUITESPARSE) ENDIF (SUITESPARSE_FOUND) -ENDIF (DEFINED SUITESPARSE) +ELSE (SUITESPARSE) + MESSAGE("-- Building without SuiteSparse.") + ADD_DEFINITIONS(-DCERES_NO_SUITESPARSE) +ENDIF (SUITESPARSE) -# By default, if all of CXSparse's dependencies are found, Ceres is -# built with CXSparse support. -DCXSPARSE=ON/OFF can be used to -# enable/disable CXSparse explicitly. -IF ((NOT DEFINED CXSPARSE) OR (DEFINED CXSPARSE AND CXSPARSE)) +# CXSparse. +IF (CXSPARSE) + SET(CXSPARSE_FOUND ON) + FIND_LIBRARY(CXSPARSE_LIB NAMES cxsparse) + IF (EXISTS ${CXSPARSE_LIB}) + MESSAGE("-- Found CXSparse library in: ${CXSPARSE_LIB}") + ELSE (EXISTS ${CXSPARSE_LIB}) + MESSAGE("-- Did not find CXSparse header") + SET(CXSPARSE_FOUND FALSE) + ENDIF (EXISTS ${CXSPARSE_LIB}) + MARK_AS_ADVANCED(CXSPARSE_LIB) -SET(CXSPARSE_FOUND ON) -FIND_LIBRARY(CXSPARSE_LIB NAMES cxsparse) -IF (EXISTS ${CXSPARSE_LIB}) - MESSAGE("-- Found CXSparse library in: ${CXSPARSE_LIB}") -ELSE (EXISTS ${CXSPARSE_LIB}) - MESSAGE("-- Did not find CXSparse header") - SET(CXSPARSE_FOUND FALSE) -ENDIF (EXISTS ${CXSPARSE_LIB}) + FIND_PATH(CXSPARSE_INCLUDE NAMES cs.h) + IF (EXISTS ${CXSPARSE_INCLUDE}) + MESSAGE("-- Found CXSparse header in: ${CXSPARSE_INCLUDE}") + ELSE (EXISTS ${CXSPARSE_INCLUDE}) + MESSAGE("-- Did not find CXSparse header") + SET(CXSPARSE_FOUND FALSE) + ENDIF (EXISTS ${CXSPARSE_INCLUDE}) + MARK_AS_ADVANCED(CXSPARSE_INCLUDE) -FIND_PATH(CXSPARSE_INCLUDE NAMES cs.h) -IF (EXISTS ${CXSPARSE_INCLUDE}) - MESSAGE("-- Found CXSparse header in: ${CXSPARSE_INCLUDE}") -ELSE (EXISTS ${CXSPARSE_INCLUDE}) - MESSAGE("-- Did not find CXSparse header") - SET(CXSPARSE_FOUND FALSE) -ENDIF (EXISTS ${CXSPARSE_INCLUDE}) -ENDIF ((NOT DEFINED CXSPARSE) OR (DEFINED CXSPARSE AND CXSPARSE)) - -IF (DEFINED CXSPARSE) - IF (CXSPARSE) - IF (NOT CXSPARSE_FOUND) - MESSAGE(FATAL_ERROR "-- CXSparse not found.") - ENDIF (NOT CXSPARSE_FOUND) - ELSE (CXSPARSE) - ADD_DEFINITIONS(-DCERES_NO_CXSPARSE) - ENDIF (CXSPARSE) -ELSE (DEFINED CXSPARSE) IF (CXSPARSE_FOUND) - MESSAGE("-- Building with CXSparse support.") - SET(CXSPARSE ON) + # By default, if CXSparse and all dependencies are found, Ceres is + # built with CXSparse support. + MESSAGE("-- Building with CXSparse.") ELSE (CXSPARSE_FOUND) - MESSAGE("-- Building without CXSparse.") - SET(CXSPARSE OFF) + # Disable use of CXSparse if it cannot be found and continue. + MESSAGE("-- Did not find CXSparse, Building without CXSparse.") + # Retain the help string associated with the CXSPARSE option + # when updating it to disable use of CXSparse. + GET_PROPERTY(HELP_STRING CACHE CXSPARSE PROPERTY HELPSTRING) + SET(CXSPARSE OFF CACHE BOOL "${HELP_STRING}" FORCE) ADD_DEFINITIONS(-DCERES_NO_CXSPARSE) ENDIF (CXSPARSE_FOUND) -ENDIF (DEFINED CXSPARSE) +ELSE (CXSPARSE) + MESSAGE("-- Building without CXSparse.") + ADD_DEFINITIONS(-DCERES_NO_CXSPARSE) +ENDIF (CXSPARSE) +# GFlags. IF (GFLAGS) FIND_LIBRARY(GFLAGS_LIB NAMES gflags) IF (NOT EXISTS ${GFLAGS_LIB}) @@ -447,6 +255,7 @@ "Can't find Google Flags. Please specify: " "-DGFLAGS_LIB=...") ENDIF (NOT EXISTS ${GFLAGS_LIB}) + MARK_AS_ADVANCED(GFLAGS_LIB) MESSAGE("-- Found Google Flags library: ${GFLAGS_LIB}") FIND_PATH(GFLAGS_INCLUDE NAMES gflags/gflags.h) IF (NOT EXISTS ${GFLAGS_INCLUDE}) @@ -454,12 +263,14 @@ "Can't find Google Flags. Please specify: " "-DGFLAGS_INCLUDE=...") ENDIF (NOT EXISTS ${GFLAGS_INCLUDE}) + MARK_AS_ADVANCED(GFLAGS_INCLUDE) MESSAGE("-- Found Google Flags header in: ${GFLAGS_INCLUDE}") ELSE (GFLAGS) MESSAGE("-- Google Flags disabled; no tests or tools will be built!") ADD_DEFINITIONS(-DCERES_NO_GFLAGS) ENDIF (GFLAGS) +# MiniGLog. IF (MINIGLOG) SET(GLOG_LIB miniglog) MESSAGE("-- Using minimal Glog substitute (library): ${GLOG_LIB}") @@ -473,6 +284,7 @@ MESSAGE(FATAL_ERROR "Can't find Google Log. Please specify: -DGLOG_LIB=...") ENDIF (EXISTS ${GLOG_LIB}) + MARK_AS_ADVANCED(GLOG_LIB) FIND_PATH(GLOG_INCLUDE NAMES glog/logging.h) IF (EXISTS ${GLOG_INCLUDE}) @@ -481,6 +293,7 @@ MESSAGE(FATAL_ERROR "Can't find Google Log. Please specify: -DGLOG_INCLUDE=...") ENDIF (EXISTS ${GLOG_INCLUDE}) + MARK_AS_ADVANCED(GLOG_INCLUDE) ENDIF (MINIGLOG) IF (NOT SCHUR_SPECIALIZATIONS) @@ -502,7 +315,7 @@ SET(OPENMP_FOUND FALSE) ELSE (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") IF (OPENMP) - FIND_PACKAGE(OpenMP) + FIND_PACKAGE(OpenMP REQUIRED) ENDIF (OPENMP) ENDIF (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") @@ -573,18 +386,7 @@ INSTALL(FILES ${CERES_PUBLIC_INTERNAL_HDRS} DESTINATION include/ceres/internal) IF (SUITESPARSE) - INCLUDE_DIRECTORIES(${AMD_INCLUDE}) - INCLUDE_DIRECTORIES(${CAMD_INCLUDE}) - INCLUDE_DIRECTORIES(${COLAMD_INCLUDE}) - INCLUDE_DIRECTORIES(${CCOLAMD_INCLUDE}) - INCLUDE_DIRECTORIES(${CHOLMOD_INCLUDE}) - INCLUDE_DIRECTORIES(${SUITESPARSEQR_INCLUDE}) - IF (SUITESPARSE_CONFIG_FOUND) - INCLUDE_DIRECTORIES(${SUITESPARSE_CONFIG_INCLUDE}) - ENDIF (SUITESPARSE_CONFIG_FOUND) - IF (UFCONFIG_FOUND) - INCLUDE_DIRECTORIES(${UFCONFIG_INCLUDE}) - ENDIF (UFCONFIG_FOUND) + INCLUDE_DIRECTORIES(${SUITESPARSE_INCLUDE_DIRS}) ENDIF (SUITESPARSE) IF (CXSPARSE) @@ -595,6 +397,12 @@ INCLUDE_DIRECTORIES(${GFLAGS_INCLUDE}) ENDIF (GFLAGS) +IF (BUILD_SHARED_LIBS) + MESSAGE("-- Building Ceres as a shared library.") +ELSE (BUILD_SHARED_LIBS) + MESSAGE("-- Building Ceres as a static library.") +ENDIF (BUILD_SHARED_LIBS) + # Change the default build type from Debug to Release, while still # supporting overriding the build type. # @@ -712,9 +520,6 @@ IF (BUILD_DOCUMENTATION) MESSAGE("-- Documentation building is enabled") - # Make CMake aware of the cmake folder, in order to find 'FindSphinx.cmake' - SET (CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") - # Generate the User's Guide (html). # The corresponding target is UserGuide, but is included in ALL. ADD_SUBDIRECTORY(docs)
diff --git a/cmake/FindSuiteSparse.cmake b/cmake/FindSuiteSparse.cmake new file mode 100644 index 0000000..53dd038 --- /dev/null +++ b/cmake/FindSuiteSparse.cmake
@@ -0,0 +1,506 @@ +# Ceres Solver - A fast non-linear least squares minimizer +# Copyright 2013 Google Inc. All rights reserved. +# http://code.google.com/p/ceres-solver/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# Author: alexs.mac@gmail.com (Alex Stewart) +# + +# FindSuiteSparse.cmake - Find SuiteSparse libraries & dependencies. +# +# This module defines the following variables: +# +# SUITESPARSE_FOUND: TRUE iff SuiteSparse and all dependencies have been found. +# SUITESPARSE_INCLUDE_DIRS: Include directories for all SuiteSparse components. +# SUITESPARSE_LIBRARIES: Libraries for all SuiteSparse component libraries and +# dependencies. +# SUITESPARSE_VERSION: Extracted from UFconfig.h (<= v3) or +# SuiteSparse_config.h (>= v4). +# SUITESPARSE_MAIN_VERSION: Equal to 4 if SUITESPARSE_VERSION = 4.2.1 +# SUITESPARSE_SUB_VERSION: Equal to 2 if SUITESPARSE_VERSION = 4.2.1 +# SUITESPARSE_SUBSUB_VERSION: Equal to 1 if SUITESPARSE_VERSION = 4.2.1 +# +# SUITESPARSE_IS_BROKEN_SHARED_LINKING_UBUNTU_SYSTEM_VERSION: TRUE iff running +# on Ubuntu, SUITESPARSE_VERSION is 3.4.0 and found SuiteSparse is a system +# install, in which case found version of SuiteSparse cannot be used to link +# a shared library due to a bug (static linking is unaffected). +# +# The following variables define the presence / includes & libraries for the +# SuiteSparse components searched for, the SUITESPARSE_XX variables are the +# union of the variables for all components. +# +# == Symmetric Approximate Minimum Degree (AMD) +# AMD_FOUND +# AMD_INCLUDE_DIR +# AMD_LIBRARY +# +# == Constrained Approximate Minimum Degree (CAMD) +# CAMD_FOUND +# CAMD_INCLUDE_DIR +# CAMD_LIBRARY +# +# == Column Approximate Minimum Degree (COLAMD) +# COLAMD_FOUND +# COLAMD_INCLUDE_DIR +# COLAMD_LIBRARY +# +# Constrained Column Approximate Minimum Degree (CCOLAMD) +# CCOLAMD_FOUND +# CCOLAMD_INCLUDE_DIR +# CCOLAMD_LIBRARY +# +# == Sparse Supernodal Cholesky Factorization and Update/Downdate (CHOLMOD) +# CHOLMOD_FOUND +# CHOLMOD_INCLUDE_DIR +# CHOLMOD_LIBRARY +# +# == Multifrontal Sparse QR (SuiteSparseQR) +# SUITESPARSEQR_FOUND +# SUITESPARSEQR_INCLUDE_DIR +# SUITESPARSEQR_LIBRARY +# +# == Common configuration for all but CSparse (SuiteSparse version >= 4). +# SUITESPARSE_CONFIG_FOUND +# SUITESPARSE_CONFIG_INCLUDE_DIR +# SUITESPARSE_CONFIG_LIBRARY +# +# == Common configuration for all but CSparse (SuiteSparse version < 4). +# UFCONFIG_FOUND +# UFCONFIG_INCLUDE_DIR +# +# Optional SuiteSparse Dependencies: +# +# == Serial Graph Partitioning and Fill-reducing Matrix Ordering (METIS) +# METIS_FOUND +# METIS_LIBRARY +# +# == Intel Thread Building Blocks (TBB) +# TBB_FOUND +# TBB_LIBRARIES + +# Specify search directories for include files and libraries (this is the union +# of the search directories for all OSs). +LIST(APPEND SUITESPARSE_CHECK_INCLUDE_DIRS + /opt/local/include + /opt/local/include/ufsparse # Mac OS X + /usr/include + /usr/include/suitesparse # Ubuntu + /usr/local/homebrew/include # Mac OS X + /usr/local/include + /usr/local/include/suitesparse) +LIST(APPEND SUITESPARSE_CHECK_LIBRARY_DIRS + /opt/local/lib + /opt/local/lib/ufsparse # Mac OS X + /usr/lib + /usr/lib/suitesparse # Ubuntu + /usr/local/homebrew/lib # Mac OS X + /usr/local/lib + /usr/local/lib/suitesparse) + +# BLAS. +FIND_PACKAGE(BLAS QUIET) +IF (NOT BLAS_FOUND) + MESSAGE("-- Did not find BLAS library (required for SuiteSparse).") +ENDIF (NOT BLAS_FOUND) + +# LAPACK. +FIND_PACKAGE(LAPACK QUIET) +IF (NOT LAPACK_FOUND) + MESSAGE("-- Did not find LAPACK library (required for SuiteSparse).") +ENDIF (NOT LAPACK_FOUND) + +# AMD. +SET(AMD_FOUND TRUE) +FIND_LIBRARY(AMD_LIBRARY NAMES amd + PATHS ${SUITESPARSE_CHECK_LIBRARY_DIRS}) +IF (EXISTS ${AMD_LIBRARY}) + MESSAGE("-- Found AMD library: ${AMD_LIBRARY}") +ELSE (EXISTS ${AMD_LIBRARY}) + MESSAGE("-- Did not find AMD library") + SET(AMD_FOUND FALSE) +ENDIF (EXISTS ${AMD_LIBRARY}) +MARK_AS_ADVANCED(AMD_LIBRARY) + +FIND_PATH(AMD_INCLUDE_DIR NAMES amd.h + PATHS ${SUITESPARSE_CHECK_INCLUDE_DIRS}) +IF (EXISTS ${AMD_INCLUDE_DIR}) + MESSAGE("-- Found AMD header in: ${AMD_INCLUDE_DIR}") +ELSE (EXISTS ${AMD_INCLUDE_DIR}) + MESSAGE("-- Did not find AMD header") + SET(AMD_FOUND FALSE) +ENDIF (EXISTS ${AMD_INCLUDE_DIR}) +MARK_AS_ADVANCED(AMD_INCLUDE_DIR) + +# CAMD. +SET(CAMD_FOUND TRUE) +FIND_LIBRARY(CAMD_LIBRARY NAMES camd + PATHS ${SUITESPARSE_CHECK_LIBRARY_DIRS}) +IF (EXISTS ${CAMD_LIBRARY}) + MESSAGE("-- Found CAMD library: ${CAMD_LIBRARY}") +ELSE (EXISTS ${CAMD_LIBRARY}) + MESSAGE("-- Did not find CAMD library") + SET(CAMD_FOUND FALSE) +ENDIF (EXISTS ${CAMD_LIBRARY}) +MARK_AS_ADVANCED(CAMD_LIBRARY) + +FIND_PATH(CAMD_INCLUDE_DIR NAMES camd.h + PATHS ${SUITESPARSE_CHECK_INCLUDE_DIRS}) +IF (EXISTS ${CAMD_INCLUDE_DIR}) + MESSAGE("-- Found CAMD header in: ${CAMD_INCLUDE_DIR}") +ELSE (EXISTS ${CAMD_INCLUDE_DIR}) + MESSAGE("-- Did not find CAMD header") + SET(CAMD_FOUND FALSE) +ENDIF (EXISTS ${CAMD_INCLUDE_DIR}) +MARK_AS_ADVANCED(CAMD_INCLUDE_DIR) + +# COLAMD. +SET(COLAMD_FOUND TRUE) +FIND_LIBRARY(COLAMD_LIBRARY NAMES colamd + PATHS ${SUITESPARSE_CHECK_LIBRARY_DIRS}) +IF (EXISTS ${COLAMD_LIBRARY}) + MESSAGE("-- Found COLAMD library: ${COLAMD_LIBRARY}") +ELSE (EXISTS ${COLAMD_LIBRARY}) + MESSAGE("-- Did not find COLAMD library") + SET(COLAMD_FOUND FALSE) +ENDIF (EXISTS ${COLAMD_LIBRARY}) +MARK_AS_ADVANCED(COLAMD_LIBRARY) + +FIND_PATH(COLAMD_INCLUDE_DIR NAMES colamd.h + PATHS ${SUITESPARSE_CHECK_INCLUDE_DIRS}) +IF (EXISTS ${COLAMD_INCLUDE_DIR}) + MESSAGE("-- Found COLAMD header in: ${COLAMD_INCLUDE_DIR}") +ELSE (EXISTS ${COLAMD_INCLUDE_DIR}) + MESSAGE("-- Did not find COLAMD header") + SET(COLAMD_FOUND FALSE) +ENDIF (EXISTS ${COLAMD_INCLUDE_DIR}) +MARK_AS_ADVANCED(COLAMD_INCLUDE_DIR) + +# CCOLAMD. +SET(CCOLAMD_FOUND TRUE) +FIND_LIBRARY(CCOLAMD_LIBRARY NAMES ccolamd + PATHS ${SUITESPARSE_CHECK_LIBRARY_DIRS}) +IF (EXISTS ${CCOLAMD_LIBRARY}) + MESSAGE("-- Found CCOLAMD library: ${CCOLAMD_LIBRARY}") +ELSE (EXISTS ${CCOLAMD_LIBRARY}) + MESSAGE("-- Did not find CCOLAMD library") + SET(CCOLAMD_FOUND FALSE) +ENDIF (EXISTS ${CCOLAMD_LIBRARY}) +MARK_AS_ADVANCED(CCOLAMD_LIBRARY) + +FIND_PATH(CCOLAMD_INCLUDE_DIR NAMES ccolamd.h + PATHS ${SUITESPARSE_CHECK_INCLUDE_DIRS}) +IF (EXISTS ${CCOLAMD_INCLUDE_DIR}) + MESSAGE("-- Found CCOLAMD header in: ${CCOLAMD_INCLUDE_DIR}") +ELSE (EXISTS ${CCOLAMD_INCLUDE_DIR}) + MESSAGE("-- Did not find CCOLAMD header") + SET(CCOLAMD_FOUND FALSE) +ENDIF (EXISTS ${CCOLAMD_INCLUDE_DIR}) +MARK_AS_ADVANCED(CCOLAMD_INCLUDE_DIR) + +# CHOLMOD. +SET(CHOLMOD_FOUND TRUE) +FIND_LIBRARY(CHOLMOD_LIBRARY NAMES cholmod + PATHS ${SUITESPARSE_CHECK_LIBRARY_DIRS}) +IF (EXISTS ${CHOLMOD_LIBRARY}) + MESSAGE("-- Found CHOLMOD library: ${CHOLMOD_LIBRARY}") +ELSE (EXISTS ${CHOLMOD_LIBRARY}) + MESSAGE("-- Did not find CHOLMOD library") + SET(CHOLMOD_FOUND FALSE) +ENDIF (EXISTS ${CHOLMOD_LIBRARY}) +MARK_AS_ADVANCED(CHOLMOD_LIBRARY) + +FIND_PATH(CHOLMOD_INCLUDE_DIR NAMES cholmod.h + PATHS ${SUITESPARSE_CHECK_INCLUDE_DIRS}) +IF (EXISTS ${CHOLMOD_INCLUDE_DIR}) + MESSAGE("-- Found CHOLMOD header in: ${CHOLMOD_INCLUDE_DIR}") +ELSE (EXISTS ${CHOLMOD_INCLUDE_DIR}) + MESSAGE("-- Did not find CHOLMOD header") + SET(CHOLMOD_FOUND FALSE) +ENDIF (EXISTS ${CHOLMOD_INCLUDE_DIR}) +MARK_AS_ADVANCED(CHOLMOD_INCLUDE_DIR) + +# SuiteSparseQR. +SET(SUITESPARSEQR_FOUND TRUE) +FIND_LIBRARY(SUITESPARSEQR_LIBRARY NAMES spqr + PATHS ${SUITESPARSE_CHECK_LIBRARY_DIRS}) +IF (EXISTS ${SUITESPARSEQR_LIBRARY}) + MESSAGE("-- Found SuiteSparseQR library: ${SUITESPARSEQR_LIBRARY}") +ELSE (EXISTS ${SUITESPARSEQR_LIBRARY}) + MESSAGE("-- Did not find SUITESPARSEQR library") + SET(SUITESPARSEQR_FOUND FALSE) +ENDIF (EXISTS ${SUITESPARSEQR_LIBRARY}) +MARK_AS_ADVANCED(SUITESPARSEQR_LIBRARY) + +FIND_PATH(SUITESPARSEQR_INCLUDE_DIR NAMES SuiteSparseQR.hpp + PATHS ${SUITESPARSE_CHECK_INCLUDE_DIRS}) +IF (EXISTS ${SUITESPARSEQR_INCLUDE_DIR}) + MESSAGE("-- Found SuiteSparseQR header in: ${SUITESPARSEQR_INCLUDE_DIR}") +ELSE (EXISTS ${SUITESPARSEQR_INCLUDE_DIR}) + MESSAGE("-- Did not find SUITESPARSEQR header") + SET(SUITESPARSEQR_FOUND FALSE) +ENDIF (EXISTS ${SUITESPARSEQR_INCLUDE_DIR}) +MARK_AS_ADVANCED(SUITESPARSEQR_INCLUDE_DIR) + +IF (SUITESPARSEQR_FOUND) + # SuiteSparseQR may be compiled with Intel Threading Building Blocks, + # we assume that if TBB is installed, SuiteSparseQR was compiled with + # support for it, this will do no harm if it wasn't. + SET(TBB_FOUND TRUE) + FIND_LIBRARY(TBB_LIBRARIES NAMES tbb + PATHS ${SUITESPARSE_CHECK_LIBRARY_DIRS}) + IF (EXISTS ${TBB_LIBRARIES}) + MESSAGE("-- Found Intel Thread Building Blocks (TBB) library: ${TBB_LIBRARIES}, " + "assuming SuiteSparseQR was compiled with TBB.") + ELSE (EXISTS ${TBB_LIBRARIES}) + MESSAGE("-- Did not find TBB library") + SET(TBB_FOUND FALSE) + ENDIF (EXISTS ${TBB_LIBRARIES}) + MARK_AS_ADVANCED(TBB_LIBRARIES) + + IF (TBB_FOUND) + FIND_LIBRARY(TBB_MALLOC_LIB NAMES tbbmalloc + PATHS ${SUITESPARSE_CHECK_LIBRARY_DIRS}) + IF (EXISTS ${TBB_MALLOC_LIB}) + MESSAGE("-- Found Intel Thread Building Blocks (TBB) Malloc library: " + "${TBB_MALLOC_LIB}") + # Append TBB malloc library to TBB libraries list whilst retaining + # any CMake generated help string (cache variable). + LIST(APPEND TBB_LIBRARIES ${TBB_MALLOC_LIB}) + GET_PROPERTY(HELP_STRING CACHE TBB_LIBRARIES PROPERTY HELPSTRING) + SET(TBB_LIBRARIES "${TBB_LIBRARIES}" CACHE STRING ${HELP_STRING}) + + # Add the TBB libraries to the SuiteSparseQR libraries (the only + # libraries to optionally depend on TBB). + LIST(APPEND SUITESPARSEQR_LIBRARY ${TBB_LIBRARIES}) + + ELSE (EXISTS ${TBB_MALLOC_LIB}) + # If we cannot find all required TBB components do not include it as + # a dependency. + MESSAGE("-- Did not find Intel Thread Building Blocks (TBB) Malloc " + "Library, discarding TBB as a dependency.") + SET(TBB_FOUND FALSE) + ENDIF (EXISTS ${TBB_MALLOC_LIB}) + MARK_AS_ADVANCED(TBB_MALLOC_LIB) + ENDIF (TBB_FOUND) +ENDIF(SUITESPARSEQR_FOUND) + +# UFconfig / SuiteSparse_config. +# +# If SuiteSparse version is >= 4 then SuiteSparse_config is required. +# For SuiteSparse 3, UFconfig.h is required. +SET(SUITESPARSE_CONFIG_FOUND TRUE) +SET(UFCONFIG_FOUND TRUE) + +FIND_LIBRARY(SUITESPARSE_CONFIG_LIBRARY NAMES suitesparseconfig + PATHS ${SUITESPARSE_CHECK_LIBRARY_DIRS}) +IF (EXISTS ${SUITESPARSE_CONFIG_LIBRARY}) + MESSAGE("-- Found SuiteSparse_config library: ${SUITESPARSE_CONFIG_LIBRARY}") +ELSE (EXISTS ${SUITESPARSE_CONFIG_LIBRARY}) + MESSAGE("-- Did not find SuiteSparse_config library") +ENDIF (EXISTS ${SUITESPARSE_CONFIG_LIBRARY}) +MARK_AS_ADVANCED(SUITESPARSE_CONFIG_LIBRARY) + +FIND_PATH(SUITESPARSE_CONFIG_INCLUDE_DIR NAMES SuiteSparse_config.h + PATHS ${SUITESPARSE_CHECK_INCLUDE_DIRS}) +IF (EXISTS ${SUITESPARSE_CONFIG_INCLUDE_DIR}) + MESSAGE("-- Found SuiteSparse_config header in: ${SUITESPARSE_CONFIG_INCLUDE_DIR}") + SET(UFCONFIG_FOUND FALSE) +ELSE (EXISTS ${SUITESPARSE_CONFIG_INCLUDE_DIR}) + MESSAGE("-- Did not find SuiteSparse_config header") +ENDIF (EXISTS ${SUITESPARSE_CONFIG_INCLUDE_DIR}) +MARK_AS_ADVANCED(SUITESPARSE_CONFIG_INCLUDE_DIR) + +IF (EXISTS ${SUITESPARSE_CONFIG_LIBRARY} AND + EXISTS ${SUITESPARSE_CONFIG_INCLUDE_DIR}) + # SuiteSparse_config (SuiteSparse version >= 4) requires librt library for + # timing by default when compiled on Linux or Unix, but not on OSX (which + # does not have librt). + IF (CMAKE_SYSTEM_NAME MATCHES "Linux" OR UNIX AND NOT APPLE) + FIND_LIBRARY(LIBRT_LIBRARY NAMES rt + PATHS ${SUITESPARSE_CHECK_LIBRARY_DIRS}) + IF (LIBRT_LIBRARY) + MESSAGE("-- Adding librt: ${LIBRT_LIBRARY} to SuiteSparse_config libraries.") + ELSE (LIBRT_LIBRARY) + MESSAGE("-- Could not find librt, but found SuiteSparse_config, " + "assuming that SuiteSparse was compiled without timing.") + ENDIF (LIBRT_LIBRARY) + MARK_AS_ADVANCED(LIBRT_LIBRARY) + LIST(APPEND SUITESPARSE_CONFIG_LIBRARY ${LIBRT_LIBRARY}) + ENDIF (CMAKE_SYSTEM_NAME MATCHES "Linux" OR UNIX AND NOT APPLE) +ELSE (EXISTS ${SUITESPARSE_CONFIG_LIBRARY} AND + EXISTS ${SUITESPARSE_CONFIG_INCLUDE_DIR}) + SET(SUITESPARSE_CONFIG_FOUND FALSE) + FIND_PATH(UFCONFIG_INCLUDE_DIR NAMES UFconfig.h + PATHS ${SUITESPARSE_CHECK_INCLUDE_DIRS}) + IF (EXISTS ${UFCONFIG_INCLUDE_DIR}) + MESSAGE("-- Found UFconfig header in: ${UFCONFIG_INCLUDE_DIR}") + ELSE (EXISTS ${UFCONFIG_INCLUDE_DIR}) + MESSAGE("-- Did not find UFconfig header") + SET(UFCONFIG_FOUND FALSE) + ENDIF (EXISTS ${UFCONFIG_INCLUDE_DIR}) + MARK_AS_ADVANCED(UFCONFIG_INCLUDE_DIR) +ENDIF (EXISTS ${SUITESPARSE_CONFIG_LIBRARY} AND + EXISTS ${SUITESPARSE_CONFIG_INCLUDE_DIR}) + +# Extract the SuiteSparse version from the appropriate header (UFconfig.h for +# <= v3, SuiteSparse_config.h for >= v4). +IF (UFCONFIG_FOUND) + # SuiteSparse version <= 3. + FILE(READ "${UFCONFIG_INCLUDE_DIR}/UFconfig.h" UFCONFIG_CONTENTS) + + STRING(REGEX MATCH "#define SUITESPARSE_MAIN_VERSION [0-9]+" + SUITESPARSE_MAIN_VERSION "${UFCONFIG_CONTENTS}") + STRING(REGEX REPLACE "#define SUITESPARSE_MAIN_VERSION ([0-9]+)" "\\1" + SUITESPARSE_MAIN_VERSION "${SUITESPARSE_MAIN_VERSION}") + + STRING(REGEX MATCH "#define SUITESPARSE_SUB_VERSION [0-9]+" + SUITESPARSE_SUB_VERSION "${UFCONFIG_CONTENTS}") + STRING(REGEX REPLACE "#define SUITESPARSE_SUB_VERSION ([0-9]+)" "\\1" + SUITESPARSE_SUB_VERSION "${SUITESPARSE_SUB_VERSION}") + + STRING(REGEX MATCH "#define SUITESPARSE_SUBSUB_VERSION [0-9]+" + SUITESPARSE_SUBSUB_VERSION "${UFCONFIG_CONTENTS}") + STRING(REGEX REPLACE "#define SUITESPARSE_SUBSUB_VERSION ([0-9]+)" "\\1" + SUITESPARSE_SUBSUB_VERSION "${SUITESPARSE_SUBSUB_VERSION}") +ENDIF (UFCONFIG_FOUND) + +IF (SUITESPARSE_CONFIG_FOUND) + # SuiteSparse version >= 4. + FILE(READ "${SUITESPARSE_CONFIG_INCLUDE_DIR}/SuiteSparse_config.h" + SUITESPARSE_CONFIG_CONTENTS) + + STRING(REGEX MATCH "#define SUITESPARSE_MAIN_VERSION [0-9]+" + SUITESPARSE_MAIN_VERSION "${SUITESPARSE_CONFIG_CONTENTS}") + STRING(REGEX REPLACE "#define SUITESPARSE_MAIN_VERSION ([0-9]+)" "\\1" + SUITESPARSE_MAIN_VERSION "${SUITESPARSE_MAIN_VERSION}") + + STRING(REGEX MATCH "#define SUITESPARSE_SUB_VERSION [0-9]+" + SUITESPARSE_SUB_VERSION "${SUITESPARSE_CONFIG_CONTENTS}") + STRING(REGEX REPLACE "#define SUITESPARSE_SUB_VERSION ([0-9]+)" "\\1" + SUITESPARSE_SUB_VERSION "${SUITESPARSE_SUB_VERSION}") + + STRING(REGEX MATCH "#define SUITESPARSE_SUBSUB_VERSION [0-9]+" + SUITESPARSE_SUBSUB_VERSION "${SUITESPARSE_CONFIG_CONTENTS}") + STRING(REGEX REPLACE "#define SUITESPARSE_SUBSUB_VERSION ([0-9]+)" "\\1" + SUITESPARSE_SUBSUB_VERSION "${SUITESPARSE_SUBSUB_VERSION}") +ENDIF (SUITESPARSE_CONFIG_FOUND) + +# This is on a single line s/t CMake does not interpret it as a list of +# elements and insert ';' separators which would result in 4.;2.;1 nonsense. +SET(SUITESPARSE_VERSION + "${SUITESPARSE_MAIN_VERSION}.${SUITESPARSE_SUB_VERSION}.${SUITESPARSE_SUBSUB_VERSION}") + +# METIS (Optional dependency). +FIND_LIBRARY(METIS_LIBRARY NAMES metis + PATHS ${SUITESPARSE_CHECK_LIBRARY_DIRS}) +IF (EXISTS ${METIS_LIBRARY}) + MESSAGE("-- Found METIS library: ${METIS_LIBRARY}") +ELSE (EXISTS ${METIS_LIBRARY}) + MESSAGE("-- Did not find METIS library") +ENDIF (EXISTS ${METIS_LIBRARY}) +MARK_AS_ADVANCED(METIS_LIBRARY) + +IF (AMD_FOUND AND + CAMD_FOUND AND + COLAMD_FOUND AND + CCOLAMD_FOUND AND + CHOLMOD_FOUND AND + (SUITESPARSE_CONFIG_FOUND OR UFCONFIG_FOUND) AND + BLAS_FOUND AND + LAPACK_FOUND) + SET(SUITESPARSE_FOUND TRUE) + LIST(APPEND SUITESPARSE_INCLUDE_DIRS + ${AMD_INCLUDE_DIR} + ${CAMD_INCLUDE_DIR} + ${COLAMD_INCLUDE_DIR} + ${CCOLAMD_INCLUDE_DIR} + ${CHOLMOD_INCLUDE_DIR} + ${SUITESPARSEQR_INCLUDE_DIR}) + # Handle config separately, as otherwise at least one of them will be set + # to NOTFOUND which would cause any check on SUITESPARSE_INCLUDE_DIRS to fail. + IF (SUITESPARSE_CONFIG_FOUND) + LIST(APPEND SUITESPARSE_INCLUDE_DIRS + ${SUITESPARSE_CONFIG_INCLUDE_DIR}) + ENDIF (SUITESPARSE_CONFIG_FOUND) + IF (UFCONFIG_FOUND) + LIST(APPEND SUITESPARSE_INCLUDE_DIRS + ${UFCONFIG_INCLUDE_DIR}) + ENDIF (UFCONFIG_FOUND) + + # Important: The ordering of these libraries is *NOT* arbitrary, as these + # could potentially be static libraries their link ordering is important. + LIST(APPEND SUITESPARSE_LIBRARIES + ${SUITESPARSEQR_LIBRARY} + ${CHOLMOD_LIBRARY} + ${CCOLAMD_LIBRARY} + ${CAMD_LIBRARY} + ${COLAMD_LIBRARY} + ${AMD_LIBRARY}) + IF (SUITESPARSE_CONFIG_FOUND) + LIST(APPEND SUITESPARSE_LIBRARIES + ${SUITESPARSE_CONFIG_LIBRARY}) + ENDIF (SUITESPARSE_CONFIG_FOUND) + IF (METIS_FOUND) + LIST(APPEND SUITESPARSE_LIBRARIES + ${METIS_LIBRARY}) + ENDIF (METIS_FOUND) + MESSAGE("-- Found SuiteSparse version: ${SUITESPARSE_VERSION}") +ELSE() + SET(SUITESPARSE_FOUND FALSE) + MESSAGE("-- Failed to find some/all required components of SuiteSparse.") +ENDIF() + +# Determine if we are running on Ubuntu with the package install of SuiteSparse +# which is broken and does not support linking a shared library. +SET(SUITESPARSE_IS_BROKEN_SHARED_LINKING_UBUNTU_SYSTEM_VERSION FALSE) +IF (CMAKE_SYSTEM_NAME MATCHES "Linux" AND + SUITESPARSE_VERSION VERSION_EQUAL 3.4.0) + FIND_PROGRAM(LSB_RELEASE_EXECUTABLE lsb_release) + IF (LSB_RELEASE_EXECUTABLE) + # Any even moderately recent Ubuntu release (likely to be affected by + # this bug) should have lsb_release, if it isn't present we are likely + # on a different Linux distribution (should be fine). + + EXECUTE_PROCESS(COMMAND ${LSB_RELEASE_EXECUTABLE} -si + OUTPUT_VARIABLE LSB_DISTRIBUTOR_ID + OUTPUT_STRIP_TRAILING_WHITESPACE) + + IF (LSB_DISTRIBUTOR_ID MATCHES "Ubuntu" AND + SUITESPARSE_LIBRARIES MATCHES "/usr/lib/libamd") + # We are on Ubuntu, and the SuiteSparse version matches the broken + # system install version and is a system install. + SET(SUITESPARSE_IS_BROKEN_SHARED_LINKING_UBUNTU_SYSTEM_VERSION TRUE) + ENDIF (LSB_DISTRIBUTOR_ID MATCHES "Ubuntu" AND + SUITESPARSE_LIBRARIES MATCHES "/usr/lib/libamd") + ENDIF (LSB_RELEASE_EXECUTABLE) +ENDIF (CMAKE_SYSTEM_NAME MATCHES "Linux" AND + SUITESPARSE_VERSION VERSION_EQUAL 3.4.0) + +# Handle REQUIRED and QUIET arguments to FIND_PACKAGE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SuiteSparse DEFAULT_MSG + SUITESPARSE_FOUND SUITESPARSE_INCLUDE_DIRS SUITESPARSE_LIBRARIES) +
diff --git a/docs/source/building.rst b/docs/source/building.rst index b74a9dd..91fdd8a 100644 --- a/docs/source/building.rst +++ b/docs/source/building.rst
@@ -66,6 +66,14 @@ We will use `Ubuntu <http://www.ubuntu.com>`_ as our example platform. Start by installing all the dependencies. +.. NOTE:: +Up to at least Ubuntu 13.10, the SuiteSparse package in the official +package repository (built from SuiteSparse v3.4.0) **cannot** be used to +build Ceres as a *shared* library. Thus if you want to build Ceres as a +shared library using SuiteSparse, you must perform a source install of +SuiteSparse. It is recommended that you use the current version of +SuiteSparse (4.2.1 at the time of writing). + .. code-block:: bash # CMake @@ -86,8 +94,14 @@ sudo apt-get install libatlas-base-dev # Eigen3 sudo apt-get install libeigen3-dev - # SuiteSparse and CXSparse + # SuiteSparse and CXSparse (optional) + # - If you want to build Ceres as a *static* library (the default) + # you can use the SuiteSparse package in the main Ubuntu package + # repository: sudo apt-get install libsuitesparse-dev + # - However, if you want to build Ceres as a *shared* library, you must + # perform a source install of SuiteSparse (and uninstall the Ubuntu + # package if it is currently installed. We are now ready to build and test Ceres. @@ -286,42 +300,48 @@ ===================== It is possible to reduce the libraries needed to build Ceres and -customize the build process by passing appropriate flags to -``CMake``. Use these flags only if you really know what you are doing. +customize the build process by setting the appropriate options in +``CMake``. These options can either be set in the ``CMake`` GUI, +or via ``-D<OPTION>=<ON/OFF>`` when running ``CMake`` from the +command line. In general, you should only modify these options from +their defaults if you know what you are doing. -#. ``-DSUITESPARSE=OFF``: By default, Ceres will link to - ``SuiteSparse`` if all its dependencies are present. Use this flag +#. ``SUITESPARSE [Default: ON]``: By default, Ceres will link to + ``SuiteSparse`` if all its dependencies are present. Turn this ``OFF`` to build Ceres without ``SuiteSparse``. This will also disable dependency checking for ``LAPACK`` and ``BLAS``. This will reduce Ceres' dependencies down to ``Eigen``, ``gflags`` and ``google-glog``. -#. ``-DCXSPARSE=OFF``: By default, Ceres will link to ``CXSparse`` if - all its dependencies are present. Use this flag to builds Ceres +#. ``CXSPARSE [Default: ON]``: By default, Ceres will link to ``CXSparse`` if + all its dependencies are present. Turn this ``OFF`` to build Ceres without ``CXSparse``. This will reduce Ceres' dependencies down to ``Eigen``, ``gflags`` and ``google-glog``. -#. ``-DGFLAGS=OFF``: Use this flag to build Ceres without +#. ``GFLAGS [Default: ON]``: Turn this ``OFF`` to build Ceres without ``gflags``. This will also prevent some of the example code from building. -#. ``-DSCHUR_SPECIALIZATIONS=OFF``: If you are concerned about binary +#. ``SCHUR_SPECIALIZATIONS [Default: ON]``: If you are concerned about binary size/compilation time over some small (10-20%) performance gains in the ``SPARSE_SCHUR`` solver, you can disable some of the template - specializations by using this flag. + specializations by turning this ``OFF``. -#. ``-DLINE_SEARCH_MINIMIZER=OFF``: The line search based minimizer is +#. ``LINE_SEARCH_MINIMIZER [Default: OFF]``: The line search based minimizer is mostly suitable for large scale optimization problems, or when sparse linear algebra libraries are not available. You can further save on - some compile time and binary size by using this flag. + some compile time and binary size by turning this ``OFF``. -#. ``-DOPENMP=OFF``: On certain platforms like Android, - multi-threading with ``OpenMP`` is not supported. Use this flag to +#. ``OPENMP [Default: ON]``: On certain platforms like Android, + multi-threading with ``OpenMP`` is not supported. Turn this ``OFF`` to disable multithreading. -#. ``-DBUILD_DOCUMENTATION=ON``: Use this flag to enable building the - documentation. In addition, ``make ceres_docs`` can be used to - build only the documentation. +#. ``BUILD_SHARED_LIBS [Default: OFF]``: By default Ceres is built as a static + library, turn this ``ON`` to instead build Ceres as a shared library. + +#. ``BUILD_DOCUMENTATION [Default: OFF]``: Use this to enable building the + documentation, requires `Sphinx <http://sphinx-doc.org/>`_. In addition, + ``make ceres_docs`` can be used to build only the documentation. .. _section-using-ceres: @@ -376,17 +396,3 @@ Note that this can be used to have multiple versions of Ceres installed. -Compiling against static or shared library ------------------------------------------- - -.. code-block:: cmake - - TARGET_LINK_LIBRARIES(helloworld ${CERES_LIBRARIES}) - -will result in a statically linked binary. Changing this line to - -.. code-block:: cmake - - TARGET_LINK_LIBRARIES(helloworld ${CERES_LIBRARIES_SHARED}) - -will result in a dynamically linked binary.
diff --git a/internal/ceres/CMakeLists.txt b/internal/ceres/CMakeLists.txt index 477cf98..30ff6f9 100644 --- a/internal/ceres/CMakeLists.txt +++ b/internal/ceres/CMakeLists.txt
@@ -147,40 +147,19 @@ LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${GFLAGS_LIB}) ENDIF (GFLAGS) -IF (SUITESPARSE_FOUND) - LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${SUITESPARSEQR_LIB}) - LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${CHOLMOD_LIB}) - LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${CCOLAMD_LIB}) - LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${CAMD_LIB}) - LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${COLAMD_LIB}) - LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${AMD_LIB}) - IF (SUITESPARSE_CONFIG_FOUND) - LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${SUITESPARSE_CONFIG_LIB}) - ENDIF (SUITESPARSE_CONFIG_FOUND) +IF (SUITESPARSE AND SUITESPARSE_FOUND) + LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${SUITESPARSE_LIBRARIES}) +ENDIF (SUITESPARSE AND SUITESPARSE_FOUND) - IF (EXISTS ${METIS_LIB}) - LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${METIS_LIB}) - ENDIF (EXISTS ${METIS_LIB}) - - IF (TBB_FOUND) - LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${TBB_LIB}) - LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${TBB_MALLOC_LIB}) - ENDIF (TBB_FOUND) -ENDIF (SUITESPARSE_FOUND) - -IF (CXSPARSE_FOUND) +IF (CXSPARSE AND CXSPARSE_FOUND) LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${CXSPARSE_LIB}) -ENDIF (CXSPARSE_FOUND) +ENDIF (CXSPARSE AND CXSPARSE_FOUND) IF (BLAS_AND_LAPACK_FOUND) LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${LAPACK_LIBRARIES}) LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${BLAS_LIBRARIES}) ENDIF (BLAS_AND_LAPACK_FOUND) -IF (CXSPARSE_FOUND) - LIST(APPEND CERES_LIBRARY_DEPENDENCIES ${CXSPARSE_LIB}) -ENDIF (CXSPARSE_FOUND) - IF (OPENMP_FOUND) IF (NOT MSVC) LIST(APPEND CERES_LIBRARY_DEPENDENCIES gomp) @@ -276,9 +255,9 @@ # TODO(sameeragarwal): This test should ultimately be made # independent of SuiteSparse. - IF (SUITESPARSE_FOUND) + IF (SUITESPARSE AND SUITESPARSE_FOUND) CERES_TEST(compressed_col_sparse_matrix_utils) - ENDIF (SUITESPARSE_FOUND) + ENDIF (SUITESPARSE AND SUITESPARSE_FOUND) CERES_TEST(symmetric_linear_solver) CERES_TEST(triplet_sparse_matrix)