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@)