Fix malformed CUDA version macro check
[alexxy/gromacs.git] / cmake / gmxGenerateVersionInfo.cmake
1 #
2 # This file is part of the GROMACS molecular simulation package.
3 #
4 # Copyright (c) 2012,2013, by the GROMACS development team, led by
5 # David van der Spoel, Berk Hess, Erik Lindahl, and including many
6 # others, as listed in the AUTHORS file in the top-level source
7 # directory and at http://www.gromacs.org.
8 #
9 # GROMACS is free software; you can redistribute it and/or
10 # modify it under the terms of the GNU Lesser General Public License
11 # as published by the Free Software Foundation; either version 2.1
12 # of the License, or (at your option) any later version.
13 #
14 # GROMACS is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 # Lesser General Public License for more details.
18 #
19 # You should have received a copy of the GNU Lesser General Public
20 # License along with GROMACS; if not, see
21 # http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23 #
24 # If you want to redistribute modifications to GROMACS, please
25 # consider that scientific software is very special. Version
26 # control is crucial - bugs must be traceable. We will be happy to
27 # consider code for inclusion in the official distribution, but
28 # derived work must not be called official GROMACS. Details are found
29 # in the README & COPYING files - if they are missing, get the
30 # official version at http://www.gromacs.org.
31 #
32 # To help us fund GROMACS development, we humbly ask that you cite
33 # the research papers on the package. Check out http://www.gromacs.org.
34 #
35 # Generate Gromacs development build version information.
36 #
37 # The script generates version information for a build from a development
38 # source tree based on git repository information.
39 # It is assumed that by default the script is run in cmake script mode.
40 # If *not* called in script mode but used in generating cache variables,
41 # GEN_VERSION_INFO_INTERNAL has to be set ON.
42 #
43 # The following variables have to be previously defined:
44 # GIT_EXECUTABLE        - path to git binary
45 # GIT_VERSION           - git version (if not defined it's assumed that >=1.5.3)
46 # PROJECT_VERSION       - hard-coded version string, should have the following structure:
47 #                       VERSION[-dev-SUFFIX] where the VERSION can have any form and the suffix
48 #                       is optional but should start with -dev
49 # PROJECT_SOURCE_DIR    - top level source directory (which has to be in git)
50 # VERSION_C_CMAKEIN     - path to the version.c.cmakein file
51 # VERSION_C_OUT         - path to the version.c output file
52 #
53 # Output:
54 # i)  Script mode: version.c configured from the input version.c.cmakein using
55 # the variables listed below.
56 # ii) Cache variable mode: the varables below are set in cache.
57 #
58 # GMX_PROJECT_VERSION_STR   - version string
59 # GMX_GIT_HEAD_HASH         - git hash of current local HEAD
60 # GMX_GIT_REMOTE_HASH       - git hash of the first ancestor commit from the
61 #                             main Gromacs repository
62 #
63 # Szilard Pall (pszilard@cbr.su.se)
64
65 if("${PROJECT_VERSION}" STREQUAL "")
66     message(FATAL_ERROR "PROJECT_VERSION undefined!")
67 endif()
68 set(VER ${PROJECT_VERSION})
69
70 # if we're generating variables for cache unset the variables
71 if(GEN_VERSION_INFO_INTERNAL)
72     set(GMX_PROJECT_VERSION_STR)
73     set(GMX_GIT_HEAD_HASH)
74     set(GMX_GIT_REMOTE_HASH)
75 endif()
76
77 # bail if the source tree is not in a git repository
78 if(NOT EXISTS "${PROJECT_SOURCE_DIR}/.git")
79     message(FATAL_ERROR "Project source directory ${PROJECT_SOURCE_DIR} not in git")
80 endif()
81
82 # if git executable exists and it's compatible version
83 # build the development version string
84 # this should at some point become VERSION_LESS
85 if(EXISTS "${GIT_EXECUTABLE}" AND NOT GIT_VERSION STRLESS "1.5.3")
86     # refresh git index 
87     execute_process(COMMAND ${GIT_EXECUTABLE} update-index -q --refresh
88         WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
89         TIMEOUT 5
90         OUTPUT_QUIET
91         ERROR_VARIABLE EXEC_ERR
92         OUTPUT_STRIP_TRAILING_WHITESPACE
93     )
94
95     # get the full hash of the current HEAD
96     execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
97         WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
98         OUTPUT_VARIABLE HEAD_HASH
99         ERROR_VARIABLE EXEC_ERR
100         OUTPUT_STRIP_TRAILING_WHITESPACE
101     )
102     set(GMX_GIT_HEAD_HASH ${HEAD_HASH})
103     # extract the shortened hash (7 char)
104     execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
105         WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
106         OUTPUT_VARIABLE HEAD_HASH_SHORT
107         ERROR_VARIABLE EXEC_ERR
108         OUTPUT_STRIP_TRAILING_WHITESPACE
109     )
110
111     # if there are local uncommitted changes, the build gets labeled "dirty"
112     execute_process(COMMAND ${GIT_EXECUTABLE} diff-index --name-only HEAD
113         WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
114         OUTPUT_VARIABLE SRC_LOCAL_CHANGES
115         ERROR_VARIABLE EXEC_ERR
116         OUTPUT_STRIP_TRAILING_WHITESPACE
117     )
118     if(NOT "${SRC_LOCAL_CHANGES}" STREQUAL "")
119         set(DIRTY_STR "-dirty")
120         set(GMX_GIT_HEAD_HASH "${GMX_GIT_HEAD_HASH} (dirty)")
121     endif()
122
123     # get the date of the HEAD commit
124     execute_process(COMMAND ${GIT_EXECUTABLE} rev-list -n1 "--pretty=format:%ci" HEAD
125         WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
126         OUTPUT_VARIABLE HEAD_DATE
127         ERROR_VARIABLE EXEC_ERR
128         OUTPUT_STRIP_TRAILING_WHITESPACE
129     )
130     string(REGEX REPLACE "\n| " ";" HEAD_DATE "${HEAD_DATE}")
131     list(GET HEAD_DATE 2 HEAD_DATE)
132     string(REGEX REPLACE "-" "" HEAD_DATE "${HEAD_DATE}")
133
134     # compile the version string suffix
135     set(VERSION_STR_SUFFIX "${HEAD_DATE}-${HEAD_HASH_SHORT}${DIRTY_STR}")
136
137     # find the names of remotes that are located on the official gromacs
138     # git/gerrit servers
139     execute_process(COMMAND ${GIT_EXECUTABLE} config --get-regexp
140                     "remote\\..*\\.url" "\\.gromacs\\.org[:/].*gromacs(\\.git)?$"
141         WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
142         OUTPUT_VARIABLE GMX_REMOTES
143         ERROR_VARIABLE EXEC_ERR
144         OUTPUT_STRIP_TRAILING_WHITESPACE
145     )
146     # if there are remotes from the gromacs git servers, try to find ancestor
147     # commits of the current HEAD from this remote;
148     # otherwise, label the build "unknown"
149     if("${GMX_REMOTES}" STREQUAL "")
150         set(VERSION_STR_SUFFIX "${VERSION_STR_SUFFIX}-unknown")
151         set(GMX_GIT_REMOTE_HASH "unknown")
152     else()
153         string(REPLACE "\n" ";" GMX_REMOTES ${GMX_REMOTES})
154         # construct a command pipeline that produces a reverse-time-ordered
155         # list of commits and their annotated names in GMX_REMOTES
156         # the max-count limit is there to put an upper bound on the execution time
157         set(BASEREVCOMMAND "COMMAND ${GIT_EXECUTABLE} rev-list --max-count=1000 HEAD")
158         foreach(REMOTE ${GMX_REMOTES})
159             string(REGEX REPLACE "remote\\.(.*)\\.url.*" "\\1" REMOTE ${REMOTE})
160             set(BASEREVCOMMAND "${BASEREVCOMMAND} COMMAND ${GIT_EXECUTABLE} name-rev --stdin --refs=refs/remotes/${REMOTE}/*")
161         endforeach(REMOTE)
162         # this is necessary for CMake to properly split the variable into
163         # parameters for execute_process().
164         string(REPLACE " " ";" BASEREVCOMMAND ${BASEREVCOMMAND})
165         # find the first ancestor in the list provided by rev-list (not
166         # necessarily the last though) which is in GMX_REMOTE, extract the
167         # hash and the number of commits HEAD is ahead with
168         execute_process(${BASEREVCOMMAND}
169             WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
170             OUTPUT_VARIABLE ANCESTOR_LIST
171         )
172         string(REGEX REPLACE "\n" ";" ANCESTOR_LIST "${ANCESTOR_LIST}")
173
174         set(AHEAD 0)
175         set(GMX_GIT_REMOTE_HASH "")
176         foreach(ANCESTOR ${ANCESTOR_LIST})
177             string(REPLACE "\n" "" HASH_AND_REVNAMES "${ANCESTOR}")
178             string(REPLACE " " ";" HASH_AND_REVNAMES "${HASH_AND_REVNAMES}")
179             list(LENGTH HASH_AND_REVNAMES COUNT)
180             # stop and set the hash if we have a hit, otherwise loop and count
181             # how far ahead is the local repo
182             if(COUNT GREATER 1)
183                 LIST(GET HASH_AND_REVNAMES 0 GMX_GIT_REMOTE_HASH)
184                 break()
185             endif()
186             math(EXPR AHEAD ${AHEAD}+1)
187         endforeach(ANCESTOR)
188         # mark the build "local" if didn't find any commits that are from
189         # remotes/${GMX_REMOTE}/*
190         if("${GMX_GIT_REMOTE_HASH}" STREQUAL "")
191             set(GMX_GIT_REMOTE_HASH "unknown")
192             set(VERSION_STR_SUFFIX "${VERSION_STR_SUFFIX}-local")
193         # don't print the remote hash if there are no local commits
194         elseif("${GMX_GIT_REMOTE_HASH}" STREQUAL "${HEAD_HASH}")
195             set(GMX_GIT_REMOTE_HASH "")
196         else()
197             set(GMX_GIT_REMOTE_HASH "${GMX_GIT_REMOTE_HASH} (${AHEAD} newer local commits)")
198         endif()
199     endif()
200
201     # compile final version string, if there is already a -dev suffix in VER
202     # remove everything after this and replace it with the generated suffix
203     string(REGEX REPLACE "(.*)-dev.*" "\\1" VER "${VER}")
204     set(GMX_PROJECT_VERSION_STR "${VER}-dev-${VERSION_STR_SUFFIX}")
205 else()
206     # the version has to be defined - if not we're not using version.h/.c and set
207     # the GIT related information to "unknown"
208     message(WARNING "Source tree seems to be a repository, but no compatible git is available, using hard-coded version string")
209     set(GMX_PROJECT_VERSION_STR "${PROJECT_VERSION}")
210     set(GMX_GIT_HEAD_HASH "unknown")
211     set(GMX_GIT_REMOTE_HASH "unknown")
212 endif()
213
214 # if we're generating cache variables set these
215 # otherwise it's assumed that it's called in script mode to generate version.c
216 if(GEN_VERSION_INFO_INTERNAL)
217     set(GMX_PROJECT_VERSION_STR ${GMX_PROJECT_VERSION_STR}
218         CACHE STRING "Gromacs version string" FORCE)
219     set(GMX_GIT_HEAD_HASH ${GMX_GIT_HEAD_HASH}${DIRTY_STR}
220         CACHE STRING "Current git HEAD commit object" FORCE)
221     set(GMX_GIT_REMOTE_HASH ${GMX_GIT_REMOTE_HASH}
222         CACHE STRING "Commmit object of the nearest ancestor present in the Gromacs git repository" FORCE)
223     mark_as_advanced(GMX_GIT_HEAD_HASH GMX_GIT_REMOTE_HASH)
224 else()
225     if("${VERSION_C_CMAKEIN}" STREQUAL "")
226         message(FATAL_ERROR "Missing input parameter VERSION_C_CMAKEIN!")
227     endif()
228     if("${VERSION_C_OUT}" STREQUAL "")
229         message(FATAL_ERROR "Missing input parameter VERSION_C_OUT!")
230     endif()
231     # generate version.c
232     configure_file(${VERSION_C_CMAKEIN} ${VERSION_C_OUT})
233 endif()