CeresConfig.cmake.in 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  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: pablo.speciale@gmail.com (Pablo Speciale)
  30. # alexs.mac@gmail.com (Alex Stewart)
  31. #
  32. # Config file for Ceres Solver - Find Ceres & dependencies.
  33. #
  34. # This file is used by CMake when find_package(Ceres) is invoked and either
  35. # the directory containing this file either is present in CMAKE_MODULE_PATH
  36. # (if Ceres was installed), or exists in the local CMake package registry if
  37. # the Ceres build directory was exported.
  38. #
  39. # This module defines the following variables:
  40. #
  41. # Ceres_FOUND / CERES_FOUND: True if Ceres has been successfully
  42. # found. Both variables are set as although
  43. # FindPackage() only references Ceres_FOUND
  44. # in Config mode, given the conventions for
  45. # <package>_FOUND when FindPackage() is
  46. # called in Module mode, users could
  47. # reasonably expect to use CERES_FOUND
  48. # instead.
  49. #
  50. # CERES_VERSION: Version of Ceres found.
  51. #
  52. # CERES_LIBRARIES: Libraries for Ceres and all
  53. # dependencies against which Ceres was
  54. # compiled. This will not include any optional
  55. # dependencies that were disabled when Ceres was
  56. # compiled.
  57. #
  58. # NOTE: There is no equivalent of CERES_INCLUDE_DIRS as the exported
  59. # CMake target already includes the definition of its public
  60. # include directories.
  61. include(CMakeFindDependencyMacro)
  62. # Called if we failed to find Ceres or any of its required dependencies,
  63. # unsets all public (designed to be used externally) variables and reports
  64. # error message at priority depending upon [REQUIRED/QUIET/<NONE>] argument.
  65. macro(CERES_REPORT_NOT_FOUND REASON_MSG)
  66. # FindPackage() only references Ceres_FOUND, and requires it to be
  67. # explicitly set FALSE to denote not found (not merely undefined).
  68. set(Ceres_FOUND FALSE)
  69. set(CERES_FOUND FALSE)
  70. unset(CERES_INCLUDE_DIR)
  71. unset(CERES_INCLUDE_DIRS)
  72. unset(CERES_LIBRARIES)
  73. # Reset the CMake module path to its state when this script was called.
  74. set(CMAKE_MODULE_PATH ${CALLERS_CMAKE_MODULE_PATH})
  75. # Note <package>_FIND_[REQUIRED/QUIETLY] variables defined by
  76. # FindPackage() use the camelcase library name, not uppercase.
  77. if (Ceres_FIND_QUIETLY)
  78. message(STATUS "Failed to find Ceres - " ${REASON_MSG} ${ARGN})
  79. elseif (Ceres_FIND_REQUIRED)
  80. message(FATAL_ERROR "Failed to find Ceres - " ${REASON_MSG} ${ARGN})
  81. else()
  82. # Neither QUIETLY nor REQUIRED, use SEND_ERROR which emits an error
  83. # that prevents generation, but continues configuration.
  84. message(SEND_ERROR "Failed to find Ceres - " ${REASON_MSG} ${ARGN})
  85. endif ()
  86. return()
  87. endmacro(CERES_REPORT_NOT_FOUND)
  88. # ceres_message([mode] "message text")
  89. #
  90. # Wraps the standard cmake 'message' command, but suppresses output
  91. # if the QUIET flag was passed to the find_package(Ceres ...) call.
  92. function(ceres_message)
  93. if (NOT Ceres_FIND_QUIETLY)
  94. message(${ARGN})
  95. endif()
  96. endfunction()
  97. # ceres_pretty_print_cmake_list( OUTPUT_VAR [item1 [item2 ... ]] )
  98. #
  99. # Sets ${OUTPUT_VAR} in the caller's scope to a human-readable string
  100. # representation of the list passed as the remaining arguments formed
  101. # as: "[item1, item2, ..., itemN]".
  102. function(ceres_pretty_print_cmake_list OUTPUT_VAR)
  103. string(REPLACE ";" ", " PRETTY_LIST_STRING "[${ARGN}]")
  104. set(${OUTPUT_VAR} "${PRETTY_LIST_STRING}" PARENT_SCOPE)
  105. endfunction()
  106. # The list of (optional) components this version of Ceres was compiled with.
  107. set(CERES_COMPILED_COMPONENTS "@CERES_COMPILED_COMPONENTS@")
  108. # If Ceres was not installed, then by definition it was exported
  109. # from a build directory.
  110. set(CERES_WAS_INSTALLED @SETUP_CERES_CONFIG_FOR_INSTALLATION@)
  111. # Record the state of the CMake module path when this script was
  112. # called so that we can ensure that we leave it in the same state on
  113. # exit as it was on entry, but modify it locally.
  114. set(CALLERS_CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH})
  115. # Get the (current, i.e. installed) directory containing this file.
  116. get_filename_component(CERES_CURRENT_CONFIG_DIR
  117. "${CMAKE_CURRENT_LIST_FILE}" PATH)
  118. if (CERES_WAS_INSTALLED)
  119. # Reset CMake module path to the installation directory of this
  120. # script, thus we will use the FindPackage() scripts shipped with
  121. # Ceres to find Ceres' dependencies, even if the user has equivalently
  122. # named FindPackage() scripts in their project.
  123. set(CMAKE_MODULE_PATH ${CERES_CURRENT_CONFIG_DIR})
  124. # Build the absolute root install directory as a relative path
  125. # (determined when Ceres was configured & built) from the current
  126. # install directory for this this file. This allows for the install
  127. # tree to be relocated, after Ceres was built, outside of CMake.
  128. get_filename_component(CURRENT_ROOT_INSTALL_DIR
  129. "${CERES_CURRENT_CONFIG_DIR}/@INSTALL_ROOT_REL_CONFIG_INSTALL_DIR@"
  130. ABSOLUTE)
  131. if (NOT EXISTS ${CURRENT_ROOT_INSTALL_DIR})
  132. ceres_report_not_found(
  133. "Ceres install root: ${CURRENT_ROOT_INSTALL_DIR}, "
  134. "determined from relative path from CeresConfig.cmake install location: "
  135. "${CERES_CURRENT_CONFIG_DIR}, does not exist. Either the install "
  136. "directory was deleted, or the install tree was only partially relocated "
  137. "outside of CMake after Ceres was built.")
  138. endif (NOT EXISTS ${CURRENT_ROOT_INSTALL_DIR})
  139. else(CERES_WAS_INSTALLED)
  140. # Ceres was exported from the build tree.
  141. set(CERES_EXPORTED_BUILD_DIR ${CERES_CURRENT_CONFIG_DIR})
  142. get_filename_component(CERES_EXPORTED_SOURCE_DIR
  143. "${CERES_EXPORTED_BUILD_DIR}/@INSTALL_ROOT_REL_CONFIG_INSTALL_DIR@"
  144. ABSOLUTE)
  145. if (NOT EXISTS ${CERES_EXPORTED_SOURCE_DIR})
  146. ceres_report_not_found(
  147. "Ceres exported source directory: ${CERES_EXPORTED_SOURCE_DIR}, "
  148. "determined from relative path from CeresConfig.cmake exported build "
  149. "directory: ${CERES_EXPORTED_BUILD_DIR} does not exist.")
  150. endif()
  151. # Reset CMake module path to the cmake directory in the Ceres source
  152. # tree which was exported, thus we will use the FindPackage() scripts shipped
  153. # with Ceres to find Ceres' dependencies, even if the user has equivalently
  154. # named FindPackage() scripts in their project.
  155. set(CMAKE_MODULE_PATH ${CERES_EXPORTED_SOURCE_DIR}/cmake)
  156. endif(CERES_WAS_INSTALLED)
  157. # Set the version.
  158. set(CERES_VERSION @CERES_VERSION@)
  159. include(CMakeFindDependencyMacro)
  160. # Optional dependencies
  161. @METIS_DEPENDENCY@
  162. @SuiteSparse_DEPENDENCY@
  163. @CUDAToolkit_DEPENDENCY@
  164. @Threads_DEPENDENCY@
  165. # As imported CMake targets are not re-exported when a dependent target is
  166. # exported, we must invoke find_package(XXX) here to reload the definition
  167. # of their targets. Without this, the dependency target names (e.g.
  168. # 'gflags-shared') which will be present in the ceres target would not be
  169. # defined, and so CMake will assume that they refer to a library name and
  170. # fail to link correctly.
  171. # Eigen.
  172. # Flag set during configuration and build of Ceres.
  173. set(CERES_EIGEN_VERSION @Eigen3_VERSION@)
  174. # Search quietly to control the timing of the error message if not found. The
  175. # search should be for an exact match, but for usability reasons do a soft
  176. # match and reject with an explanation below.
  177. find_package(Eigen3 ${CERES_EIGEN_VERSION} QUIET)
  178. if (Eigen3_FOUND)
  179. if (NOT Eigen3_VERSION VERSION_EQUAL CERES_EIGEN_VERSION)
  180. # CMake's VERSION check in FIND_PACKAGE() will accept any version >= the
  181. # specified version. However, only version = is supported. Improve
  182. # usability by explaining why we don't accept non-exact version matching.
  183. ceres_report_not_found("Found Eigen dependency, but the version of Eigen "
  184. "found (${Eigen3_VERSION}) does not exactly match the version of Eigen "
  185. "Ceres was compiled with (${CERES_EIGEN_VERSION}). This can cause subtle "
  186. "bugs by triggering violations of the One Definition Rule. See the "
  187. "Wikipedia article http://en.wikipedia.org/wiki/One_Definition_Rule "
  188. "for more details")
  189. endif ()
  190. ceres_message(STATUS "Found required Ceres dependency: "
  191. "Eigen version ${CERES_EIGEN_VERSION} in ${Eigen3_DIR}")
  192. else (Eigen3_FOUND)
  193. ceres_report_not_found("Missing required Ceres "
  194. "dependency: Eigen version ${CERES_EIGEN_VERSION}, please set "
  195. "Eigen3_DIR.")
  196. endif (Eigen3_FOUND)
  197. # glog (and maybe gflags).
  198. #
  199. # Flags set during configuration and build of Ceres.
  200. set(CERES_USES_MINIGLOG @MINIGLOG@)
  201. set(CERES_GLOG_VERSION @glog_VERSION@)
  202. set(CERES_GLOG_WAS_BUILT_WITH_CMAKE @FOUND_INSTALLED_GLOG_CMAKE_CONFIGURATION@)
  203. set(CERES_USES_GFLAGS @GFLAGS@)
  204. set(CERES_GFLAGS_VERSION @gflags_VERSION@)
  205. if (CERES_USES_MINIGLOG)
  206. # Output message at standard log level (not the lower STATUS) so that
  207. # the message is output in GUI during configuration to warn user.
  208. ceres_message("-- Found Ceres compiled with miniglog substitute "
  209. "for glog, beware this will likely cause problems if glog is later linked.")
  210. else(CERES_USES_MINIGLOG)
  211. if (CERES_GLOG_WAS_BUILT_WITH_CMAKE)
  212. find_package(glog ${CERES_GLOG_VERSION} CONFIG QUIET)
  213. set(GLOG_FOUND ${glog_FOUND})
  214. else()
  215. # Version of glog against which Ceres was built was not built with CMake,
  216. # use the exported glog find_package() module from Ceres to find it again.
  217. # Append the locations of glog when Ceres was built to the search path hints.
  218. list(APPEND GLOG_INCLUDE_DIR_HINTS "@GLOG_INCLUDE_DIR@")
  219. get_filename_component(CERES_BUILD_GLOG_LIBRARY_DIR "@GLOG_LIBRARY@" PATH)
  220. list(APPEND GLOG_LIBRARY_DIR_HINTS ${CERES_BUILD_GLOG_LIBRARY_DIR})
  221. # Search quietly s/t we control the timing of the error message if not found.
  222. find_package(Glog QUIET)
  223. endif()
  224. if (GLOG_FOUND)
  225. ceres_message(STATUS "Found required Ceres dependency: glog")
  226. else()
  227. ceres_report_not_found("Missing required Ceres dependency: glog.")
  228. endif()
  229. # gflags is only a public dependency of Ceres via glog, thus is not required
  230. # if Ceres was built with MINIGLOG.
  231. if (CERES_USES_GFLAGS)
  232. # Search quietly s/t we control the timing of the error message if not found.
  233. find_package(gflags ${CERES_GFLAGS_VERSION} QUIET)
  234. if (gflags_FOUND AND TARGET gflags)
  235. ceres_message(STATUS "Found required Ceres dependency: gflags")
  236. else()
  237. ceres_report_not_found("Missing required Ceres "
  238. "dependency: gflags (not found, or not found as exported CMake target).")
  239. endif()
  240. endif()
  241. endif(CERES_USES_MINIGLOG)
  242. # Import exported Ceres targets, if they have not already been imported.
  243. if (NOT TARGET ceres AND NOT Ceres_BINARY_DIR)
  244. include(${CERES_CURRENT_CONFIG_DIR}/CeresTargets.cmake)
  245. endif (NOT TARGET ceres AND NOT Ceres_BINARY_DIR)
  246. # Set the expected XX_LIBRARIES variable for FindPackage().
  247. set(CERES_LIBRARIES Ceres::ceres)
  248. # Reset CMake module path to its state when this script was called.
  249. set(CMAKE_MODULE_PATH ${CALLERS_CMAKE_MODULE_PATH})
  250. # Build the detected Ceres version string to correctly capture whether it
  251. # was installed, or exported.
  252. ceres_pretty_print_cmake_list(CERES_COMPILED_COMPONENTS_STRING
  253. ${CERES_COMPILED_COMPONENTS})
  254. if (CERES_WAS_INSTALLED)
  255. set(CERES_DETECTED_VERSION_STRING "Ceres version: ${CERES_VERSION} "
  256. "installed in: ${CURRENT_ROOT_INSTALL_DIR} with components: "
  257. "${CERES_COMPILED_COMPONENTS_STRING}")
  258. else (CERES_WAS_INSTALLED)
  259. set(CERES_DETECTED_VERSION_STRING "Ceres version: ${CERES_VERSION} "
  260. "exported from build directory: ${CERES_EXPORTED_BUILD_DIR} with "
  261. "components: ${CERES_COMPILED_COMPONENTS_STRING}")
  262. endif()
  263. # If the user called this script through find_package() whilst specifying
  264. # particular Ceres components that should be found via:
  265. # find_package(Ceres COMPONENTS XXX YYY), check the requested components against
  266. # those with which Ceres was compiled. In this case, we should only report
  267. # Ceres as found if all the requested components have been found.
  268. if (Ceres_FIND_COMPONENTS)
  269. foreach (REQUESTED_COMPONENT ${Ceres_FIND_COMPONENTS})
  270. list(FIND CERES_COMPILED_COMPONENTS ${REQUESTED_COMPONENT} HAVE_REQUESTED_COMPONENT)
  271. # list(FIND ..) returns -1 if the element was not in the list, but CMake
  272. # interprets if (VAR) to be true if VAR is any non-zero number, even
  273. # negative ones, hence we have to explicitly check for >= 0.
  274. if (HAVE_REQUESTED_COMPONENT EQUAL -1)
  275. # Check for the presence of all requested components before reporting
  276. # not found, such that we report all of the missing components rather
  277. # than just the first.
  278. list(APPEND MISSING_CERES_COMPONENTS ${REQUESTED_COMPONENT})
  279. endif()
  280. endforeach()
  281. if (MISSING_CERES_COMPONENTS)
  282. ceres_pretty_print_cmake_list(REQUESTED_CERES_COMPONENTS_STRING
  283. ${Ceres_FIND_COMPONENTS})
  284. ceres_pretty_print_cmake_list(MISSING_CERES_COMPONENTS_STRING
  285. ${MISSING_CERES_COMPONENTS})
  286. ceres_report_not_found("Missing requested Ceres components: "
  287. "${MISSING_CERES_COMPONENTS_STRING} (components requested: "
  288. "${REQUESTED_CERES_COMPONENTS_STRING}). Detected "
  289. "${CERES_DETECTED_VERSION_STRING}.")
  290. endif()
  291. endif()
  292. # As we use CERES_REPORT_NOT_FOUND() to abort, if we reach this point we have
  293. # found Ceres and all required dependencies.
  294. ceres_message(STATUS "Found " ${CERES_DETECTED_VERSION_STRING})
  295. # Set CERES_FOUND to be equivalent to Ceres_FOUND, which is set to
  296. # TRUE by FindPackage() if this file is found and run, and after which
  297. # Ceres_FOUND is not (explicitly, i.e. undefined does not count) set
  298. # to FALSE.
  299. set(CERES_FOUND TRUE)
  300. if (NOT TARGET ceres)
  301. # For backwards compatibility, create a local 'alias' target with the
  302. # non-namespace-qualified Ceres target name. Note that this is not a
  303. # true ALIAS library in CMake terms as they cannot point to imported targets.
  304. add_library(ceres INTERFACE IMPORTED)
  305. set_target_properties(ceres PROPERTIES INTERFACE_LINK_LIBRARIES Ceres::ceres)
  306. endif()