Update versioning for new scheme
[alexxy/gromacs.git] / cmake / gmxVersionInfo.cmake
1 #
2 # This file is part of the GROMACS molecular simulation package.
3 #
4 # Copyright (c) 2014,2015, by the GROMACS development team, led by
5 # Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 # and including many others, as listed in the AUTHORS file in the
7 # top-level source 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 # Sets version information variables and provides CMake functions for
36 # generating files based on them
37 #
38 # This script provides the following basic version variables that need to be
39 # maintained manually:
40 #   GMX_VERSION_MAJOR      Major version number.
41 #   GMX_VERSION_PATCH      Patch version number.
42 #       Should always be defined: zero for, e.g., 2016.
43 #   GMX_VERSION_SUFFIX     String suffix to add to numeric version string.
44 #       "-dev" is automatically added when not building from a source package,
45 #       and does not need to be kept here. This mechanism is not quite enough
46 #       for building a tarball, but setting the CMake cache variable
47 #       GMX_BUILD_TARBALL=on will suppress the addition of "-dev" to the
48 #       version string.
49 #   LIBRARY_SOVERSION_MAJOR so major version for the built libraries.
50 #       Should be increased for each binary incompatible release. In GROMACS,
51 #       the typical policy is to increase it at the start of the development
52 #       cycle for each major/minor version change, but not for patch releases,
53 #       even if the latter may not always be fully binary compatible.
54 #       Table of historical values
55 #         GROMACS     5.0    0
56 #         GROMACS     5.1    1
57 #   LIBRARY_SOVERSION_MINOR so minor version for the built libraries.
58 #       Should be increased for each release that changes only the implementation.
59 #       In GROMACS, the typical policy is to increase it for each patch version
60 #       change, even if they may not always be fully binary compatible.
61 #       If it is somehow clear that the ABI implementation has not changed
62 #       in a patch release, this variable should not increase. Release candidate
63 #       and beta versions will not increase this number, since nobody should
64 #       write code against such versions.
65 #   LIBRARY_VERSION        Full library version.
66 #   REGRESSIONTEST_BRANCH  For builds not from source packages, name of the
67 #       regressiontests branch at gerrit.gromacs.org whose HEAD can test this
68 #       code, *if* this code is recent enough (i.e., contains all changes from
69 #       the corresponding code branch that affects the regression test
70 #       results). Even after a release branch is forked for the source
71 #       repository, the correct regressiontests branch can still be master,
72 #       because we do not fork it until behaviour needs to change.
73 #   REGRESSIONTEST_MD5SUM
74 #       The MD5 checksum of the regressiontest tarball. Only used when building
75 #       from a source package.
76 # They are collected into a single section below.
77 # The following variables are set based on these:
78 #   GMX_VERSION            String composed from GMX_VERSION_* numeric variables
79 #       above. Example: 4.6.1, 5.0, 2016
80 #   GMX_VERSION_STRING     String with GMX_VERSION suffixed with the given
81 #       suffix and possibly "-dev" for builds not from a source package.
82 #   GMX_VERSION_NUMERIC    Numeric version number (e.g., 40601 for 4.6.1, 20160001 for 2016.1).
83 #   GMX_API_VERSION        Numeric API version.
84 #       This is currently set automatically to GMX_VERSION_NUMERIC, but may
85 #       become manually maintained in the future if there will be releases
86 #       where the API does not change, but programs/libraries do.
87 #       In such a case, this should be the first version where the current API
88 #       appeared.
89 #   REGRESSIONTEST_VERSION For source packages, version number of the
90 #       matching regressiontests tarball.  Not used for builds not from source
91 #       packages.
92 # The latter two are used to generate gromacs/version.h to allow software
93 # written against the GROMACS API to provide some #ifdef'ed code to support
94 # multiple GROMACS versions.
95 #
96 # The following variables are defined without manual intervention:
97 #   SOURCE_IS_SOURCE_DISTRIBUTION  The source tree is from a source tarball.
98 #   SOURCE_IS_GIT_REPOSITORY       The source tree is a git repository.
99 # Note that both can be false if the tree has been extracted, e.g., as a
100 # tarball directly from git.
101 # Additionally, the following variable is defined:
102 #   BUILD_IS_INSOURCE              The build is happening in-source.
103 #
104 # This script also declares machinery to generate and obtain version
105 # information from a git repository.  This is enabled by default if the source
106 # tree is a git, but can be disabled with
107 #   GMX_GIT_VERSION_INFO           Advanced CMake variable to disable git
108 #                                  version info generation.
109 # The main interface to this machinery is the gmx_configure_version_file()
110 # CMake function.  The signature is
111 #   gmx_configure_version_file(<input> <output>
112 #                              [REMOTE_HASH] [SOURCE_FILE]
113 #                              [TARGET <target>]
114 #                              [COMMENT <comment>])
115 #   <input>      Specify the input and output files as for configure_file().
116 #   <output>     The configuration is done with configure_file(... @ONLY) with
117 #                the following variables defined (as well as all the
118 #                GMX_VERSION* variables from above):
119 #                  GMX_VERSION_STRING_FULL
120 #                  GMX_VERSION_FULL_HASH
121 #                  GMX_VERSION_CENTRAL_BASE_HASH
122 #                The output file is created during build time, so any dependent
123 #                targets should specify it as a dependency.
124 #   REMOTE_HASH  Currently, this has no effect, but it signifies that the
125 #                <input> file is using the CENTRAL_BASE_HASH variable.
126 #                This variable is much more expensive to initialize than the
127 #                others, so this allows local changes in this file to only
128 #                compute that value when required if that becomes necessary.
129 #   SOURCE_FILE  Signals that <output> will be used as a source file.
130 #                The function will set properties for the source file
131 #                appropriately to signify that it is generated.
132 #   TARGET       By default, this function uses add_custom_command() to
133 #                generate the output file.  If TARGET is specified, then
134 #                add_custom_target() is used to create a target with the given
135 #                name <target> that runs this custom command.  Use this if
136 #                the same file will be used for multiple downstream targets,
137 #                or if the explicit target for the file is otherwise
138 #                necessary.
139 #   COMMENT      Set a custom comment to be shown when building the rule
140 #                (see add_custom_command(... COMMENT <comment>)).
141 # As an alternative to using this script, also the following variables are
142 # provided (can be useful when generating more complex CMake scripts that do
143 # build-time tasks):
144 #   VERSION_INFO_CMAKE_SCRIPT
145 #       Absolute path to a CMake script that can be included using include()
146 #       to declare the GMX_VERSION_* variables documented for
147 #       gmx_configure_version_file().
148 #   VERSION_INFO_DEPS
149 #       If a custom command depends on VERSION_INFO_CMAKE_SCRIPT, then it
150 #       should add ${VERSION_INFO_DEPS} to its DEPENDS list to get the
151 #       appropriate dependencies.
152 # TODO: If someone wants to add a custom target that depends on
153 # VERSION_INFO_CMAKE_SCRIPT, a separate variable may be needed for those
154 # dependencies.
155 #
156 # The version string printed by 'gmx -version' (and also printed in the startup
157 # header) can provide useful information for, e.g., diagnosing bug reports and
158 # identifying what exact version the user was using.  The following formats are
159 # possible (with examples given for a particular version):
160 #   4.6.1       Plain version number without any suffix signifies a build from
161 #               a released source tarball.
162 #   4.6.1-dev   '-dev' suffix signifies all other builds. If there is no other
163 #               information, either the user built the code outside any git
164 #               repository, or disabled the version info generation.
165 #   4.6.1-dev-YYYYMMDD-1234abc
166 #               The YYYYMMDD part shows the commit date (not author date) of
167 #               the HEAD commit from which the code was built.  The abbreviated
168 #               hash is the hash of that commit (the full hash is available in
169 #               'gmx -version' output).
170 #               If the HEAD hash is not identified as coming from branches in
171 #               "authoritative" GROMACS repositories, 'gmx -version' will show
172 #               the nearest ancestor commit that is identified as such (but see
173 #               the '-local' and '-unknown' suffixes below).
174 #   4.6.1-dev-YYYYMMDD-1234abc-dirty
175 #               As above, but there were local modifications in the source tree
176 #               when the code was built.
177 #   4.6.1-dev-YYYYMMDD-1234abc-unknown
178 #               As above, but there were no remotes in the repository that
179 #               could be identified as "authoritative" GROMACS repositories.
180 #               This happens if the code is not cloned from git.gromacs.org
181 #               or gerrit.gromacs.org.
182 #   4.6.1-dev-YYYYMMDD-1234abc-local
183 #               As above, but there were no commits in the recent history of
184 #               the branch that could be identified as coming from
185 #               "authoritative" GROMACS repositories.  This should be
186 #               relatively rare.
187 #
188 # Other variables set here are not intended for use outside this file.
189 # The scripts gmxGenerateVersionInfo.cmake and gmxConfigureVersionInfo.cmake
190 # are used internally by this machinery, as well as VersionInfo.cmake.cmakein.
191
192 #####################################################################
193 # Basic nature of the source tree
194
195 set(SOURCE_IS_GIT_REPOSITORY OFF)
196 set(SOURCE_IS_SOURCE_DISTRIBUTION OFF)
197 if (EXISTS "${PROJECT_SOURCE_DIR}/.git")
198     set(SOURCE_IS_GIT_REPOSITORY ON)
199 endif()
200 # This file is excluded from CPack source packages, but part of the repository,
201 # so it should get included everywhere else.
202 if (NOT EXISTS "${PROJECT_SOURCE_DIR}/admin/.isreposource")
203     set(SOURCE_IS_SOURCE_DISTRIBUTION ON)
204 endif()
205 set(BUILD_IS_INSOURCE OFF)
206 if ("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}")
207     set(BUILD_IS_INSOURCE ON)
208 endif()
209
210 #####################################################################
211 # Manually maintained version info
212
213 # The GROMACS convention is that these are the version number of the next
214 # release that is going to be made from this branch.
215 set(GMX_VERSION_MAJOR 2016)
216 set(GMX_VERSION_PATCH 0)
217 # The suffix, on the other hand, is used mainly for betas and release
218 # candidates, where it signifies the most recent such release from
219 # this branch; it will be empty before the first such release, as well
220 # as after the final release is out.
221 set(GMX_VERSION_SUFFIX "")
222
223 # Conventionally with libtool, any ABI change must change the major
224 # version number, the minor version number should change if it's just
225 # the implementation that has been altered, and the third number
226 # counts the number of old major versions that will still run if
227 # linked to this library (i.e. it is not a patch number). See the
228 # above descriptions of LIBRARY_SOVERSION_* for policy for changes
229 # here. The important thing is to minimize the chance of third-party
230 # code being able to dynamically link with a version of libgromacs
231 # that might not work.
232 set(LIBRARY_SOVERSION_MAJOR 2)
233 set(LIBRARY_SOVERSION_MINOR 0)
234 set(LIBRARY_VERSION ${LIBRARY_SOVERSION_MAJOR}.${LIBRARY_SOVERSION_MINOR}.0)
235
236 #####################################################################
237 # General version management based on manually set numbers
238
239 if (GMX_VERSION_PATCH)
240     set(GMX_VERSION "${GMX_VERSION_MAJOR}.${GMX_VERSION_PATCH}")
241 else()
242     set(GMX_VERSION "${GMX_VERSION_MAJOR}")
243 endif()
244 set(GMX_VERSION_STRING "${GMX_VERSION}${GMX_VERSION_SUFFIX}")
245 option(GMX_BUILD_TARBALL "Build tarball without -dev version suffix" OFF)
246 mark_as_advanced(GMX_BUILD_TARBALL)
247 if (NOT SOURCE_IS_SOURCE_DISTRIBUTION AND NOT GMX_BUILD_TARBALL)
248     set(GMX_VERSION_STRING "${GMX_VERSION_STRING}-dev")
249 endif()
250
251 set(REGRESSIONTEST_VERSION "${GMX_VERSION_STRING}")
252 set(REGRESSIONTEST_BRANCH "refs/heads/master")
253 # TODO Find some way of ensuring that this is bumped appropriately for
254 # each release. It's hard to test because it is only used for
255 # REGRESSIONTEST_DOWNLOAD, which doesn't work until that tarball has
256 # been placed on the server.
257 set(REGRESSIONTEST_MD5SUM "614a74e9b143bda5476f87f4ce08eec0" CACHE INTERNAL "MD5 sum of the regressiontests tarball")
258
259 math(EXPR GMX_VERSION_NUMERIC
260      "${GMX_VERSION_MAJOR}*10000 + ${GMX_VERSION_PATCH}")
261 set(GMX_API_VERSION ${GMX_VERSION_NUMERIC})
262
263 #####################################################################
264 # git version info management
265
266 # There can be clusters where git and CMake can run on nodes where the other is
267 # not available, accessing the same source tree.
268 # Should be unlikely, but doesn't hurt to check.
269 set(_git_info_default OFF)
270 if (SOURCE_IS_GIT_REPOSITORY)
271     find_package(Git)
272     if (GIT_FOUND)
273         set(_git_info_default ON)
274     endif()
275 endif()
276 option(GMX_GIT_VERSION_INFO "Generate git version information" ${_git_info_default})
277 mark_as_advanced(GMX_GIT_VERSION_INFO)
278 # Detect preconditions for version info generation if it is requested.
279 if (GMX_GIT_VERSION_INFO)
280     if (NOT SOURCE_IS_GIT_REPOSITORY)
281         message(FATAL_ERROR
282             "Cannot generate git version information from source tree not under git. "
283             "Set GMX_GIT_VERSION_INFO=OFF to proceed.")
284     endif()
285     # We need at least git v1.5.3 be able to parse git's date output.
286     if (NOT GIT_FOUND OR GIT_VERSION_STRING VERSION_LESS "1.5.3")
287         message(FATAL_ERROR
288             "No compatible git version found (>= 1.5.3 required). "
289             "Won't be able to generate development version information. "
290             "Set GMX_GIT_VERSION_INFO=OFF to proceed.")
291     endif()
292 endif()
293
294 include(gmxCustomCommandUtilities)
295
296 # The first two are also for use outside this file, encapsulating the details
297 # of how to use the generated VersionInfo.cmake.
298 set(VERSION_INFO_CMAKE_FILE   ${PROJECT_BINARY_DIR}/VersionInfo.cmake)
299 set(VERSION_INFO_DEPS         ${VERSION_INFO_CMAKE_FILE})
300 # Capture the location of the necessary files in internal variables for use in
301 # the function below.
302 set(VERSION_INFO_CMAKEIN_FILE     ${CMAKE_CURRENT_LIST_DIR}/VersionInfo.cmake.cmakein)
303 set(VERSION_INFO_CONFIGURE_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/gmxConfigureVersionInfo.cmake)
304
305 # Rules to create the VersionInfo.cmake file.
306 # For git info, the sequence is:
307 #   1. (configure time) VersionInfo.cmake.cmakein -> VersionInfo-partial.cmake.cmakein
308 #        - Set all variables that are known at configure time.
309 #   2. (build time)     VersionInfo-partial.cmake.cmakein -> VersionInfo.cmake
310 #        - Set variables that may change as result of repository state changes
311 #          (i.e., everything that requires running git).
312 #        - Runs every time as a git-version-info target, but the output file
313 #          timestamp only changes if its contents actually change.
314 #        - Depending on the native build system, this may run once per build
315 #          or once per each time it is required for step 3.
316 #   3. (build time)     VersionInfo.cmake -> other files
317 #        - Set variables in files specified with gmx_configure_version_file()
318 #          using the values generated in step 2.
319 #        - Each file runs as a custom command that depends on the previous
320 #          steps, and runs only if the VersionInfo.cmake file is newer than the
321 #          output file.
322 # Without git info, the sequence is:
323 #  1. (configure time) VersionInfo.cmake.cmakein -> VersionInfo.cmake
324 #        - Everything is known at configure time, so the output is generated
325 #          immediately with all variables set (git info will be empty).
326 #  2. (build time)     VersionInfo.cmake -> other files
327 #        - As with git info, processes files from gmx_configure_version_file().
328 #        - These are again custom commands that depend on the output from
329 #          step 1, so they get regenerated only when the static version info
330 #          changes.
331 if (GMX_GIT_VERSION_INFO)
332     # Configure information known at this time into a partially filled
333     # version info file.
334     set(VERSION_INFO_CMAKEIN_FILE_PARTIAL
335         ${PROJECT_BINARY_DIR}/VersionInfo-partial.cmake.cmakein)
336     # Leave these to be substituted by the custom target below.
337     set(GMX_VERSION_STRING_FULL       "\@GMX_VERSION_STRING_FULL\@")
338     set(GMX_VERSION_FULL_HASH         "\@GMX_VERSION_FULL_HASH\@")
339     set(GMX_VERSION_CENTRAL_BASE_HASH "\@GMX_VERSION_CENTRAL_BASE_HASH\@")
340     configure_file(${VERSION_INFO_CMAKEIN_FILE}
341                    ${VERSION_INFO_CMAKEIN_FILE_PARTIAL}
342                    @ONLY)
343     # If generating the version info, create a target that runs on every build
344     # and does the actual git calls, storing the results into a CMake script.
345     # This needs to be run at build time to update the version information
346     # properly when the git hash changes, but the build system does not.
347     # All targets added by gmx_configure_version_file() use the information
348     # from this script to get their variables from, removing the need to run
349     # git multiple times and simplifying reuse for other purposes.
350     gmx_add_custom_output_target(git-version-info RUN_ALWAYS
351         OUTPUT ${VERSION_INFO_CMAKE_FILE}
352         COMMAND ${CMAKE_COMMAND}
353             -D GIT_EXECUTABLE=${GIT_EXECUTABLE}
354             -D PROJECT_VERSION=${GMX_VERSION_STRING}
355             -D PROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}
356             -D VERSION_CMAKEIN=${VERSION_INFO_CMAKEIN_FILE_PARTIAL}
357             -D VERSION_OUT=${VERSION_INFO_CMAKE_FILE}
358             -P ${CMAKE_CURRENT_LIST_DIR}/gmxGenerateVersionInfo.cmake
359         WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
360         COMMENT "Generating git version information")
361     list(APPEND VERSION_INFO_DEPS git-version-info)
362 else()
363     # If the version info is static, just generate the CMake script with the
364     # version variables during the CMake run.
365     set(GMX_VERSION_STRING_FULL       ${GMX_VERSION_STRING})
366     set(GMX_VERSION_FULL_HASH         "")
367     set(GMX_VERSION_CENTRAL_BASE_HASH "")
368     configure_file(${VERSION_INFO_CMAKEIN_FILE} ${VERSION_INFO_CMAKE_FILE})
369 endif()
370 unset(GMX_VERSION_STRING_FULL)
371 unset(GMX_VERSION_FULL_HASH)
372 unset(GMX_VERSION_CENTRAL_BASE_HASH)
373
374 # The main user-visible interface to the machinery.
375 # See documentation at the top of the script.
376 function (gmx_configure_version_file INFILE OUTFILE)
377     include(CMakeParseArguments)
378     set(_options REMOTE_HASH SOURCE_FILE)
379     set(_one_value_args COMMENT TARGET)
380     set(_multi_value_args EXTRA_VARS)
381     cmake_parse_arguments(
382         ARG "${_options}" "${_one_value_args}" "${_multi_value_args}" ${ARGN})
383     if (ARG_UNPARSED_ARGUMENTS)
384         message(FATAL_ERROR "Unknown arguments: ${ARG_UNPARSED_ARGUMENTS}")
385     endif()
386     # Some callers may pass partial paths that do not really make sense,
387     # so create a default comment that only contains the actual file name.
388     get_filename_component(_basename ${OUTFILE} NAME)
389     set(_comment "Generating ${_basename}")
390     if (ARG_COMMENT)
391         set(_comment ${ARG_COMMENT})
392     endif()
393     # Mimic configure_file()
394     if (NOT IS_ABSOLUTE ${INFILE})
395         set(INFILE ${CMAKE_CURRENT_SOURCE_DIR}/${INFILE})
396     endif()
397     # Create command-line definitions for the requested variables
398     set(_extra_var_defines)
399     foreach(_var ${ARG_EXTRA_VARS})
400         list(APPEND _extra_var_defines -D "${_var}=${${_var}}")
401     endforeach()
402     # The touch command is necessary to ensure that after the target is run,
403     # the timestamp is newer than in the input files.
404     add_custom_command(OUTPUT ${OUTFILE}
405         COMMAND ${CMAKE_COMMAND}
406             -D VERSION_VARIABLES=${VERSION_INFO_CMAKE_FILE}
407             -D VERSION_CMAKEIN=${INFILE}
408             -D VERSION_OUT=${OUTFILE}
409             ${_extra_var_defines}
410             -P ${VERSION_INFO_CONFIGURE_SCRIPT}
411         COMMAND ${CMAKE_COMMAND} -E touch ${OUTFILE}
412         WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
413         DEPENDS ${INFILE} ${VERSION_INFO_DEPS} ${VERSION_INFO_CONFIGURE_SCRIPT}
414         COMMENT "${_comment}"
415         VERBATIM)
416     if (ARG_TARGET)
417         add_custom_target(${ARG_TARGET} DEPENDS ${OUTFILE} VERBATIM)
418         gmx_set_custom_target_output(${ARG_TARGET} ${OUTFILE})
419     endif()
420     if (ARG_SOURCE_FILE)
421         set_source_files_properties(${OUTFILE} PROPERTIES GENERATED true)
422     endif()
423 endfunction()