Skip to content

BareCpper/Version.cmake

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Version.cmake

Simplify your Semantic-Version automation within every developer build using code commits and repository tags.

Prerequisites

  1. Use CMake to build your project.
  2. Use Git as your code repository.
    💡 If you are using a different SCM please raise an issue
  3. Structure your project. See Here.
  4. Use modern CMake features like targets and properties. See here and here.
  5. Understand semantic versioning here and here.
  6. Tag your releases with the version prefixed by a v.
    💎 This is now optional but still preferred - Version.cmake should detect if your tag is 'version-like'
  7. Use a 'Prefix' for your project options in CMake options:
    💎 Instead of BUILD_TESTING use MYLIBRARY_BUILD_TESTING

Output Variables

All CMake variables use the form VERSION_<field>:

Variable Description Example
VERSION_SET TRUE if version fields were populated successfully TRUE
VERSION_MAJOR Major semantic-version extracted from repository tag 0
VERSION_MINOR Minor semantic-version extracted from repository tag 1
VERSION_PATCH Patch semantic-version extracted from repository tag 2
VERSION_COMMIT Commit count since last tag 30
VERSION_SHA Revision-specific unique SHA hash 4c757e7
VERSION_SEMANTIC Full semantic version major.minor.patch.commit 0.1.2.30
VERSION_FULL Full git describe output, useful for ABI compatibility v0.1.2-30-g4c757e7-dirty

Adding Version.cmake

We recommend using CPM.cmake so you stay up to date with the latest fixes and features.

Alternatively, you may directly include Version.cmake in your project but we don't encourage this as you may miss important updates.

Basic Usage

After adding CPM.cmake, add the following to your CMakeLists.txt:

CPMAddPackage("gh:BareCpper/[email protected]")

You may wish to optionally set the project version on the project(...) call. If so, we recommend checking VERSION_SET:

if(NOT VERSION_SET)
    message(FATAL_ERROR "Version.cmake is required")
endif()
project(MyProject VERSION ${VERSION_SEMANTIC})

To use the version information within a CMake build target:

  1. Add version::version to the target_link_libraries for the target library/executable.
  2. Add Version.h via the #include directive.
  3. Use the VERSION_<field> preprocessor values in your code.
    💎 The default template defines C-preprocessor directives. For C++17 and later, see the constexpr template below.
target_link_libraries(MyLibrary
    PRIVATE
        version::version
)
#include "Version.h"

Configuration Variables

All variables are optional — sensible defaults are provided for every one. Override any of them in your CMakeLists.txt before calling CPMAddPackage / include(Version.cmake):

Variable Default Description
VERSION_OUT_DIR CMAKE_BINARY_DIR Output directory for the generated header. Override to place the header inside a sub-directory already on the include path (e.g. ${CMAKE_BINARY_DIR}/include/myapp).
VERSION_SOURCE_DIR CMAKE_SOURCE_DIR The git repository root to query. Override for sub-module or CPM-fetched versioning.
VERSION_PREFIX "" Optional prefix for C preprocessor macros. "MYAPP_" produces MYAPP_VERSION_MAJOR. Useful when multiple libraries use Version.cmake in the same build.
VERSION_H_FILENAME "${VERSION_PREFIX}Version.h" Output filename. Set to "version.hpp" to select the C++17 constexpr template instead of the default C-preprocessor template.
VERSION_NAMESPACE "" Optional C++ namespace for constexpr constants in Version.hpp.in. Supports nested namespaces (e.g. "myapp::version"). Only used when VERSION_H_FILENAME ends in .hpp.

C++17 Usage (constexpr namespace)

Set VERSION_H_FILENAME and VERSION_NAMESPACE to get inline constexpr constants in a named namespace:
💎 This is the recommended approach for C++17 (and later) projects.

set(VERSION_OUT_DIR    "${CMAKE_BINARY_DIR}/include/myapp")
set(VERSION_PREFIX     "MYAPP_")
set(VERSION_H_FILENAME "version.hpp")
set(VERSION_NAMESPACE  "myapp::version")

CPMAddPackage("gh:BareCpper/[email protected]")
target_link_libraries(MyLibrary PUBLIC version::version)

Generated include/myapp/version.hpp:

// Generated by Version.cmake -- do not edit.
#pragma once
#include <cstdint>
#include <string_view>

namespace myapp::version {
    inline constexpr std::uint32_t  version_major   = 0;
    inline constexpr std::uint32_t  version_minor   = 1;
    inline constexpr std::uint32_t  version_patch   = 2;
    inline constexpr std::uint32_t  version_commit  = 30;
    inline constexpr std::string_view version_sha    = "4c757e7";
    inline constexpr std::string_view version_string = "0.1.2.30";
    inline constexpr std::string_view version_full   = "v0.1.2-30-g4c757e7";
} // namespace myapp::version

// Legacy C preprocessor macros (for C ABI and pre-C++20 code)
#define MYAPP_VERSION_MAJOR   0
#define MYAPP_VERSION_STRING  "0.1.2.30"
// ...
#include "myapp/version.hpp"

// C++ constexpr path
static_assert(myapp::version::version_major >= 0);

// C legacy path (e.g. in a C ABI header)
// MYAPP_VERSION_MAJOR == 0

Custom Templates

Set VERSION_H_FILENAME to any filename; Version.cmake looks for a matching .in file in the Version.cmake package directory. If no matching .in file is found, the default C-preprocessor template is auto-generated.

To provide your own template, place a <filename>.in file in your project and point VERSION_H_TEMPLATE at it:

set(VERSION_H_TEMPLATE "${CMAKE_SOURCE_DIR}/cmake/MyVersion.h.in")

Available substitution variables inside any template:

Template variable Value
@_VERSION_MAJOR@ Major component (integer)
@_VERSION_MINOR@ Minor component (integer)
@_VERSION_PATCH@ Patch component (integer)
@_VERSION_COMMIT@ Commit count (integer)
@_VERSION_SHA@ Short SHA string
@_VERSION_SEMANTIC@ Full semantic string
@_VERSION_FULL@ Full git describe string
@_VERSION_PREFIX@ Resolved prefix (with trailing _ if non-empty)
@_VERSION_NAMESPACE_BEGIN@ namespace X { or empty
@_VERSION_NAMESPACE_END@ } // namespace X or empty

Advantages

  • Small and reusable so can be added to any CMake build.
  • No re-configuring of CMake necessary — the build-time step updates version information transparently.
  • C and C++ compatible — default template uses C preprocessor; C++17 constexpr template available via VERSION_H_FILENAME.
  • Namespace scopingVERSION_NAMESPACE prevents symbol collisions when multiple libraries use Version.cmake.
  • Prefix scopingVERSION_PREFIX scopes C preprocessor macros.

Limitations

  • Requires git on PATH at build time.
  • The generated header is regenerated on every build (tracks HEAD and .git/index) — this is intentional, ensuring version information always reflects the actual commit.
  • No support for non-git SCMs — raise an issue if you need support for another SCM.

About

Simplify your Semantic-Versioning! `Version.cmake` automates versioning every developer build using code commits and repository tags.

Topics

Resources

License

Stars

Watchers

Forks

Contributors