FindGit.cmake 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. # file LICENSE.rst or https://cmake.org/licensing for details.
  3. #[=======================================================================[.rst:
  4. FindGit
  5. -------
  6. Finds the Git distributed version control system:
  7. .. code-block:: cmake
  8. find_package(Git [<version>] [...])
  9. Imported Targets
  10. ^^^^^^^^^^^^^^^^
  11. This module provides the following :ref:`Imported Targets` when the
  12. :prop_gbl:`CMAKE_ROLE` is ``PROJECT``:
  13. ``Git::Git``
  14. .. versionadded:: 3.14
  15. Target that encapsulates Git command-line client executable. It can be used
  16. in :manual:`generator expressions <cmake-generator-expressions(7)>`, and
  17. commands like :command:`add_custom_target` and :command:`add_custom_command`.
  18. This target is available only if Git is found.
  19. Result Variables
  20. ^^^^^^^^^^^^^^^^
  21. This module defines the following variables:
  22. ``Git_FOUND``
  23. Boolean indicating whether the Git was found. For backward compatibility, the
  24. ``GIT_FOUND`` variable is also set to the same value.
  25. ``GIT_VERSION_STRING``
  26. The version of Git found.
  27. Cache Variables
  28. ^^^^^^^^^^^^^^^
  29. The following cache variables may also be set:
  30. ``GIT_EXECUTABLE``
  31. Path to the ``git`` command-line client executable.
  32. Examples
  33. ^^^^^^^^
  34. Finding Git and retrieving the latest commit from the project repository:
  35. .. code-block:: cmake
  36. find_package(Git)
  37. if(Git_FOUND)
  38. execute_process(
  39. COMMAND ${GIT_EXECUTABLE} --no-pager log -n 1 HEAD "--pretty=format:%h %s"
  40. OUTPUT_VARIABLE output
  41. RESULT_VARIABLE result
  42. ERROR_QUIET
  43. OUTPUT_STRIP_TRAILING_WHITESPACE
  44. )
  45. if(result EQUAL 0)
  46. message(STATUS "Last Git commit: ${output}")
  47. endif()
  48. endif()
  49. #]=======================================================================]
  50. # Look for 'git'
  51. #
  52. set(git_names git)
  53. # Prefer .cmd variants on Windows unless running in a Makefile
  54. # in the MSYS shell.
  55. #
  56. if(CMAKE_HOST_WIN32)
  57. if(NOT CMAKE_GENERATOR MATCHES "MSYS")
  58. set(git_names git.cmd git)
  59. # GitHub search path for Windows
  60. file(GLOB github_path
  61. "$ENV{LOCALAPPDATA}/Github/PortableGit*/cmd"
  62. "$ENV{LOCALAPPDATA}/Github/PortableGit*/bin"
  63. )
  64. # SourceTree search path for Windows
  65. set(_git_sourcetree_path "$ENV{LOCALAPPDATA}/Atlassian/SourceTree/git_local/bin")
  66. endif()
  67. endif()
  68. # First search the PATH and specific locations.
  69. find_program(GIT_EXECUTABLE
  70. NAMES ${git_names}
  71. PATHS ${github_path} ${_git_sourcetree_path}
  72. DOC "Git command line client"
  73. )
  74. if(CMAKE_HOST_WIN32)
  75. # Now look for installations in Git/ directories under typical installation
  76. # prefixes on Windows. Exclude PATH from this search because VS 2017's
  77. # command prompt happens to have a PATH entry with a Git/ subdirectory
  78. # containing a minimal git not meant for general use.
  79. find_program(GIT_EXECUTABLE
  80. NAMES ${git_names}
  81. PATH_SUFFIXES Git/cmd Git/bin
  82. NO_SYSTEM_ENVIRONMENT_PATH
  83. DOC "Git command line client"
  84. )
  85. endif()
  86. mark_as_advanced(GIT_EXECUTABLE)
  87. unset(git_names)
  88. unset(_git_sourcetree_path)
  89. if(GIT_EXECUTABLE)
  90. # Avoid querying the version if we've already done that this run. For
  91. # projects that use things like ExternalProject or FetchContent heavily,
  92. # this saving can be measurable on some platforms.
  93. #
  94. # This is an internal property, projects must not try to use it.
  95. # We don't want this stored in the cache because it might still change
  96. # between CMake runs, but it shouldn't change during a run for a given
  97. # git executable location.
  98. set(__doGitVersionCheck TRUE)
  99. get_property(__gitVersionProp GLOBAL
  100. PROPERTY _CMAKE_FindGit_GIT_EXECUTABLE_VERSION
  101. )
  102. if(__gitVersionProp)
  103. list(GET __gitVersionProp 0 __gitExe)
  104. list(GET __gitVersionProp 1 __gitVersion)
  105. if(__gitExe STREQUAL GIT_EXECUTABLE AND NOT __gitVersion STREQUAL "")
  106. set(GIT_VERSION_STRING "${__gitVersion}")
  107. set(__doGitVersionCheck FALSE)
  108. endif()
  109. unset(__gitExe)
  110. unset(__gitVersion)
  111. endif()
  112. unset(__gitVersionProp)
  113. if(__doGitVersionCheck)
  114. execute_process(COMMAND ${GIT_EXECUTABLE} --version
  115. OUTPUT_VARIABLE git_version
  116. ERROR_QUIET
  117. OUTPUT_STRIP_TRAILING_WHITESPACE)
  118. if (git_version MATCHES "^git version [0-9]")
  119. string(REPLACE "git version " "" GIT_VERSION_STRING "${git_version}")
  120. set_property(GLOBAL PROPERTY _CMAKE_FindGit_GIT_EXECUTABLE_VERSION
  121. "${GIT_EXECUTABLE};${GIT_VERSION_STRING}"
  122. )
  123. endif()
  124. unset(git_version)
  125. endif()
  126. unset(__doGitVersionCheck)
  127. get_property(_findgit_role GLOBAL PROPERTY CMAKE_ROLE)
  128. if(_findgit_role STREQUAL "PROJECT" AND NOT TARGET Git::Git)
  129. add_executable(Git::Git IMPORTED)
  130. set_property(TARGET Git::Git PROPERTY IMPORTED_LOCATION "${GIT_EXECUTABLE}")
  131. endif()
  132. unset(_findgit_role)
  133. endif()
  134. include(FindPackageHandleStandardArgs)
  135. find_package_handle_standard_args(Git
  136. REQUIRED_VARS GIT_EXECUTABLE
  137. VERSION_VAR GIT_VERSION_STRING)