diff --git a/CMakeLists.txt b/CMakeLists.txt index ed1425a45..97a172664 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -380,13 +380,12 @@ else (MINIGLOG) # Don't search with REQUIRED so that configuration continues if not found and # we can output an error messages explaining MINIGLOG option. find_package(Glog) - if (GLOG_FOUND) - message("-- Found Google Log header in: ${GLOG_INCLUDE_DIRS}") - else (GLOG_FOUND) - message(FATAL_ERROR "Can't find Google Log. Please set GLOG_INCLUDE_DIR & " + if (NOT GLOG_FOUND) + message(FATAL_ERROR "Can't find Google Log (glog). Please set either: " + "glog_DIR (newer CMake built versions of glog) or GLOG_INCLUDE_DIR & " "GLOG_LIBRARY or enable MINIGLOG option to use minimal glog " "implementation.") - endif (GLOG_FOUND) + endif(NOT GLOG_FOUND) endif (MINIGLOG) if (NOT SCHUR_SPECIALIZATIONS) diff --git a/cmake/FindGlog.cmake b/cmake/FindGlog.cmake index 3057b312d..3a6f79645 100644 --- a/cmake/FindGlog.cmake +++ b/cmake/FindGlog.cmake @@ -39,6 +39,16 @@ # # The following variables control the behaviour of this module: # +# GLOG_PREFER_EXPORTED_GLOG_CMAKE_CONFIGURATION: TRUE/FALSE, iff TRUE then +# then prefer using an exported CMake configuration +# generated by glog > 0.3.4 over searching for the +# glog components manually. Otherwise (FALSE) +# ignore any exported glog CMake configurations and +# always perform a manual search for the components. +# Default: TRUE iff user does not define this variable +# before we are called, and does NOT specify either +# GLOG_INCLUDE_DIR_HINTS or GLOG_LIBRARY_DIR_HINTS +# otherwise FALSE. # GLOG_INCLUDE_DIR_HINTS: List of additional directories in which to # search for glog includes, e.g: /timbuktu/include. # GLOG_LIBRARY_DIR_HINTS: List of additional directories in which to @@ -63,9 +73,9 @@ # Reset CALLERS_CMAKE_FIND_LIBRARY_PREFIXES to its value when # FindGlog was invoked. macro(GLOG_RESET_FIND_LIBRARY_PREFIX) - if (MSVC) + if (MSVC AND CALLERS_CMAKE_FIND_LIBRARY_PREFIXES) set(CMAKE_FIND_LIBRARY_PREFIXES "${CALLERS_CMAKE_FIND_LIBRARY_PREFIXES}") - endif (MSVC) + endif() endmacro(GLOG_RESET_FIND_LIBRARY_PREFIX) # Called if we failed to find glog or any of it's required dependencies, @@ -96,98 +106,188 @@ macro(GLOG_REPORT_NOT_FOUND REASON_MSG) return() endmacro(GLOG_REPORT_NOT_FOUND) -# Handle possible presence of lib prefix for libraries on MSVC, see -# also GLOG_RESET_FIND_LIBRARY_PREFIX(). -if (MSVC) - # Preserve the caller's original values for CMAKE_FIND_LIBRARY_PREFIXES - # s/t we can set it back before returning. - set(CALLERS_CMAKE_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}") - # The empty string in this list is important, it represents the case when - # the libraries have no prefix (shared libraries / DLLs). - set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "" "${CMAKE_FIND_LIBRARY_PREFIXES}") -endif (MSVC) +# ----------------------------------------------------------------- +# By default, if the user has expressed no preference for using an exported +# glog CMake configuration over performing a search for the installed +# components, and has not specified any hints for the search locations, then +# prefer a glog exported configuration if available. +if (NOT DEFINED GLOG_PREFER_EXPORTED_GLOG_CMAKE_CONFIGURATION + AND NOT GLOG_INCLUDE_DIR_HINTS + AND NOT GLOG_LIBRARY_DIR_HINTS) + message(STATUS "No preference for use of exported glog CMake configuration " + "set, and no hints for include/library directories provided. " + "Defaulting to preferring an installed/exported glog CMake configuration " + "if available.") + set(GLOG_PREFER_EXPORTED_GLOG_CMAKE_CONFIGURATION TRUE) +endif() -# Search user-installed locations first, so that we prefer user installs -# to system installs where both exist. -list(APPEND GLOG_CHECK_INCLUDE_DIRS - /usr/local/include - /usr/local/homebrew/include # Mac OS X - /opt/local/var/macports/software # Mac OS X. - /opt/local/include - /usr/include) -# Windows (for C:/Program Files prefix). -list(APPEND GLOG_CHECK_PATH_SUFFIXES - glog/include - glog/Include - Glog/include - Glog/Include) +if (GLOG_PREFER_EXPORTED_GLOG_CMAKE_CONFIGURATION) + # Try to find an exported CMake configuration for glog, as generated by + # glog versions > 0.3.4 + # + # We search twice, s/t we can invert the ordering of precedence used by + # find_package() for exported package build directories, and installed + # packages (found via CMAKE_SYSTEM_PREFIX_PATH), listed as items 6) and 7) + # respectively in [1]. + # + # By default, exported build directories are (in theory) detected first, and + # this is usually the case on Windows. However, on OS X & Linux, the install + # path (/usr/local) is typically present in the PATH environment variable + # which is checked in item 4) in [1] (i.e. before both of the above, unless + # NO_SYSTEM_ENVIRONMENT_PATH is passed). As such on those OSs installed + # packages are usually detected in preference to exported package build + # directories. + # + # To ensure a more consistent response across all OSs, and as users usually + # want to prefer an installed version of a package over a locally built one + # where both exist (esp. as the exported build directory might be removed + # after installation), we first search with NO_CMAKE_PACKAGE_REGISTRY which + # means any build directories exported by the user are ignored, and thus + # installed directories are preferred. If this fails to find the package + # we then research again, but without NO_CMAKE_PACKAGE_REGISTRY, so any + # exported build directories will now be detected. + # + # To prevent confusion on Windows, we also pass NO_CMAKE_BUILDS_PATH (which + # is item 5) in [1]), to not preferentially use projects that were built + # recently with the CMake GUI to ensure that we always prefer an installed + # version if available. + # + # [1] http://www.cmake.org/cmake/help/v2.8.11/cmake.html#command:find_package + find_package(glog QUIET + NO_MODULE + NO_CMAKE_PACKAGE_REGISTRY + NO_CMAKE_BUILDS_PATH) + if (glog_FOUND) + message(STATUS "Found installed version of glog: ${glog_DIR}") + else() + # Failed to find an installed version of glog, repeat search allowing + # exported build directories. + message(STATUS "Failed to find installed glog CMake configuration, " + "searching for glog build directories exported with CMake.") + # Again pass NO_CMAKE_BUILDS_PATH, as we know that glog is exported and + # do not want to treat projects built with the CMake GUI preferentially. + find_package(glog QUIET + NO_MODULE + NO_CMAKE_BUILDS_PATH) + if (glog_FOUND) + message(STATUS "Found exported glog build directory: ${glog_DIR}") + endif(glog_FOUND) + endif(glog_FOUND) -list(APPEND GLOG_CHECK_LIBRARY_DIRS - /usr/local/lib - /usr/local/homebrew/lib # Mac OS X. - /opt/local/lib - /usr/lib) -# Windows (for C:/Program Files prefix). -list(APPEND GLOG_CHECK_LIBRARY_SUFFIXES - glog/lib - glog/Lib - Glog/lib - Glog/Lib) + set(FOUND_INSTALLED_GLOG_CMAKE_CONFIGURATION ${glog_FOUND}) -# Search supplied hint directories first if supplied. -find_path(GLOG_INCLUDE_DIR - NAMES glog/logging.h - PATHS ${GLOG_INCLUDE_DIR_HINTS} - ${GLOG_CHECK_INCLUDE_DIRS} - PATH_SUFFIXES ${GLOG_CHECK_PATH_SUFFIXES}) -if (NOT GLOG_INCLUDE_DIR OR + if (FOUND_INSTALLED_GLOG_CMAKE_CONFIGURATION) + message(STATUS "Detected glog version: ${glog_VERSION}") + set(GLOG_FOUND ${glog_FOUND}) + # glog wraps the include directories into the exported glog::glog target. + set(GLOG_INCLUDE_DIR "") + set(GLOG_LIBRARY glog::glog) + else (FOUND_INSTALLED_GLOG_CMAKE_CONFIGURATION) + message(STATUS "Failed to find an installed/exported CMake configuration " + "for glog, will perform search for installed glog components.") + endif (FOUND_INSTALLED_GLOG_CMAKE_CONFIGURATION) +endif(GLOG_PREFER_EXPORTED_GLOG_CMAKE_CONFIGURATION) + +if (NOT GLOG_FOUND) + # Either failed to find an exported glog CMake configuration, or user + # told us not to use one. Perform a manual search for all glog components. + + # Handle possible presence of lib prefix for libraries on MSVC, see + # also GLOG_RESET_FIND_LIBRARY_PREFIX(). + if (MSVC) + # Preserve the caller's original values for CMAKE_FIND_LIBRARY_PREFIXES + # s/t we can set it back before returning. + set(CALLERS_CMAKE_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}") + # The empty string in this list is important, it represents the case when + # the libraries have no prefix (shared libraries / DLLs). + set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "" "${CMAKE_FIND_LIBRARY_PREFIXES}") + endif (MSVC) + + # Search user-installed locations first, so that we prefer user installs + # to system installs where both exist. + list(APPEND GLOG_CHECK_INCLUDE_DIRS + /usr/local/include + /usr/local/homebrew/include # Mac OS X + /opt/local/var/macports/software # Mac OS X. + /opt/local/include + /usr/include) + # Windows (for C:/Program Files prefix). + list(APPEND GLOG_CHECK_PATH_SUFFIXES + glog/include + glog/Include + Glog/include + Glog/Include) + + list(APPEND GLOG_CHECK_LIBRARY_DIRS + /usr/local/lib + /usr/local/homebrew/lib # Mac OS X. + /opt/local/lib + /usr/lib) + # Windows (for C:/Program Files prefix). + list(APPEND GLOG_CHECK_LIBRARY_SUFFIXES + glog/lib + glog/Lib + Glog/lib + Glog/Lib) + + # Search supplied hint directories first if supplied. + find_path(GLOG_INCLUDE_DIR + NAMES glog/logging.h + PATHS ${GLOG_INCLUDE_DIR_HINTS} + ${GLOG_CHECK_INCLUDE_DIRS} + PATH_SUFFIXES ${GLOG_CHECK_PATH_SUFFIXES}) + if (NOT GLOG_INCLUDE_DIR OR + NOT EXISTS ${GLOG_INCLUDE_DIR}) + glog_report_not_found( + "Could not find glog include directory, set GLOG_INCLUDE_DIR " + "to directory containing glog/logging.h") + endif (NOT GLOG_INCLUDE_DIR OR NOT EXISTS ${GLOG_INCLUDE_DIR}) - glog_report_not_found( - "Could not find glog include directory, set GLOG_INCLUDE_DIR " - "to directory containing glog/logging.h") -endif (NOT GLOG_INCLUDE_DIR OR - NOT EXISTS ${GLOG_INCLUDE_DIR}) -find_library(GLOG_LIBRARY NAMES glog - PATHS ${GLOG_LIBRARY_DIR_HINTS} - ${GLOG_CHECK_LIBRARY_DIRS} - PATH_SUFFIXES ${GLOG_CHECK_LIBRARY_SUFFIXES}) -if (NOT GLOG_LIBRARY OR + find_library(GLOG_LIBRARY NAMES glog + PATHS ${GLOG_LIBRARY_DIR_HINTS} + ${GLOG_CHECK_LIBRARY_DIRS} + PATH_SUFFIXES ${GLOG_CHECK_LIBRARY_SUFFIXES}) + if (NOT GLOG_LIBRARY OR + NOT EXISTS ${GLOG_LIBRARY}) + glog_report_not_found( + "Could not find glog library, set GLOG_LIBRARY " + "to full path to libglog.") + endif (NOT GLOG_LIBRARY OR NOT EXISTS ${GLOG_LIBRARY}) - glog_report_not_found( - "Could not find glog library, set GLOG_LIBRARY " - "to full path to libglog.") -endif (NOT GLOG_LIBRARY OR - NOT EXISTS ${GLOG_LIBRARY}) -# Mark internally as found, then verify. GLOG_REPORT_NOT_FOUND() unsets -# if called. -set(GLOG_FOUND TRUE) + # Mark internally as found, then verify. GLOG_REPORT_NOT_FOUND() unsets + # if called. + set(GLOG_FOUND TRUE) -# Glog does not seem to provide any record of the version in its -# source tree, thus cannot extract version. + # Glog does not seem to provide any record of the version in its + # source tree, thus cannot extract version. -# Catch case when caller has set GLOG_INCLUDE_DIR in the cache / GUI and -# thus FIND_[PATH/LIBRARY] are not called, but specified locations are -# invalid, otherwise we would report the library as found. -if (GLOG_INCLUDE_DIR AND + # Catch case when caller has set GLOG_INCLUDE_DIR in the cache / GUI and + # thus FIND_[PATH/LIBRARY] are not called, but specified locations are + # invalid, otherwise we would report the library as found. + if (GLOG_INCLUDE_DIR AND + NOT EXISTS ${GLOG_INCLUDE_DIR}/glog/logging.h) + glog_report_not_found( + "Caller defined GLOG_INCLUDE_DIR:" + " ${GLOG_INCLUDE_DIR} does not contain glog/logging.h header.") + endif (GLOG_INCLUDE_DIR AND NOT EXISTS ${GLOG_INCLUDE_DIR}/glog/logging.h) - glog_report_not_found( - "Caller defined GLOG_INCLUDE_DIR:" - " ${GLOG_INCLUDE_DIR} does not contain glog/logging.h header.") -endif (GLOG_INCLUDE_DIR AND - NOT EXISTS ${GLOG_INCLUDE_DIR}/glog/logging.h) -# TODO: This regex for glog library is pretty primitive, we use lowercase -# for comparison to handle Windows using CamelCase library names, could -# this check be better? -string(TOLOWER "${GLOG_LIBRARY}" LOWERCASE_GLOG_LIBRARY) -if (GLOG_LIBRARY AND + # TODO: This regex for glog library is pretty primitive, we use lowercase + # for comparison to handle Windows using CamelCase library names, could + # this check be better? + string(TOLOWER "${GLOG_LIBRARY}" LOWERCASE_GLOG_LIBRARY) + if (GLOG_LIBRARY AND + NOT "${LOWERCASE_GLOG_LIBRARY}" MATCHES ".*glog[^/]*") + glog_report_not_found( + "Caller defined GLOG_LIBRARY: " + "${GLOG_LIBRARY} does not match glog.") + endif (GLOG_LIBRARY AND NOT "${LOWERCASE_GLOG_LIBRARY}" MATCHES ".*glog[^/]*") - glog_report_not_found( - "Caller defined GLOG_LIBRARY: " - "${GLOG_LIBRARY} does not match glog.") -endif (GLOG_LIBRARY AND - NOT "${LOWERCASE_GLOG_LIBRARY}" MATCHES ".*glog[^/]*") + + glog_reset_find_library_prefix() + +endif(NOT GLOG_FOUND) # Set standard CMake FindPackage variables if found. if (GLOG_FOUND) @@ -195,16 +295,25 @@ if (GLOG_FOUND) set(GLOG_LIBRARIES ${GLOG_LIBRARY}) endif (GLOG_FOUND) -glog_reset_find_library_prefix() +# If we are using an exported CMake glog target, the include directories are +# wrapped into the target itself, and do not have to be (and are not) +# separately specified. In which case, we should not add GLOG_INCLUDE_DIRS +# to the list of required variables in order that glog be reported as found. +if (FOUND_INSTALLED_GLOG_CMAKE_CONFIGURATION) + set(GLOG_REQUIRED_VARIABLES GLOG_LIBRARIES) +else() + set(GLOG_REQUIRED_VARIABLES GLOG_INCLUDE_DIRS GLOG_LIBRARIES) +endif() # Handle REQUIRED / QUIET optional arguments. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Glog DEFAULT_MSG - GLOG_INCLUDE_DIRS GLOG_LIBRARIES) + ${GLOG_REQUIRED_VARIABLES}) # Only mark internal variables as advanced if we found glog, otherwise # leave them visible in the standard GUI for the user to set manually. if (GLOG_FOUND) mark_as_advanced(FORCE GLOG_INCLUDE_DIR - GLOG_LIBRARY) + GLOG_LIBRARY + glog_DIR) # Autogenerated by find_package(glog) endif (GLOG_FOUND)