From ded631dad6301fac78377aaa3f401af627256a3d Mon Sep 17 00:00:00 2001 From: Daniel Evans Date: Sat, 2 Jul 2016 23:00:11 +0100 Subject: [PATCH] Add Git SHA1 hash to RWGame for versioning --- CMakeLists.txt | 4 + cmake/modules/GetGitRevisionDescription.cmake | 130 ++++++++++++++++++ .../GetGitRevisionDescription.cmake.in | 41 ++++++ rwgame/CMakeLists.txt | 10 +- rwgame/GameWindow.cpp | 4 +- rwgame/GameWindow.hpp | 2 +- rwgame/GitSHA1.cpp.in | 2 + rwgame/GitSHA1.h | 1 + rwgame/RWGame.cpp | 9 +- tests/test_globals.hpp | 2 +- 10 files changed, 199 insertions(+), 6 deletions(-) create mode 100644 cmake/modules/GetGitRevisionDescription.cmake create mode 100644 cmake/modules/GetGitRevisionDescription.cmake.in create mode 100644 rwgame/GitSHA1.cpp.in create mode 100644 rwgame/GitSHA1.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f2daf792..f6fb10fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,6 +100,10 @@ include_directories( # External-internal dependencies add_subdirectory(cmake/external) +# Include git hash in source +include(GetGitRevisionDescription) +get_git_head_revision(GIT_REFSPEC GIT_SHA1) + # # Components # diff --git a/cmake/modules/GetGitRevisionDescription.cmake b/cmake/modules/GetGitRevisionDescription.cmake new file mode 100644 index 00000000..85eae156 --- /dev/null +++ b/cmake/modules/GetGitRevisionDescription.cmake @@ -0,0 +1,130 @@ +# - Returns a version string from Git +# +# These functions force a re-configure on each git commit so that you can +# trust the values of the variables in your build system. +# +# get_git_head_revision( [ ...]) +# +# Returns the refspec and sha hash of the current head revision +# +# git_describe( [ ...]) +# +# Returns the results of git describe on the source tree, and adjusting +# the output so that it tests false if an error occurs. +# +# git_get_exact_tag( [ ...]) +# +# Returns the results of git describe --exact-match on the source tree, +# and adjusting the output so that it tests false if there was no exact +# matching tag. +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +if(__get_git_revision_description) + return() +endif() +set(__get_git_revision_description YES) + +# We must run the following at "include" time, not at function call time, +# to find the path to this module rather than the path to a calling list file +get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) + +function(get_git_head_revision _refspecvar _hashvar) + set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + set(GIT_DIR "${GIT_PARENT_DIR}/.git") + while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories + set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") + get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH) + if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT) + # We have reached the root directory, we are not in git + set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE) + set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE) + return() + endif() + set(GIT_DIR "${GIT_PARENT_DIR}/.git") + endwhile() + # check if this is a submodule + if(NOT IS_DIRECTORY ${GIT_DIR}) + file(READ ${GIT_DIR} submodule) + string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) + get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) + get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE) + endif() + set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") + if(NOT EXISTS "${GIT_DATA}") + file(MAKE_DIRECTORY "${GIT_DATA}") + endif() + + if(NOT EXISTS "${GIT_DIR}/HEAD") + return() + endif() + set(HEAD_FILE "${GIT_DATA}/HEAD") + configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) + + configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" + "${GIT_DATA}/grabRef.cmake" + @ONLY) + include("${GIT_DATA}/grabRef.cmake") + + set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE) + set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE) +endfunction() + +function(git_describe _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash) + if(NOT GIT_FOUND) + set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) + return() + endif() + if(NOT hash) + set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) + return() + endif() + + # TODO sanitize + #if((${ARGN}" MATCHES "&&") OR + # (ARGN MATCHES "||") OR + # (ARGN MATCHES "\\;")) + # message("Please report the following error to the project!") + # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") + #endif() + + #message(STATUS "Arguments to execute_process: ${ARGN}") + + execute_process(COMMAND + "${GIT_EXECUTABLE}" + describe + ${hash} + ${ARGN} + WORKING_DIRECTORY + "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE + res + OUTPUT_VARIABLE + out + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT res EQUAL 0) + set(out "${out}-${res}-NOTFOUND") + endif() + + set(${_var} "${out}" PARENT_SCOPE) +endfunction() + +function(git_get_exact_tag _var) + git_describe(out --exact-match ${ARGN}) + set(${_var} "${out}" PARENT_SCOPE) +endfunction() diff --git a/cmake/modules/GetGitRevisionDescription.cmake.in b/cmake/modules/GetGitRevisionDescription.cmake.in new file mode 100644 index 00000000..6d8b708e --- /dev/null +++ b/cmake/modules/GetGitRevisionDescription.cmake.in @@ -0,0 +1,41 @@ +# +# Internal file for GetGitRevisionDescription.cmake +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +set(HEAD_HASH) + +file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) + +string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) +if(HEAD_CONTENTS MATCHES "ref") + # named branch + string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") + if(EXISTS "@GIT_DIR@/${HEAD_REF}") + configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) + else() + configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) + file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) + if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") + set(HEAD_HASH "${CMAKE_MATCH_1}") + endif() + endif() +else() + # detached HEAD + configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) +endif() + +if(NOT HEAD_HASH) + file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) + string(STRIP "${HEAD_HASH}" HEAD_HASH) +endif() diff --git a/rwgame/CMakeLists.txt b/rwgame/CMakeLists.txt index 09c41faf..2647df08 100644 --- a/rwgame/CMakeLists.txt +++ b/rwgame/CMakeLists.txt @@ -1,4 +1,9 @@ -add_executable(rwgame +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/GitSHA1.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/GitSHA1.cpp" @ONLY) + +set(RWGAME_SOURCES + GitSHA1.h + "${CMAKE_CURRENT_BINARY_DIR}/GitSHA1.cpp" + main.cpp RWGame.cpp @@ -21,6 +26,9 @@ add_executable(rwgame debug/TcpSocket.cpp ) +add_executable(rwgame + ${RWGAME_SOURCES}) + include_directories(SYSTEM ${BULLET_INCLUDE_DIR} ${OPENAL_INCLUDE_DIR} diff --git a/rwgame/GameWindow.cpp b/rwgame/GameWindow.cpp index 1105f73b..2dc70d21 100644 --- a/rwgame/GameWindow.cpp +++ b/rwgame/GameWindow.cpp @@ -11,7 +11,7 @@ GameWindow::GameWindow() : } -void GameWindow::create(size_t w, size_t h, bool fullscreen) +void GameWindow::create(const std::string& title, size_t w, size_t h, bool fullscreen) { uint32_t style = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; if (fullscreen) @@ -24,7 +24,7 @@ void GameWindow::create(size_t w, size_t h, bool fullscreen) SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); - window = SDL_CreateWindow("RWGame", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, h, style); + window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, h, style); glcontext = SDL_GL_CreateContext(window); } diff --git a/rwgame/GameWindow.hpp b/rwgame/GameWindow.hpp index e094b249..bed90396 100644 --- a/rwgame/GameWindow.hpp +++ b/rwgame/GameWindow.hpp @@ -16,7 +16,7 @@ class GameWindow public: GameWindow(); - void create(size_t w, size_t h, bool fullscreen); + void create(const std::string& title, size_t w, size_t h, bool fullscreen); void close(); void showCursor(); diff --git a/rwgame/GitSHA1.cpp.in b/rwgame/GitSHA1.cpp.in new file mode 100644 index 00000000..407158cd --- /dev/null +++ b/rwgame/GitSHA1.cpp.in @@ -0,0 +1,2 @@ +#define GIT_SHA1 "@GIT_SHA1@" +const char* kGitSHA1Hash = GIT_SHA1; diff --git a/rwgame/GitSHA1.h b/rwgame/GitSHA1.h new file mode 100644 index 00000000..6bc60232 --- /dev/null +++ b/rwgame/GitSHA1.h @@ -0,0 +1 @@ +extern const char* kGitSHA1Hash; diff --git a/rwgame/RWGame.cpp b/rwgame/RWGame.cpp index 94094082..b5bf4c7c 100644 --- a/rwgame/RWGame.cpp +++ b/rwgame/RWGame.cpp @@ -26,6 +26,12 @@ #include #include +#include "GitSHA1.h" + +// Use first 8 chars of git hash as the build string +const std::string kBuildStr(kGitSHA1Hash, 8); +const std::string kWindowTitle = "RWGame"; + #define MOUSE_SENSITIVITY_SCALE 2.5f DebugDraw* debug; @@ -92,13 +98,14 @@ RWGame::RWGame(int argc, char* argv[]) throw std::runtime_error("Failed to initialize SDL2!"); window = new GameWindow(); - window->create(w, h, fullscreen); + window->create(kWindowTitle + " [" + kBuildStr + "]", w, h, fullscreen); window->hideCursor(); work = new WorkContext(); log.addReciever(&logPrinter); log.info("Game", "Game directory: " + config.getGameDataPath()); + log.info("Game", "Build: " + kBuildStr); if(! GameData::isValidGameDirectory(config.getGameDataPath()) ) { diff --git a/tests/test_globals.hpp b/tests/test_globals.hpp index b011ca4f..8ade5c13 100644 --- a/tests/test_globals.hpp +++ b/tests/test_globals.hpp @@ -61,7 +61,7 @@ public: if (SDL_Init(SDL_INIT_VIDEO) < 0) throw std::runtime_error("Failed to initialize SDL2!"); - window.create(800, 600, false); + window.create("Tests", 800, 600, false); window.hideCursor(); #if RW_TEST_WITH_DATA