From a2a5c2af19c21094215aaaaba2b66924a5fe7bd7 Mon Sep 17 00:00:00 2001 From: Ahnaf Tahmid Chowdhury Date: Sat, 22 Feb 2025 05:48:11 +0600 Subject: [PATCH] Add Versioning Support from `version.txt` (#3140) Co-authored-by: Jonathan Shimwell Co-authored-by: Paul Wilson Co-authored-by: Paul Romano --- .git_archival.txt | 3 + .gitattributes | 1 + .github/workflows/ci.yml | 5 +- CMakeLists.txt | 34 +++----- cmake/Modules/GetVersionFromGit.cmake | 109 ++++++++++++++++++++++++++ docs/source/conf.py | 8 +- include/openmc/version.h.in | 6 +- pyproject.toml | 6 +- src/mcpl_interface.cpp | 4 +- src/output.cpp | 21 +++-- 10 files changed, 153 insertions(+), 44 deletions(-) create mode 100644 .git_archival.txt create mode 100644 .gitattributes create mode 100644 cmake/Modules/GetVersionFromGit.cmake diff --git a/.git_archival.txt b/.git_archival.txt new file mode 100644 index 00000000000..f2f118c0d67 --- /dev/null +++ b/.git_archival.txt @@ -0,0 +1,3 @@ +commit: $Format:%H$ +commit-date: $Format:%cI$ +describe-name: $Format:%(describe:tags=true,match=*[0-9]*)$ \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..82bf71c1c5b --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +.git_archival.txt export-subst \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de99bbbe20a..7fe3e1557b6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -87,9 +87,10 @@ jobs: RDMAV_FORK_SAFE: 1 steps: - - uses: actions/checkout@v4 + - name: Checkout repository + uses: actions/checkout@v4 with: - fetch-depth: 2 + fetch-depth: 0 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 diff --git a/CMakeLists.txt b/CMakeLists.txt index f76fcb247d9..385ce85aaaf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,18 @@ cmake_minimum_required(VERSION 3.16 FATAL_ERROR) project(openmc C CXX) -# Set version numbers -set(OPENMC_VERSION_MAJOR 0) -set(OPENMC_VERSION_MINOR 15) -set(OPENMC_VERSION_RELEASE 1) -set(OPENMC_VERSION ${OPENMC_VERSION_MAJOR}.${OPENMC_VERSION_MINOR}.${OPENMC_VERSION_RELEASE}) +# Set module path +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules) + +include(GetVersionFromGit) + +# Output version information +message(STATUS "OpenMC version: ${OPENMC_VERSION}") +message(STATUS "OpenMC dev state: ${OPENMC_DEV_STATE}") +message(STATUS "OpenMC commit hash: ${OPENMC_COMMIT_HASH}") +message(STATUS "OpenMC commit count: ${OPENMC_COMMIT_COUNT}") + +# Generate version.h configure_file(include/openmc/version.h.in "${CMAKE_BINARY_DIR}/include/openmc/version.h" @ONLY) # Setup output directories @@ -13,9 +20,6 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) -# Set module path -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules) - # Enable correct usage of CXX_EXTENSIONS if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.22) cmake_policy(SET CMP0128 NEW) @@ -240,8 +244,6 @@ endif() #=============================================================================== # Update git submodules as needed #=============================================================================== - -find_package(Git) if(GIT_FOUND AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git") option(GIT_SUBMODULE "Check submodules during build" ON) if(GIT_SUBMODULE) @@ -493,18 +495,6 @@ if (OPENMC_USE_MPI) target_compile_definitions(libopenmc PUBLIC -DOPENMC_MPI) endif() -# Set git SHA1 hash as a compile definition -if(GIT_FOUND) - execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse HEAD - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - RESULT_VARIABLE GIT_SHA1_SUCCESS - OUTPUT_VARIABLE GIT_SHA1 - ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) - if(GIT_SHA1_SUCCESS EQUAL 0) - target_compile_definitions(libopenmc PRIVATE -DGIT_SHA1="${GIT_SHA1}") - endif() -endif() - # target_link_libraries treats any arguments starting with - but not -l as # linker flags. Thus, we can pass both linker flags and libraries together. target_link_libraries(libopenmc ${ldflags} ${HDF5_LIBRARIES} ${HDF5_HL_LIBRARIES} diff --git a/cmake/Modules/GetVersionFromGit.cmake b/cmake/Modules/GetVersionFromGit.cmake new file mode 100644 index 00000000000..ee6bac827e3 --- /dev/null +++ b/cmake/Modules/GetVersionFromGit.cmake @@ -0,0 +1,109 @@ +# GetVersionFromGit.cmake +# Standalone script to retrieve versioning information from Git or .git_archival.txt. +# Customizable for any project by setting variables before including this file. + +# Configurable variables: +# - VERSION_PREFIX: Prefix for version tags (default: "v"). +# - VERSION_SUFFIX: Suffix for version tags (default: "[~+-]([a-zA-Z0-9]+)"). +# - VERSION_REGEX: Regex to extract version (default: "(?[0-9]+\\.[0-9]+\\.[0-9]+)"). +# - ARCHIVAL_FILE: Path to .git_archival.txt (default: "${CMAKE_SOURCE_DIR}/.git_archival.txt"). +# - DESCRIBE_NAME_KEY: Key for describe name in .git_archival.txt (default: "describe-name: "). +# - COMMIT_HASH_KEY: Key for commit hash in .git_archival.txt (default: "commit: "). + +# Default Format Example: +# 1.2.3 v1.2.3 v1.2.3-rc1 + +set(VERSION_PREFIX "v" CACHE STRING "Prefix used in version tags") +set(VERSION_SUFFIX "[~+-]([a-zA-Z0-9]+)" CACHE STRING "Suffix used in version tags") +set(VERSION_REGEX "?([0-9]+\\.[0-9]+\\.[0-9]+)" CACHE STRING "Regex for extracting version") +set(ARCHIVAL_FILE "${CMAKE_SOURCE_DIR}/.git_archival.txt" CACHE STRING "Path to .git_archival.txt") +set(DESCRIBE_NAME_KEY "describe-name: " CACHE STRING "Key for describe name in .git_archival.txt") +set(COMMIT_HASH_KEY "commit: " CACHE STRING "Key for commit hash in .git_archival.txt") + + +# Combine prefix and regex +set(VERSION_REGEX_WITH_PREFIX "^${VERSION_PREFIX}${VERSION_REGEX}") + +# Find Git +find_package(Git) + +# Attempt to retrieve version from Git +if(EXISTS "${CMAKE_SOURCE_DIR}/.git" AND GIT_FOUND) + message(STATUS "Using git describe for versioning") + + # Extract the version string + execute_process( + COMMAND git describe --tags --dirty + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE VERSION_STRING + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + # Extract the commit hash + execute_process( + COMMAND git rev-parse HEAD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE COMMIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +else() + message(STATUS "Using archival file for versioning: ${ARCHIVAL_FILE}") + if(EXISTS "${ARCHIVAL_FILE}") + file(READ "${ARCHIVAL_FILE}" ARCHIVAL_CONTENT) + + # Extract the describe-name line + string(REGEX MATCH "${DESCRIBE_NAME_KEY}([^\\n]+)" VERSION_STRING "${ARCHIVAL_CONTENT}") + if(VERSION_STRING MATCHES "${DESCRIBE_NAME_KEY}(.*)") + set(VERSION_STRING "${CMAKE_MATCH_1}") + else() + message(FATAL_ERROR "Could not extract version from ${ARCHIVAL_FILE}") + endif() + + # Extract the commit hash + string(REGEX MATCH "${COMMIT_HASH_KEY}([a-f0-9]+)" COMMIT_HASH "${ARCHIVAL_CONTENT}") + if(COMMIT_HASH MATCHES "${COMMIT_HASH_KEY}([a-f0-9]+)") + set(COMMIT_HASH "${CMAKE_MATCH_1}") + else() + message(FATAL_ERROR "Could not extract commit hash from ${ARCHIVAL_FILE}") + endif() + else() + message(FATAL_ERROR "Neither git describe nor ${ARCHIVAL_FILE} is available for versioning.") + endif() +endif() + +# Ensure version string format +if(VERSION_STRING MATCHES "${VERSION_REGEX_WITH_PREFIX}") + set(VERSION_NO_SUFFIX "${CMAKE_MATCH_1}") +else() + message(FATAL_ERROR "Invalid version format: Missing base version in ${VERSION_STRING}") +endif() + +# Check for development state +if(VERSION_STRING MATCHES "-([0-9]+)-g([0-9a-f]+)") + set(DEV_STATE "true") + set(COMMIT_COUNT "${CMAKE_MATCH_1}") + string(REGEX REPLACE "-([0-9]+)-g([0-9a-f]+)" "" VERSION_WITHOUT_META "${VERSION_STRING}") +else() + set(DEV_STATE "false") + set(VERSION_WITHOUT_META "${VERSION_STRING}") +endif() + +# Split and set version components +string(REPLACE "." ";" VERSION_LIST "${VERSION_NO_SUFFIX}") +list(GET VERSION_LIST 0 VERSION_MAJOR) +list(GET VERSION_LIST 1 VERSION_MINOR) +list(GET VERSION_LIST 2 VERSION_PATCH) + +# Increment patch number for dev versions +if(DEV_STATE) + math(EXPR VERSION_PATCH "${VERSION_PATCH} + 1") +endif() + +# Export variables +set(OPENMC_VERSION_MAJOR "${VERSION_MAJOR}") +set(OPENMC_VERSION_MINOR "${VERSION_MINOR}") +set(OPENMC_VERSION_PATCH "${VERSION_PATCH}") +set(OPENMC_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") +set(OPENMC_COMMIT_HASH "${COMMIT_HASH}") +set(OPENMC_DEV_STATE "${DEV_STATE}") +set(OPENMC_COMMIT_COUNT "${COMMIT_COUNT}") diff --git a/docs/source/conf.py b/docs/source/conf.py index 60bd406fba5..b9db835077b 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -68,10 +68,14 @@ # |version| and |release|, also used in various other places throughout the # built documents. # + +import openmc + # The short X.Y version. -version = "0.15" +version = ".".join(openmc.__version__.split('.')[:2]) + # The full version, including alpha/beta/rc tags. -release = "0.15.1-dev" +release = openmc.__version__ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/include/openmc/version.h.in b/include/openmc/version.h.in index e1c2b0541a5..6dfc7c7dd67 100644 --- a/include/openmc/version.h.in +++ b/include/openmc/version.h.in @@ -9,8 +9,10 @@ namespace openmc { // clang-format off constexpr int VERSION_MAJOR {@OPENMC_VERSION_MAJOR@}; constexpr int VERSION_MINOR {@OPENMC_VERSION_MINOR@}; -constexpr int VERSION_RELEASE {@OPENMC_VERSION_RELEASE@}; -constexpr bool VERSION_DEV {true}; +constexpr int VERSION_RELEASE {@OPENMC_VERSION_PATCH@}; +constexpr bool VERSION_DEV {@OPENMC_DEV_STATE@}; +constexpr const char* VERSION_COMMIT_COUNT = "@OPENMC_COMMIT_COUNT@"; +constexpr const char* VERSION_COMMIT_HASH = "@OPENMC_COMMIT_HASH@"; constexpr std::array VERSION {VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE}; // clang-format on diff --git a/pyproject.toml b/pyproject.toml index 1f8de10e3b3..6e8ed798e78 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools", "wheel"] +requires = ["setuptools", "setuptools-scm", "wheel"] build-backend = "setuptools.build_meta" [project] @@ -8,7 +8,7 @@ authors = [ {name = "The OpenMC Development Team", email = "openmc@anl.gov"}, ] description = "OpenMC" -version = "0.15.1-dev" +dynamic = ["version"] requires-python = ">=3.11" license = {file = "LICENSE"} classifiers = [ @@ -66,3 +66,5 @@ exclude = ['tests*'] "openmc.data.effective_dose" = ["**/*.txt"] "openmc.data" = ["*.txt", "*.DAT", "*.json", "*.h5"] "openmc.lib" = ["libopenmc.dylib", "libopenmc.so"] + +[tool.setuptools_scm] diff --git a/src/mcpl_interface.cpp b/src/mcpl_interface.cpp index a8de5fdb0e0..83ef6332097 100644 --- a/src/mcpl_interface.cpp +++ b/src/mcpl_interface.cpp @@ -207,8 +207,8 @@ void write_mcpl_source_point(const char* filename, span source_bank, if (mpi::master) { file_id = mcpl_create_outfile(filename_.c_str()); if (VERSION_DEV) { - line = fmt::format("OpenMC {0}.{1}.{2}-development", VERSION_MAJOR, - VERSION_MINOR, VERSION_RELEASE); + line = fmt::format("OpenMC {0}.{1}.{2}-dev{3}", VERSION_MAJOR, + VERSION_MINOR, VERSION_RELEASE, VERSION_COMMIT_COUNT); } else { line = fmt::format( "OpenMC {0}.{1}.{2}", VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE); diff --git a/src/output.cpp b/src/output.cpp index 8494450c409..63e7fe55331 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -75,13 +75,12 @@ void title() // Write version information fmt::print( " | The OpenMC Monte Carlo Code\n" - " Copyright | 2011-2024 MIT, UChicago Argonne LLC, and contributors\n" + " Copyright | 2011-2025 MIT, UChicago Argonne LLC, and contributors\n" " License | https://docs.openmc.org/en/latest/license.html\n" - " Version | {}.{}.{}{}\n", - VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE, VERSION_DEV ? "-dev" : ""); -#ifdef GIT_SHA1 - fmt::print(" Git SHA1 | {}\n", GIT_SHA1); -#endif + " Version | {}.{}.{}{}{}\n", + VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE, VERSION_DEV ? "-dev" : "", + VERSION_COMMIT_COUNT); + fmt::print(" Commit Hash | {}\n", VERSION_COMMIT_HASH); // Write the date and time fmt::print(" Date/Time | {}\n", time_stamp()); @@ -291,12 +290,10 @@ void print_usage() void print_version() { if (mpi::master) { - fmt::print("OpenMC version {}.{}.{}\n", VERSION_MAJOR, VERSION_MINOR, - VERSION_RELEASE); -#ifdef GIT_SHA1 - fmt::print("Git SHA1: {}\n", GIT_SHA1); -#endif - fmt::print("Copyright (c) 2011-2024 MIT, UChicago Argonne LLC, and " + fmt::print("OpenMC version {}.{}.{}{}{}\n", VERSION_MAJOR, VERSION_MINOR, + VERSION_RELEASE, VERSION_DEV ? "-dev" : "", VERSION_COMMIT_COUNT); + fmt::print("Commit hash: {}\n", VERSION_COMMIT_HASH); + fmt::print("Copyright (c) 2011-2025 MIT, UChicago Argonne LLC, and " "contributors\nMIT/X license at " "\n"); }