Friday, June 1, 2018

Compiling Ceres Solver on Windows with SuiteSparse Support

It took me a while to get all the CMake parameters just right, and a few colleagues needed to do the same. So I decided to write this document and share it with the world. Hope it helps someone, somewhere, sometime.

Environment

My building environment is as follows:
  • Windows 7 (yeah our work PCs are obsolete). But it should work on 10.
  • Visual Studio 2015, 64 bits compiler
  • CMake 3.10.3
It might work in other environments, but I haven't tested it, sorry...

Downloads

Here are the versions of Ceres and it's dependencies I used:
So download these, unzip them, and let's get to work.

Configuring and building dependencies

Eigen

Nothing to do here really, just unzip it somewhere.

gflags

  • Run CMake.
  • Set the CMAKE_INSTALL_PREFIX if you want.
  • Build and install.
The problem with gflags is that its Debug and Release targets produce the same libraries, with the exact same name, in the exact same folder. So, with the default CMAke settings, you can only have either Debug or Release, but not both.

And since both glog and ceres depend on gflags, you have to choose the same configuration for both of them. However, you might get away with compiling glog without the gflags dependency (it compiles but I haven't tested it any further).

However, you can have CMake generate a Debug library with a suffix, so it will generate gflagsd.lib. To do so you just need to click on the "+Add Entry" button in your CMake GUI and create the following variable:

  • CMAKE_DEBUG_POSTFIX, Type String, Value d.

glog

  • Run CMake.
  • Set the SUITESPARSE_INSTALL_PREFIX if you want.
  • It should detect the gflags install folder automatically. If not, specify it manually.
  • Build and install.
Don't forget to build the same configuration (Debug or Release) as gflags. Or if you want to have both, just do as above and add the CMAKE_DEBUG_POSTFIX CMake variable.

SuiteSparse

If you're using Visual Studio 2013 or newer (which you should be because this guide assumes you're using VS20015), there is a problem with the declaration of rint().

Int the folder where you unzipped SuiteSparse go to the folder metis/GKlib, open the file gk_arch.h. At line 62 you should see this code block:
#ifdef __MSC__
/* MSC does not have rint() function */
#define rint(x) ((int)((x)+0.5))

Replace it with this:

#ifdef __MSC__
#if (_MSC_VER < 1800)
/* MSC does not have rint() function */
#define rint(x) ((int)((x)+0.5))  
#endif

Now you can:
  • Run CMake.
  • Set the CMAKE_INSTALL_PREFIX if you want.
  • Build and install.

Configuring and building Ceres Solver

This section assumes you will be building a Release version of ceres. For building in Debug, see section Building in Debug below.

Fire up CMake, click Configure and let's get to work.

First, we need to set up a few things for the first configuration run:
  1. Set CMAKE_INSTALL_PREFIX if you want.
  2. Set EIGEN_INCLUDE_DIR to the folder where you unzipped Eigen earlier.
  3. Make sure CUSTOM_BLAS is checked.
  4. Make sure LAPACK is checked.
  5. Make sure SUITESPARSE is checked.
  6. Click Configure.

THE CONFIGURATION WILL FAIL!

Now, before going any further, you need to check the Advanced box in the CMake GUI:

YOU NEED TO RECHECK SUITESPARSE and LAPACK BECAUSE THEY ARE AUTOMATICALLY UNCHECKED EVERY TIME CMAKE FAILS TO FIND THEM!

