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, should have the following structure:
11 # VERSION[-dev-SUFFIX] where the VERSION can have any form and the suffix
12 # is optional but should start with -dev
13 # PROJECT_SOURCE_DIR - top level source directory
14 # VERSION_C_CMAKEIN - path to the version.c.cmakein file
15 # VERSION_C_OUT - path to the version.c output file
18 # i) Script mode: version.c configured from the input version.c.cmakein using
19 # the variables listed below.
20 # ii) Cache variable mode: the varables below are set in cache.
22 # GMX_PROJECT_VERSION_STR - version string
23 # GMX_GIT_HEAD_HASH - git hash of current local HEAD
24 # GMX_GIT_REMOTE_HASH - git hash of the first ancestor commit from the
25 # main Gromacs repository
28 if(${PROJECT_VERSION} STREQUAL "")
29 message(FATAL_ERROR "PROJECT_VERSION undefined!")
31 set(VER ${PROJECT_VERSION})
33 # if we're generating variables for cache unset the variables
34 if(GEN_VERSION_INFO_INTERNAL)
35 set(GMX_PROJECT_VERSION_STR)
36 set(GMX_GIT_HEAD_HASH)
37 set(GMX_GIT_REMOTE_HASH)
41 find_program(GIT_BIN "git")
42 mark_as_advanced(GIT_BIN)
44 # if the source tree is a git repository extract the necessary information for
45 # building the development version string
46 if(NOT "${GIT_BIN}" MATCHES ".*-NOTFOUND"
47 AND IS_DIRECTORY "${PROJECT_SOURCE_DIR}/.git")
49 execute_process(COMMAND ${GIT_BIN} update-index -q --refresh
50 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
53 ERROR_VARIABLE EXEC_ERR
54 OUTPUT_STRIP_TRAILING_WHITESPACE
57 # get the full hash of the current HEAD
58 execute_process(COMMAND ${GIT_BIN} rev-parse -q HEAD
59 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
61 OUTPUT_VARIABLE GMX_GIT_HEAD_HASH
62 ERROR_VARIABLE EXEC_ERR
63 OUTPUT_STRIP_TRAILING_WHITESPACE
65 # extract the shortened hash (7 char)
66 string(SUBSTRING ${GMX_GIT_HEAD_HASH} 0 5 HEAD_HASH_SHORT)
68 # if there are local uncommitted changes, the build gets labeled "dirty"
69 execute_process(COMMAND ${GIT_BIN} diff-index --name-only HEAD
70 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
72 OUTPUT_VARIABLE SRC_LOCAL_CHANGES
73 ERROR_VARIABLE EXEC_ERR
74 OUTPUT_STRIP_TRAILING_WHITESPACE
76 if(NOT ${SRC_LOCAL_CHANGES} STREQUAL "")
77 set(DIRTY_STR "-dirty")
78 set(GMX_GIT_HEAD_HASH "${GMX_GIT_HEAD_HASH} (dirty)")
81 # get the date of the HEAD commit
82 execute_process(COMMAND ${GIT_BIN} rev-list -n1 "--pretty=format:%ci" HEAD
83 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
85 OUTPUT_VARIABLE HEAD_DATE
86 ERROR_VARIABLE EXEC_ERR
87 OUTPUT_STRIP_TRAILING_WHITESPACE
89 string(REGEX REPLACE "\n| " ";" HEAD_DATE ${HEAD_DATE})
90 list(GET HEAD_DATE 2 HEAD_DATE)
91 string(REGEX REPLACE "-" "" HEAD_DATE ${HEAD_DATE})
93 # compile the version string suffix
94 set(VERSION_STR_SUFFIX "${HEAD_DATE}-${HEAD_HASH_SHORT}${DIRTY_STR}")
96 # find the name of the remote which is located on the official gromacs git server
97 execute_process(COMMAND ${GIT_BIN} config --get-regexp
98 "remote\\..*\\.url" "git\\.gromacs\\.org[:|/]gromacs"
99 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
101 OUTPUT_VARIABLE GMX_REMOTE
102 ERROR_VARIABLE EXEC_ERR
103 OUTPUT_STRIP_TRAILING_WHITESPACE
105 # if there's a remote from the gromacs git, try to find ancestor commits of the
106 # current HEAD from this remote; otherwise, label the buld "unknown"
107 if(GMX_REMOTE STREQUAL "")
108 set(VERSION_STR_SUFFIX "${VERSION_STR_SUFFIX}-unknown")
109 set(GMX_GIT_REMOTE_HASH "unknown")
111 string(REGEX REPLACE "remote\\.(.*)\\.url.*" "\\1" GMX_REMOTE ${GMX_REMOTE})
112 # find the first ancestor in the list provided by rev-list (not
113 # necessarily the last though) which is in GMX_REMOTE, extract the
114 # hash and the number of commits HEAD is ahead with
115 execute_process(COMMAND ${GIT_BIN} rev-list --max-count=100 HEAD
116 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
118 OUTPUT_VARIABLE ANCESTOR_LIST
120 string(REGEX REPLACE "\n" ";" ANCESTOR_LIST ${ANCESTOR_LIST})
123 set(GMX_GIT_REMOTE_HASH "")
124 foreach(OBJ ${ANCESTOR_LIST})
125 execute_process(COMMAND ${GIT_BIN} name-rev --refs=refs/remotes/${GMX_REMOTE}/* ${OBJ}
126 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
128 OUTPUT_VARIABLE HASH_AND_REVNAME
129 OUTPUT_STRIP_TRAILING_WHITESPACE
131 string(REGEX REPLACE "\n" "" HASH_AND_REVNAME ${HASH_AND_REVNAME})
132 string(REGEX REPLACE " " ";" HASH_AND_REVNAME ${HASH_AND_REVNAME})
133 list(GET HASH_AND_REVNAME 0 GMX_GIT_REMOTE_HASH)
134 list(GET HASH_AND_REVNAME 1 REVNAME)
135 # stop and set the hash if we have a hit, otherwise loop and count
136 # how far ahead is the local repo
137 if(${REVNAME} MATCHES "remotes/${GMX_REMOTE}/.*")
138 set(GMX_GIT_REMOTE_HASH
139 "${GMX_GIT_REMOTE_HASH} (${AHEAD} newer local commits)")
142 math(EXPR AHEAD ${AHEAD}+1)
145 # mark the build "local" if didn't find any commits that are from
146 # remotes/${GMX_REMOTE}/*
147 if(${GMX_GIT_REMOTE_HASH} STREQUAL "")
148 set(GMX_GIT_REMOTE_HASH "unknown")
149 set(VERSION_STR_SUFFIX "${VERSION_STR_SUFFIX}-local")
153 # compile final version string, if there is already a -dev suffix in VER
154 # remove everything after this and replace it with the generated suffix
155 string(REGEX REPLACE "(.*)-dev.*" "\\1" VER ${VER})
156 set(GMX_PROJECT_VERSION_STR "${VER}-dev-${VERSION_STR_SUFFIX}")
158 # the version has to be defined - if not we're not using version.h/.c and set
159 # the GIT related information to "unknown"
160 message(WARNING " Not a git repository and/or git not found, using hard-coded version.")
161 set(GMX_PROJECT_VERSION_STR "${PROJECT_VERSION}")
162 set(GMX_GIT_HEAD_HASH "unknown")
163 set(GMX_GIT_REMOTE_HASH "unknown")
164 set(USE_VERSION_H OFF)
167 # if we're generating cache variables set these
168 # otherwise it's assumed that it's called in script mode to generate version.c
169 if(GEN_VERSION_INFO_INTERNAL)
170 set(GMX_PROJECT_VERSION_STR ${GMX_PROJECT_VERSION_STR}
171 CACHE STRING "Gromacs version string" FORCE)
172 set(GMX_GIT_HEAD_HASH ${GMX_GIT_HEAD_HASH}${DIRTY_STR}
173 CACHE STRING "Current git HEAD commit object" FORCE)
174 set(GMX_GIT_REMOTE_HASH ${GMX_GIT_REMOTE_HASH}
175 CACHE STRING "Commmit object of the nearest ancestor present in the Gromacs git repository" FORCE)
176 mark_as_advanced(GMX_GIT_HEAD_HASH GMX_GIT_REMOTE_HASH)
178 if(${VERSION_C_CMAKEIN} STREQUAL "")
179 message(FATAL_ERROR "Missing input parameter VERSION_C_CMAKEIN!")
181 if(${VERSION_C_OUT} STREQUAL "")
182 message(FATAL_ERROR "Missing input parameter VERSION_C_OUT!")
185 configure_file(${VERSION_C_CMAKEIN} ${VERSION_C_OUT})