Fix missing gflags imported target definition in CeresConfig.cmake - If gflags was built & exported with CMake but glog was not, but both were found then as we now make gflags a public dependency of Ceres if both it and glog are found, the *name* of the exported gflags CMake target (gflags-shared or similar) will appear in CERES_LIBRARIES. - However, as imported targets are not re-exported, this results in a linker error when compiling client code, as the name of the exported gflags target is not known to CMake, it assumes it is a library name, which it is not. - Confusingly, if glog was built with CMake, this problem would not occur, as in that case glog’s CMake target would bring in gflags’. - Now we explicitly call find_package(Gflags) in CeresConfig.cmake if Ceres was built with gflags as a public dependency (via glog). Change-Id: I5cc9483a1fae50f4e9e3a8fbba491b645fd45db6
diff --git a/CMakeLists.txt b/CMakeLists.txt index 89d0bf0..eda2aec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -842,6 +842,7 @@ install(FILES "${CMAKE_BINARY_DIR}/CeresConfigVersion.cmake" "${CMAKE_SOURCE_DIR}/cmake/FindEigen.cmake" "${CMAKE_SOURCE_DIR}/cmake/FindGlog.cmake" + "${CMAKE_SOURCE_DIR}/cmake/FindGflags.cmake" DESTINATION ${RELATIVE_CMAKECONFIG_INSTALL_DIR}) # Create an uninstall target to remove all installed files.
diff --git a/cmake/CeresConfig.cmake.in b/cmake/CeresConfig.cmake.in index cdb3797..c0e7767 100644 --- a/cmake/CeresConfig.cmake.in +++ b/cmake/CeresConfig.cmake.in
@@ -233,6 +233,7 @@ # Glog. # Flag set during configuration and build of Ceres. set(CERES_USES_MINIGLOG @MINIGLOG@) +set(CERES_USES_GFLAGS @GFLAGS@) if (CERES_USES_MINIGLOG) set(MINIGLOG_INCLUDE_DIR ${CERES_INCLUDE_DIR}/ceres/internal/miniglog) if (NOT EXISTS ${MINIGLOG_INCLUDE_DIR}) @@ -248,20 +249,59 @@ "for glog, beware this will likely cause problems if glog is later linked.") else (CERES_USES_MINIGLOG) # Append the locations of glog when Ceres was built to the search path hints. - list(APPEND GLOG_INCLUDE_DIR_HINTS @GLOG_INCLUDE_DIR@) - get_filename_component(CERES_BUILD_GLOG_LIBRARY_DIR @GLOG_LIBRARY@ PATH) - list(APPEND GLOG_LIBRARY_DIR_HINTS ${CERES_BUILD_GLOG_LIBRARY_DIR}) + set(GLOG_WAS_BUILT_WITH_CMAKE @FOUND_INSTALLED_GLOG_CMAKE_CONFIGURATION@) + if (GLOG_WAS_BUILT_WITH_CMAKE) + set(glog_DIR @glog_DIR@) + set(GLOG_PREFER_EXPORTED_GLOG_CMAKE_CONFIGURATION TRUE) + else() + list(APPEND GLOG_INCLUDE_DIR_HINTS @GLOG_INCLUDE_DIR@) + get_filename_component(CERES_BUILD_GLOG_LIBRARY_DIR @GLOG_LIBRARY@ PATH) + list(APPEND GLOG_LIBRARY_DIR_HINTS ${CERES_BUILD_GLOG_LIBRARY_DIR}) + endif() # Search quietly s/t we control the timing of the error message if not found. find_package(Glog QUIET) if (GLOG_FOUND) - message(STATUS "Found required Ceres dependency: " - "Glog in ${GLOG_INCLUDE_DIRS}") + message(STATUS "Found required Ceres dependency: glog") else (GLOG_FOUND) ceres_report_not_found("Missing required Ceres " - "dependency: Glog, please set GLOG_INCLUDE_DIR.") + "dependency: glog. Searched using GLOG_INCLUDE_DIR_HINTS: " + "${GLOG_INCLUDE_DIR_HINTS} and glog_DIR: ${glog_DIR}.") endif (GLOG_FOUND) list(APPEND CERES_INCLUDE_DIRS ${GLOG_INCLUDE_DIRS}) + + # gflags is only a public dependency of Ceres via glog, thus is not required + # if Ceres was built with MINIGLOG. + if (CERES_USES_GFLAGS) + # If gflags was found as an imported CMake target, we need to call + # find_packge(Gflags) again here, as imported CMake targets are not + # re-exported. Without this, the 'gflags-shared' target name which is + # present in CERES_LIBRARIES in this case would not be defined, and so + # CMake will assume it is a library name (which it is not) and fail to link. + # + # Append the locations of gflags when Ceres was built to the search path + # hints. + set(GFLAGS_WAS_BUILT_WITH_CMAKE @FOUND_INSTALLED_GFLAGS_CMAKE_CONFIGURATION@) + if (GFLAGS_WAS_BUILT_WITH_CMAKE) + set(gflags_DIR @gflags_DIR@) + set(GFLAGS_PREFER_EXPORTED_GFLAGS_CMAKE_CONFIGURATION TRUE) + else() + list(APPEND GFLAGS_INCLUDE_DIR_HINTS @GFLAGS_INCLUDE_DIR@) + get_filename_component(CERES_BUILD_GFLAGS_LIBRARY_DIR @GFLAGS_LIBRARY@ PATH) + list(APPEND GFLAGS_LIBRARY_DIR_HINTS ${CERES_BUILD_GFLAGS_LIBRARY_DIR}) + endif() + + # Search quietly s/t we control the timing of the error message if not found. + find_package(Gflags QUIET) + if (GFLAGS_FOUND) + message(STATUS "Found required Ceres dependency: gflags") + else() + ceres_report_not_found("Missing required Ceres " + "dependency: gflags. Searched using GFLAGS_INCLUDE_DIR_HINTS: " + "${GFLAGS_INCLUDE_DIR_HINTS} and gflags_DIR: ${gflags_DIR}.") + endif() + list(APPEND CERES_INCLUDE_DIRS ${GFLAGS_INCLUDE_DIR_HINTS}) + endif() endif (CERES_USES_MINIGLOG) # Import exported Ceres targets, if they have not already been imported.
diff --git a/cmake/FindGflags.cmake b/cmake/FindGflags.cmake index 8f5cd3c..751771d 100644 --- a/cmake/FindGflags.cmake +++ b/cmake/FindGflags.cmake
@@ -47,6 +47,9 @@ # by default gflags, although can be configured when building # gflags to be something else (i.e. google for legacy # compatibility). +# FOUND_INSTALLED_GFLAGS_CMAKE_CONFIGURATION: True iff the version of gflags +# found was built & installed / +# exported as a CMake package. # # The following variables control the behaviour of this module when an exported # gflags CMake configuration is not found.
diff --git a/cmake/FindGlog.cmake b/cmake/FindGlog.cmake index 3a6f796..17b8bc5 100644 --- a/cmake/FindGlog.cmake +++ b/cmake/FindGlog.cmake
@@ -36,6 +36,9 @@ # GLOG_FOUND: TRUE iff glog is found. # GLOG_INCLUDE_DIRS: Include directories for glog. # GLOG_LIBRARIES: Libraries required to link glog. +# FOUND_INSTALLED_GLOG_CMAKE_CONFIGURATION: True iff the version of glog found +# was built & installed / exported +# as a CMake package. # # The following variables control the behaviour of this module: #