We now need to manually st ALL dependcies, one by one. I will be using SUITESPARSE_INSTALL_DIR to refer to the folder where you installed SuiteSparse. It should be the same value you gave CMake in SUITESPARSE_INSTALL_PREFIX when you configured and built SuiteSparse:
  1. Set AMD_INCLUDE_DIR to SUITESPARSE_INSTALL_DIR/include/suitesparse
  2. Set AMD_LIBRARY to SUITESPARSE_INSTALL_DIR/lib64/libamd.lib
  3. Set BLAS_blas_LIBRARY to SUITESPARSE_INSTALL_DIR/lib64/lapack_blas_windows/libblas.lib
  4. Set CAMD_INCLUDE_DIR to SUITESPARSE_INSTALL_DIR/include/suitesparse
  5. Set CAMD_LIBRARY to SUITESPARSE_INSTALL_DIR/lib64/libcamd.lib
  6. Set CCOLAMD_INCLUDE_DIR to SUITESPARSE_INCLUDE_DIR/include/suitesparse
  7. Set CCOLAMD_LIBRARY to SUITESPARSE_INSTALL_DIR/lib64/libccolamd.lib
  8. Set CHOLMOD_INCLUDE_DIR to SUITESPARSE_INSTALL_DIR/include/suitesparse
  9. Set CHOLMOD_LIBRARY to SUITESPARSE_INSTALL_DIR/lib64/libcholmod.lib
  10. Set COLAMD_INCLUDE_DIR to SUITESPARSE_INSTALL_DIR/include/suitesparse
  11. Set COLAMD_LIBRARY to SUITESPARSE_INSTALL_DIR/lib64/libcolamd.lib
  12. Set METIS_LIBRARY to SUITESPARSE_INSTALL_DIR/lib64/metis.lib
  13. Set SUITESPARSEQR_INCLUDE_DIR to SUITESPARSE_INSTALL_DIR/include/suitesparse
  14. Set SUITESPARSEQR_LIBRARY to SUITESPARSE_INSTALL_DIR/lib64/libspqr.lib
  15. Set SUITESPARSE_CONFIG_INCLUDE_DIR to SUITESPARSE_INSTALL_DIR/include/suitesparse
  16. Set SUITESPARSE_CONFIG_LIBRARY to SUITESPARSE_INSTALL_DIR/lib64/suitesparseconfig.lib
  17. Check CUSTOM_BLAS, if it's not already checked.
  18. Check LAPACK, if it's not already checked.
  19. Check SUITE_SPARSE, if it's not already checked.
  20. Finally, set CMAKE_BUILD_TYPE to Release.
Click Configure again. IT WILL FAIL AGAIN!

But now we can setup the final missing variables concerning Lapack.

YOU NEED TO RECHECK SUITESPARSE and LAPACK BECAUSE THEY ARE AUTOMATICALLY UNCHECKED EVERY TIME CMAKE FAILS TO FIND THEM!

  1. Set LAPACK_lapack_LIBRARY to SUITESPARSE_INSTALL_DIR/lib64/lapack_blas_windows/liblapack.lib
  2. Check LAPACK
  3. Check SUITE_SPARSE
Your final CMake options should look like this (click to enlarge and/or download full size image):

You can now build the Release version, install and enjoy!

Building in Debug

  • First you need to build gflags and glog in Debug.
  • In step 26 above, set CMAKE_BUILD_TYPE to Debug.
  • Add the suffix d to all libraries in steps, 8, 11, 13, 15, 17, 18, 20 and 22. (i.e. libamd.lib becomes libamdd.lib). Do NOT do this for BLAS and LAPACK.
  • Add the flag /bigobj to CMAKE_CXX_FLAGS_DEBUG.
Configure and build (in Debug of course).

Troubleshooting the Debug Build in your project

First, check out how to correctly use ceres with CMake on the official ceres installation page.

This works perfectly if you have either a Release build or a Debug build, but sometimes, not all the time, for some reason I cannot understand, CMake doesn't generate the proper include paths for glog and gflags for the Debug config of your project.

So you just need to simply manually add them to your CMake file, either hardcoded (which is bad, bad, bad, shame on you!) or using some kind of Environment or CMake variable (because, for another reason I don't understand GLOG_INCLUDE_DIRS and GFLAGS_INCLUDE_DIRS stay blank even though CMake finds the libraries and paths).

Here's what mine looks like:

set( INCLUDE_DIRS "$ENV{THIRD_PARTY_LIBS}/glog/include;${INCLUDE_DIRS}")
set( INCLUDE_DIRS "$ENV{THIRD_PARTY_LIBS}/gflags/include;${INCLUDE_DIRS}")

Troubleshooting

If you encounter the following errors, here's how to solve them:

Error LNK2038

gflags_static.lib(gflags.obj) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in stl_logging_unittest.obj

It's Debug/Release mismatch.It means you're trying to build glog or ceres in Debug when you compiled gflags in Release (or the opposite). You need to compile everything in either Debug or Release.

Error MSB3491

Could not write lines to file "ba_iterschur_suitesparse_clustjacobi_auto_threads_test.dir\Release\ba_iters.8A65E343.tlog\ba_iterschur_suitesparse_clustjacobi_auto_threads_test.lastbuildstate". The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.

Windows has a limit on the number of characters in a path. Try moving your ceres source files to a shallower folder with a shorter name. In my example, the source files are in D:/Dev_MAW/ceres.


Fatal Error C1128


cwisenullaryop.h(84): fatal error C1128: number of sections exceeded object file format limit: compile with /bigobj

You are building in Debug and forgot to add the /bigobj flag to CMAKE_CXX_FLAGS_DEBUG as explained in the Building in Debug section above.

Fatal Error C1083


fatal error C1083: Cannot open include file: 'glog/glog.h': No such file or directory

Try to manually add the include paths for gflags and glog as explained here.

No comments:

Post a Comment