Simple Directmedia Layer

cmake: generate git hash using GetRevisionDescription CMake module

This allows the build system (ninja/make/VS) to detect whether the current
checkout git commit has changed. If so, SDL_revision.h will be updated.

authored by Anonymous Maarten and committed by Anonymous Maarten f53d797c d4f7b0aa

+14 -31
CMakeLists.txt
··· 1 1 if(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) 2 - message(FATAL_ERROR "Prevented in-tree build. Please create a build directory outside of the SDL source code and run \"cmake -S ${CMAKE_SOURCE_DIR} -B .\" from there") 2 + message(FATAL_ERROR "Prevented in-tree build. Please create a build directory outside of the SDL source code and run \"cmake -S ${CMAKE_SOURCE_DIR} -B .\" from there") 3 3 endif() 4 4 5 5 cmake_minimum_required(VERSION 3.0.0) ··· 74 74 include(${SDL3_SOURCE_DIR}/cmake/sdlchecks.cmake) 75 75 include(${SDL3_SOURCE_DIR}/cmake/sdlplatform.cmake) 76 76 include(${SDL3_SOURCE_DIR}/cmake/CheckCPUArchitecture.cmake) 77 + include(${SDL3_SOURCE_DIR}/cmake/GetGitRevisionDescription.cmake) 77 78 78 79 # Enable large file support on 32-bit glibc, so that we can access files 79 80 # with large inode numbers ··· 2843 2844 endif() 2844 2845 endforeach() 2845 2846 2846 - # Compat helpers for the configuration files 2847 - 2848 - if(EXISTS "${PROJECT_SOURCE_DIR}/VERSION.txt") 2849 - file(READ "${PROJECT_SOURCE_DIR}/VERSION.txt" SDL_SOURCE_VERSION) 2850 - string(STRIP "${SDL_SOURCE_VERSION}" SDL_SOURCE_VERSION) 2851 - endif() 2852 - 2853 - find_package(Git) 2854 - if(Git_FOUND) 2855 - execute_process(COMMAND 2856 - "${GIT_EXECUTABLE}" describe --always --tags --long 2857 - WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" 2858 - RESULT_VARIABLE GIT_REVISION_STATUS 2859 - OUTPUT_VARIABLE GIT_REVISION 2860 - ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) 2847 + set(SDL_REVISION_SUFFIX "" CACHE STRING "Suffix for the SDL revision") 2848 + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION.txt") 2849 + # If VERSION exists, it contains the SDL version 2850 + file(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION.txt" SDL_REVISION_CENTER) 2851 + string(STRIP "${SDL_REVISION_CENTER}" SDL_REVISION_CENTER) 2861 2852 else() 2862 - set(GIT_REVISION_STATUS 1) 2863 - set(GIT_REVISION "") 2864 - endif() 2865 - 2866 - if(SDL_SOURCE_VERSION) 2867 - set(SDL_REVISION "SDL-${SDL_SOURCE_VERSION}") 2868 - elseif(GIT_REVISION_STATUS EQUAL 0) 2869 - if(GIT_REVISION MATCHES "^[0-9a-f]+$") 2870 - # Just a truncated sha1, so prefix it with the version number 2871 - set(SDL_REVISION "SDL-${SDL_VERSION}-g${GIT_REVISION}") 2872 - else() 2873 - # e.g. release-2.24.0-542-g96361fc47 2874 - set(SDL_REVISION "SDL-${GIT_REVISION}") 2853 + # If VERSION does not exist, use git to calculate a version 2854 + git_describe(SDL_REVISION_CENTER) 2855 + if(NOT SDL_REVISION_CENTER) 2856 + set(SDL_REVISION_CENTER "${SDL_VERSION}-no-vcs") 2875 2857 endif() 2876 - else() 2877 - set(SDL_REVISION "SDL-${SDL_VERSION}-no-vcs") 2878 2858 endif() 2859 + set(SDL_REVISION "SDL-${SDL_REVISION_CENTER}${SDL_REVISION_SUFFIX}") 2879 2860 2880 2861 execute_process(COMMAND "${CMAKE_COMMAND}" -E make_directory "${SDL3_BINARY_DIR}/include/SDL3") 2881 2862 configure_file("${SDL3_SOURCE_DIR}/include/build_config/SDL_revision.h.cmake" ··· 2887 2868 else() 2888 2869 set(sdl_static_libname "SDL3") 2889 2870 endif() 2871 + 2872 + # Clean up variables for sdl3.pc 2890 2873 2891 2874 if(SDL_SHARED) 2892 2875 set(PKGCONFIG_LIBS_PRIV "\nLibs.private:")
+284
cmake/GetGitRevisionDescription.cmake
··· 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 + 46 + if(__get_git_revision_description) 47 + return() 48 + endif() 49 + set(__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 53 + get_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 wil return 63 + # C:/bla/.git 64 + # 65 + function(_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) 84 + endfunction() 85 + 86 + function(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) 173 + endfunction() 174 + 175 + function(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) 216 + endfunction() 217 + 218 + function(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) 242 + endfunction() 243 + 244 + function(git_get_exact_tag _var) 245 + git_describe(out --exact-match ${ARGN}) 246 + set(${_var} 247 + "${out}" 248 + PARENT_SCOPE) 249 + endfunction() 250 + 251 + function(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() 284 + endfunction()
+43
cmake/GetGitRevisionDescription.cmake.in
··· 1 + # 2 + # Internal file for GetGitRevisionDescription.cmake 3 + # 4 + # Requires CMake 2.6 or newer (uses the 'function' command) 5 + # 6 + # Original Author: 7 + # 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net> 8 + # http://academic.cleardefinition.com 9 + # Iowa State University HCI Graduate Program/VRAC 10 + # 11 + # Copyright 2009-2012, Iowa State University 12 + # Copyright 2011-2015, Contributors 13 + # Distributed under the Boost Software License, Version 1.0. 14 + # (See accompanying file LICENSE_1_0.txt or copy at 15 + # http://www.boost.org/LICENSE_1_0.txt) 16 + # SPDX-License-Identifier: BSL-1.0 17 + 18 + set(HEAD_HASH) 19 + 20 + file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) 21 + 22 + string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) 23 + if(HEAD_CONTENTS MATCHES "ref") 24 + # named branch 25 + string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") 26 + if(EXISTS "@GIT_DIR@/${HEAD_REF}") 27 + configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) 28 + else() 29 + configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) 30 + file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) 31 + if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") 32 + set(HEAD_HASH "${CMAKE_MATCH_1}") 33 + endif() 34 + endif() 35 + else() 36 + # detached HEAD 37 + configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) 38 + endif() 39 + 40 + if(NOT HEAD_HASH) 41 + file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) 42 + string(STRIP "${HEAD_HASH}" HEAD_HASH) 43 + endif()
-1
include/SDL3/SDL.h
··· 64 64 #include <SDL3/SDL_quit.h> 65 65 #include <SDL3/SDL_rect.h> 66 66 #include <SDL3/SDL_render.h> 67 - #include <SDL3/SDL_revision.h> 68 67 #include <SDL3/SDL_rwops.h> 69 68 #include <SDL3/SDL_scancode.h> 70 69 #include <SDL3/SDL_sensor.h>
+1
src/SDL.c
··· 19 19 3. This notice may not be removed or altered from any source distribution. 20 20 */ 21 21 #include "SDL_internal.h" 22 + #include "SDL3/SDL_revision.h" 22 23 23 24 #if defined(__WIN32__) || defined(__GDK__) 24 25 #include "core/windows/SDL_windows.h"
+1
test/testver.c
··· 15 15 */ 16 16 #include <SDL3/SDL.h> 17 17 #include <SDL3/SDL_main.h> 18 + #include <SDL3/SDL_revision.h> 18 19 19 20 int main(int argc, char *argv[]) 20 21 {