1 # Generate Gromacs development build version information.
3 # The script generates version information for a build from a development
4 # source tree based on git repository information.
5 # It is assumed that by default the script is run in cmake script mode.
6 # If *not* called in script mode but used in generating cache variables,
7 # GEN_VERSION_INFO_INTERNAL has to be set ON.
9 # The following variables have to be previously defined:
10 # PROJECT_VERSION - hard-coded version string
11 # PROJECT_SOURCE_DIR - top level source directory
12 # VERSION_C_CMAKEIN - path to the version.c.cmakein file
13 # VERSION_C_OUT - path to the version.c output file
16 # i) Script mode: version.c configured from the input version.c.cmakein using
17 # the variables listed below.
18 # ii) Cache variable mode: the varables below are set in cache.
20 # GMX_PROJECT_VERSION_STR - version string
21 # GMX_GIT_HEAD_HASH - git hash of current local HEAD
22 # GMX_GIT_REMOTE_HASH - git hash of the first ancestor commit from the
23 # main Gromacs repository
26 if(${PROJECT_VERSION} STREQUAL "")
27 message(FATAL_ERROR "PROJECT_VERSION undefined!")
29 set(VER ${PROJECT_VERSION})
31 # if we're generating variables for cache unset the variables
32 if(GEN_VERSION_INFO_INTERNAL)
33 unset(GMX_PROJECT_VERSION_STR CACHE)
34 unset(GMX_GIT_HEAD_HASH CACHE)
35 unset(GMX_GIT_REMOTE_HASH CACHE)
36 unset(USE_VERSION_H CACHE)
40 find_program(GIT_BIN "git")
41 mark_as_advanced(GIT_BIN)
43 # if the source tree is a git repository extract the necessary information for
44 # building the development version string
45 if(NOT "${GIT_BIN}" MATCHES ".*-NOTFOUND"
46 AND IS_DIRECTORY "${PROJECT_SOURCE_DIR}/.git")
48 execute_process(COMMAND ${GIT_BIN} update-index -q --refresh
49 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
52 ERROR_VARIABLE EXEC_ERR
53 OUTPUT_STRIP_TRAILING_WHITESPACE
56 # get the full hash of the current HEAD
57 execute_process(COMMAND ${GIT_BIN} rev-parse -q HEAD
58 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
60 OUTPUT_VARIABLE GMX_GIT_HEAD_HASH
61 ERROR_VARIABLE EXEC_ERR
62 OUTPUT_STRIP_TRAILING_WHITESPACE
64 # extract the shortened hash (7 char)
65 string(SUBSTRING ${GMX_GIT_HEAD_HASH} 0 5 HEAD_HASH_SHORT)
67 # if there are local uncommitted changes, the build gets labeled "dirty"
68 execute_process(COMMAND ${GIT_BIN} diff-index --name-only HEAD
69 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
71 OUTPUT_VARIABLE SRC_LOCAL_CHANGES
72 ERROR_VARIABLE EXEC_ERR
73 OUTPUT_STRIP_TRAILING_WHITESPACE
75 if(NOT ${SRC_LOCAL_CHANGES} STREQUAL "")
76 set(DIRTY_STR "-dirty")
77 set(GMX_GIT_HEAD_HASH "${GMX_GIT_HEAD_HASH} (dirty)")
80 # get the date of the HEAD commit
81 execute_process(COMMAND ${GIT_BIN} rev-list -n1 "--pretty=format:%ci" HEAD
82 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
84 OUTPUT_VARIABLE HEAD_DATE
85 ERROR_VARIABLE EXEC_ERR
86 OUTPUT_STRIP_TRAILING_WHITESPACE
88 string(REGEX REPLACE "\n| " ";" HEAD_DATE ${HEAD_DATE})
89 list(GET HEAD_DATE 2 HEAD_DATE)
90 string(REGEX REPLACE "-" "" HEAD_DATE ${HEAD_DATE})
92 # compile the version string suffix
93 set(VERSION_STR_SUFFIX "${HEAD_DATE}-${HEAD_HASH_SHORT}${DIRTY_STR}")
95 # find the name of the remote which is located on the official gromacs git server
96 execute_process(COMMAND ${GIT_BIN} config --get-regexp
97 "remote\\..*\\.url" "git\\.gromacs\\.org[:|/]gromacs"
98 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
100 OUTPUT_VARIABLE GMX_REMOTE
101 ERROR_VARIABLE EXEC_ERR
102 OUTPUT_STRIP_TRAILING_WHITESPACE
104 # if there's a remote from the gromacs git, try to find ancestor commits of the
105 # current HEAD from this remote; otherwise, label the buld "unknown"
106 if(GMX_REMOTE STREQUAL "")
107 set(VERSION_STR_SUFFIX "${VERSION_STR_SUFFIX}-unknown")
108 set(GMX_GIT_REMOTE_HASH "unknown")
110 string(REGEX REPLACE "remote\\.(.*)\\.url.*" "\\1" GMX_REMOTE ${GMX_REMOTE})
111 # find the first ancestor in the list provided by rev-list (not
112 # necessarily the last though) which is in GMX_REMOTE, extract the
113 # hash and the number of commits HEAD is ahead with
114 execute_process(COMMAND ${GIT_BIN} rev-list --max-count=100 HEAD
115 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
117 OUTPUT_VARIABLE ANCESTOR_LIST
119 string(REGEX REPLACE "\n" ";" ANCESTOR_LIST ${ANCESTOR_LIST})
122 set(GMX_GIT_REMOTE_HASH "")
123 foreach(OBJ ${ANCESTOR_LIST})
124 execute_process(COMMAND ${GIT_BIN} name-rev --refs=refs/remotes/${GMX_REMOTE}/* ${OBJ}
125 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
127 OUTPUT_VARIABLE HASH_AND_REVNAME
128 OUTPUT_STRIP_TRAILING_WHITESPACE
130 string(REGEX REPLACE "\n" "" HASH_AND_REVNAME ${HASH_AND_REVNAME})
131 string(REGEX REPLACE " " ";" HASH_AND_REVNAME ${HASH_AND_REVNAME})
132 list(GET HASH_AND_REVNAME 0 GMX_GIT_REMOTE_HASH)
133 list(GET HASH_AND_REVNAME 1 REVNAME)
134 # stop and set the hash if we have a hit, otherwise loop and count
135 # how far ahead is the local repo
136 if(${REVNAME} MATCHES "remotes/${GMX_REMOTE}/.*")
137 set(GMX_GIT_REMOTE_HASH
138 "${GMX_GIT_REMOTE_HASH} (${AHEAD} newer local commits)")
141 math(EXPR AHEAD ${AHEAD}+1)
144 # mark the build "local" if didn't find any commits that are from
145 # remotes/${GMX_REMOTE}/*
146 if(${GMX_GIT_REMOTE_HASH} STREQUAL "")
147 set(GMX_GIT_REMOTE_HASH "unknown")
148 set(VERSION_STR_SUFFIX "${VERSION_STR_SUFFIX}-local")
152 # compile final version string, if there is already a -dev suffix in VER
153 # remove everything after this and replace it with the generated suffix
154 string(REGEX REPLACE "(.*)-dev.*" "\\1" VER ${VER})
155 set(GMX_PROJECT_VERSION_STR "${VER}-dev-${VERSION_STR_SUFFIX}")
157 # the version has to be defined
158 message(WARNING " Not a git repository and/or git not found, using hard-coded version.")
159 set(GMX_PROJECT_VERSION_STR "${PROJECT_VERSION}")
160 set(GMX_GIT_HEAD_HASH "unknown")
161 set(GMX_GIT_REMOTE_HASH "unknown")
164 # if we're generating cache variables set these
165 # otherwise it's assumed that it's called in script mode to generate version.c
166 if(GEN_VERSION_INFO_INTERNAL)
167 set(GMX_PROJECT_VERSION_STR ${GMX_PROJECT_VERSION_STR}
168 CACHE STRING "Gromacs version string" FORCE)
169 set(GMX_GIT_HEAD_HASH ${GMX_GIT_HEAD_HASH}${DIRTY_STR}
170 CACHE STRING "Current git HEAD commit object" FORCE)
171 set(GMX_GIT_REMOTE_HASH ${GMX_GIT_REMOTE_HASH}
172 CACHE STRING "Commmit object of the nearest ancestor present in the Gromacs git repository" FORCE)
173 mark_as_advanced(GMX_GIT_HEAD_HASH GMX_GIT_REMOTE_HASH USE_VERSION_H)
175 if(${VERSION_C_CMAKEIN} STREQUAL "")
176 message(FATAL_ERROR "Missing input parameter VERSION_C_CMAKEIN!")
178 if(${VERSION_C_OUT} STREQUAL "")
179 message(FATAL_ERROR "Missing input parameter VERSION_C_OUT!")
182 configure_file(${VERSION_C_CMAKEIN} ${VERSION_C_OUT})