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