From dcc26c5d7abf4164f506c024247c6884c227b8a7 Mon Sep 17 00:00:00 2001 From: Dasperal Date: Sat, 19 Oct 2024 16:55:08 +0300 Subject: [PATCH] Get the package version from git on CI --- .devcontainer/Dockerfile | 2 +- .github/workflows/continuous-integration.yml | 9 +- CMakeLists.txt | 23 ++- cmake/UpdateRevision.cmake | 196 +++++++++++++++++++ cmake/Utils.cmake | 8 + cmake/git_info.h.in | 11 ++ src/CMakeLists.txt | 4 + 7 files changed, 246 insertions(+), 7 deletions(-) create mode 100644 cmake/UpdateRevision.cmake create mode 100644 cmake/Utils.cmake create mode 100644 cmake/git_info.h.in diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index b6cc336..51f2697 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -27,7 +27,7 @@ ARG USER_GID=1001 # 5) Clean up # 6) Setup user RUN apt -y update && apt -y upgrade && \ - apt -y install wget procps cmake && \ + apt -y install wget procps cmake git && \ \ wget -P /tmp https://github.com/open-watcom/open-watcom-v2/releases/download/${OW2_RELEASE_VERSION}/${OW2_INSTALLER_NAME} && \ echo "${OW2_INSTALLER_SHA256} /tmp/${OW2_INSTALLER_NAME}" | sha256sum --check && \ diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 3de412d..0dafc4a 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -54,11 +54,10 @@ jobs: # env: # CC: ${{ matrix.config.compiler_name }} run: | - rev_number=$(git rev-list --count HEAD) + export MAKEFLAGS=--keep-going cmake --workflow --preset "${{ matrix.config.cmake_preset }}" - sha_short=$(echo ${{ github.sha }} | cut -c1-7) - echo "sha_short=$sha_short" >> $GITHUB_OUTPUT - echo "rev_number=r$rev_number" >> $GITHUB_OUTPUT + git_version=$(cmake -P ./cmake/UpdateRevision.cmake "git" 2>&1) + echo "version=$git_version" >> $GITHUB_OUTPUT - name: Install if: | @@ -71,5 +70,5 @@ jobs: github.repository == 'Russian-Doom/russian-doom-dos' uses: actions/upload-artifact@v4 with: - name: russian-doom-dos-${{ steps.configure.outputs.rev_number }}-${{ steps.configure.outputs.sha_short }}-${{ matrix.config.build_suffix }} + name: russian-doom-dos-${{ steps.configure.outputs.version }}-${{ matrix.config.build_suffix }} path: ./build/install/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 9edcc35..97095f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,28 @@ cmake_minimum_required(VERSION 3.0...3.29) -project("Russian Doom DOS" VERSION 1.9 LANGUAGES C NONE) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) +project("Russian Doom DOS" VERSION 1.8 LANGUAGES C NONE) + +include(CMakeDependentOption) +include(Utils) + +# Git info options +find_package(Git) +cmake_dependent_option(RD_GIT_NO_HASH "For Devs only! Don't run 'revision_check' at all" OFF "GIT_FOUND" ON) + +# Update git_info.h +if(RD_GIT_NO_HASH) + # Use a function to avoid accidentally messing the real variables + configure_empty_git_info("cmake/git_info.h.in" "git_info.h") +else() + add_custom_target(revision_check + COMMAND "${CMAKE_COMMAND}" -P "\"${PROJECT_SOURCE_DIR}/cmake/UpdateRevision.cmake\"" "${GIT_EXECUTABLE}" "\"git_info.h\"" + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + ) +endif() + +# Sources add_subdirectory(audio) add_subdirectory(src) diff --git a/cmake/UpdateRevision.cmake b/cmake/UpdateRevision.cmake new file mode 100644 index 0000000..a8bfaa1 --- /dev/null +++ b/cmake/UpdateRevision.cmake @@ -0,0 +1,196 @@ +#!/usr/bin/cmake -P + +# UpdateRevision.cmake +# +# Public domain. This program uses git commands command to get +# various bits of repository status for a particular directory +# and writes it into a header file so that it can be used for a +# project's versioning. + +# Boilerplate to return a variable from a function. +macro(ret_var VAR) + set(${VAR} "${${VAR}}" PARENT_SCOPE) +endmacro() + +# Populate variables "Hash", "Timestamp", "Version_suffix" with relevant information +# from source repository. If anything goes wrong return something in "Error." +function(query_repo_info Tag ProjectDir) + execute_process( + COMMAND "${Git_executable}" log -1 "--format=%ai;%H" + WORKING_DIRECTORY "${ProjectDir}" + RESULT_VARIABLE Error + OUTPUT_VARIABLE CommitInfo + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(NOT "${Error}" STREQUAL "0") + ret_var(Error) + return() + endif() + list(GET CommitInfo 0 Timestamp) + list(GET CommitInfo 1 Hash) + + ret_var(Hash) + ret_var(Timestamp) + + execute_process( + COMMAND "${Git_executable}" rev-list "${Tag}.." --count + WORKING_DIRECTORY "${ProjectDir}" + RESULT_VARIABLE Error + OUTPUT_VARIABLE Commits_from_release + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + if(NOT "${Error}" STREQUAL "0") + return() + endif() + + if("${Commits_from_release}" STREQUAL "0") + return() + endif() + + execute_process( + COMMAND "${Git_executable}" rev-parse --abbrev-ref HEAD + WORKING_DIRECTORY "${ProjectDir}" + RESULT_VARIABLE Error + OUTPUT_VARIABLE Branch + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + if(NOT "${Error}" STREQUAL "0") + return() + endif() + + if("${Branch}" STREQUAL "makepkg") + execute_process( + COMMAND "${Git_executable}" log -n 1 "--pretty='%(decorate:separator=;,prefix=,suffix=)'" HEAD + WORKING_DIRECTORY "${ProjectDir}" + RESULT_VARIABLE Error + OUTPUT_VARIABLE Branch + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + if(NOT "${Error}" STREQUAL "0") + return() + endif() + + list(GET Branch 1 Branch) + string(REPLACE "origin/" "" Branch "${Branch}") + endif() + + if("${Branch}" STREQUAL "master") + set(Version_suffix "~${Commits_from_release}") + set(Display_version_suffix "-${Commits_from_release}") + set(On_master_branch 1) + ret_var(Version_suffix) + ret_var(Display_version_suffix) + ret_var(On_master_branch) + return() + endif() + + execute_process( + COMMAND "${Git_executable}" rev-list origin/master.. --count + WORKING_DIRECTORY "${ProjectDir}" + RESULT_VARIABLE Error + OUTPUT_VARIABLE Commits_in_branch + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + if(NOT "${Error}" STREQUAL "0") + return() + endif() + + math(EXPR Commits_from_master "${Commits_from_release} - ${Commits_in_branch}" OUTPUT_FORMAT DECIMAL) + string(SUBSTRING "${Branch}" 0 1 Branch_short) + + set(Version_suffix "~${Commits_from_master}+${Branch_short}${Commits_in_branch}") + set(Display_version_suffix "-${Commits_from_master}-${Branch_short}${Commits_in_branch}") + ret_var(Version_suffix) + ret_var(Display_version_suffix) +endfunction() + +# Although configure_file doesn't overwrite the file if the contents are the +# same we can't easily observe that to change the status message. This +# function parses the existing file (if it exists) and puts the hash in +# variable "OldHash" +function(get_existing_hash File) + if(EXISTS "${File}") + file(STRINGS "${File}" OldHash LIMIT_COUNT 1) + if(OldHash) + string(SUBSTRING "${OldHash}" 3 -1 OldHash) + ret_var(OldHash) + endif() + endif() +endfunction() + +function(get_project_version CmakeFile) + file(STRINGS "${CmakeFile}" Project_statement REGEX "project\(.*\)") + string(REGEX REPLACE "[()\" ]" ";" Project_statement "${Project_statement}") + if(Project_statement) + cmake_parse_arguments("PROJECT" + "" # List of Options + "VERSION" # List of Values + "" # List of Lists + ${Project_statement} + ) + ret_var(PROJECT_VERSION) + endif() +endfunction() + +function(main) + if(CMAKE_ARGC LESS 4) # cmake -P UpdateRevision.cmake [] + message(NOTICE "Usage: ${CMAKE_ARGV2} []") + return() + endif() + set(Git_executable "${CMAKE_ARGV3}") + + get_filename_component(ScriptDir "${CMAKE_SCRIPT_MODE_FILE}" DIRECTORY) + get_filename_component(ProjectDir "${ScriptDir}" DIRECTORY) + get_project_version("${ProjectDir}/CMakeLists.txt") + + query_repo_info("${PROJECT_VERSION}" "${ProjectDir}") + + if(NOT Hash) + message(NOTICE "Failed to get commit info: ${Error}") + set(Hash "") + set(Timestamp "") + set(Version_suffix "") + set(Display_version_suffix "") + else() + string(SUBSTRING "${Hash}" 0 7 Hash_suffix) + + if(NOT Version_suffix) + set(Version_suffix "") + set(Display_version_suffix "") + else() + String(APPEND Display_version_suffix " ${Hash_suffix}") + endif() + + string(SUBSTRING "${Timestamp}" 0 10 Date) + String(APPEND Display_version_suffix " (${Date})") + endif() + + if(CMAKE_ARGV4) + set(OutputFile "${CMAKE_ARGV4}") + get_existing_hash("${OutputFile}") + if("${Hash}${Version_suffix}" STREQUAL OldHash) + return() + endif() + + configure_file("${ScriptDir}/git_info.h.in" "${OutputFile}" @ONLY) + + message(STATUS "Configuring ${OutputFile} - updated to commit ${Hash_suffix}") + else() + if(On_master_branch) + message(NOTICE "${PROJECT_VERSION}${Version_suffix}") + else() + message(NOTICE "${PROJECT_VERSION}${Version_suffix}-${Hash_suffix}") + endif() + endif() +endfunction() + +main() \ No newline at end of file diff --git a/cmake/Utils.cmake b/cmake/Utils.cmake new file mode 100644 index 0000000..8c185a1 --- /dev/null +++ b/cmake/Utils.cmake @@ -0,0 +1,8 @@ +# configure_empty_git_info(