Fix Abseil usage of installed cmake-config
Fix the generated cmake-config file to look for the used Abseil-cpp
config files providing the needed targets.
When using Abseil from system (or locally installed and set via
`absl_DIR`) the used targets like `absl::log` need to be made available
in downstream projects using `ceres-solver`.
For system packages with no `absl_VERSION` info check for the required
target `absl::absl_vlog_is_on`, just like we do in `CMakeLists.txt`.
Error on installation/export of "no-absl-VERSION" as we can't check
version mismatches.
When using `abseil-cpp` as submodule the abseil-configs are added to the
install target as well. Use these config files to make the needed Abseil
targets available.
In the submodule case extract the `absl_VERSION` variable from its
`CMakeLists.txt` file for us to check against in the generated
cmake-config-file.
Fixes: https://github.com/ceres-solver/ceres-solver/issues/1089
Change-Id: I3e3d079ddf931e7fe1b57783471c32c19e4d31b6
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d13c213..f53e998 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -124,7 +124,23 @@
# Abseil
if (EXISTS "${Ceres_SOURCE_DIR}/third_party/abseil-cpp/CMakeLists.txt")
- message("-- Using the version of abseil in ceres-solver/third_party/abseil-cpp")
+ # extract submodule absl_VERSION
+ file(STRINGS "${Ceres_SOURCE_DIR}/third_party/abseil-cpp/CMakeLists.txt" project_calls REGEX "[ \t]*project\\([ \t]*absl")
+ foreach(project_call IN LISTS project_calls)
+ string(REGEX MATCH "VERSION[ ]+([0-9]+(\.(rc)?[0-9]+)?)" version_param "${project_call}")
+ if (version_param)
+ set(absl_VERSION "${CMAKE_MATCH_1}")
+ message("-- Using the version of abseil in ceres-solver/third_party/abseil-cpp with version ${absl_VERSION}")
+ break ()
+ endif()
+ endforeach()
+ unset(project_calls)
+ unset(project_call)
+ unset(version_param)
+ if (NOT absl_VERSION)
+ message("-- Using the version of abseil in ceres-solver/third_party/abseil-cpp")
+ endif()
+
# In the normal course of things, we would not need the following constraint.
# However, if we do not set the standard, then std::basic_string_view is not
# available, which absl depends on and linking the test fails.
@@ -150,6 +166,8 @@
set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
+
+ set(CERES_USE_SYSTEM_ABSL NO)
else()
message("-- ceres-solver/third_party/abseil-cpp is empty, so falling back to system installed abseil")
find_package(absl REQUIRED 20240116)
@@ -162,6 +180,13 @@
message(FATAL_ERROR "The version of abseil installed on the system provides no version info and is missing TARGET 'absl::absl_vlog_is_on', need at least 20240116")
endif()
endif()
+ set(CERES_USE_SYSTEM_ABSL YES)
+endif()
+if (NOT absl_VERSION)
+ if (EXPORT_BUILD_DIR)
+ message(FATAL_ERROR "Cannot generate CeresConfig.cmake due to missing Abseil version. Using resulting package configuration will likely result in integration errors. Set absl_VERSION manually to disable this error message")
+ endif()
+ install (CODE [=[message (FATAL_ERROR "Cannot generate CeresConfig.cmake due to missing Abseil version. Using resulting package configuration will likely result in integration errors. Set absl_VERSION manually to disable this error message.")]=])
endif()
# Google Test
diff --git a/cmake/CeresConfig.cmake.in b/cmake/CeresConfig.cmake.in
index 4acc8cf..9396d84 100644
--- a/cmake/CeresConfig.cmake.in
+++ b/cmake/CeresConfig.cmake.in
@@ -190,6 +190,29 @@
# defined, and so CMake will assume that they refer to a library name and
# fail to link correctly.
+# Abseil
+set(_CERES_ABSL_VERSION @absl_VERSION@)
+set(_CERES_USE_SYSTEM_ABSL @CERES_USE_SYSTEM_ABSL@)
+if (_CERES_USE_SYSTEM_ABSL)
+ find_dependency(absl ${_CERES_ABSL_VERSION})
+ if (NOT absl_VERSION)
+ if (NOT TARGET absl::absl_vlog_is_on)
+ ceres_report_not_found("The version of abseil installed on the system "
+ "provides no version info and is missing TARGET 'absl::absl_vlog_is_on'")
+ endif ()
+ endif ()
+else ()
+ # absl from submodule, configs installed with ceres-solver
+ get_filename_component(_ABSL_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
+ get_filename_component(_ABSL_IMPORT_PREFIX "${_ABSL_IMPORT_PREFIX}" PATH)
+ set(_ABSL_IMPORT_PREFIX "${_ABSL_IMPORT_PREFIX}/absl")
+ find_dependency(absl ${_CERES_ABSL_VERSION} HINTS "${_ABSL_IMPORT_PREFIX}")
+endif ()
+ceres_message(STATUS "Found required Ceres dependency: "
+ "absl version ${_CERES_ABSL_VERSION} in ${absl_DIR}")
+unset(_CERES_ABSL_VERSION)
+unset(_CERES_USE_SYSTEM_ABSL)
+
# Eigen.
# Flag set during configuration and build of Ceres.
set(CERES_EIGEN_VERSION @Eigen3_VERSION@)