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