CMakeLists.txt 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. # Ceres Solver - A fast non-linear least squares minimizer
  2. # Copyright 2022 Google Inc. All rights reserved.
  3. # http://ceres-solver.org/
  4. #
  5. # Redistribution and use in source and binary forms, with or without
  6. # modification, are permitted provided that the following conditions are met:
  7. #
  8. # * Redistributions of source code must retain the above copyright notice,
  9. # this list of conditions and the following disclaimer.
  10. # * Redistributions in binary form must reproduce the above copyright notice,
  11. # this list of conditions and the following disclaimer in the documentation
  12. # and/or other materials provided with the distribution.
  13. # * Neither the name of Google Inc. nor the names of its contributors may be
  14. # used to endorse or promote products derived from this software without
  15. # specific prior written permission.
  16. #
  17. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  18. # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  21. # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22. # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23. # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  24. # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  25. # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  26. # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  27. # POSSIBILITY OF SUCH DAMAGE.
  28. #
  29. # Authors: keir@google.com (Keir Mierle)
  30. # alexs.mac@gmail.com (Alex Stewart)
  31. cmake_minimum_required(VERSION 3.11)
  32. if (POLICY CMP0074) # Added in CMake 3.12
  33. # FindTBB.cmake uses TBB_ROOT in a way that is historical, but also compliant
  34. # with CMP0074 so suppress the legacy compatibility warning and allow its use.
  35. cmake_policy(SET CMP0074 NEW)
  36. endif()
  37. # On macOS, add the Homebrew prefix (with appropriate suffixes) to the
  38. # respective HINTS directories (after any user-specified locations). This
  39. # handles Homebrew installations into non-standard locations (not /usr/local).
  40. # We do not use CMAKE_PREFIX_PATH for this as given the search ordering of
  41. # find_xxx(), doing so would override any user-specified HINTS locations with
  42. # the Homebrew version if it exists.
  43. if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
  44. find_program(HOMEBREW_EXECUTABLE brew)
  45. mark_as_advanced(FORCE HOMEBREW_EXECUTABLE)
  46. if (HOMEBREW_EXECUTABLE)
  47. # Detected a Homebrew install, query for its install prefix.
  48. execute_process(COMMAND ${HOMEBREW_EXECUTABLE} --prefix
  49. OUTPUT_VARIABLE HOMEBREW_INSTALL_PREFIX
  50. OUTPUT_STRIP_TRAILING_WHITESPACE)
  51. message(STATUS "Detected Homebrew with install prefix: "
  52. "${HOMEBREW_INSTALL_PREFIX}, adding to CMake search paths.")
  53. list(APPEND CMAKE_PREFIX_PATH "${HOMEBREW_INSTALL_PREFIX}")
  54. endif()
  55. endif()
  56. project(Ceres C CXX)
  57. # NOTE: The following CMake variables must be applied consistently to all
  58. # targets in project to avoid visibility warnings by placing the variables at
  59. # the project top.
  60. # Always build position-independent code (PIC), even when building Ceres as a
  61. # static library so that shared libraries can link against it, not just
  62. # executables (PIC does not apply on Windows). Global variable can be overridden
  63. # by the user whereas target properties can be not.
  64. set(CMAKE_POSITION_INDEPENDENT_CODE ON)
  65. # Set the default symbol visibility to hidden to unify the behavior among
  66. # the various compilers and to get smaller binaries
  67. set(CMAKE_C_VISIBILITY_PRESET hidden)
  68. set(CMAKE_CXX_VISIBILITY_PRESET hidden)
  69. set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
  70. # NOTE: The 'generic' CMake variables CMAKE_[SOURCE/BINARY]_DIR should not be
  71. # used. Always use the project-specific variants (generated by CMake):
  72. # <PROJECT_NAME_MATCHING_CASE>_[SOURCE/BINARY]_DIR, e.g.
  73. # Ceres_SOURCE_DIR (note, *not* CERES_SOURCE_DIR) instead, as these will
  74. # always point to the correct directories for the Ceres project, even if
  75. # it is nested inside another source tree, whereas the 'generic'
  76. # CMake variables refer to the *first* project() declaration, i.e. the
  77. # top-level project, not Ceres, if Ceres is nested.
  78. # Make CMake aware of the cmake folder for local FindXXX scripts,
  79. # append rather than set in case the user has passed their own
  80. # additional paths via -D.
  81. list(APPEND CMAKE_MODULE_PATH "${Ceres_SOURCE_DIR}/cmake")
  82. include(AddCompileFlagsIfSupported)
  83. include(CheckCXXCompilerFlag)
  84. include(CheckLibraryExists)
  85. include(GNUInstallDirs)
  86. include(UpdateCacheVariable)
  87. check_cxx_compiler_flag(/bigobj HAVE_BIGOBJ)
  88. check_library_exists(m pow "" HAVE_LIBM)
  89. # Xcode 11.0-1 with macOS 10.15 (Catalina) broke alignment.
  90. include(DetectBrokenStackCheckMacOSXcodePairing)
  91. detect_broken_stack_check_macos_xcode_pairing()
  92. # Set up the git hook to make Gerrit Change-Id: lines in commit messages.
  93. include(AddGerritCommitHook)
  94. add_gerrit_commit_hook(${Ceres_SOURCE_DIR} ${Ceres_BINARY_DIR})
  95. set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${Ceres_BINARY_DIR}/bin)
  96. set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${Ceres_BINARY_DIR}/lib)
  97. set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${Ceres_BINARY_DIR}/lib)
  98. # Set postfixes for generated libraries based on buildtype.
  99. set(CMAKE_RELEASE_POSTFIX "")
  100. set(CMAKE_DEBUG_POSTFIX "-debug")
  101. # Read the Ceres version from the source, such that we only ever have a single
  102. # definition of the Ceres version.
  103. include(ReadCeresVersionFromSource)
  104. read_ceres_version_from_source(${Ceres_SOURCE_DIR})
  105. enable_testing()
  106. include(CMakeDependentOption)
  107. include(PrettyPrintCMakeList)
  108. option(MINIGLOG "Use a stripped down version of glog." OFF)
  109. option(GFLAGS "Enable Google Flags." ON)
  110. option(SUITESPARSE "Enable SuiteSparse." ON)
  111. if (APPLE)
  112. option(ACCELERATESPARSE
  113. "Enable use of sparse solvers in Apple's Accelerate framework." ON)
  114. option(ENABLE_BITCODE
  115. "Enable bitcode for iOS builds (disables inline optimizations for Eigen)." OFF)
  116. endif()
  117. # We can't have an option called 'CUDA' since that is a reserved word -- a
  118. # language definition.
  119. option(USE_CUDA "Enable use of CUDA linear algebra solvers." ON)
  120. option(LAPACK "Enable use of LAPACK directly within Ceres." ON)
  121. # Template specializations for the Schur complement based solvers. If
  122. # compile time, binary size or compiler performance is an issue, you
  123. # may consider disabling this.
  124. option(SCHUR_SPECIALIZATIONS "Enable fixed-size schur specializations." ON)
  125. option(CUSTOM_BLAS
  126. "Use handcoded BLAS routines (usually faster) instead of Eigen."
  127. ON)
  128. # Enable the use of Eigen as a sparse linear algebra library for
  129. # solving the nonlinear least squares problems.
  130. option(EIGENSPARSE "Enable Eigen as a sparse linear algebra library." ON)
  131. cmake_dependent_option(EIGENMETIS "Enable Eigen METIS support." ON EIGENSPARSE OFF)
  132. option(EXPORT_BUILD_DIR
  133. "Export build directory using CMake (enables external use without install)." OFF)
  134. option(BUILD_TESTING "Enable tests" ON)
  135. option(BUILD_DOCUMENTATION "Build User's Guide (html)" OFF)
  136. option(BUILD_EXAMPLES "Build examples" ON)
  137. option(BUILD_BENCHMARKS "Build Ceres benchmarking suite" ON)
  138. option(BUILD_SHARED_LIBS "Build Ceres as a shared library." OFF)
  139. option(PROVIDE_UNINSTALL_TARGET "Add a custom target to ease removal of installed targets" ON)
  140. set(SANITIZERS "" CACHE STRING "Semicolon-separated list of sanitizers to use (e.g address, memory, thread)")
  141. include(EnableSanitizer)
  142. enable_sanitizer(${SANITIZERS})
  143. if (ANDROID)
  144. option(ANDROID_STRIP_DEBUG_SYMBOLS "Strip debug symbols from Android builds (reduces file sizes)" ON)
  145. endif()
  146. if (MSVC)
  147. # TODO Not needed starting CMake 3.15 which provides CMAKE_MSVC_RUNTIME_LIBRARY
  148. option(MSVC_USE_STATIC_CRT
  149. "MS Visual Studio: Use static C-Run Time Library in place of shared." OFF)
  150. endif()
  151. # IOS is defined iff using the iOS.cmake CMake toolchain to build a static
  152. # library for iOS.
  153. if (IOS)
  154. message(STATUS "Building Ceres for iOS platform: ${IOS_PLATFORM}")
  155. # Ceres requires at least iOS 7.0+.
  156. if (IOS_DEPLOYMENT_TARGET VERSION_LESS 7.0)
  157. message(FATAL_ERROR "Unsupported iOS version: ${IOS_DEPLOYMENT_TARGET}, Ceres "
  158. "requires at least iOS version 7.0")
  159. endif()
  160. update_cache_variable(MINIGLOG ON)
  161. message(STATUS "Building for iOS: Forcing use of miniglog instead of glog.")
  162. # Apple claims that the BLAS call dsyrk_ is a private API, and will not allow
  163. # you to submit to the Apple Store if the symbol is present.
  164. update_cache_variable(LAPACK OFF)
  165. message(STATUS "Building for iOS: SuiteSparse, LAPACK, gflags "
  166. "are not available.")
  167. update_cache_variable(BUILD_EXAMPLES OFF)
  168. message(STATUS "Building for iOS: Will not build examples.")
  169. endif (IOS)
  170. unset(CERES_COMPILE_OPTIONS)
  171. # Eigen.
  172. # Eigen delivers Eigen3Config.cmake since v3.3.3
  173. find_package(Eigen3 3.3 REQUIRED)
  174. if (Eigen3_FOUND)
  175. message("-- Found Eigen version ${Eigen3_VERSION}: ${Eigen3_DIR}")
  176. if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*)" AND
  177. Eigen3_VERSION VERSION_LESS 3.3.4)
  178. # As per issue #289: https://github.com/ceres-solver/ceres-solver/issues/289
  179. # the bundle_adjustment_test will fail for Eigen < 3.3.4 on aarch64.
  180. message(FATAL_ERROR "-- Ceres requires Eigen version >= 3.3.4 on aarch64. "
  181. "Detected version of Eigen is: ${Eigen3_VERSION}.")
  182. endif()
  183. if (EIGENSPARSE)
  184. message("-- Enabling use of Eigen as a sparse linear algebra library.")
  185. list(APPEND CERES_COMPILE_OPTIONS CERES_USE_EIGEN_SPARSE)
  186. else (EIGENSPARSE)
  187. message("-- Disabling use of Eigen as a sparse linear algebra library.")
  188. message(" This does not affect the covariance estimation algorithm ")
  189. message(" which can still use the EIGEN_SPARSE_QR algorithm.")
  190. add_definitions(-DEIGEN_MPL2_ONLY)
  191. endif (EIGENSPARSE)
  192. endif (Eigen3_FOUND)
  193. if (USE_CUDA)
  194. if (CMAKE_VERSION VERSION_LESS 3.17)
  195. # On older versions of CMake (20.04 default is 3.16) FindCUDAToolkit was
  196. # not available, but FindCUDA was deprecated. To avoid special-case handling
  197. # elsewhere, emulate the effects of FindCUDAToolkit locally in terms of the
  198. # expected CMake imported targets and defined variables. This can be removed
  199. # from as soon as the min CMake version is >= 3.17.
  200. find_package(CUDA QUIET)
  201. if (CUDA_FOUND)
  202. message("-- Found CUDA version ${CUDA_VERSION} installed in: "
  203. "${CUDA_TOOLKIT_ROOT_DIR} via legacy (< 3.17) CMake module. "
  204. "Using the legacy CMake module means that any installation of "
  205. "Ceres will require that the CUDA libraries be installed in a "
  206. "location included in the LD_LIBRARY_PATH.")
  207. enable_language(CUDA)
  208. macro(DECLARE_IMPORTED_CUDA_TARGET COMPONENT)
  209. add_library(CUDA::${COMPONENT} INTERFACE IMPORTED)
  210. target_include_directories(
  211. CUDA::${COMPONENT} INTERFACE ${CUDA_INCLUDE_DIRS})
  212. target_link_libraries(
  213. CUDA::${COMPONENT} INTERFACE ${CUDA_${COMPONENT}_LIBRARY} ${ARGN})
  214. endmacro()
  215. declare_imported_cuda_target(cublas)
  216. declare_imported_cuda_target(cusolver)
  217. declare_imported_cuda_target(cusparse)
  218. declare_imported_cuda_target(cudart ${CUDA_LIBRARIES})
  219. set(CUDAToolkit_BIN_DIR ${CUDA_TOOLKIT_ROOT_DIR}/bin)
  220. else (CUDA_FOUND)
  221. message("-- Did not find CUDA, disabling CUDA support.")
  222. update_cache_variable(USE_CUDA OFF)
  223. endif (CUDA_FOUND)
  224. else (CMAKE_VERSION VERSION_LESS 3.17)
  225. find_package(CUDAToolkit QUIET)
  226. if (CUDAToolkit_FOUND)
  227. message("-- Found CUDA version ${CUDAToolkit_VERSION} installed in: "
  228. "${CUDAToolkit_TARGET_DIR}")
  229. set(CUDAToolkit_DEPENDENCY
  230. "find_dependency(CUDAToolkit ${CUDAToolkit_VERSION})")
  231. enable_language(CUDA)
  232. if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
  233. # Support Maxwell, Pascal, Volta, Turing, and Ampere GPUs.
  234. set(CMAKE_CUDA_ARCHITECTURES "50;60;70;80")
  235. message("-- Setting CUDA Architecture to ${CMAKE_CUDA_ARCHITECTURES}")
  236. endif()
  237. list(APPEND CERES_CUDA_LIBRARIES
  238. CUDA::cublas
  239. CUDA::cudart
  240. CUDA::cusolver
  241. CUDA::cusparse)
  242. else (CUDAToolkit_FOUND)
  243. message("-- Did not find CUDA, disabling CUDA support.")
  244. update_cache_variable(USE_CUDA OFF)
  245. endif (CUDAToolkit_FOUND)
  246. endif (CMAKE_VERSION VERSION_LESS 3.17)
  247. endif (USE_CUDA)
  248. if (NOT USE_CUDA)
  249. message("-- Building without CUDA.")
  250. list(APPEND CERES_COMPILE_OPTIONS CERES_NO_CUDA)
  251. endif (NOT USE_CUDA)
  252. if (LAPACK)
  253. find_package(LAPACK QUIET)
  254. if (LAPACK_FOUND)
  255. message("-- Found LAPACK library: ${LAPACK_LIBRARIES}")
  256. else (LAPACK_FOUND)
  257. message("-- Did not find LAPACK library, disabling LAPACK support.")
  258. update_cache_variable(LAPACK OFF)
  259. list(APPEND CERES_COMPILE_OPTIONS CERES_NO_LAPACK)
  260. endif (LAPACK_FOUND)
  261. else (LAPACK)
  262. message("-- Building without LAPACK.")
  263. list(APPEND CERES_COMPILE_OPTIONS CERES_NO_LAPACK)
  264. endif (LAPACK)
  265. # Set the install path for the installed CeresConfig.cmake configuration file
  266. # relative to CMAKE_INSTALL_PREFIX.
  267. set(RELATIVE_CMAKECONFIG_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/Ceres)
  268. if (SUITESPARSE)
  269. # By default, if SuiteSparse and all dependencies are found, Ceres is
  270. # built with SuiteSparse support.
  271. # Check for SuiteSparse and dependencies.
  272. find_package(SuiteSparse 4.5.6 COMPONENTS CHOLMOD SPQR
  273. OPTIONAL_COMPONENTS Partition)
  274. if (SuiteSparse_FOUND)
  275. set(SuiteSparse_DEPENDENCY "find_dependency(SuiteSparse ${SuiteSparse_VERSION})")
  276. # By default, if all of SuiteSparse's dependencies are found, Ceres is
  277. # built with SuiteSparse support.
  278. message("-- Found SuiteSparse ${SuiteSparse_VERSION}, "
  279. "building with SuiteSparse.")
  280. if (SuiteSparse_NO_CMAKE OR NOT SuiteSparse_DIR)
  281. install(FILES ${Ceres_SOURCE_DIR}/cmake/FindSuiteSparse.cmake
  282. ${Ceres_SOURCE_DIR}/cmake/FindMETIS.cmake
  283. DESTINATION ${RELATIVE_CMAKECONFIG_INSTALL_DIR})
  284. endif (SuiteSparse_NO_CMAKE OR NOT SuiteSparse_DIR)
  285. else (SuiteSparse_FOUND)
  286. # Disable use of SuiteSparse if it cannot be found and continue.
  287. message("-- Did not find all SuiteSparse dependencies, disabling "
  288. "SuiteSparse support.")
  289. update_cache_variable(SUITESPARSE OFF)
  290. list(APPEND CERES_COMPILE_OPTIONS CERES_NO_SUITESPARSE)
  291. endif (SuiteSparse_FOUND)
  292. else (SUITESPARSE)
  293. message("-- Building without SuiteSparse.")
  294. list(APPEND CERES_COMPILE_OPTIONS CERES_NO_SUITESPARSE)
  295. endif (SUITESPARSE)
  296. if (NOT SuiteSparse_Partition_FOUND)
  297. list (APPEND CERES_COMPILE_OPTIONS CERES_NO_CHOLMOD_PARTITION)
  298. endif (NOT SuiteSparse_Partition_FOUND)
  299. if (EIGENMETIS)
  300. find_package (METIS)
  301. if (METIS_FOUND)
  302. # Since METIS is a private dependency of Ceres, it requires access to the
  303. # link-only METIS::METIS target to avoid undefined linker errors in projects
  304. # relying on Ceres. We do not actually need to propagate anything besides
  305. # the link libraries (such as include directories.)
  306. set(METIS_DEPENDENCY "find_dependency(METIS ${METIS_VERSION})")
  307. # METIS find module must be installed unless a package config is being used.
  308. if (NOT METIS_DIR)
  309. install(FILES ${Ceres_SOURCE_DIR}/cmake/FindMETIS.cmake
  310. DESTINATION ${RELATIVE_CMAKECONFIG_INSTALL_DIR})
  311. endif (NOT METIS_DIR)
  312. else (METIS_FOUND)
  313. message("-- Did not find METIS, disabling Eigen METIS support.")
  314. update_cache_variable(EIGENMETIS OFF)
  315. list (APPEND CERES_COMPILE_OPTIONS CERES_NO_EIGEN_METIS)
  316. endif (METIS_FOUND)
  317. else (EIGENMETIS)
  318. message("-- Building without Eigen METIS support.")
  319. list (APPEND CERES_COMPILE_OPTIONS CERES_NO_EIGEN_METIS)
  320. endif (EIGENMETIS)
  321. if (ACCELERATESPARSE)
  322. find_package(AccelerateSparse)
  323. if (AccelerateSparse_FOUND)
  324. message("-- Found Apple's Accelerate framework with sparse solvers, "
  325. "building with Accelerate sparse support.")
  326. else()
  327. message("-- Failed to find Apple's Accelerate framework with sparse solvers, "
  328. "building without Accelerate sparse support.")
  329. update_cache_variable(ACCELERATESPARSE OFF)
  330. list(APPEND CERES_COMPILE_OPTIONS CERES_NO_ACCELERATE_SPARSE)
  331. endif()
  332. else()
  333. message("-- Building without Apple's Accelerate sparse support.")
  334. list(APPEND CERES_COMPILE_OPTIONS CERES_NO_ACCELERATE_SPARSE)
  335. mark_as_advanced(FORCE AccelerateSparse_INCLUDE_DIR
  336. AccelerateSparse_LIBRARY)
  337. endif()
  338. # Ensure that the user understands they have disabled all sparse libraries.
  339. if (NOT SUITESPARSE AND NOT EIGENSPARSE AND NOT ACCELERATESPARSE)
  340. message(" ===============================================================")
  341. message(" Compiling without any sparse library: SuiteSparse, ")
  342. message(" EigenSparse & Apple's Accelerate are all disabled or unavailable. ")
  343. message(" No sparse linear solvers (SPARSE_NORMAL_CHOLESKY & SPARSE_SCHUR)")
  344. message(" will be available when Ceres is used.")
  345. message(" ===============================================================")
  346. endif()
  347. # ANDROID define is set by the Android CMake toolchain file.
  348. if (ANDROID)
  349. message(" ================================================================")
  350. if (ANDROID_STRIP_DEBUG_SYMBOLS)
  351. # Strip debug information unconditionally to avoid +200MB library file sizes.
  352. set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s" )
  353. set( CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -s" )
  354. message(" Stripping debug information from Android build of Ceres library ")
  355. message(" to avoid +200MB library files.")
  356. else()
  357. message(" Warning: not stripping debug information from Android build of ")
  358. message(" Ceres library. This will result in a large (+200MB) library.")
  359. endif()
  360. message("")
  361. message(" You can control whether debug information is stripped via the ")
  362. message(" ANDROID_STRIP_DEBUG_SYMBOLS CMake option when configuring Ceres.")
  363. message(" ================================================================")
  364. endif()
  365. # GFlags.
  366. if (GFLAGS)
  367. # Don't search with REQUIRED as we can continue without gflags.
  368. find_package(gflags 2.2.0)
  369. if (gflags_FOUND)
  370. if (TARGET gflags)
  371. message("-- Found Google Flags (gflags) version ${gflags_VERSION}: ${gflags_DIR}")
  372. else()
  373. message("-- Detected version of gflags: ${gflags_VERSION} does not define "
  374. "expected gflags CMake target which should be exported by gflags 2.2+. "
  375. "Building without gflags.")
  376. update_cache_variable(GFLAGS OFF)
  377. endif()
  378. else (gflags_FOUND)
  379. message("-- Did not find Google Flags (gflags), Building without gflags.")
  380. update_cache_variable(GFLAGS OFF)
  381. endif (gflags_FOUND)
  382. endif()
  383. if (NOT GFLAGS)
  384. message("-- Use of gflags disabled - no tests or tools will be built!")
  385. endif()
  386. # MiniGLog.
  387. if (MINIGLOG)
  388. message("-- Compiling minimal glog substitute into Ceres.")
  389. set(GLOG_INCLUDE_DIRS internal/ceres/miniglog)
  390. set(MINIGLOG_MAX_LOG_LEVEL 2 CACHE STRING "The maximum message severity level to be logged")
  391. add_definitions("-DMAX_LOG_LEVEL=${MINIGLOG_MAX_LOG_LEVEL}")
  392. message("-- Using minimal glog substitute (include): ${GLOG_INCLUDE_DIRS}")
  393. message("-- Max log level for minimal glog substitute: ${MINIGLOG_MAX_LOG_LEVEL}")
  394. # Mark as advanced (remove from default GUI view) the glog search
  395. # variables in case user disables MINIGLOG, FindGlog did not find it, so
  396. # made search variables visible in GUI for user to set, but then user enables
  397. # MINIGLOG instead of setting them.
  398. mark_as_advanced(FORCE GLOG_INCLUDE_DIR
  399. GLOG_LIBRARY)
  400. else (MINIGLOG)
  401. unset(MINIGLOG_MAX_LOG_LEVEL CACHE)
  402. # Don't search with REQUIRED so that configuration continues if not found and
  403. # we can output an error messages explaining MINIGLOG option.
  404. find_package(Glog)
  405. if (NOT GLOG_FOUND)
  406. message(FATAL_ERROR "Can't find Google Log (glog). Please set either: "
  407. "glog_DIR (newer CMake built versions of glog) or GLOG_INCLUDE_DIR & "
  408. "GLOG_LIBRARY or enable MINIGLOG option to use minimal glog "
  409. "implementation.")
  410. endif(NOT GLOG_FOUND)
  411. # By default, assume gflags was found, updating the message if it was not.
  412. set(GLOG_GFLAGS_DEPENDENCY_MESSAGE
  413. " Assuming glog was built with gflags support as gflags was found. "
  414. "This will make gflags a public dependency of Ceres.")
  415. if (NOT gflags_FOUND)
  416. set(GLOG_GFLAGS_DEPENDENCY_MESSAGE
  417. " Assuming glog was NOT built with gflags support as gflags was "
  418. "not found. If glog was built with gflags, please set the "
  419. "gflags search locations such that it can be found by Ceres. "
  420. "Otherwise, Ceres may fail to link due to missing gflags symbols.")
  421. endif(NOT gflags_FOUND)
  422. message("-- Found Google Log (glog)." ${GLOG_GFLAGS_DEPENDENCY_MESSAGE})
  423. endif (MINIGLOG)
  424. if (NOT SCHUR_SPECIALIZATIONS)
  425. list(APPEND CERES_COMPILE_OPTIONS CERES_RESTRICT_SCHUR_SPECIALIZATION)
  426. message("-- Disabling Schur specializations (faster compiles)")
  427. endif (NOT SCHUR_SPECIALIZATIONS)
  428. if (NOT CUSTOM_BLAS)
  429. list(APPEND CERES_COMPILE_OPTIONS CERES_NO_CUSTOM_BLAS)
  430. message("-- Disabling custom blas")
  431. endif (NOT CUSTOM_BLAS)
  432. if (BUILD_BENCHMARKS)
  433. # Version 1.3 was first to provide import targets
  434. find_package(benchmark 1.3 QUIET)
  435. if (benchmark_FOUND)
  436. message("-- Found Google benchmark library. Building Ceres benchmarks.")
  437. else()
  438. message("-- Failed to find Google benchmark library, disabling build of benchmarks.")
  439. update_cache_variable(BUILD_BENCHMARKS OFF)
  440. endif()
  441. mark_as_advanced(benchmark_DIR)
  442. endif()
  443. # TODO Report features using the FeatureSummary CMake module
  444. if (BUILD_SHARED_LIBS)
  445. message("-- Building Ceres as a shared library.")
  446. else (BUILD_SHARED_LIBS)
  447. message("-- Building Ceres as a static library.")
  448. endif (BUILD_SHARED_LIBS)
  449. # Change the default build type from Debug to Release, while still
  450. # supporting overriding the build type.
  451. #
  452. # The CACHE STRING logic here and elsewhere is needed to force CMake
  453. # to pay attention to the value of these variables.
  454. if (NOT CMAKE_BUILD_TYPE)
  455. message("-- No build type specified; defaulting to CMAKE_BUILD_TYPE=Release.")
  456. set(CMAKE_BUILD_TYPE Release CACHE STRING
  457. "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
  458. FORCE)
  459. else (NOT CMAKE_BUILD_TYPE)
  460. if (CMAKE_BUILD_TYPE STREQUAL "Debug")
  461. message("\n=================================================================================")
  462. message("\n-- Build type: Debug. Performance will be terrible!")
  463. message("-- Add -DCMAKE_BUILD_TYPE=Release to the CMake command line to get an optimized build.")
  464. message("\n=================================================================================")
  465. endif (CMAKE_BUILD_TYPE STREQUAL "Debug")
  466. endif (NOT CMAKE_BUILD_TYPE)
  467. if (MINGW)
  468. # MinGW produces code that segfaults when performing matrix multiplications
  469. # in Eigen when compiled with -O3 (see [1]), as such force the use of -O2
  470. # which works.
  471. #
  472. # [1] http://eigen.tuxfamily.org/bz/show_bug.cgi?id=556
  473. message("-- MinGW detected, forcing -O2 instead of -O3 in Release for Eigen due "
  474. "to a MinGW bug: http://eigen.tuxfamily.org/bz/show_bug.cgi?id=556")
  475. string(REPLACE "-O3" "-O2" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
  476. update_cache_variable(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
  477. endif (MINGW)
  478. # After the tweaks for the compile settings, disable some warnings on MSVC.
  479. if (MSVC)
  480. # On MSVC, math constants are not included in <cmath> or <math.h> unless
  481. # _USE_MATH_DEFINES is defined [1]. As we use M_PI in the examples, ensure
  482. # that _USE_MATH_DEFINES is defined before the first inclusion of <cmath>.
  483. #
  484. # [1] https://msdn.microsoft.com/en-us/library/4hwaceh6.aspx
  485. add_definitions("-D_USE_MATH_DEFINES")
  486. # Disable signed/unsigned int conversion warnings.
  487. add_compile_options("/wd4018" "/wd4267")
  488. # Disable warning about using struct/class for the same symbol.
  489. add_compile_options("/wd4099")
  490. # Disable warning about the insecurity of using "std::copy".
  491. add_compile_options("/wd4996")
  492. # Disable performance warning about int-to-bool conversion.
  493. add_compile_options("/wd4800")
  494. # Disable performance warning about fopen insecurity.
  495. add_compile_options("/wd4996")
  496. # Disable warning about int64 to int32 conversion. Disabling
  497. # this warning may not be correct; needs investigation.
  498. # TODO(keir): Investigate these warnings in more detail.
  499. add_compile_options("/wd4244")
  500. # It's not possible to use STL types in DLL interfaces in a portable and
  501. # reliable way. However, that's what happens with Google Log and Google Flags
  502. # on Windows. MSVC gets upset about this and throws warnings that we can't do
  503. # much about. The real solution is to link static versions of Google Log and
  504. # Google Test, but that seems tricky on Windows. So, disable the warning.
  505. add_compile_options("/wd4251")
  506. # Add bigobj flag otherwise the build would fail due to large object files
  507. # probably resulting from generated headers (like the fixed-size schur
  508. # specializations).
  509. add_compile_options("/bigobj")
  510. # Google Flags doesn't have their DLL import/export stuff set up correctly,
  511. # which results in linker warnings. This is irrelevant for Ceres, so ignore
  512. # the warnings.
  513. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ignore:4049")
  514. # Update the C/CXX flags for MSVC to use either the static or shared
  515. # C-Run Time (CRT) library based on the user option: MSVC_USE_STATIC_CRT.
  516. list(APPEND C_CXX_FLAGS
  517. CMAKE_CXX_FLAGS
  518. CMAKE_CXX_FLAGS_DEBUG
  519. CMAKE_CXX_FLAGS_RELEASE
  520. CMAKE_CXX_FLAGS_MINSIZEREL
  521. CMAKE_CXX_FLAGS_RELWITHDEBINFO)
  522. foreach(FLAG_VAR ${C_CXX_FLAGS})
  523. if (MSVC_USE_STATIC_CRT)
  524. # Use static CRT.
  525. if (${FLAG_VAR} MATCHES "/MD")
  526. string(REGEX REPLACE "/MD" "/MT" ${FLAG_VAR} "${${FLAG_VAR}}")
  527. endif (${FLAG_VAR} MATCHES "/MD")
  528. else (MSVC_USE_STATIC_CRT)
  529. # Use shared, not static, CRT.
  530. if (${FLAG_VAR} MATCHES "/MT")
  531. string(REGEX REPLACE "/MT" "/MD" ${FLAG_VAR} "${${FLAG_VAR}}")
  532. endif (${FLAG_VAR} MATCHES "/MT")
  533. endif (MSVC_USE_STATIC_CRT)
  534. endforeach()
  535. # Tuple sizes of 10 are used by Gtest.
  536. add_definitions("-D_VARIADIC_MAX=10")
  537. include(CheckIfUnderscorePrefixedBesselFunctionsExist)
  538. check_if_underscore_prefixed_bessel_functions_exist(
  539. HAVE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
  540. if (HAVE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
  541. list(APPEND CERES_COMPILE_OPTIONS
  542. CERES_MSVC_USE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
  543. endif()
  544. endif (MSVC)
  545. if (UNIX)
  546. # Flags which we add to GCC to make it more picky about stuff
  547. # we do care about,
  548. add_cxx_compiler_flag_if_supported(CERES_STRICT_CXX_FLAGS
  549. -Wmissing-declarations)
  550. # Flags which we add to GCC to silence lots of annoying false-positives.
  551. add_cxx_compiler_flag_if_supported(CERES_STRICT_CXX_FLAGS
  552. -Wno-unknown-pragmas)
  553. add_cxx_compiler_flag_if_supported(CERES_STRICT_CXX_FLAGS
  554. -Wno-sign-compare)
  555. add_cxx_compiler_flag_if_supported(CERES_STRICT_CXX_FLAGS
  556. -Wno-unused-parameter)
  557. add_cxx_compiler_flag_if_supported(CERES_STRICT_CXX_FLAGS
  558. -Wno-missing-field-initializers)
  559. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CERES_STRICT_CXX_FLAGS}")
  560. endif (UNIX)
  561. if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") # Matches Clang & AppleClang.
  562. # Optimize for Eigen OR enable bitcode; you cannot do both since bitcode is an
  563. # intermediate representation.
  564. if (ENABLE_BITCODE)
  565. set(CMAKE_CXX_FLAGS
  566. "${CMAKE_CXX_FLAGS} -fembed-bitcode")
  567. else ()
  568. # Use a larger inlining threshold for Clang, since it hobbles Eigen,
  569. # resulting in an unreasonably slow version of the blas routines. The
  570. # -Qunused-arguments is needed because CMake passes the inline
  571. # threshold to the linker and clang complains about it and dies.
  572. set(CMAKE_CXX_FLAGS
  573. "${CMAKE_CXX_FLAGS} -Qunused-arguments -mllvm -inline-threshold=600")
  574. endif ()
  575. # Older versions of Clang (<= 2.9) do not support the 'return-type-c-linkage'
  576. # option, so check for its presence before adding it to the default flags set.
  577. check_cxx_compiler_flag("-Wno-return-type-c-linkage"
  578. HAVE_RETURN_TYPE_C_LINKAGE)
  579. if (HAVE_RETURN_TYPE_C_LINKAGE)
  580. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type-c-linkage")
  581. endif(HAVE_RETURN_TYPE_C_LINKAGE)
  582. endif ()
  583. if (CMAKE_VERSION VERSION_LESS 3.12)
  584. # Disable the definition of min/max macros within the project
  585. if (WIN32)
  586. add_definitions (-DNOMINMAX)
  587. endif (WIN32)
  588. else (CMAKE_VERSION VERSION_LESS 3.12)
  589. add_compile_definitions($<$<BOOL:${WIN32}>:NOMINMAX>)
  590. endif (CMAKE_VERSION VERSION_LESS 3.12)
  591. # Configure the Ceres config.h compile options header using the current
  592. # compile options and put the configured header into the Ceres build
  593. # directory. Note that the ceres/internal subdir in <build>/config where
  594. # the configured config.h is placed is important, because Ceres will be
  595. # built against this configured header, it needs to have the same relative
  596. # include path as it would if it were in the source tree (or installed).
  597. list(REMOVE_DUPLICATES CERES_COMPILE_OPTIONS)
  598. include(CreateCeresConfig)
  599. create_ceres_config("${CERES_COMPILE_OPTIONS}"
  600. ${Ceres_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR}/ceres/internal)
  601. add_subdirectory(internal/ceres)
  602. if (BUILD_DOCUMENTATION)
  603. find_package(Sphinx)
  604. if (NOT SPHINX_FOUND)
  605. message("-- Failed to find Sphinx and/or its dependencies, disabling build of documentation.")
  606. update_cache_variable(BUILD_DOCUMENTATION OFF)
  607. else()
  608. # Generate the User's Guide (html).
  609. # The corresponding target is ceres_docs, but is included in ALL.
  610. message("-- Build the HTML documentation.")
  611. add_subdirectory(docs)
  612. endif()
  613. endif (BUILD_DOCUMENTATION)
  614. if (BUILD_EXAMPLES)
  615. message("-- Build the examples.")
  616. add_subdirectory(examples)
  617. else (BUILD_EXAMPLES)
  618. message("-- Do not build any example.")
  619. endif (BUILD_EXAMPLES)
  620. # Setup installation of Ceres public headers.
  621. file(GLOB CERES_HDRS ${Ceres_SOURCE_DIR}/include/ceres/*.h)
  622. install(FILES ${CERES_HDRS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ceres)
  623. file(GLOB CERES_PUBLIC_INTERNAL_HDRS ${Ceres_SOURCE_DIR}/include/ceres/internal/*.h)
  624. install(FILES ${CERES_PUBLIC_INTERNAL_HDRS} DESTINATION
  625. ${CMAKE_INSTALL_INCLUDEDIR}/ceres/internal)
  626. # Also setup installation of Ceres config.h configured with the current
  627. # build options and export.h into the installed headers directory.
  628. install(DIRECTORY ${Ceres_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR}/
  629. DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
  630. if (MINIGLOG)
  631. # Install miniglog header if being used as logging #includes appear in
  632. # installed public Ceres headers.
  633. install(FILES ${Ceres_SOURCE_DIR}/internal/ceres/miniglog/glog/logging.h
  634. DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ceres/internal/miniglog/glog)
  635. endif (MINIGLOG)
  636. # Ceres supports two mechanisms by which it can be detected & imported into
  637. # client code which uses CMake via find_package(Ceres):
  638. #
  639. # 1) Installation (e.g. to /usr/local), using CMake's install() function.
  640. #
  641. # 2) (Optional) Export of the current build directory into the local CMake
  642. # package registry, using CMake's export() function. This allows use of
  643. # Ceres from other projects without requiring installation.
  644. #
  645. # In both cases, we need to generate a configured CeresConfig.cmake which
  646. # includes additional autogenerated files which in concert create an imported
  647. # target for Ceres in a client project when find_package(Ceres) is invoked.
  648. # The key distinctions are where this file is located, and whether client code
  649. # references installed copies of the compiled Ceres headers/libraries,
  650. # (option #1: installation), or the originals in the source/build directories
  651. # (option #2: export of build directory).
  652. #
  653. # NOTE: If Ceres is both exported and installed, provided that the installation
  654. # path is present in CMAKE_MODULE_PATH when find_package(Ceres) is called,
  655. # the installed version is preferred.
  656. # Build the list of Ceres components for CeresConfig.cmake from the current set
  657. # of compile options.
  658. include(CeresCompileOptionsToComponents)
  659. ceres_compile_options_to_components("${CERES_COMPILE_OPTIONS}"
  660. CERES_COMPILED_COMPONENTS)
  661. include(CMakePackageConfigHelpers)
  662. # Create a CeresConfigVersion.cmake file containing the version information,
  663. # used by both export() & install().
  664. write_basic_package_version_file("${Ceres_BINARY_DIR}/CeresConfigVersion.cmake"
  665. VERSION ${CERES_VERSION}
  666. COMPATIBILITY SameMajorVersion)
  667. # Install method #1: Put Ceres in CMAKE_INSTALL_PREFIX: /usr/local or equivalent.
  668. # This "exports" for installation all targets which have been put into the
  669. # export set "CeresExport". This generates a CeresTargets.cmake file which,
  670. # when read in by a client project as part of find_package(Ceres) creates
  671. # imported library targets for Ceres (with dependency relations) which can be
  672. # used in target_link_libraries() calls in the client project to use Ceres.
  673. install(EXPORT CeresExport
  674. NAMESPACE Ceres::
  675. DESTINATION ${RELATIVE_CMAKECONFIG_INSTALL_DIR} FILE CeresTargets.cmake)
  676. # Save the relative path from the installed CeresConfig.cmake file to the
  677. # install prefix. We do not save an absolute path in case the installed package
  678. # is subsequently relocated after installation (on Windows).
  679. file(RELATIVE_PATH INSTALL_ROOT_REL_CONFIG_INSTALL_DIR
  680. ${CMAKE_INSTALL_PREFIX}/${RELATIVE_CMAKECONFIG_INSTALL_DIR}
  681. ${CMAKE_INSTALL_PREFIX})
  682. # Configure a CeresConfig.cmake file for an installed version of Ceres from the
  683. # template, reflecting the current build options.
  684. #
  685. # NOTE: The -install suffix is necessary to distinguish the install version from
  686. # the exported version, which must be named CeresConfig.cmake in
  687. # Ceres_BINARY_DIR to be detected. The suffix is removed when
  688. # it is installed.
  689. set(SETUP_CERES_CONFIG_FOR_INSTALLATION TRUE)
  690. configure_file("${Ceres_SOURCE_DIR}/cmake/CeresConfig.cmake.in"
  691. "${Ceres_BINARY_DIR}/CeresConfig-install.cmake" @ONLY)
  692. # Install the configuration files into the same directory as the autogenerated
  693. # CeresTargets.cmake file. We include the find_package() scripts for libraries
  694. # whose headers are included in the public API of Ceres and should thus be
  695. # present in CERES_INCLUDE_DIRS.
  696. install(FILES "${Ceres_BINARY_DIR}/CeresConfig-install.cmake"
  697. RENAME CeresConfig.cmake
  698. DESTINATION ${RELATIVE_CMAKECONFIG_INSTALL_DIR})
  699. install(FILES "${Ceres_BINARY_DIR}/CeresConfigVersion.cmake"
  700. DESTINATION ${RELATIVE_CMAKECONFIG_INSTALL_DIR})
  701. if (GLOG_FOUND AND NOT FOUND_INSTALLED_GLOG_CMAKE_CONFIGURATION)
  702. # Version of glog detected was not built with CMake, install our glog module
  703. # file to enable detection in CeresConfig.
  704. install(FILES "${Ceres_SOURCE_DIR}/cmake/FindGlog.cmake"
  705. DESTINATION ${RELATIVE_CMAKECONFIG_INSTALL_DIR})
  706. endif()
  707. if (PROVIDE_UNINSTALL_TARGET)
  708. # Create an uninstall target to remove all installed files.
  709. configure_file("${Ceres_SOURCE_DIR}/cmake/uninstall.cmake.in"
  710. "${Ceres_BINARY_DIR}/cmake/uninstall.cmake"
  711. @ONLY)
  712. add_custom_target(uninstall
  713. COMMAND ${CMAKE_COMMAND} -P ${Ceres_BINARY_DIR}/cmake/uninstall.cmake)
  714. endif()
  715. # Install method #2: Put Ceres build into local CMake registry.
  716. #
  717. # Optionally export the Ceres build directory into the local CMake package
  718. # registry (~/.cmake/packages on *nix & OS X). This allows the detection &
  719. # use of Ceres without requiring that it be installed.
  720. if (EXPORT_BUILD_DIR)
  721. message("-- Export Ceres build directory to local CMake package registry.")
  722. # Save the relative path from the build directory to the source directory.
  723. file(RELATIVE_PATH INSTALL_ROOT_REL_CONFIG_INSTALL_DIR
  724. ${Ceres_BINARY_DIR}
  725. ${Ceres_SOURCE_DIR})
  726. # Analogously to install(EXPORT ...), export the Ceres target from the build
  727. # directory as a package called Ceres into the local CMake package registry.
  728. export(TARGETS ceres
  729. NAMESPACE Ceres::
  730. FILE ${Ceres_BINARY_DIR}/CeresTargets.cmake)
  731. export(PACKAGE ${CMAKE_PROJECT_NAME})
  732. # Configure a CeresConfig.cmake file for the export of the Ceres build
  733. # directory from the template, reflecting the current build options.
  734. set(SETUP_CERES_CONFIG_FOR_INSTALLATION FALSE)
  735. configure_file("${Ceres_SOURCE_DIR}/cmake/CeresConfig.cmake.in"
  736. "${Ceres_BINARY_DIR}/CeresConfig.cmake" @ONLY)
  737. endif (EXPORT_BUILD_DIR)