cmakeexternal-projectceres-solver

Difference in behavior between between "normal" build and ExternalProject_Add


I am trying to build the ceres-solver on linux using CMake's external project feature.

I have a specific version of Eigen that I built and the other dependencies are installed through my packet manager (BLAS, LAPACK and Suitesparse).

If I build Ceres-solver directly from source:

cmake -G Ninja -DEIGEN_INCLUDE_DIR='<path-to-eigen>' -DEIGEN_BUILD_DIR='<path-to-eigen-build>' ..

It automatically finds suitesparse and all its dependencies (BLAS, LAPACK, AMD, COLAMD, etc.) and it build with no problems.

Here is CMake output :

-- Detected Ceres version: 2.0.0 from <path>/ceres-solver/include/ceres/version.h
-- Detected available Ceres threading models: [CXX11_THREADS, OPENMP, NO_THREADS]
-- Building with C++17
-- No preference for use of exported Eigen CMake configuration set, and no hints for include directory provided. Defaulting to preferring an installed/exported Eigen CMake configuration if available.
-- Found installed version of Eigen: <path>/eigen-3.3.5/share/eigen3/cmake
-- Found Eigen version 3.3.5: <path>/eigen-3.3.5/include/eigen3
-- Disabling use of Eigen as a sparse linear algebra library.
   This does not affect the covariance estimation algorithm 
   which can still use the EIGEN_SPARSE_QR algorithm.
-- Found LAPACK library: /usr/lib/liblapack.so;/usr/lib/libblas.so
-- Found AMD headers in: /usr/include
-- Found AMD library: /usr/lib/libamd.so
-- Found CAMD headers in: /usr/include
-- Found CAMD library: /usr/lib/libcamd.so
-- Found COLAMD headers in: /usr/include
-- Found COLAMD library: /usr/lib/libcolamd.so
-- Found CCOLAMD headers in: /usr/include
-- Found CCOLAMD library: /usr/lib/libccolamd.so
-- Found CHOLMOD headers in: /usr/include
-- Found CHOLMOD library: /usr/lib/libcholmod.so
-- Found SUITESPARSEQR headers in: /usr/include
-- Found SUITESPARSEQR library: /usr/lib/libspqr.so
-- Found Intel Thread Building Blocks (TBB) library (2019.0) assuming SuiteSparseQR was compiled with TBB.
-- Found SUITESPARSE_CONFIG headers in: /usr/include
-- Found SUITESPARSE_CONFIG library: /usr/lib/libsuitesparseconfig.so
-- Found LIBRT library: /usr/lib/librt.so
-- Adding librt: /usr/lib/librt.so to SuiteSparse_config libraries (required on Linux & Unix [not OSX] if SuiteSparse is compiled with timing).
-- Found METIS library: /usr/lib/libmetis.so
-- Found SuiteSparse 5.4.0, building with SuiteSparse.
-- Building without CXSparse.
-- Building without Apple's Accelerate sparse support.
-- No preference for use of exported gflags CMake configuration set, and no hints for include/library directories provided. Defaulting to preferring an installed/exported gflags CMake configuration if available.
-- Found installed version of gflags: <path>
-- Detected gflags version: 2.2.2
-- Found Google Flags header in: <path>/include, in namespace: google
-- No preference for use of exported glog CMake configuration set, and no hints for include/library directories provided. Defaulting to preferring an installed/exported glog CMake configuration if available.
-- Found installed version of glog: <path>/glog
-- Detected glog version: 0.3.5
-- Found Google Log (glog). Assuming glog was built with gflags support as gflags was found. This will make gflags a public dependency of Ceres.
-- Using Ceres threading model: OPENMP
-- Building Ceres as a static library.
-- Enabling CERES_NO_CXSPARSE in Ceres config.h
-- Enabling CERES_NO_ACCELERATE_SPARSE in Ceres config.h
-- Enabling CERES_USE_OPENMP in Ceres config.h
-- Do not build any example.
-- Configuring done
-- Generating done

But If I build Ceres-solver as an external project, It does not find BLAS (the same BLAS that is automatically found when I build directly from source).

Is there a difference in behavior when building a library through ExternalProject_Add vs. building it separately by hand ? Can options & variables defined in my "master" project (the one calling ExternalProject_Add) leak to the external project (and if yes, how can I prevent that ?).

