Simple Directmedia Layer
at main 9.5 kB view raw
1# - Returns a version string from Git 2# 3# These functions force a re-configure on each git commit so that you can 4# trust the values of the variables in your build system. 5# 6# get_git_head_revision(<refspecvar> <hashvar> [ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR]) 7# 8# Returns the refspec and sha hash of the current head revision 9# 10# git_describe(<var> [<additional arguments to git describe> ...]) 11# 12# Returns the results of git describe on the source tree, and adjusting 13# the output so that it tests false if an error occurs. 14# 15# git_describe_working_tree(<var> [<additional arguments to git describe> ...]) 16# 17# Returns the results of git describe on the working tree (--dirty option), 18# and adjusting the output so that it tests false if an error occurs. 19# 20# git_get_exact_tag(<var> [<additional arguments to git describe> ...]) 21# 22# Returns the results of git describe --exact-match on the source tree, 23# and adjusting the output so that it tests false if there was no exact 24# matching tag. 25# 26# git_local_changes(<var>) 27# 28# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes. 29# Uses the return code of "git diff-index --quiet HEAD --". 30# Does not regard untracked files. 31# 32# Requires CMake 2.6 or newer (uses the 'function' command) 33# 34# Original Author: 35# 2009-2020 Ryan Pavlik <ryan.pavlik@gmail.com> <abiryan@ryand.net> 36# http://academic.cleardefinition.com 37# 38# Copyright 2009-2013, Iowa State University. 39# Copyright 2013-2020, Ryan Pavlik 40# Copyright 2013-2020, Contributors 41# SPDX-License-Identifier: BSL-1.0 42# Distributed under the Boost Software License, Version 1.0. 43# (See accompanying file LICENSE_1_0.txt or copy at 44# http://www.boost.org/LICENSE_1_0.txt) 45 46if(__get_git_revision_description) 47 return() 48endif() 49set(__get_git_revision_description YES) 50 51# We must run the following at "include" time, not at function call time, 52# to find the path to this module rather than the path to a calling list file 53get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) 54 55# Function _git_find_closest_git_dir finds the next closest .git directory 56# that is part of any directory in the path defined by _start_dir. 57# The result is returned in the parent scope variable whose name is passed 58# as variable _git_dir_var. If no .git directory can be found, the 59# function returns an empty string via _git_dir_var. 60# 61# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and 62# neither foo nor bar contain a file/directory .git. This will return 63# C:/bla/.git 64# 65function(_git_find_closest_git_dir _start_dir _git_dir_var) 66 set(cur_dir "${_start_dir}") 67 set(git_dir "${_start_dir}/.git") 68 while(NOT EXISTS "${git_dir}") 69 # .git dir not found, search parent directories 70 set(git_previous_parent "${cur_dir}") 71 get_filename_component(cur_dir "${cur_dir}" DIRECTORY) 72 if(cur_dir STREQUAL git_previous_parent) 73 # We have reached the root directory, we are not in git 74 set(${_git_dir_var} 75 "" 76 PARENT_SCOPE) 77 return() 78 endif() 79 set(git_dir "${cur_dir}/.git") 80 endwhile() 81 set(${_git_dir_var} 82 "${git_dir}" 83 PARENT_SCOPE) 84endfunction() 85 86function(get_git_head_revision _refspecvar _hashvar) 87 _git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR) 88 89 if("${ARGN}" STREQUAL "ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR") 90 set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR TRUE) 91 else() 92 set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR FALSE) 93 endif() 94 if(NOT "${GIT_DIR}" STREQUAL "") 95 file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}" 96 "${GIT_DIR}") 97 if("${_relative_to_source_dir}" MATCHES "[.][.]" AND NOT ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR) 98 # We've gone above the CMake root dir. 99 set(GIT_DIR "") 100 endif() 101 endif() 102 if("${GIT_DIR}" STREQUAL "") 103 set(${_refspecvar} 104 "GITDIR-NOTFOUND" 105 PARENT_SCOPE) 106 set(${_hashvar} 107 "GITDIR-NOTFOUND" 108 PARENT_SCOPE) 109 return() 110 endif() 111 112 # Check if the current source dir is a git submodule or a worktree. 113 # In both cases .git is a file instead of a directory. 114 # 115 if(NOT IS_DIRECTORY ${GIT_DIR}) 116 # The following git command will return a non empty string that 117 # points to the super project working tree if the current 118 # source dir is inside a git submodule. 119 # Otherwise the command will return an empty string. 120 # 121 execute_process( 122 COMMAND "${GIT_EXECUTABLE}" rev-parse 123 --show-superproject-working-tree 124 WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 125 OUTPUT_VARIABLE out 126 ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) 127 if(NOT "${out}" STREQUAL "") 128 # If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule 129 file(READ ${GIT_DIR} submodule) 130 string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE 131 ${submodule}) 132 string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE) 133 get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) 134 get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} 135 ABSOLUTE) 136 set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD") 137 else() 138 # GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree 139 file(READ ${GIT_DIR} worktree_ref) 140 # The .git directory contains a path to the worktree information directory 141 # inside the parent git repo of the worktree. 142 # 143 string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir 144 ${worktree_ref}) 145 string(STRIP ${git_worktree_dir} git_worktree_dir) 146 _git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR) 147 set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD") 148 endif() 149 else() 150 set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD") 151 endif() 152 set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") 153 if(NOT EXISTS "${GIT_DATA}") 154 file(MAKE_DIRECTORY "${GIT_DATA}") 155 endif() 156 157 if(NOT EXISTS "${HEAD_SOURCE_FILE}") 158 return() 159 endif() 160 set(HEAD_FILE "${GIT_DATA}/HEAD") 161 configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY) 162 163 configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" 164 "${GIT_DATA}/grabRef.cmake" @ONLY) 165 include("${GIT_DATA}/grabRef.cmake") 166 167 set(${_refspecvar} 168 "${HEAD_REF}" 169 PARENT_SCOPE) 170 set(${_hashvar} 171 "${HEAD_HASH}" 172 PARENT_SCOPE) 173endfunction() 174 175function(git_describe _var) 176 if(NOT GIT_FOUND) 177 find_package(Git QUIET) 178 endif() 179 get_git_head_revision(refspec hash) 180 if(NOT GIT_FOUND) 181 set(${_var} 182 "GIT-NOTFOUND" 183 PARENT_SCOPE) 184 return() 185 endif() 186 if(NOT hash) 187 set(${_var} 188 "HEAD-HASH-NOTFOUND" 189 PARENT_SCOPE) 190 return() 191 endif() 192 193 # TODO sanitize 194 #if((${ARGN}" MATCHES "&&") OR 195 # (ARGN MATCHES "||") OR 196 # (ARGN MATCHES "\\;")) 197 # message("Please report the following error to the project!") 198 # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") 199 #endif() 200 201 #message(STATUS "Arguments to execute_process: ${ARGN}") 202 203 execute_process( 204 COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN} 205 WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 206 RESULT_VARIABLE res 207 OUTPUT_VARIABLE out 208 ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) 209 if(NOT res EQUAL 0) 210 set(out "${out}-${res}-NOTFOUND") 211 endif() 212 213 set(${_var} 214 "${out}" 215 PARENT_SCOPE) 216endfunction() 217 218function(git_describe_working_tree _var) 219 if(NOT GIT_FOUND) 220 find_package(Git QUIET) 221 endif() 222 if(NOT GIT_FOUND) 223 set(${_var} 224 "GIT-NOTFOUND" 225 PARENT_SCOPE) 226 return() 227 endif() 228 229 execute_process( 230 COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN} 231 WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 232 RESULT_VARIABLE res 233 OUTPUT_VARIABLE out 234 ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) 235 if(NOT res EQUAL 0) 236 set(out "${out}-${res}-NOTFOUND") 237 endif() 238 239 set(${_var} 240 "${out}" 241 PARENT_SCOPE) 242endfunction() 243 244function(git_get_exact_tag _var) 245 git_describe(out --exact-match ${ARGN}) 246 set(${_var} 247 "${out}" 248 PARENT_SCOPE) 249endfunction() 250 251function(git_local_changes _var) 252 if(NOT GIT_FOUND) 253 find_package(Git QUIET) 254 endif() 255 get_git_head_revision(refspec hash) 256 if(NOT GIT_FOUND) 257 set(${_var} 258 "GIT-NOTFOUND" 259 PARENT_SCOPE) 260 return() 261 endif() 262 if(NOT hash) 263 set(${_var} 264 "HEAD-HASH-NOTFOUND" 265 PARENT_SCOPE) 266 return() 267 endif() 268 269 execute_process( 270 COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD -- 271 WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 272 RESULT_VARIABLE res 273 OUTPUT_VARIABLE out 274 ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) 275 if(res EQUAL 0) 276 set(${_var} 277 "CLEAN" 278 PARENT_SCOPE) 279 else() 280 set(${_var} 281 "DIRTY" 282 PARENT_SCOPE) 283 endif() 284endfunction()