blob: e37384db38ab2fdedc664833001e43119ba48825 [file] [log] [blame]
Austin Schuh70cc9552019-01-21 19:46:48 -08001# Ceres Solver - A fast non-linear least squares minimizer
2# Copyright 2015 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
32cmake_minimum_required(VERSION 3.5)
33cmake_policy(VERSION 3.5)
34
35# Set the C++ version (must be >= C++11) when compiling Ceres.
36#
37# Reflect a user-specified (via -D) CMAKE_CXX_STANDARD if present, otherwise
38# default to C++11.
39set(DEFAULT_CXX_STANDARD ${CMAKE_CXX_STANDARD})
40if (NOT DEFAULT_CXX_STANDARD)
41 set(DEFAULT_CXX_STANDARD 11)
42endif()
43set(CMAKE_CXX_STANDARD ${DEFAULT_CXX_STANDARD} CACHE STRING
44 "C++ standard (minimum 11)" FORCE)
45# Restrict CMAKE_CXX_STANDARD to the valid versions permitted and ensure that
46# if one was forced via -D that it is in the valid set.
47set(ALLOWED_CXX_STANDARDS 11 14 17)
48set_property(CACHE CMAKE_CXX_STANDARD PROPERTY STRINGS ${ALLOWED_CXX_STANDARDS})
49list(FIND ALLOWED_CXX_STANDARDS ${CMAKE_CXX_STANDARD} POSITION)
50if (POSITION LESS 0)
51 message(FATAL_ERROR "Invalid CMAKE_CXX_STANDARD: ${CMAKE_CXX_STANDARD}. "
52 "Must be one of: ${ALLOWED_CXX_STANDARDS}")
53endif()
54# Specify the standard as a hard requirement, otherwise CMAKE_CXX_STANDARD is
55# interpreted as a suggestion that can decay *back* to lower versions.
56set(CMAKE_CXX_STANDARD_REQUIRED ON CACHE BOOL "")
57mark_as_advanced(CMAKE_CXX_STANDARD_REQUIRED)
58
59# MSVC versions < 2013 did not fully support >= C++11.
60if (MSVC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0)
61 message(FATAL_ERROR "Invalid CMAKE_CXX_COMPILER_VERSION: "
62 "${CMAKE_CXX_COMPILER_VERSION}. Ceres requires at least MSVC 2013 Update 4+")
63endif()
64
65project(Ceres C CXX)
66
67# NOTE: The 'generic' CMake variables CMAKE_[SOURCE/BINARY]_DIR should not be
68# used. Always use the project-specific variants (generated by CMake):
69# <PROJECT_NAME_MATCHING_CASE>_[SOURCE/BINARY]_DIR, e.g.
70# Ceres_SOURCE_DIR (note, *not* CERES_SOURCE_DIR) instead, as these will
71# always point to the correct directories for the Ceres project, even if
72# it is nested inside another source tree, whereas the 'generic'
73# CMake variables refer to the *first* project() declaration, i.e. the
74# top-level project, not Ceres, if Ceres is nested.
75
76# Make CMake aware of the cmake folder for local FindXXX scripts,
77# append rather than set in case the user has passed their own
78# additional paths via -D.
79list(APPEND CMAKE_MODULE_PATH "${Ceres_SOURCE_DIR}/cmake")
80include(UpdateCacheVariable)
81
82# Set up the git hook to make Gerrit Change-Id: lines in commit messages.
83include(AddGerritCommitHook)
84add_gerrit_commit_hook(${Ceres_SOURCE_DIR} ${Ceres_BINARY_DIR})
85
86# On OS X, add the Homebrew prefix to the set of prefixes searched by
87# CMake in find_path & find_library. This should ensure that we can
88# still build Ceres even if Homebrew is installed in a non-standard
89# location (not /usr/local).
90if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
91 find_program(HOMEBREW_EXECUTABLE brew)
92 mark_as_advanced(FORCE HOMEBREW_EXECUTABLE)
93 if (HOMEBREW_EXECUTABLE)
94 # Detected a Homebrew install, query for its install prefix.
95 execute_process(COMMAND ${HOMEBREW_EXECUTABLE} --prefix
96 OUTPUT_VARIABLE HOMEBREW_INSTALL_PREFIX
97 OUTPUT_STRIP_TRAILING_WHITESPACE)
98 message(STATUS "Detected Homebrew with install prefix: "
99 "${HOMEBREW_INSTALL_PREFIX}, adding to CMake search paths.")
100 list(APPEND CMAKE_PREFIX_PATH "${HOMEBREW_INSTALL_PREFIX}")
101 endif()
102endif()
103
104set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${Ceres_BINARY_DIR}/bin)
105set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${Ceres_BINARY_DIR}/lib)
106set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${Ceres_BINARY_DIR}/lib)
107# Set postfixes for generated libraries based on buildtype.
108set(CMAKE_RELEASE_POSTFIX "")
109set(CMAKE_DEBUG_POSTFIX "-debug")
110
111# Read the Ceres version from the source, such that we only ever have a single
112# definition of the Ceres version.
113include(ReadCeresVersionFromSource)
114read_ceres_version_from_source(${Ceres_SOURCE_DIR})
115
116enable_testing()
117
118include(CeresThreadingModels)
119include(PrettyPrintCMakeList)
120find_available_ceres_threading_models(CERES_THREADING_MODELS_AVAILABLE)
121pretty_print_cmake_list(PRETTY_CERES_THREADING_MODELS_AVAILABLE
122 ${CERES_THREADING_MODELS_AVAILABLE})
123message("-- Detected available Ceres threading models: "
124 "${PRETTY_CERES_THREADING_MODELS_AVAILABLE}")
125set(CERES_THREADING_MODEL "${CERES_THREADING_MODEL}" CACHE STRING
126 "Ceres threading back-end" FORCE)
127if (NOT CERES_THREADING_MODEL)
128 list(GET CERES_THREADING_MODELS_AVAILABLE 0 DEFAULT_THREADING_MODEL)
129 update_cache_variable(CERES_THREADING_MODEL ${DEFAULT_THREADING_MODEL})
130endif()
131set_property(CACHE CERES_THREADING_MODEL PROPERTY STRINGS
132 ${CERES_THREADING_MODELS_AVAILABLE})
133
134option(MINIGLOG "Use a stripped down version of glog." OFF)
135option(GFLAGS "Enable Google Flags." ON)
136option(SUITESPARSE "Enable SuiteSparse." ON)
137option(CXSPARSE "Enable CXSparse." ON)
138if (APPLE)
139 option(ACCELERATESPARSE
140 "Enable use of sparse solvers in Apple's Accelerate framework." ON)
141endif()
142option(LAPACK "Enable use of LAPACK directly within Ceres." ON)
143# Template specializations for the Schur complement based solvers. If
144# compile time, binary size or compiler performance is an issue, you
145# may consider disabling this.
146option(SCHUR_SPECIALIZATIONS "Enable fixed-size schur specializations." ON)
147option(CUSTOM_BLAS
148 "Use handcoded BLAS routines (usually faster) instead of Eigen."
149 ON)
150# Enable the use of Eigen as a sparse linear algebra library for
151# solving the nonlinear least squares problems.
152option(EIGENSPARSE "Enable Eigen as a sparse linear algebra library." ON)
153option(EXPORT_BUILD_DIR
154 "Export build directory using CMake (enables external use without install)." OFF)
155option(BUILD_TESTING "Enable tests" ON)
156option(BUILD_DOCUMENTATION "Build User's Guide (html)" OFF)
157option(BUILD_EXAMPLES "Build examples" ON)
158option(BUILD_BENCHMARKS "Build Ceres benchmarking suite" ON)
159option(BUILD_SHARED_LIBS "Build Ceres as a shared library." OFF)
160if (ANDROID)
161 option(ANDROID_STRIP_DEBUG_SYMBOLS "Strip debug symbols from Android builds (reduces file sizes)" ON)
162endif()
163if (MSVC)
164 option(MSVC_USE_STATIC_CRT
165 "MS Visual Studio: Use static C-Run Time Library in place of shared." OFF)
166
167 if (BUILD_TESTING AND BUILD_SHARED_LIBS)
168 message(
169 "-- Disabling tests. The flags BUILD_TESTING and BUILD_SHARED_LIBS"
170 " are incompatible with MSVC.")
171 update_cache_variable(BUILD_TESTING OFF)
172 endif (BUILD_TESTING AND BUILD_SHARED_LIBS)
173endif (MSVC)
174# Allow user to specify a suffix for the library install directory, the only
175# really sensible option (other than "") being "64", such that:
176# ${CMAKE_INSTALL_PREFIX}/lib -> ${CMAKE_INSTALL_PREFIX}/lib64.
177#
178# Heuristic for determining LIB_SUFFIX. FHS recommends that 64-bit systems
179# install native libraries to lib64 rather than lib. Most distros seem to
180# follow this convention with a couple notable exceptions (Debian-based and
181# Arch-based distros) which we try to detect here.
182if (CMAKE_SYSTEM_NAME MATCHES "Linux" AND
183 NOT DEFINED LIB_SUFFIX AND
184 NOT CMAKE_CROSSCOMPILING AND
185 CMAKE_SIZEOF_VOID_P EQUAL "8" AND
186 NOT EXISTS "/etc/debian_version" AND
187 NOT EXISTS "/etc/arch-release")
188 message("-- Detected non-Debian/Arch-based 64-bit Linux distribution. "
189 "Defaulting to library install directory: lib${LIB_SUFFIX}. You can "
190 "override this by specifying LIB_SUFFIX.")
191 set(LIB_SUFFIX "64")
192endif ()
193# Only create the cache variable (for the CMake GUI) after attempting to detect
194# the suffix *if not specified by the user* (NOT DEFINED LIB_SUFFIX in if())
195# s/t the user could override our autodetected suffix with "" if desired.
196set(LIB_SUFFIX "${LIB_SUFFIX}" CACHE STRING
197 "Suffix of library install directory (to support lib/lib64)." FORCE)
198
199# IOS is defined iff using the iOS.cmake CMake toolchain to build a static
200# library for iOS.
201if (IOS)
202 message(STATUS "Building Ceres for iOS platform: ${IOS_PLATFORM}")
203
204 # Ceres requires at least iOS 7.0+.
205 if (IOS_DEPLOYMENT_TARGET VERSION_LESS 7.0)
206 message(FATAL_ERROR "Unsupported iOS version: ${IOS_DEPLOYMENT_TARGET}, Ceres "
207 "requires at least iOS version 7.0")
208 endif()
209
210 update_cache_variable(MINIGLOG ON)
211 message(STATUS "Building for iOS: Forcing use of miniglog instead of glog.")
212
213 # Apple claims that the BLAS call dsyrk_ is a private API, and will not allow
214 # you to submit to the Apple Store if the symbol is present.
215 update_cache_variable(LAPACK OFF)
216 message(STATUS "Building for iOS: SuiteSparse, CXSparse, LAPACK, gflags, "
217 "and OpenMP are not available.")
218
219 update_cache_variable(BUILD_EXAMPLES OFF)
220 message(STATUS "Building for iOS: Will not build examples.")
221endif (IOS)
222
223unset(CERES_COMPILE_OPTIONS)
224message("-- Building with C++${CMAKE_CXX_STANDARD}")
225
226# Eigen.
227find_package(Eigen REQUIRED)
228if (EIGEN_FOUND)
229 message("-- Found Eigen version ${EIGEN_VERSION}: ${EIGEN_INCLUDE_DIRS}")
230 if (EIGEN_VERSION VERSION_LESS 3.1.0)
231 message(FATAL_ERROR "-- Ceres requires Eigen version >= 3.1.0 in order "
232 "that Eigen/SparseCore be available, detected version of Eigen is: "
233 "${EIGEN_VERSION}")
234 endif (EIGEN_VERSION VERSION_LESS 3.1.0)
235
236 if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*)" AND
237 EIGEN_VERSION VERSION_LESS 3.3.4)
238 # As per issue #289: https://github.com/ceres-solver/ceres-solver/issues/289
239 # the bundle_adjustment_test will fail for Eigen < 3.3.4 on aarch64.
240 message(FATAL_ERROR "-- Ceres requires Eigen version >= 3.3.4 on aarch64. "
241 "Detected version of Eigen is: ${EIGEN_VERSION}.")
242 endif()
243
244 if (EIGENSPARSE)
245 message("-- Enabling use of Eigen as a sparse linear algebra library.")
246 list(APPEND CERES_COMPILE_OPTIONS CERES_USE_EIGEN_SPARSE)
247 if (EIGEN_VERSION VERSION_LESS 3.2.2)
248 message(" WARNING:")
249 message("")
250 message(" Your version of Eigen (${EIGEN_VERSION}) is older than ")
251 message(" version 3.2.2. The performance of SPARSE_NORMAL_CHOLESKY ")
252 message(" and SPARSE_SCHUR linear solvers will suffer.")
253 endif (EIGEN_VERSION VERSION_LESS 3.2.2)
254 else (EIGENSPARSE)
255 message("-- Disabling use of Eigen as a sparse linear algebra library.")
256 message(" This does not affect the covariance estimation algorithm ")
257 message(" which can still use the EIGEN_SPARSE_QR algorithm.")
258 add_definitions(-DEIGEN_MPL2_ONLY)
259 endif (EIGENSPARSE)
260endif (EIGEN_FOUND)
261
262if (LAPACK)
263 find_package(LAPACK QUIET)
264 if (LAPACK_FOUND)
265 message("-- Found LAPACK library: ${LAPACK_LIBRARIES}")
266 else (LAPACK_FOUND)
267 message("-- Did not find LAPACK library, disabling LAPACK support.")
268 update_cache_variable(LAPACK OFF)
269 list(APPEND CERES_COMPILE_OPTIONS CERES_NO_LAPACK)
270 endif (LAPACK_FOUND)
271else (LAPACK)
272 message("-- Building without LAPACK.")
273 list(APPEND CERES_COMPILE_OPTIONS CERES_NO_LAPACK)
274endif (LAPACK)
275
276if (SUITESPARSE)
277 # By default, if SuiteSparse and all dependencies are found, Ceres is
278 # built with SuiteSparse support.
279
280 # Check for SuiteSparse and dependencies.
281 find_package(SuiteSparse)
282 if (SUITESPARSE_FOUND)
283 # On Ubuntu the system install of SuiteSparse (v3.4.0) up to at least
284 # Ubuntu 13.10 cannot be used to link shared libraries.
285 if (BUILD_SHARED_LIBS AND
286 SUITESPARSE_IS_BROKEN_SHARED_LINKING_UBUNTU_SYSTEM_VERSION)
287 message(FATAL_ERROR "You are attempting to build Ceres as a shared "
288 "library on Ubuntu using a system package install of SuiteSparse "
289 "3.4.0. This package is broken and does not support the "
290 "construction of shared libraries (you can still build Ceres as "
291 "a static library). If you wish to build a shared version of Ceres "
292 "you should uninstall the system install of SuiteSparse "
293 "(libsuitesparse-dev) and perform a source install of SuiteSparse "
294 "(we recommend that you use the latest version), "
295 "see http://ceres-solver.org/building.html for more information.")
296 endif (BUILD_SHARED_LIBS AND
297 SUITESPARSE_IS_BROKEN_SHARED_LINKING_UBUNTU_SYSTEM_VERSION)
298
299 # By default, if all of SuiteSparse's dependencies are found, Ceres is
300 # built with SuiteSparse support.
301 message("-- Found SuiteSparse ${SUITESPARSE_VERSION}, "
302 "building with SuiteSparse.")
303 else (SUITESPARSE_FOUND)
304 # Disable use of SuiteSparse if it cannot be found and continue.
305 message("-- Did not find all SuiteSparse dependencies, disabling "
306 "SuiteSparse support.")
307 update_cache_variable(SUITESPARSE OFF)
308 list(APPEND CERES_COMPILE_OPTIONS CERES_NO_SUITESPARSE)
309 endif (SUITESPARSE_FOUND)
310else (SUITESPARSE)
311 message("-- Building without SuiteSparse.")
312 list(APPEND CERES_COMPILE_OPTIONS CERES_NO_SUITESPARSE)
313endif (SUITESPARSE)
314
315# CXSparse.
316if (CXSPARSE)
317 # Don't search with REQUIRED as we can continue without CXSparse.
318 find_package(CXSparse)
319 if (CXSPARSE_FOUND)
320 # By default, if CXSparse and all dependencies are found, Ceres is
321 # built with CXSparse support.
322 message("-- Found CXSparse version: ${CXSPARSE_VERSION}, "
323 "building with CXSparse.")
324 else (CXSPARSE_FOUND)
325 # Disable use of CXSparse if it cannot be found and continue.
326 message("-- Did not find CXSparse, Building without CXSparse.")
327 update_cache_variable(CXSPARSE OFF)
328 list(APPEND CERES_COMPILE_OPTIONS CERES_NO_CXSPARSE)
329 endif (CXSPARSE_FOUND)
330else (CXSPARSE)
331 message("-- Building without CXSparse.")
332 list(APPEND CERES_COMPILE_OPTIONS CERES_NO_CXSPARSE)
333 # Mark as advanced (remove from default GUI view) the CXSparse search
334 # variables in case user enabled CXSPARSE, FindCXSparse did not find it, so
335 # made search variables visible in GUI for user to set, but then user disables
336 # CXSPARSE instead of setting them.
337 mark_as_advanced(FORCE CXSPARSE_INCLUDE_DIR
338 CXSPARSE_LIBRARY)
339endif (CXSPARSE)
340
341if (ACCELERATESPARSE)
342 find_package(AccelerateSparse)
343 if (AccelerateSparse_FOUND)
344 message("-- Found Apple's Accelerate framework with sparse solvers, "
345 "building with Accelerate sparse support.")
346 else()
347 message("-- Failed to find Apple's Accelerate framework with sparse solvers, "
348 "building without Accelerate sparse support.")
349 update_cache_variable(ACCELERATESPARSE OFF)
350 list(APPEND CERES_COMPILE_OPTIONS CERES_NO_ACCELERATE_SPARSE)
351 endif()
352else()
353 message("-- Building without Apple's Accelerate sparse support.")
354 list(APPEND CERES_COMPILE_OPTIONS CERES_NO_ACCELERATE_SPARSE)
355 mark_as_advanced(FORCE AccelerateSparse_INCLUDE_DIR
356 AccelerateSparse_LIBRARY)
357endif()
358
359# Ensure that the user understands they have disabled all sparse libraries.
360if (NOT SUITESPARSE AND NOT CXSPARSE AND NOT EIGENSPARSE AND NOT ACCELERATESPARSE)
361 message(" ===============================================================")
362 message(" Compiling without any sparse library: SuiteSparse, CXSparse ")
363 message(" EigenSparse & Apple's Accelerate are all disabled or unavailable. ")
364 message(" No sparse linear solvers (SPARSE_NORMAL_CHOLESKY & SPARSE_SCHUR)")
365 message(" will be available when Ceres is used.")
366 message(" ===============================================================")
367endif()
368
369# ANDROID define is set by the Android CMake toolchain file.
370if (ANDROID)
371 message(" ================================================================")
372 if (ANDROID_STRIP_DEBUG_SYMBOLS)
373 # Strip debug information unconditionally to avoid +200MB library file sizes.
374 set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s" )
375 set( CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -s" )
376 message(" Stripping debug information from Android build of Ceres library ")
377 message(" to avoid +200MB library files.")
378 else()
379 message(" Warning: not stripping debug information from Android build of ")
380 message(" Ceres library. This will result in a large (+200MB) library.")
381 endif()
382 message("")
383 message(" You can control whether debug information is stripped via the ")
384 message(" ANDROID_STRIP_DEBUG_SYMBOLS CMake option when configuring Ceres.")
385 message(" ================================================================")
386endif()
387
388# GFlags.
389if (GFLAGS)
390 # Don't search with REQUIRED as we can continue without gflags.
391 find_package(Gflags)
392 if (GFLAGS_FOUND)
393 message("-- Found Google Flags header in: ${GFLAGS_INCLUDE_DIRS}, "
394 "in namespace: ${GFLAGS_NAMESPACE}")
395 add_definitions(-DCERES_GFLAGS_NAMESPACE=${GFLAGS_NAMESPACE})
396 else (GFLAGS_FOUND)
397 message("-- Did not find Google Flags (gflags), Building without gflags "
398 "- no tests or tools will be built!")
399 update_cache_variable(GFLAGS OFF)
400 endif (GFLAGS_FOUND)
401else (GFLAGS)
402 message("-- Google Flags disabled; no tests or tools will be built!")
403 # Mark as advanced (remove from default GUI view) the gflags search
404 # variables in case user enabled GFLAGS, FindGflags did not find it, so
405 # made search variables visible in GUI for user to set, but then user disables
406 # GFLAGS instead of setting them.
407 mark_as_advanced(FORCE GFLAGS_INCLUDE_DIR
408 GFLAGS_LIBRARY
409 GFLAGS_NAMESPACE)
410endif (GFLAGS)
411
412# MiniGLog.
413if (MINIGLOG)
414 message("-- Compiling minimal glog substitute into Ceres.")
415 set(GLOG_INCLUDE_DIRS internal/ceres/miniglog)
416 set(MINIGLOG_MAX_LOG_LEVEL 2 CACHE STRING "The maximum message severity level to be logged")
417 add_definitions("-DMAX_LOG_LEVEL=${MINIGLOG_MAX_LOG_LEVEL}")
418 message("-- Using minimal glog substitute (include): ${GLOG_INCLUDE_DIRS}")
419 message("-- Max log level for minimal glog substitute: ${MINIGLOG_MAX_LOG_LEVEL}")
420
421 # Mark as advanced (remove from default GUI view) the glog search
422 # variables in case user disables MINIGLOG, FindGlog did not find it, so
423 # made search variables visible in GUI for user to set, but then user enables
424 # MINIGLOG instead of setting them.
425 mark_as_advanced(FORCE GLOG_INCLUDE_DIR
426 GLOG_LIBRARY)
427else (MINIGLOG)
428 unset(MINIGLOG_MAX_LOG_LEVEL CACHE)
429 # Don't search with REQUIRED so that configuration continues if not found and
430 # we can output an error messages explaining MINIGLOG option.
431 find_package(Glog)
432 if (NOT GLOG_FOUND)
433 message(FATAL_ERROR "Can't find Google Log (glog). Please set either: "
434 "glog_DIR (newer CMake built versions of glog) or GLOG_INCLUDE_DIR & "
435 "GLOG_LIBRARY or enable MINIGLOG option to use minimal glog "
436 "implementation.")
437 endif(NOT GLOG_FOUND)
438 # By default, assume gflags was found, updating the message if it was not.
439 set(GLOG_GFLAGS_DEPENDENCY_MESSAGE
440 " Assuming glog was built with gflags support as gflags was found. "
441 "This will make gflags a public dependency of Ceres.")
442 if (NOT GFLAGS_FOUND)
443 set(GLOG_GFLAGS_DEPENDENCY_MESSAGE
444 " Assuming glog was NOT built with gflags support as gflags was "
445 "not found. If glog was built with gflags, please set the "
446 "gflags search locations such that it can be found by Ceres. "
447 "Otherwise, Ceres may fail to link due to missing gflags symbols.")
448 endif(NOT GFLAGS_FOUND)
449 message("-- Found Google Log (glog)." ${GLOG_GFLAGS_DEPENDENCY_MESSAGE})
450endif (MINIGLOG)
451
452if (NOT SCHUR_SPECIALIZATIONS)
453 list(APPEND CERES_COMPILE_OPTIONS CERES_RESTRICT_SCHUR_SPECIALIZATION)
454 message("-- Disabling Schur specializations (faster compiles)")
455endif (NOT SCHUR_SPECIALIZATIONS)
456
457if (NOT CUSTOM_BLAS)
458 list(APPEND CERES_COMPILE_OPTIONS CERES_NO_CUSTOM_BLAS)
459 message("-- Disabling custom blas")
460endif (NOT CUSTOM_BLAS)
461
462set_ceres_threading_model("${CERES_THREADING_MODEL}")
463
464if (BUILD_BENCHMARKS)
465 find_package(benchmark QUIET)
466 if (benchmark_FOUND)
467 message("-- Found Google benchmark library. Building Ceres benchmarks.")
468 else()
469 message("-- Failed to find Google benchmark library, disabling build of benchmarks.")
470 update_cache_variable(BUILD_BENCHMARKS OFF)
471 endif()
472 mark_as_advanced(benchmark_DIR)
473endif()
474
475if (BUILD_SHARED_LIBS)
476 message("-- Building Ceres as a shared library.")
477 # The CERES_BUILDING_SHARED_LIBRARY compile definition is NOT stored in
478 # CERES_COMPILE_OPTIONS as it must only be defined when Ceres is compiled
479 # not when it is used as it controls the CERES_EXPORT macro which provides
480 # dllimport/export support in MSVC.
481 add_definitions(-DCERES_BUILDING_SHARED_LIBRARY)
482 list(APPEND CERES_COMPILE_OPTIONS CERES_USING_SHARED_LIBRARY)
483else (BUILD_SHARED_LIBS)
484 message("-- Building Ceres as a static library.")
485endif (BUILD_SHARED_LIBS)
486
487# Change the default build type from Debug to Release, while still
488# supporting overriding the build type.
489#
490# The CACHE STRING logic here and elsewhere is needed to force CMake
491# to pay attention to the value of these variables.
492if (NOT CMAKE_BUILD_TYPE)
493 message("-- No build type specified; defaulting to CMAKE_BUILD_TYPE=Release.")
494 set(CMAKE_BUILD_TYPE Release CACHE STRING
495 "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
496 FORCE)
497else (NOT CMAKE_BUILD_TYPE)
498 if (CMAKE_BUILD_TYPE STREQUAL "Debug")
499 message("\n=================================================================================")
500 message("\n-- Build type: Debug. Performance will be terrible!")
501 message("-- Add -DCMAKE_BUILD_TYPE=Release to the CMake command line to get an optimized build.")
502 message("\n=================================================================================")
503 endif (CMAKE_BUILD_TYPE STREQUAL "Debug")
504endif (NOT CMAKE_BUILD_TYPE)
505
506if (MINGW)
507 # MinGW produces code that segfaults when performing matrix multiplications
508 # in Eigen when compiled with -O3 (see [1]), as such force the use of -O2
509 # which works.
510 #
511 # [1] http://eigen.tuxfamily.org/bz/show_bug.cgi?id=556
512 message("-- MinGW detected, forcing -O2 instead of -O3 in Release for Eigen due "
513 "to a MinGW bug: http://eigen.tuxfamily.org/bz/show_bug.cgi?id=556")
514 string(REPLACE "-O3" "-O2" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
515 update_cache_variable(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
516endif (MINGW)
517
518# After the tweaks for the compile settings, disable some warnings on MSVC.
519if (MSVC)
520 # On MSVC, math constants are not included in <cmath> or <math.h> unless
521 # _USE_MATH_DEFINES is defined [1]. As we use M_PI in the examples, ensure
522 # that _USE_MATH_DEFINES is defined before the first inclusion of <cmath>.
523 #
524 # [1] https://msdn.microsoft.com/en-us/library/4hwaceh6.aspx
525 add_definitions("-D_USE_MATH_DEFINES")
526 # Disable signed/unsigned int conversion warnings.
527 add_definitions("/wd4018")
528 # Disable warning about using struct/class for the same symobl.
529 add_definitions("/wd4099")
530 # Disable warning about the insecurity of using "std::copy".
531 add_definitions("/wd4996")
532 # Disable performance warning about int-to-bool conversion.
533 add_definitions("/wd4800")
534 # Disable performance warning about fopen insecurity.
535 add_definitions("/wd4996")
536 # Disable warning about int64 to int32 conversion. Disabling
537 # this warning may not be correct; needs investigation.
538 # TODO(keir): Investigate these warnings in more detail.
539 add_definitions("/wd4244")
540 # It's not possible to use STL types in DLL interfaces in a portable and
541 # reliable way. However, that's what happens with Google Log and Google Flags
542 # on Windows. MSVC gets upset about this and throws warnings that we can't do
543 # much about. The real solution is to link static versions of Google Log and
544 # Google Test, but that seems tricky on Windows. So, disable the warning.
545 add_definitions("/wd4251")
546
547 # Google Flags doesn't have their DLL import/export stuff set up correctly,
548 # which results in linker warnings. This is irrelevant for Ceres, so ignore
549 # the warnings.
550 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ignore:4049")
551
552 # Update the C/CXX flags for MSVC to use either the static or shared
553 # C-Run Time (CRT) library based on the user option: MSVC_USE_STATIC_CRT.
554 list(APPEND C_CXX_FLAGS
555 CMAKE_CXX_FLAGS
556 CMAKE_CXX_FLAGS_DEBUG
557 CMAKE_CXX_FLAGS_RELEASE
558 CMAKE_CXX_FLAGS_MINSIZEREL
559 CMAKE_CXX_FLAGS_RELWITHDEBINFO)
560
561 foreach(FLAG_VAR ${C_CXX_FLAGS})
562 if (MSVC_USE_STATIC_CRT)
563 # Use static CRT.
564 if (${FLAG_VAR} MATCHES "/MD")
565 string(REGEX REPLACE "/MD" "/MT" ${FLAG_VAR} "${${FLAG_VAR}}")
566 endif (${FLAG_VAR} MATCHES "/MD")
567 else (MSVC_USE_STATIC_CRT)
568 # Use shared, not static, CRT.
569 if (${FLAG_VAR} MATCHES "/MT")
570 string(REGEX REPLACE "/MT" "/MD" ${FLAG_VAR} "${${FLAG_VAR}}")
571 endif (${FLAG_VAR} MATCHES "/MT")
572 endif (MSVC_USE_STATIC_CRT)
573 endforeach()
574
575 # Tuple sizes of 10 are used by Gtest.
576 add_definitions("-D_VARIADIC_MAX=10")
577
578 include(CheckIfUnderscorePrefixedBesselFunctionsExist)
579 check_if_underscore_prefixed_bessel_functions_exist(
580 HAVE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
581 if (HAVE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
582 list(APPEND CERES_COMPILE_OPTIONS
583 CERES_MSVC_USE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
584 endif()
585endif (MSVC)
586
587if (UNIX)
588 # GCC is not strict enough by default, so enable most of the warnings.
589 set(CMAKE_CXX_FLAGS
590 "${CMAKE_CXX_FLAGS} -Wno-unknown-pragmas -Wno-sign-compare -Wno-unused-parameter -Wno-missing-field-initializers")
591endif (UNIX)
592
593# Use a larger inlining threshold for Clang, since it hobbles Eigen,
594# resulting in an unreasonably slow version of the blas routines. The
595# -Qunused-arguments is needed because CMake passes the inline
596# threshold to the linker and clang complains about it and dies.
597if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") # Matches Clang & AppleClang.
598 set(CMAKE_CXX_FLAGS
599 "${CMAKE_CXX_FLAGS} -Qunused-arguments -mllvm -inline-threshold=600")
600
601 # Older versions of Clang (<= 2.9) do not support the 'return-type-c-linkage'
602 # option, so check for its presence before adding it to the default flags set.
603 include(CheckCXXCompilerFlag)
604 check_cxx_compiler_flag("-Wno-return-type-c-linkage"
605 HAVE_RETURN_TYPE_C_LINKAGE)
606 if (HAVE_RETURN_TYPE_C_LINKAGE)
607 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type-c-linkage")
608 endif(HAVE_RETURN_TYPE_C_LINKAGE)
609endif ()
610
611# Configure the Ceres config.h compile options header using the current
612# compile options and put the configured header into the Ceres build
613# directory. Note that the ceres/internal subdir in <build>/config where
614# the configured config.h is placed is important, because Ceres will be
615# built against this configured header, it needs to have the same relative
616# include path as it would if it were in the source tree (or installed).
617list(REMOVE_DUPLICATES CERES_COMPILE_OPTIONS)
618include(CreateCeresConfig)
619create_ceres_config("${CERES_COMPILE_OPTIONS}"
620 ${Ceres_BINARY_DIR}/config/ceres/internal)
621
622add_subdirectory(internal/ceres)
623
624if (BUILD_DOCUMENTATION)
625 set(CERES_DOCS_INSTALL_DIR "share/doc/ceres" CACHE STRING
626 "Ceres docs install path relative to CMAKE_INSTALL_PREFIX")
627
628 find_package(Sphinx QUIET)
629 if (NOT SPHINX_FOUND)
630 message("-- Failed to find Sphinx, disabling build of documentation.")
631 update_cache_variable(BUILD_DOCUMENTATION OFF)
632 else()
633 # Generate the User's Guide (html).
634 # The corresponding target is ceres_docs, but is included in ALL.
635 message("-- Build the HTML documentation.")
636 add_subdirectory(docs)
637 endif()
638endif (BUILD_DOCUMENTATION)
639
640if (BUILD_EXAMPLES)
641 message("-- Build the examples.")
642 add_subdirectory(examples)
643else (BUILD_EXAMPLES)
644 message("-- Do not build any example.")
645endif (BUILD_EXAMPLES)
646
647# Setup installation of Ceres public headers.
648file(GLOB CERES_HDRS ${Ceres_SOURCE_DIR}/include/ceres/*.h)
649install(FILES ${CERES_HDRS} DESTINATION include/ceres)
650
651file(GLOB CERES_PUBLIC_INTERNAL_HDRS ${Ceres_SOURCE_DIR}/include/ceres/internal/*.h)
652install(FILES ${CERES_PUBLIC_INTERNAL_HDRS} DESTINATION include/ceres/internal)
653
654# Also setup installation of Ceres config.h configured with the current
655# build options into the installed headers directory.
656install(FILES ${Ceres_BINARY_DIR}/config/ceres/internal/config.h
657 DESTINATION include/ceres/internal)
658
659if (MINIGLOG)
660 # Install miniglog header if being used as logging #includes appear in
661 # installed public Ceres headers.
662 install(FILES ${Ceres_SOURCE_DIR}/internal/ceres/miniglog/glog/logging.h
663 DESTINATION include/ceres/internal/miniglog/glog)
664endif (MINIGLOG)
665
666# Ceres supports two mechanisms by which it can be detected & imported into
667# client code which uses CMake via find_package(Ceres):
668#
669# 1) Installation (e.g. to /usr/local), using CMake's install() function.
670#
671# 2) (Optional) Export of the current build directory into the local CMake
672# package registry, using CMake's export() function. This allows use of
673# Ceres from other projects without requiring installation.
674#
675# In both cases, we need to generate a configured CeresConfig.cmake which
676# includes additional autogenerated files which in concert create an imported
677# target for Ceres in a client project when find_package(Ceres) is invoked.
678# The key distinctions are where this file is located, and whether client code
679# references installed copies of the compiled Ceres headers/libraries,
680# (option #1: installation), or the originals in the source/build directories
681# (option #2: export of build directory).
682#
683# NOTE: If Ceres is both exported and installed, provided that the installation
684# path is present in CMAKE_MODULE_PATH when find_package(Ceres) is called,
685# the installed version is preferred.
686
687# Build the list of Ceres components for CeresConfig.cmake from the current set
688# of compile options.
689include(CeresCompileOptionsToComponents)
690ceres_compile_options_to_components("${CERES_COMPILE_OPTIONS}"
691 CERES_COMPILED_COMPONENTS)
692
693# Create a CeresConfigVersion.cmake file containing the version information,
694# used by both export() & install().
695configure_file("${Ceres_SOURCE_DIR}/cmake/CeresConfigVersion.cmake.in"
696 "${Ceres_BINARY_DIR}/CeresConfigVersion.cmake" @ONLY)
697
698# Install method #1: Put Ceres in CMAKE_INSTALL_PREFIX: /usr/local or equivalent.
699
700# Set the install path for the installed CeresConfig.cmake configuration file
701# relative to CMAKE_INSTALL_PREFIX.
702if (WIN32)
703 set(RELATIVE_CMAKECONFIG_INSTALL_DIR CMake)
704else ()
705 set(RELATIVE_CMAKECONFIG_INSTALL_DIR lib${LIB_SUFFIX}/cmake/Ceres)
706endif ()
707
708# This "exports" for installation all targets which have been put into the
709# export set "CeresExport". This generates a CeresTargets.cmake file which,
710# when read in by a client project as part of find_package(Ceres) creates
711# imported library targets for Ceres (with dependency relations) which can be
712# used in target_link_libraries() calls in the client project to use Ceres.
713install(EXPORT CeresExport
714 DESTINATION ${RELATIVE_CMAKECONFIG_INSTALL_DIR} FILE CeresTargets.cmake)
715
716# Save the relative path from the installed CeresConfig.cmake file to the
717# install prefix. We do not save an absolute path in case the installed package
718# is subsequently relocated after installation (on Windows).
719file(RELATIVE_PATH INSTALL_ROOT_REL_CONFIG_INSTALL_DIR
720 ${CMAKE_INSTALL_PREFIX}/${RELATIVE_CMAKECONFIG_INSTALL_DIR}
721 ${CMAKE_INSTALL_PREFIX})
722
723# Configure a CeresConfig.cmake file for an installed version of Ceres from the
724# template, reflecting the current build options.
725#
726# NOTE: The -install suffix is necessary to distinguish the install version from
727# the exported version, which must be named CeresConfig.cmake in
728# Ceres_BINARY_DIR to be detected. The suffix is removed when
729# it is installed.
730set(SETUP_CERES_CONFIG_FOR_INSTALLATION TRUE)
731configure_file("${Ceres_SOURCE_DIR}/cmake/CeresConfig.cmake.in"
732 "${Ceres_BINARY_DIR}/CeresConfig-install.cmake" @ONLY)
733
734# Install the configuration files into the same directory as the autogenerated
735# CeresTargets.cmake file. We include the find_package() scripts for libraries
736# whose headers are included in the public API of Ceres and should thus be
737# present in CERES_INCLUDE_DIRS.
738install(FILES "${Ceres_BINARY_DIR}/CeresConfig-install.cmake"
739 RENAME CeresConfig.cmake
740 DESTINATION ${RELATIVE_CMAKECONFIG_INSTALL_DIR})
741install(FILES "${Ceres_BINARY_DIR}/CeresConfigVersion.cmake"
742 "${Ceres_SOURCE_DIR}/cmake/FindEigen.cmake"
743 "${Ceres_SOURCE_DIR}/cmake/FindGlog.cmake"
744 "${Ceres_SOURCE_DIR}/cmake/FindGflags.cmake"
745 DESTINATION ${RELATIVE_CMAKECONFIG_INSTALL_DIR})
746
747# Create an uninstall target to remove all installed files.
748configure_file("${Ceres_SOURCE_DIR}/cmake/uninstall.cmake.in"
749 "${Ceres_BINARY_DIR}/cmake/uninstall.cmake"
750 @ONLY)
751add_custom_target(uninstall
752 COMMAND ${CMAKE_COMMAND} -P ${Ceres_BINARY_DIR}/cmake/uninstall.cmake)
753
754# Install method #2: Put Ceres build into local CMake registry.
755#
756# Optionally export the Ceres build directory into the local CMake package
757# registry (~/.cmake/packages on *nix & OS X). This allows the detection &
758# use of Ceres without requiring that it be installed.
759if (EXPORT_BUILD_DIR)
760 message("-- Export Ceres build directory to local CMake package registry.")
761
762 # Save the relative path from the build directory to the source directory.
763 file(RELATIVE_PATH INSTALL_ROOT_REL_CONFIG_INSTALL_DIR
764 ${Ceres_BINARY_DIR}
765 ${Ceres_SOURCE_DIR})
766
767 # Analogously to install(EXPORT ...), export the Ceres target from the build
768 # directory as a package called Ceres into the local CMake package registry.
769 export(TARGETS ceres FILE ${Ceres_BINARY_DIR}/CeresTargets.cmake)
770 export(PACKAGE ${CMAKE_PROJECT_NAME})
771
772 # Configure a CeresConfig.cmake file for the export of the Ceres build
773 # directory from the template, reflecting the current build options.
774 set(SETUP_CERES_CONFIG_FOR_INSTALLATION FALSE)
775 configure_file("${Ceres_SOURCE_DIR}/cmake/CeresConfig.cmake.in"
776 "${Ceres_BINARY_DIR}/CeresConfig.cmake" @ONLY)
777
778endif (EXPORT_BUILD_DIR)