blob: 32c04ea0cdf9c8a0245921d3f2f63a1e10c84820 [file] [log] [blame]
Austin Schuh70cc9552019-01-21 19:46:48 -08001# Ceres Solver - A fast non-linear least squares minimizer
2# Copyright 2015 Google Inc. All rights reserved.
3# http://ceres-solver.org/
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are met:
7#
8# * Redistributions of source code must retain the above copyright notice,
9# this list of conditions and the following disclaimer.
10# * Redistributions in binary form must reproduce the above copyright notice,
11# this list of conditions and the following disclaimer in the documentation
12# and/or other materials provided with the distribution.
13# * Neither the name of Google Inc. nor the names of its contributors may be
14# used to endorse or promote products derived from this software without
15# specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27# POSSIBILITY OF SUCH DAMAGE.
28#
29# Author: alexs.mac@gmail.com (Alex Stewart)
30#
31
32# FindGflags.cmake - Find Google gflags logging library.
33#
34# This module will attempt to find gflags, either via an exported CMake
35# configuration (generated by gflags >= 2.1 which are built with CMake), or
36# by performing a standard search for all gflags components. The order of
37# precedence for these two methods of finding gflags is controlled by:
38# GFLAGS_PREFER_EXPORTED_GFLAGS_CMAKE_CONFIGURATION.
39#
40# This module defines the following variables:
41#
42# GFLAGS_FOUND: TRUE iff gflags is found.
43# GFLAGS_INCLUDE_DIRS: Include directories for gflags.
44# GFLAGS_LIBRARIES: Libraries required to link gflags.
45# GFLAGS_NAMESPACE: The namespace in which gflags is defined. In versions of
46# gflags < 2.1, this was google, for versions >= 2.1 it is
47# by default gflags, although can be configured when building
48# gflags to be something else (i.e. google for legacy
49# compatibility).
50# FOUND_INSTALLED_GFLAGS_CMAKE_CONFIGURATION: True iff the version of gflags
51# found was built & installed /
52# exported as a CMake package.
53#
54# The following variables control the behaviour of this module when an exported
55# gflags CMake configuration is not found.
56#
57# GFLAGS_PREFER_EXPORTED_GFLAGS_CMAKE_CONFIGURATION: TRUE/FALSE, iff TRUE then
58# then prefer using an exported CMake configuration
59# generated by gflags >= 2.1 over searching for the
60# gflags components manually. Otherwise (FALSE)
61# ignore any exported gflags CMake configurations and
62# always perform a manual search for the components.
63# Default: TRUE iff user does not define this variable
64# before we are called, and does NOT specify either
65# GFLAGS_INCLUDE_DIR_HINTS or GFLAGS_LIBRARY_DIR_HINTS
66# otherwise FALSE.
67# GFLAGS_INCLUDE_DIR_HINTS: List of additional directories in which to
68# search for gflags includes, e.g: /timbuktu/include.
69# GFLAGS_LIBRARY_DIR_HINTS: List of additional directories in which to
70# search for gflags libraries, e.g: /timbuktu/lib.
71#
72# The following variables are also defined by this module, but in line with
73# CMake recommended FindPackage() module style should NOT be referenced directly
74# by callers (use the plural variables detailed above instead). These variables
75# do however affect the behaviour of the module via FIND_[PATH/LIBRARY]() which
76# are NOT re-called (i.e. search for library is not repeated) if these variables
77# are set with valid values _in the CMake cache_. This means that if these
78# variables are set directly in the cache, either by the user in the CMake GUI,
79# or by the user passing -DVAR=VALUE directives to CMake when called (which
80# explicitly defines a cache variable), then they will be used verbatim,
81# bypassing the HINTS variables and other hard-coded search locations.
82#
83# GFLAGS_INCLUDE_DIR: Include directory for gflags, not including the
84# include directory of any dependencies.
85# GFLAGS_LIBRARY: gflags library, not including the libraries of any
86# dependencies.
87
88# Reset CALLERS_CMAKE_FIND_LIBRARY_PREFIXES to its value when FindGflags was
89# invoked, necessary for MSVC.
90macro(GFLAGS_RESET_FIND_LIBRARY_PREFIX)
91 if (MSVC AND CALLERS_CMAKE_FIND_LIBRARY_PREFIXES)
92 set(CMAKE_FIND_LIBRARY_PREFIXES "${CALLERS_CMAKE_FIND_LIBRARY_PREFIXES}")
93 endif()
94endmacro(GFLAGS_RESET_FIND_LIBRARY_PREFIX)
95
96# Called if we failed to find gflags or any of it's required dependencies,
97# unsets all public (designed to be used externally) variables and reports
98# error message at priority depending upon [REQUIRED/QUIET/<NONE>] argument.
99macro(GFLAGS_REPORT_NOT_FOUND REASON_MSG)
100 unset(GFLAGS_FOUND)
101 unset(GFLAGS_INCLUDE_DIRS)
102 unset(GFLAGS_LIBRARIES)
103 # Do not use unset, as we want to keep GFLAGS_NAMESPACE in the cache,
104 # but simply clear its value.
105 set(GFLAGS_NAMESPACE "" CACHE STRING
106 "gflags namespace (google or gflags)" FORCE)
107
108 # Make results of search visible in the CMake GUI if gflags has not
109 # been found so that user does not have to toggle to advanced view.
110 mark_as_advanced(CLEAR GFLAGS_INCLUDE_DIR
111 GFLAGS_LIBRARY
112 GFLAGS_NAMESPACE)
113
114 gflags_reset_find_library_prefix()
115
116 # Note <package>_FIND_[REQUIRED/QUIETLY] variables defined by FindPackage()
117 # use the camelcase library name, not uppercase.
118 if (Gflags_FIND_QUIETLY)
119 message(STATUS "Failed to find gflags - " ${REASON_MSG} ${ARGN})
120 elseif (Gflags_FIND_REQUIRED)
121 message(FATAL_ERROR "Failed to find gflags - " ${REASON_MSG} ${ARGN})
122 else()
123 # Neither QUIETLY nor REQUIRED, use no priority which emits a message
124 # but continues configuration and allows generation.
125 message("-- Failed to find gflags - " ${REASON_MSG} ${ARGN})
126 endif ()
127 return()
128endmacro(GFLAGS_REPORT_NOT_FOUND)
129
130# Verify that all variable names passed as arguments are defined (can be empty
131# but must be defined) or raise a fatal error.
132macro(GFLAGS_CHECK_VARS_DEFINED)
133 foreach(CHECK_VAR ${ARGN})
134 if (NOT DEFINED ${CHECK_VAR})
135 message(FATAL_ERROR "Ceres Bug: ${CHECK_VAR} is not defined.")
136 endif()
137 endforeach()
138endmacro(GFLAGS_CHECK_VARS_DEFINED)
139
140# Use check_cxx_source_compiles() to compile trivial test programs to determine
141# the gflags namespace. This works on all OSs except Windows. If using Visual
142# Studio, it fails because msbuild forces check_cxx_source_compiles() to use
143# CMAKE_BUILD_TYPE=Debug for the test project, which usually breaks detection
144# because MSVC requires that the test project use the same build type as gflags,
145# which would normally be built in Release.
146#
147# Defines: GFLAGS_NAMESPACE in the caller's scope with the detected namespace,
148# which is blank (empty string, will test FALSE is CMake conditionals)
149# if detection failed.
150function(GFLAGS_CHECK_GFLAGS_NAMESPACE_USING_TRY_COMPILE)
151 # Verify that all required variables are defined.
152 gflags_check_vars_defined(
153 GFLAGS_INCLUDE_DIR GFLAGS_LIBRARY)
154 # Ensure that GFLAGS_NAMESPACE is always unset on completion unless
155 # we explicitly set if after having the correct namespace.
156 set(GFLAGS_NAMESPACE "" PARENT_SCOPE)
157
158 include(CheckCXXSourceCompiles)
159 # Setup include path & link library for gflags for CHECK_CXX_SOURCE_COMPILES.
160 set(CMAKE_REQUIRED_INCLUDES ${GFLAGS_INCLUDE_DIR})
161 set(CMAKE_REQUIRED_LIBRARIES ${GFLAGS_LIBRARY} ${GFLAGS_LINK_LIBRARIES})
162 # First try the (older) google namespace. Note that the output variable
163 # MUST be unique to the build type as otherwise the test is not repeated as
164 # it is assumed to have already been performed.
165 check_cxx_source_compiles(
166 "#include <gflags/gflags.h>
167 int main(int argc, char * argv[]) {
168 google::ParseCommandLineFlags(&argc, &argv, true);
169 return 0;
170 }"
171 GFLAGS_IN_GOOGLE_NAMESPACE)
172 if (GFLAGS_IN_GOOGLE_NAMESPACE)
173 set(GFLAGS_NAMESPACE google PARENT_SCOPE)
174 return()
175 endif()
176
177 # Try (newer) gflags namespace instead. Note that the output variable
178 # MUST be unique to the build type as otherwise the test is not repeated as
179 # it is assumed to have already been performed.
180 set(CMAKE_REQUIRED_INCLUDES ${GFLAGS_INCLUDE_DIR})
181 set(CMAKE_REQUIRED_LIBRARIES ${GFLAGS_LIBRARY} ${GFLAGS_LINK_LIBRARIES})
182 check_cxx_source_compiles(
183 "#include <gflags/gflags.h>
184 int main(int argc, char * argv[]) {
185 gflags::ParseCommandLineFlags(&argc, &argv, true);
186 return 0;
187 }"
188 GFLAGS_IN_GFLAGS_NAMESPACE)
189 if (GFLAGS_IN_GFLAGS_NAMESPACE)
190 set(GFLAGS_NAMESPACE gflags PARENT_SCOPE)
191 return()
192 endif (GFLAGS_IN_GFLAGS_NAMESPACE)
193endfunction(GFLAGS_CHECK_GFLAGS_NAMESPACE_USING_TRY_COMPILE)
194
195# Use regex on the gflags headers to attempt to determine the gflags namespace.
196# Checks both gflags.h (contained namespace on versions < 2.1.2) and
197# gflags_declare.h, which contains the namespace on versions >= 2.1.2.
198# In general, this method should only be used when
199# GFLAGS_CHECK_GFLAGS_NAMESPACE_USING_TRY_COMPILE() cannot be used, or has
200# failed.
201#
202# Defines: GFLAGS_NAMESPACE in the caller's scope with the detected namespace,
203# which is blank (empty string, will test FALSE is CMake conditionals)
204# if detection failed.
205function(GFLAGS_CHECK_GFLAGS_NAMESPACE_USING_REGEX)
206 # Verify that all required variables are defined.
207 gflags_check_vars_defined(GFLAGS_INCLUDE_DIR)
208 # Ensure that GFLAGS_NAMESPACE is always undefined on completion unless
209 # we explicitly set if after having the correct namespace.
210 set(GFLAGS_NAMESPACE "" PARENT_SCOPE)
211
212 # Scan gflags.h to identify what namespace gflags was built with. On
213 # versions of gflags < 2.1.2, gflags.h was configured with the namespace
214 # directly, on >= 2.1.2, gflags.h uses the GFLAGS_NAMESPACE #define which
215 # is defined in gflags_declare.h, we try each location in turn.
216 set(GFLAGS_HEADER_FILE ${GFLAGS_INCLUDE_DIR}/gflags/gflags.h)
217 if (NOT EXISTS ${GFLAGS_HEADER_FILE})
218 gflags_report_not_found(
219 "Could not find file: ${GFLAGS_HEADER_FILE} "
220 "containing namespace information in gflags install located at: "
221 "${GFLAGS_INCLUDE_DIR}.")
222 endif()
223 file(READ ${GFLAGS_HEADER_FILE} GFLAGS_HEADER_FILE_CONTENTS)
224
225 string(REGEX MATCH "namespace [A-Za-z]+"
226 GFLAGS_NAMESPACE "${GFLAGS_HEADER_FILE_CONTENTS}")
227 string(REGEX REPLACE "namespace ([A-Za-z]+)" "\\1"
228 GFLAGS_NAMESPACE "${GFLAGS_NAMESPACE}")
229
230 if (NOT GFLAGS_NAMESPACE)
231 gflags_report_not_found(
232 "Failed to extract gflags namespace from header file: "
233 "${GFLAGS_HEADER_FILE}.")
234 endif (NOT GFLAGS_NAMESPACE)
235
236 if (GFLAGS_NAMESPACE STREQUAL "google" OR
237 GFLAGS_NAMESPACE STREQUAL "gflags")
238 # Found valid gflags namespace from gflags.h.
239 set(GFLAGS_NAMESPACE "${GFLAGS_NAMESPACE}" PARENT_SCOPE)
240 return()
241 endif()
242
243 # Failed to find gflags namespace from gflags.h, gflags is likely a new
244 # version, check gflags_declare.h, which in newer versions (>= 2.1.2) contains
245 # the GFLAGS_NAMESPACE #define, which is then referenced in gflags.h.
246 set(GFLAGS_DECLARE_FILE ${GFLAGS_INCLUDE_DIR}/gflags/gflags_declare.h)
247 if (NOT EXISTS ${GFLAGS_DECLARE_FILE})
248 gflags_report_not_found(
249 "Could not find file: ${GFLAGS_DECLARE_FILE} "
250 "containing namespace information in gflags install located at: "
251 "${GFLAGS_INCLUDE_DIR}.")
252 endif()
253 file(READ ${GFLAGS_DECLARE_FILE} GFLAGS_DECLARE_FILE_CONTENTS)
254
255 string(REGEX MATCH "#define GFLAGS_NAMESPACE [A-Za-z]+"
256 GFLAGS_NAMESPACE "${GFLAGS_DECLARE_FILE_CONTENTS}")
257 string(REGEX REPLACE "#define GFLAGS_NAMESPACE ([A-Za-z]+)" "\\1"
258 GFLAGS_NAMESPACE "${GFLAGS_NAMESPACE}")
259
260 if (NOT GFLAGS_NAMESPACE)
261 gflags_report_not_found(
262 "Failed to extract gflags namespace from declare file: "
263 "${GFLAGS_DECLARE_FILE}.")
264 endif (NOT GFLAGS_NAMESPACE)
265
266 if (GFLAGS_NAMESPACE STREQUAL "google" OR
267 GFLAGS_NAMESPACE STREQUAL "gflags")
268 # Found valid gflags namespace from gflags.h.
269 set(GFLAGS_NAMESPACE "${GFLAGS_NAMESPACE}" PARENT_SCOPE)
270 return()
271 endif()
272endfunction(GFLAGS_CHECK_GFLAGS_NAMESPACE_USING_REGEX)
273
274# Protect against any alternative find_package scripts for this library having
275# been called previously (in a client project) which set GFLAGS_FOUND, but not
276# the other variables we require / set here which could cause the search logic
277# here to fail.
278unset(GFLAGS_FOUND)
279
280# -----------------------------------------------------------------
281# By default, if the user has expressed no preference for using an exported
282# gflags CMake configuration over performing a search for the installed
283# components, and has not specified any hints for the search locations, then
284# prefer a gflags exported configuration if available.
285if (NOT DEFINED GFLAGS_PREFER_EXPORTED_GFLAGS_CMAKE_CONFIGURATION
286 AND NOT GFLAGS_INCLUDE_DIR_HINTS
287 AND NOT GFLAGS_LIBRARY_DIR_HINTS)
288 message(STATUS "No preference for use of exported gflags CMake configuration "
289 "set, and no hints for include/library directories provided. "
290 "Defaulting to preferring an installed/exported gflags CMake configuration "
291 "if available.")
292 set(GFLAGS_PREFER_EXPORTED_GFLAGS_CMAKE_CONFIGURATION TRUE)
293endif()
294
295if (GFLAGS_PREFER_EXPORTED_GFLAGS_CMAKE_CONFIGURATION)
296 # Try to find an exported CMake configuration for gflags, as generated by
297 # gflags versions >= 2.1.
298 #
299 # We search twice, s/t we can invert the ordering of precedence used by
300 # find_package() for exported package build directories, and installed
301 # packages (found via CMAKE_SYSTEM_PREFIX_PATH), listed as items 6) and 7)
302 # respectively in [1].
303 #
304 # By default, exported build directories are (in theory) detected first, and
305 # this is usually the case on Windows. However, on OS X & Linux, the install
306 # path (/usr/local) is typically present in the PATH environment variable
307 # which is checked in item 4) in [1] (i.e. before both of the above, unless
308 # NO_SYSTEM_ENVIRONMENT_PATH is passed). As such on those OSs installed
309 # packages are usually detected in preference to exported package build
310 # directories.
311 #
312 # To ensure a more consistent response across all OSs, and as users usually
313 # want to prefer an installed version of a package over a locally built one
314 # where both exist (esp. as the exported build directory might be removed
315 # after installation), we first search with NO_CMAKE_PACKAGE_REGISTRY which
316 # means any build directories exported by the user are ignored, and thus
317 # installed directories are preferred. If this fails to find the package
318 # we then research again, but without NO_CMAKE_PACKAGE_REGISTRY, so any
319 # exported build directories will now be detected.
320 #
321 # To prevent confusion on Windows, we also pass NO_CMAKE_BUILDS_PATH (which
322 # is item 5) in [1]), to not preferentially use projects that were built
323 # recently with the CMake GUI to ensure that we always prefer an installed
324 # version if available.
325 #
326 # [1] http://www.cmake.org/cmake/help/v2.8.11/cmake.html#command:find_package
327 find_package(gflags QUIET
328 NO_MODULE
329 NO_CMAKE_PACKAGE_REGISTRY
330 NO_CMAKE_BUILDS_PATH)
331 if (gflags_FOUND)
332 message(STATUS "Found installed version of gflags: ${gflags_DIR}")
333 else(gflags_FOUND)
334 # Failed to find an installed version of gflags, repeat search allowing
335 # exported build directories.
336 message(STATUS "Failed to find installed gflags CMake configuration, "
337 "searching for gflags build directories exported with CMake.")
338 # Again pass NO_CMAKE_BUILDS_PATH, as we know that gflags is exported and
339 # do not want to treat projects built with the CMake GUI preferentially.
340 find_package(gflags QUIET
341 NO_MODULE
342 NO_CMAKE_BUILDS_PATH)
343 if (gflags_FOUND)
344 message(STATUS "Found exported gflags build directory: ${gflags_DIR}")
345 endif(gflags_FOUND)
346 endif(gflags_FOUND)
347
348 set(FOUND_INSTALLED_GFLAGS_CMAKE_CONFIGURATION ${gflags_FOUND})
349
350 # gflags v2.1 - 2.1.2 shipped with a bug in their gflags-config.cmake [1]
351 # whereby gflags_LIBRARIES = "gflags", but there was no imported target
352 # called "gflags", they were called: gflags[_nothreads]-[static/shared].
353 # As this causes linker errors when gflags is not installed in a location
354 # on the current library paths, detect if this problem is present and
355 # fix it.
356 #
357 # [1] https://github.com/gflags/gflags/issues/110
358 if (gflags_FOUND)
359 # NOTE: This is not written as additional conditions in the outer
360 # if (gflags_FOUND) as the NOT TARGET "${gflags_LIBRARIES}"
361 # condition causes problems if gflags is not found.
362 if (${gflags_VERSION} VERSION_LESS 2.1.3 AND
363 NOT TARGET "${gflags_LIBRARIES}")
364 message(STATUS "Detected broken gflags install in: ${gflags_DIR}, "
365 "version: ${gflags_VERSION} <= 2.1.2 which defines gflags_LIBRARIES = "
366 "${gflags_LIBRARIES} which is not an imported CMake target, see: "
367 "https://github.com/gflags/gflags/issues/110. Attempting to fix by "
368 "detecting correct gflags target.")
369 # Ordering here expresses preference for detection, specifically we do not
370 # want to use the _nothreads variants if the full library is available.
371 list(APPEND CHECK_GFLAGS_IMPORTED_TARGET_NAMES
372 gflags-shared gflags-static
373 gflags_nothreads-shared gflags_nothreads-static)
374 foreach(CHECK_GFLAGS_TARGET ${CHECK_GFLAGS_IMPORTED_TARGET_NAMES})
375 if (TARGET ${CHECK_GFLAGS_TARGET})
376 message(STATUS "Found valid gflags target: ${CHECK_GFLAGS_TARGET}, "
377 "updating gflags_LIBRARIES.")
378 set(gflags_LIBRARIES ${CHECK_GFLAGS_TARGET})
379 break()
380 endif()
381 endforeach()
382 if (NOT TARGET ${gflags_LIBRARIES})
383 message(STATUS "Failed to fix detected broken gflags install in: "
384 "${gflags_DIR}, version: ${gflags_VERSION} <= 2.1.2, none of the "
385 "imported targets for gflags: ${CHECK_GFLAGS_IMPORTED_TARGET_NAMES} "
386 "are defined. Will continue with a manual search for gflags "
387 "components. We recommend you build/install a version of gflags > "
388 "2.1.2 (or master).")
389 set(FOUND_INSTALLED_GFLAGS_CMAKE_CONFIGURATION FALSE)
390 endif()
391 endif()
392 endif()
393
394 if (FOUND_INSTALLED_GFLAGS_CMAKE_CONFIGURATION)
395 message(STATUS "Detected gflags version: ${gflags_VERSION}")
396 set(GFLAGS_FOUND ${gflags_FOUND})
397 set(GFLAGS_INCLUDE_DIR ${gflags_INCLUDE_DIR})
398 set(GFLAGS_LIBRARY ${gflags_LIBRARIES})
399
400 # gflags does not export the namespace in their CMake configuration, so
401 # use our function to determine what it should be, as it can be either
402 # gflags or google dependent upon version & configuration.
403 #
404 # NOTE: We use the regex method to determine the namespace here, as
405 # check_cxx_source_compiles() will not use imported targets, which
406 # is what gflags will be in this case.
407 gflags_check_gflags_namespace_using_regex()
408
409 if (NOT GFLAGS_NAMESPACE)
410 gflags_report_not_found(
411 "Failed to determine gflags namespace using regex for gflags "
412 "version: ${gflags_VERSION} exported here: ${gflags_DIR} using CMake.")
413 endif (NOT GFLAGS_NAMESPACE)
414 else (FOUND_INSTALLED_GFLAGS_CMAKE_CONFIGURATION)
415 message(STATUS "Failed to find an installed/exported CMake configuration "
416 "for gflags, will perform search for installed gflags components.")
417 endif (FOUND_INSTALLED_GFLAGS_CMAKE_CONFIGURATION)
418endif(GFLAGS_PREFER_EXPORTED_GFLAGS_CMAKE_CONFIGURATION)
419
420if (NOT GFLAGS_FOUND)
421 # Either failed to find an exported gflags CMake configuration, or user
422 # told us not to use one. Perform a manual search for all gflags components.
423
424 # Handle possible presence of lib prefix for libraries on MSVC, see
425 # also GFLAGS_RESET_FIND_LIBRARY_PREFIX().
426 if (MSVC)
427 # Preserve the caller's original values for CMAKE_FIND_LIBRARY_PREFIXES
428 # s/t we can set it back before returning.
429 set(CALLERS_CMAKE_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}")
430 # The empty string in this list is important, it represents the case when
431 # the libraries have no prefix (shared libraries / DLLs).
432 set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "" "${CMAKE_FIND_LIBRARY_PREFIXES}")
433 endif (MSVC)
434
435 # Search user-installed locations first, so that we prefer user installs
436 # to system installs where both exist.
437 list(APPEND GFLAGS_CHECK_INCLUDE_DIRS
438 /usr/local/include
439 /usr/local/homebrew/include # Mac OS X
440 /opt/local/var/macports/software # Mac OS X.
441 /opt/local/include
442 /usr/include)
443 list(APPEND GFLAGS_CHECK_PATH_SUFFIXES
444 gflags/include # Windows (for C:/Program Files prefix).
445 gflags/Include ) # Windows (for C:/Program Files prefix).
446
447 list(APPEND GFLAGS_CHECK_LIBRARY_DIRS
448 /usr/local/lib
449 /usr/local/homebrew/lib # Mac OS X.
450 /opt/local/lib
451 /usr/lib)
452 list(APPEND GFLAGS_CHECK_LIBRARY_SUFFIXES
453 gflags/lib # Windows (for C:/Program Files prefix).
454 gflags/Lib ) # Windows (for C:/Program Files prefix).
455
456 # Search supplied hint directories first if supplied.
457 find_path(GFLAGS_INCLUDE_DIR
458 NAMES gflags/gflags.h
459 HINTS ${GFLAGS_INCLUDE_DIR_HINTS}
460 PATHS ${GFLAGS_CHECK_INCLUDE_DIRS}
461 PATH_SUFFIXES ${GFLAGS_CHECK_PATH_SUFFIXES})
462 if (NOT GFLAGS_INCLUDE_DIR OR
463 NOT EXISTS ${GFLAGS_INCLUDE_DIR})
464 gflags_report_not_found(
465 "Could not find gflags include directory, set GFLAGS_INCLUDE_DIR "
466 "to directory containing gflags/gflags.h")
467 endif (NOT GFLAGS_INCLUDE_DIR OR
468 NOT EXISTS ${GFLAGS_INCLUDE_DIR})
469
470 find_library(GFLAGS_LIBRARY NAMES gflags
471 HINTS ${GFLAGS_LIBRARY_DIR_HINTS}
472 PATHS ${GFLAGS_CHECK_LIBRARY_DIRS}
473 PATH_SUFFIXES ${GFLAGS_CHECK_LIBRARY_SUFFIXES})
474 if (NOT GFLAGS_LIBRARY OR
475 NOT EXISTS ${GFLAGS_LIBRARY})
476 gflags_report_not_found(
477 "Could not find gflags library, set GFLAGS_LIBRARY "
478 "to full path to libgflags.")
479 endif (NOT GFLAGS_LIBRARY OR
480 NOT EXISTS ${GFLAGS_LIBRARY})
481
482 # gflags typically requires a threading library (which is OS dependent), note
483 # that this defines the CMAKE_THREAD_LIBS_INIT variable. If we are able to
484 # detect threads, we assume that gflags requires it.
485 find_package(Threads QUIET)
486 set(GFLAGS_LINK_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
487 # On Windows (including MinGW), the Shlwapi library is used by gflags if
488 # available.
489 if (WIN32)
490 include(CheckIncludeFileCXX)
491 check_include_file_cxx("shlwapi.h" HAVE_SHLWAPI)
492 if (HAVE_SHLWAPI)
493 list(APPEND GFLAGS_LINK_LIBRARIES shlwapi.lib)
494 endif(HAVE_SHLWAPI)
495 endif (WIN32)
496
497 # Mark internally as found, then verify. GFLAGS_REPORT_NOT_FOUND() unsets
498 # if called.
499 set(GFLAGS_FOUND TRUE)
500
501 # Identify what namespace gflags was built with.
502 if (GFLAGS_INCLUDE_DIR AND NOT GFLAGS_NAMESPACE)
503 # To handle Windows peculiarities / CMake bugs on MSVC we try two approaches
504 # to detect the gflags namespace:
505 #
506 # 1) Try to use check_cxx_source_compiles() to compile a trivial program
507 # with the two choices for the gflags namespace.
508 #
509 # 2) [In the event 1) fails] Use regex on the gflags headers to try to
510 # determine the gflags namespace. Whilst this is less robust than 1),
511 # it does avoid any interaction with msbuild.
512 gflags_check_gflags_namespace_using_try_compile()
513
514 if (NOT GFLAGS_NAMESPACE)
515 # Failed to determine gflags namespace using check_cxx_source_compiles()
516 # method, try and obtain it using regex on the gflags headers instead.
517 message(STATUS "Failed to find gflags namespace using using "
518 "check_cxx_source_compiles(), trying namespace regex instead, "
519 "this is expected on Windows.")
520 gflags_check_gflags_namespace_using_regex()
521
522 if (NOT GFLAGS_NAMESPACE)
523 gflags_report_not_found(
524 "Failed to determine gflags namespace either by "
525 "check_cxx_source_compiles(), or namespace regex.")
526 endif (NOT GFLAGS_NAMESPACE)
527 endif (NOT GFLAGS_NAMESPACE)
528 endif (GFLAGS_INCLUDE_DIR AND NOT GFLAGS_NAMESPACE)
529
530 # Make the GFLAGS_NAMESPACE a cache variable s/t the user can view it, and could
531 # overwrite it in the CMake GUI.
532 set(GFLAGS_NAMESPACE "${GFLAGS_NAMESPACE}" CACHE STRING
533 "gflags namespace (google or gflags)" FORCE)
534
535 # gflags does not seem to provide any record of the version in its
536 # source tree, thus cannot extract version.
537
538 # Catch case when caller has set GFLAGS_NAMESPACE in the cache / GUI
539 # with an invalid value.
540 if (GFLAGS_NAMESPACE AND
541 NOT GFLAGS_NAMESPACE STREQUAL "google" AND
542 NOT GFLAGS_NAMESPACE STREQUAL "gflags")
543 gflags_report_not_found(
544 "Caller defined GFLAGS_NAMESPACE:"
545 " ${GFLAGS_NAMESPACE} is not valid, not google or gflags.")
546 endif ()
547 # Catch case when caller has set GFLAGS_INCLUDE_DIR in the cache / GUI and
548 # thus FIND_[PATH/LIBRARY] are not called, but specified locations are
549 # invalid, otherwise we would report the library as found.
550 if (GFLAGS_INCLUDE_DIR AND
551 NOT EXISTS ${GFLAGS_INCLUDE_DIR}/gflags/gflags.h)
552 gflags_report_not_found(
553 "Caller defined GFLAGS_INCLUDE_DIR:"
554 " ${GFLAGS_INCLUDE_DIR} does not contain gflags/gflags.h header.")
555 endif (GFLAGS_INCLUDE_DIR AND
556 NOT EXISTS ${GFLAGS_INCLUDE_DIR}/gflags/gflags.h)
557 # TODO: This regex for gflags library is pretty primitive, we use lowercase
558 # for comparison to handle Windows using CamelCase library names, could
559 # this check be better?
560 string(TOLOWER "${GFLAGS_LIBRARY}" LOWERCASE_GFLAGS_LIBRARY)
561 if (GFLAGS_LIBRARY AND
562 NOT "${LOWERCASE_GFLAGS_LIBRARY}" MATCHES ".*gflags[^/]*")
563 gflags_report_not_found(
564 "Caller defined GFLAGS_LIBRARY: "
565 "${GFLAGS_LIBRARY} does not match gflags.")
566 endif (GFLAGS_LIBRARY AND
567 NOT "${LOWERCASE_GFLAGS_LIBRARY}" MATCHES ".*gflags[^/]*")
568
569 gflags_reset_find_library_prefix()
570
571endif(NOT GFLAGS_FOUND)
572
573# Set standard CMake FindPackage variables if found.
574if (GFLAGS_FOUND)
575 set(GFLAGS_INCLUDE_DIRS ${GFLAGS_INCLUDE_DIR})
576 set(GFLAGS_LIBRARIES ${GFLAGS_LIBRARY} ${GFLAGS_LINK_LIBRARIES})
577endif (GFLAGS_FOUND)
578
579# Handle REQUIRED / QUIET optional arguments.
580include(FindPackageHandleStandardArgs)
581find_package_handle_standard_args(Gflags DEFAULT_MSG
582 GFLAGS_INCLUDE_DIRS GFLAGS_LIBRARIES GFLAGS_NAMESPACE)
583
584# Only mark internal variables as advanced if we found gflags, otherwise
585# leave them visible in the standard GUI for the user to set manually.
586if (GFLAGS_FOUND)
587 mark_as_advanced(FORCE GFLAGS_INCLUDE_DIR
588 GFLAGS_LIBRARY
589 GFLAGS_NAMESPACE
590 gflags_DIR) # Autogenerated by find_package(gflags)
591endif (GFLAGS_FOUND)