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