My call to ExternalProject_Add :

        ExternalProject_Add(ceres-solver
            PREFIX CeresSolver
            BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/ceres-solver
            SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ceres-solver
            INSTALL_DIR ${DEFAULT_INSTALL_ROOT}/ceres-solver
            LOG_DIR ${DEFAULT_INSTALL_ROOT}/ceres-solver/log
            LOG_CONFIGURE ON
            CMAKE_ARGS
                -DCERES_THREADING_MODEL=OPENMP
                -DCMAKE_CXX_STANDARD=17
                -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
                -DCMAKE_INSTALL_PREFIX=${DEFAULT_INSTALL_ROOT}/ceres-solver

                -DBUILD_BENCHMARKS=OFF
                -DBUILD_DOCUMENTATION=OFF
                -DBUILD_EXAMPLES=OFF
                -DBUILD_SHARED_LIBS=ON
                -DBUILD_TESTING=OFF

                -DCXSPARSE=OFF
                -DEIGENSPARSE=OFF

                -DEIGEN_INCLUDE_DIR=${EIGEN3_INCLUDE_DIR}
                -DEigen3_DIR=${Eigen3_DIR}
                -DSUITESPARSE=ON
                -DLAPACK=ON)

And the output of the configure for ceres-solver :

- Detected available Ceres threading models: [CXX11_THREADS, OPENMP, NO_THREADS]
-- Building with C++17
-- Found Eigen version 3.3.5: <path>
-- Disabling use of Eigen as a sparse linear algebra library.
   This does not affect the covariance estimation algorithm 
   which can still use the EIGEN_SPARSE_QR algorithm.
-- Did not find LAPACK library, disabling LAPACK support.
-- Failed to find SuiteSparse - Did not find BLAS library (required for SuiteSparse).
-- Failed to find SuiteSparse - Did not find LAPACK library (required for SuiteSparse).
-- Failed to find SuiteSparse - Did not find AMD header (required SuiteSparse component).
-- Failed to find SuiteSparse - Did not find AMD library (required SuiteSparse component).
-- Failed to find SuiteSparse - Did not find CAMD header (required SuiteSparse component).
-- Failed to find SuiteSparse - Did not find CAMD library (required SuiteSparse component).
-- Failed to find SuiteSparse - Did not find COLAMD header (required SuiteSparse component).
-- Failed to find SuiteSparse - Did not find COLAMD library (required SuiteSparse component).
-- Failed to find SuiteSparse - Did not find CCOLAMD header (required SuiteSparse component).
-- Failed to find SuiteSparse - Did not find CCOLAMD library (required SuiteSparse component).
-- Failed to find SuiteSparse - Did not find CHOLMOD header (required SuiteSparse component).
-- Failed to find SuiteSparse - Did not find CHOLMOD library (required SuiteSparse component).
-- Failed to find SuiteSparse - Did not find SUITESPARSEQR header (required SuiteSparse component).
-- Failed to find SuiteSparse - Did not find SUITESPARSEQR library (required SuiteSparse component).
-- Failed to find SuiteSparse - Failed to find either: SuiteSparse_config header & library (should be present in all SuiteSparse >= v4 installs), or UFconfig header (should be present in all SuiteSparse < v4 installs).
-- Did not find all SuiteSparse dependencies, disabling SuiteSparse support.
-- Building without CXSparse.
-- Building without Apple's Accelerate sparse support.
   ===============================================================
   Compiling without any sparse library: SuiteSparse, CXSparse 
   EigenSparse & Apple's Accelerate are all disabled or unavailable.  
   No sparse linear solvers (SPARSE_NORMAL_CHOLESKY & SPARSE_SCHUR)
   will be available when Ceres is used.
   ===============================================================
-- Found Google Flags header in: <path>, in namespace: google
-- Found Google Log (glog). Assuming glog was built with gflags support as gflags was found. This will make gflags a public dependency of Ceres.
-- Using Ceres threading model: OPENMP
-- Building Ceres as a shared library.
-- Do not build any example.

Solution

  • It seems my build folder was corrupted. I just deleted the build folder & the install folder. When I re-run the install, everything worked perfectly.