Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .git_archival.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node: $Format:%H$
node-date: $Format:%cI$
describe-name: $Format:%(describe:tags=true,match=v[0-9]*)$
ref-names: $Format:%D$
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
.git* export-ignore
.hooks* export-ignore
.mailmap export-ignore
# Override the .git* export-ignore above: this file MUST ship in archives, and
# git substitutes the describe string into it so tarballs compute the tweak.
.git_archival.txt -export-ignore export-subst

*.bat -crlf
*.bin -crlf
Expand Down
7 changes: 7 additions & 0 deletions CMake/ITKConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ set(ITK_REQUIRED_LINK_FLAGS "@ITK_REQUIRED_LINK_FLAGS@")
set(ITK_VERSION_MAJOR "@ITK_VERSION_MAJOR@")
set(ITK_VERSION_MINOR "@ITK_VERSION_MINOR@")
set(ITK_VERSION_PATCH "@ITK_VERSION_PATCH@")
# Tweak is the YYYYMMDD date of the most recent commit; enables fine-grained
# downstream gating between release tags via ITK_VERSION_FULL.
set(ITK_VERSION_TWEAK "@ITK_VERSION_TWEAK@")
set(
ITK_VERSION_FULL
"@ITK_VERSION_MAJOR@.@ITK_VERSION_MINOR@.@ITK_VERSION_PATCH@.@ITK_VERSION_TWEAK@"
)

# Remove all legacy code completely.
set(ITK_LEGACY_REMOVE "@ITK_LEGACY_REMOVE@")
Expand Down
11 changes: 9 additions & 2 deletions CMake/ITKConfigVersion.cmake.in
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
set(PACKAGE_VERSION "@ITK_VERSION_MAJOR@.@ITK_VERSION_MINOR@.@ITK_VERSION_PATCH@")
set(
PACKAGE_VERSION
"@ITK_VERSION_MAJOR@.@ITK_VERSION_MINOR@.@ITK_VERSION_PATCH@.@ITK_VERSION_TWEAK@"
)
if(NOT "${PACKAGE_FIND_VERSION}" VERSION_GREATER "${PACKAGE_VERSION}")
set(PACKAGE_VERSION_COMPATIBLE 1) # compatible with older
if("${PACKAGE_FIND_VERSION}" VERSION_EQUAL "${PACKAGE_VERSION}")
if(
"${PACKAGE_FIND_VERSION}" VERSION_EQUAL "${PACKAGE_VERSION}"
OR "${PACKAGE_FIND_VERSION}" VERSION_EQUAL
"@ITK_VERSION_MAJOR@.@ITK_VERSION_MINOR@.@ITK_VERSION_PATCH@"
)
set(PACKAGE_VERSION_EXACT 1) # exact match for this version
endif()
endif()
63 changes: 63 additions & 0 deletions CMake/itkVersionTweak.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Compute ITK_VERSION_TWEAK: the YYYYMMDD date of the most recent commit, at
# configure time. The tweak must never reach itkConfigure.h, so a per-commit
# change of this value cannot invalidate ccache.
#
# .git_archival.txt is consulted before git so that an archive, or a fork that
# commits a substituted file, pins the date it declares. In this repository the
# file holds unexpanded $Format:$ placeholders, so a working tree falls through
# to `git log`, which succeeds even in a shallow or tagless clone.
function(_itk_version_tweak_from_date date outvar)
if(date MATCHES "([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])")
set(
${outvar}
"${CMAKE_MATCH_1}${CMAKE_MATCH_2}${CMAKE_MATCH_3}"
PARENT_SCOPE
)
else()
set(${outvar} "" PARENT_SCOPE)
endif()
endfunction()

function(_itk_compute_version_tweak outvar)
set(tweak "")

if(EXISTS "${ITK_SOURCE_DIR}/.git_archival.txt")
file(
STRINGS
"${ITK_SOURCE_DIR}/.git_archival.txt"
archival
REGEX "^node-date:"
)
if(archival)
list(GET archival 0 node_date)
# Unexpanded placeholders mean this is a checkout, not an archive.
if(NOT node_date MATCHES "\\$Format:")
_itk_version_tweak_from_date("${node_date}" tweak)
endif()
endif()
endif()

if(NOT tweak MATCHES "^[0-9]+$")
find_package(Git QUIET)
if(Git_FOUND)
execute_process(
COMMAND
"${GIT_EXECUTABLE}" -C "${ITK_SOURCE_DIR}" log -1 --format=%cd
--date=short
OUTPUT_VARIABLE commit_date
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
_itk_version_tweak_from_date("${commit_date}" tweak)
endif()
endif()

# Neither archive metadata nor git history, e.g. an unpacked plain tarball.
if(NOT tweak MATCHES "^[0-9]+$")
set(tweak "0")
endif()
set(${outvar} "${tweak}" PARENT_SCOPE)
endfunction()

_itk_compute_version_tweak(ITK_VERSION_TWEAK)
set(ITK_VERSION_FULL "${ITK_VERSION}.${ITK_VERSION_TWEAK}")
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ project(
C
)

# Fourth (tweak) version component, auto-computed as the YYYYMMDD date of the
# most recent commit. Enables downstream between-tag gating via
# ITK_VERSION_FULL; see Documentation/docs/migration_guides/index.md.
include(itkVersionTweak)

# Required as a cache variable for FetchContent parent projects can
# resolve ITK's CMake macros and config paths.
set(
Expand Down
28 changes: 28 additions & 0 deletions Documentation/docs/migration_guides/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,34 @@

These migration guides explain how to update major versions of ITK, whic may contain breaking changes to the API.

## Fine-grained versioning between release tags

ITK's fourth (tweak) version component is the `YYYYMMDD` date of the most
recent commit, computed automatically at configure time. It exists so
downstream projects building against untagged ITK commits — for example during
a `git bisect` — can make configure-time decisions at day granularity between
release tags:

```cmake
find_package(ITK REQUIRED)
if(ITK_VERSION_FULL VERSION_GREATER_EQUAL 6.0.0.20260722)
set(BASELINE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Baseline/post-change)
else()
set(BASELINE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Baseline/legacy)
endif()
```

`ITK_VERSION_FULL` and `ITK_VERSION_TWEAK` are exported through
`ITKConfig.cmake`. Against an older ITK that predates the tweak component,
`ITK_VERSION_FULL` is unset and the comparison is false, so the legacy branch
is taken.

The date comes from `git log` in a working tree — including a shallow or
tagless clone — and from the `git archive`-substituted `.git_archival.txt` in
an exported source tarball; it falls back to `0` only when neither git history
nor that substitution is available. No manual edits are needed — the tweak
advances with every commit.

```{toctree}
:hidden:
:maxdepth: 3
Expand Down
Loading