Reorganize CMake version information management
authorTeemu Murtola <teemu.murtola@gmail.com>
Mon, 28 Jul 2014 04:08:19 +0000 (07:08 +0300)
committerGerrit Code Review <gerrit@gerrit.gromacs.org>
Wed, 13 Aug 2014 21:38:23 +0000 (23:38 +0200)
Main benefits:
 - Less clutter in the beginning of the main CMakeLists.txt.
 - CPack and regression test version numbers no longer need to be
   updated separately.
 - Easier to reuse the individual GMX_VERSION_* variables instead of
   trying to parse PROJECT_VERSION.
 - -dev suffix in the version string is now automatically managed, with
   no need to patch the source code before packaging a source
   distribution.
 - All stuff related to git version info generation is now in one place,
   and easy to reuse if one wants to add new files that would like to
   embed the full version string.  At least the new documentation build
   targets could probably use this.
 - Additional targets of such type do not cause the git commands to
   generate the info run more than once per build (at least in most
   cases).
 - Remove some unused functionality and unnecessary checking from
   gmxGenerateVersionInfo.cmake to streamline it.  All the checks are
   already done at a higher level.

Some cleanup on the way:
 - Remove enable_language(C/CXX), as CMake by default enables C and C++.
 - Clean up some indentation in affected parts.
 - Rename variables to have consistent names throughout.
   PROJECT_VERSION is now called GMX_VERSION_STRING, as the old name was
   probably there mainly because autoconf named a similar variable in
   config.h that way.
 - Remove CUSTOM_VERSION_STRING, as it does not have a well-defined use.
   If someone can come up with a use case, we can reintroduce a more
   targeted mechanism for such customization.

Change-Id: I23ec2dc6a3ec7b33ba18272e766057f67ffb4bd4

15 files changed:
.gitignore
CMakeLists.txt
cmake/VersionInfo.cmake.cmakein [new file with mode: 0644]
cmake/gmxConfigureVersionInfo.cmake [new file with mode: 0644]
cmake/gmxGenerateVersionInfo.cmake
cmake/gmxVersionInfo.cmake [new file with mode: 0644]
doxygen/CMakeLists.txt
doxygen/Doxyfile-version.cmakein
install-guide/configure-install-guide.cmake.in
manual/macros.tex
src/gromacs/CMakeLists.txt
src/gromacs/libgromacs.pc.cmakein
src/gromacs/utility/baseversion-gen.c.cmakein
src/gromacs/version.h.cmakein
tests/CMakeLists.txt

index e61ec7a0094b540cbad36d63c8256bea1b8b2b1a..e2d97633276257ab0a470bbc256274048ea771c6 100644 (file)
@@ -13,3 +13,4 @@ lib*.pc
 .project
 .cproject
 CMakeLists.txt.user
+/VersionInfo*.cmake
index 834693f4e64466844692ba8a144a3dfe79d7a85a..4f5678f58d04069737b6d4afa2405bfacd30bdda 100644 (file)
@@ -48,56 +48,11 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
 
-# PROJECT_VERSION should have the following structure:
-# VERSION-dev[-SUFFIX] where the VERSION should have the for: vMajor.vMinor.vPatch
-#
-# The "-dev" suffix is important to keep because it makes possible to distinguish
-# between a build from official release and a build from git release branch on a
-# machine with no git.
-#
-# NOTE: when releasing the "-dev" suffix needs to be stripped off!
-# REGRESSIONTEST_VERSION and REGRESSIONTEST_BRANCH should always be
-# defined.
-set(PROJECT_VERSION "5.1-dev")
-# If this is a released tarball, "-dev" will not be present in
-# PROJECT_VERSION, and REGRESSIONTEST_VERSION specifies the version
-# number of the regressiontest tarball against which the code tarball
-# can be tested. This will be the version of the last patch release.
-set(REGRESSIONTEST_VERSION "5.0.1-dev")
-# If this is not a released tarball, "-dev" will be present in
-# PROJECT_VERSION, and REGRESSIONTEST_BRANCH specifies the name of the
-# gerrit.gromacs.org branch whose HEAD can test this code, *if* this
-# code contains all recent fixes from the corresponding code branch.
-set(REGRESSIONTEST_BRANCH "refs/heads/master")
-
-set(CUSTOM_VERSION_STRING ""
-    CACHE STRING "Custom version string (if empty, use hard-coded default)")
-mark_as_advanced(CUSTOM_VERSION_STRING)
-if (CUSTOM_VERSION_STRING)
-    set(PROJECT_VERSION ${CUSTOM_VERSION_STRING})
-endif()
-set(LIBRARY_SOVERSION 1)
-set(LIBRARY_VERSION ${LIBRARY_SOVERSION}.0.0)
-# It is a bit irritating, but this has to be set separately for now!
-SET(CPACK_PACKAGE_VERSION_MAJOR "5")
-SET(CPACK_PACKAGE_VERSION_MINOR "1")
-#SET(CPACK_PACKAGE_VERSION_PATCH "0")
-
-# The numerical gromacs version. It is 40600 for 4.6.0.
-# The #define GMX_VERSION in gromacs/version.h is set to this value.
-math(EXPR NUM_VERSION
-    "${CPACK_PACKAGE_VERSION_MAJOR}*10000 + ${CPACK_PACKAGE_VERSION_MINOR}*100")
-if(CPACK_PACKAGE_VERSION_PATCH)
-    math(EXPR NUM_VERSION
-         "${NUM_VERSION} + ${CPACK_PACKAGE_VERSION_PATCH}")
-endif()
-
-# The API version tracks the numerical Gromacs version (for now).
-# It is potentially different from the Gromacs version in the future, if
-# the programs/libraries diverge from the presumably more stable API.
-# The #define GMX_API_VERSION in version.h is set to this value to
-# provide backward compatibility of software written against the Gromacs API.
-set(API_VERSION ${NUM_VERSION})
+# Set up common version variables, as well as general information about
+# the build tree (whether the build is from a source package or from a git
+# repository).  Also declares a few functions that will be used for generating
+# version info files later.
+include(gmxVersionInfo)
 
 if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND UNIX)
     set(CMAKE_INSTALL_PREFIX "/usr/local/gromacs" CACHE STRING "Installation prefix (installation will need write permissions here)" FORCE)
@@ -128,11 +83,11 @@ if(CMAKE_CONFIGURATION_TYPES)
 endif()
 set(build_types_with_explicit_flags RELEASE DEBUG RELWITHDEBUGINFO RELWITHASSERT MINSIZEREL PROFILE)
 
-enable_language(C)
-enable_language(CXX)
-
 set(CPACK_PACKAGE_NAME "gromacs")
-set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
+set(CPACK_PACKAGE_VERSION_MAJOR ${GMX_VERSION_MAJOR})
+set(CPACK_PACKAGE_VERSION_MINOR ${GMX_VERSION_MINOR})
+set(CPACK_PACKAGE_VERSION_PATCH ${GMX_VERSION_PATCH})
+set(CPACK_PACKAGE_VERSION       ${GMX_VERSION_STRING})
 set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
 set(CPACK_PACKAGE_VENDOR "gromacs.org")
 set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Gromacs - a toolkit for high-performance molecular simulation")
@@ -162,15 +117,6 @@ set(MEMORYCHECK_SUPPRESSIONS_FILE
     "File that contains suppressions for the memory checker")
 include(CTest)
 
-set(SOURCE_IS_GIT_REPOSITORY OFF)
-set(SOURCE_IS_SOURCE_DISTRIBUTION OFF)
-if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
-    set(SOURCE_IS_GIT_REPOSITORY ON)
-endif()
-if(NOT EXISTS "${CMAKE_SOURCE_DIR}/admin/.isreposource")
-    set(SOURCE_IS_SOURCE_DISTRIBUTION ON)
-endif()
-
 ########################################################################
 # Check and warn if cache generated on a different host is being reused
 ########################################################################
@@ -289,9 +235,6 @@ option(GMX_OPENMP "Enable OpenMP-based multithreading" ON)
 
 option(GMX_USE_TNG "Use the TNG library for trajectory I/O" ON)
 
-option(GMX_GIT_VERSION_INFO "Generate git version information" ${SOURCE_IS_GIT_REPOSITORY})
-mark_as_advanced(GMX_GIT_VERSION_INFO)
-
 if(UNIX)
     option(GMX_SYMLINK_OLD_BINARY_NAMES "Create symbolic links for pre-5.0 binary names" ON)
 endif()
@@ -529,25 +472,6 @@ if(WIN32 AND NOT CYGWIN)
     add_definitions(-DNOMINMAX)
 endif()
 
-# only bother with finding git and using version.h if the source is a git repo
-if(GMX_GIT_VERSION_INFO)
-    if (NOT SOURCE_IS_GIT_REPOSITORY)
-        message(FATAL_ERROR
-            "Cannot generate git version information from source tree not under git. "
-            "Set GMX_GIT_VERSION_INFO=OFF to proceed.")
-    endif()
-    # We need at least git v1.5.3 be able to parse git's date output. If not
-    # found or the version is too small, we can't generate version information.
-    find_package(Git)
-
-    if(NOT GIT_FOUND OR GIT_VERSION_STRING VERSION_LESS "1.5.3")
-        message(FATAL_ERROR
-            "No compatible git version found (>= 1.5.3 required). "
-            "Won't be able to generate development version information. "
-            "Set GMX_GIT_VERSION_INFO=OFF to proceed.")
-    endif()
-endif()
-
 # Detect boost unless GMX_EXTERNAL_BOOST is explicitly OFF
 # Used for default if GMX_EXTERNAL_BOOST is not defined (first CMake pass)
 if(NOT DEFINED GMX_EXTERNAL_BOOST OR GMX_EXTERNAL_BOOST)
@@ -583,12 +507,6 @@ if (GMX_BUILD_UNITTESTS AND NOT HAVE_LIBXML2)
         "Either set GMX_BUILD_UNITTESTS=OFF or tell CMake how to find a working version of libxml2.")
 endif()
 
-########################################################################
-# Generate development version info for cache
-########################################################################
-# set(GEN_VERSION_INFO_INTERNAL "ON")
-# include(gmxGenerateVersionString)
-
 ########################################################################
 # Our own GROMACS tests
 ########################################################################
diff --git a/cmake/VersionInfo.cmake.cmakein b/cmake/VersionInfo.cmake.cmakein
new file mode 100644 (file)
index 0000000..b3f81b4
--- /dev/null
@@ -0,0 +1,43 @@
+#
+# This file is part of the GROMACS molecular simulation package.
+#
+# Copyright (c) 2014, by the GROMACS development team, led by
+# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+# and including many others, as listed in the AUTHORS file in the
+# top-level source directory and at http://www.gromacs.org.
+#
+# GROMACS is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1
+# of the License, or (at your option) any later version.
+#
+# GROMACS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with GROMACS; if not, see
+# http://www.gnu.org/licenses, or write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+#
+# If you want to redistribute modifications to GROMACS, please
+# consider that scientific software is very special. Version
+# control is crucial - bugs must be traceable. We will be happy to
+# consider code for inclusion in the official distribution, but
+# derived work must not be called official GROMACS. Details are found
+# in the README & COPYING files - if they are missing, get the
+# official version at http://www.gromacs.org.
+#
+# To help us fund GROMACS development, we humbly ask that you cite
+# the research papers on the package. Check out http://www.gromacs.org.
+
+set(GMX_VERSION                   "@GMX_VERSION@")
+set(GMX_VERSION_MAJOR             "@GMX_VERSION_MAJOR@")
+set(GMX_VERSION_MINOR             "@GMX_VERSION_MINOR@")
+set(GMX_VERSION_PATCH             "@GMX_VERSION_PATCH@")
+set(GMX_VERSION_STRING            "@GMX_VERSION_STRING@")
+
+set(GMX_VERSION_STRING_FULL       "@GMX_VERSION_STRING_FULL@")
+set(GMX_VERSION_FULL_HASH         "@GMX_VERSION_FULL_HASH@")
+set(GMX_VERSION_CENTRAL_BASE_HASH "@GMX_VERSION_CENTRAL_BASE_HASH@")
diff --git a/cmake/gmxConfigureVersionInfo.cmake b/cmake/gmxConfigureVersionInfo.cmake
new file mode 100644 (file)
index 0000000..a00e2c3
--- /dev/null
@@ -0,0 +1,36 @@
+#
+# This file is part of the GROMACS molecular simulation package.
+#
+# Copyright (c) 2014, by the GROMACS development team, led by
+# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+# and including many others, as listed in the AUTHORS file in the
+# top-level source directory and at http://www.gromacs.org.
+#
+# GROMACS is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1
+# of the License, or (at your option) any later version.
+#
+# GROMACS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with GROMACS; if not, see
+# http://www.gnu.org/licenses, or write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+#
+# If you want to redistribute modifications to GROMACS, please
+# consider that scientific software is very special. Version
+# control is crucial - bugs must be traceable. We will be happy to
+# consider code for inclusion in the official distribution, but
+# derived work must not be called official GROMACS. Details are found
+# in the README & COPYING files - if they are missing, get the
+# official version at http://www.gromacs.org.
+#
+# To help us fund GROMACS development, we humbly ask that you cite
+# the research papers on the package. Check out http://www.gromacs.org.
+
+include(${VERSION_VARIABLES})
+configure_file(${VERSION_CMAKEIN} ${VERSION_OUT} @ONLY)
index 8db1e10400d878cb679d0a653d8e271a7abe02e8..9c64eb580c95588f6504df61123d2fce7e8947f7 100644 (file)
 # PROJECT_SOURCE_DIR     - top level source directory (which has to be in git)
 # VERSION_CMAKEIN        - path to an input template file
 # VERSION_OUT            - path to the output file
-# VERSION_NO_REMOTE_HASH - if set, GMX_GIT_REMOTE_HASH is not generated
 #
 # Output:
-# i)  Script mode: VERSION_OUT is configured from the input VERSION_CMAKEIN
+# VERSION_OUT is configured from the input VERSION_CMAKEIN
 # using the variables listed below.
-# ii) Cache variable mode: the variables below are set in cache.
 #
-# GMX_PROJECT_VERSION_STR   - version string
-# GMX_GIT_HEAD_HASH         - git hash of current local HEAD
-# GMX_GIT_REMOTE_HASH       - git hash of the first ancestor commit from the
-#                             main Gromacs repository
+# GMX_VERSION_STRING_FULL       - version string
+# GMX_VERSION_FULL_HASH         - git hash of current local HEAD
+# GMX_VERSION_CENTRAL_BASE_HASH - git hash of the first ancestor commit from the
+#                                 main Gromacs repository
 #
 # Szilard Pall (pszilard@cbr.su.se)
 # Teemu Murtola (teemu.murtola@gmail.com)
 
+# Check input variables.
 if("${PROJECT_VERSION}" STREQUAL "")
     message(FATAL_ERROR "PROJECT_VERSION undefined!")
 endif()
-
-# if we're generating variables for cache unset the variables
-if(GEN_VERSION_INFO_INTERNAL)
-    set(GMX_PROJECT_VERSION_STR)
-    set(GMX_GIT_HEAD_HASH)
-    set(GMX_GIT_REMOTE_HASH)
+if (NOT EXISTS "${GIT_EXECUTABLE}")
+    message(FATAL_ERROR "Git executable is not set correctly")
 endif()
-
-# bail if the source tree is not in a git repository
-if(NOT EXISTS "${PROJECT_SOURCE_DIR}/.git")
+if (NOT EXISTS "${PROJECT_SOURCE_DIR}/.git")
     message(FATAL_ERROR "Project source directory ${PROJECT_SOURCE_DIR} not in git")
 endif()
+if ("${VERSION_CMAKEIN}" STREQUAL "")
+    message(FATAL_ERROR "Missing input parameter VERSION_CMAKEIN!")
+endif()
+if ("${VERSION_OUT}" STREQUAL "")
+    message(FATAL_ERROR "Missing input parameter VERSION_OUT!")
+endif()
 
-# If git executable exists, build the development version string.
-if(EXISTS "${GIT_EXECUTABLE}")
-    # refresh git index
-    execute_process(COMMAND ${GIT_EXECUTABLE} update-index -q --refresh
-        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
-        TIMEOUT 5
-        OUTPUT_QUIET
-        ERROR_VARIABLE EXEC_ERR
-        OUTPUT_STRIP_TRAILING_WHITESPACE
-    )
+# refresh git index
+execute_process(COMMAND ${GIT_EXECUTABLE} update-index -q --refresh
+    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+    TIMEOUT 5
+    OUTPUT_QUIET
+    ERROR_VARIABLE EXEC_ERR
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+)
 
-    # get the full hash of the current HEAD
-    execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
-        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
-        OUTPUT_VARIABLE HEAD_HASH
-        ERROR_VARIABLE EXEC_ERR
-        OUTPUT_STRIP_TRAILING_WHITESPACE
-    )
-    set(GMX_GIT_HEAD_HASH ${HEAD_HASH})
-    # extract the shortened hash (7 char)
-    execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
-        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
-        OUTPUT_VARIABLE HEAD_HASH_SHORT
-        ERROR_VARIABLE EXEC_ERR
-        OUTPUT_STRIP_TRAILING_WHITESPACE
-    )
+# get the full hash of the current HEAD
+execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
+    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+    OUTPUT_VARIABLE HEAD_HASH
+    ERROR_VARIABLE EXEC_ERR
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+set(GMX_VERSION_FULL_HASH ${HEAD_HASH})
 
-    # if there are local uncommitted changes, the build gets labeled "dirty"
-    execute_process(COMMAND ${GIT_EXECUTABLE} diff-index --name-only HEAD
-        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
-        OUTPUT_VARIABLE SRC_LOCAL_CHANGES
-        ERROR_VARIABLE EXEC_ERR
-        OUTPUT_STRIP_TRAILING_WHITESPACE
-    )
-    if(NOT "${SRC_LOCAL_CHANGES}" STREQUAL "")
-        set(DIRTY_STR "-dirty")
-        set(GMX_GIT_HEAD_HASH "${GMX_GIT_HEAD_HASH} (dirty)")
-    endif()
+# extract the shortened hash (7 char)
+execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
+    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+    OUTPUT_VARIABLE HEAD_HASH_SHORT
+    ERROR_VARIABLE EXEC_ERR
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+)
 
-    # get the date of the HEAD commit
-    execute_process(COMMAND ${GIT_EXECUTABLE} rev-list -n1 "--pretty=format:%ci" HEAD
-        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
-        OUTPUT_VARIABLE HEAD_DATE
-        ERROR_VARIABLE EXEC_ERR
-        OUTPUT_STRIP_TRAILING_WHITESPACE
-    )
-    string(REGEX REPLACE "\n| " ";" HEAD_DATE "${HEAD_DATE}")
-    list(GET HEAD_DATE 2 HEAD_DATE)
-    string(REGEX REPLACE "-" "" HEAD_DATE "${HEAD_DATE}")
+# if there are local uncommitted changes, the build gets labeled "dirty"
+execute_process(COMMAND ${GIT_EXECUTABLE} diff-index --name-only HEAD
+    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+    OUTPUT_VARIABLE SRC_LOCAL_CHANGES
+    ERROR_VARIABLE EXEC_ERR
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+if(NOT "${SRC_LOCAL_CHANGES}" STREQUAL "")
+    set(DIRTY_STR "-dirty")
+    set(GMX_VERSION_FULL_HASH "${GMX_VERSION_FULL_HASH} (dirty)")
+endif()
 
-    # compile the version string suffix
-    set(VERSION_STR_SUFFIX "${HEAD_DATE}-${HEAD_HASH_SHORT}${DIRTY_STR}")
+# get the date of the HEAD commit
+execute_process(COMMAND ${GIT_EXECUTABLE} rev-list -n1 "--pretty=format:%ci" HEAD
+    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+    OUTPUT_VARIABLE HEAD_DATE
+    ERROR_VARIABLE EXEC_ERR
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+string(REGEX REPLACE "\n| " ";" HEAD_DATE "${HEAD_DATE}")
+list(GET HEAD_DATE 2 HEAD_DATE)
+string(REGEX REPLACE "-" "" HEAD_DATE "${HEAD_DATE}")
 
-    if (DEFINED VERSION_NO_REMOTE_HASH)
-        set(GMX_REMOTES "")
-    else()
-        # find the names of remotes that are located on the official gromacs
-        # git/gerrit servers
-        execute_process(COMMAND ${GIT_EXECUTABLE} config --get-regexp
-                        "remote\\..*\\.url" "\\.gromacs\\.org[:/].*gromacs(\\.git)?$"
-            WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
-            OUTPUT_VARIABLE GMX_REMOTES
-            ERROR_VARIABLE EXEC_ERR
-            OUTPUT_STRIP_TRAILING_WHITESPACE
-        )
-    endif()
+# compile the version string suffix
+set(VERSION_STR_SUFFIX "${HEAD_DATE}-${HEAD_HASH_SHORT}${DIRTY_STR}")
 
-    # if there are remotes from the gromacs git servers, try to find ancestor
-    # commits of the current HEAD from this remote;
-    # otherwise, label the build "unknown"
-    if("${GMX_REMOTES}" STREQUAL "")
-        if (NOT DEFINED VERSION_NO_REMOTE_HASH)
-            set(VERSION_STR_SUFFIX "${VERSION_STR_SUFFIX}-unknown")
-        endif()
-        set(GMX_GIT_REMOTE_HASH "unknown")
-    else()
-        string(REPLACE "\n" ";" GMX_REMOTES ${GMX_REMOTES})
-        # construct a command pipeline that produces a reverse-time-ordered
-        # list of commits and their annotated names in GMX_REMOTES
-        # the max-count limit is there to put an upper bound on the execution time
-        set(BASEREVCOMMAND "COMMAND ${GIT_EXECUTABLE} rev-list --max-count=1000 HEAD")
-        foreach(REMOTE ${GMX_REMOTES})
-            string(REGEX REPLACE "remote\\.(.*)\\.url.*" "\\1" REMOTE ${REMOTE})
-            set(BASEREVCOMMAND "${BASEREVCOMMAND} COMMAND ${GIT_EXECUTABLE} name-rev --stdin --refs=refs/remotes/${REMOTE}/*")
-        endforeach(REMOTE)
-        # this is necessary for CMake to properly split the variable into
-        # parameters for execute_process().
-        string(REPLACE " " ";" BASEREVCOMMAND ${BASEREVCOMMAND})
-        # find the first ancestor in the list provided by rev-list (not
-        # necessarily the last though) which is in GMX_REMOTE, extract the
-        # hash and the number of commits HEAD is ahead with
-        execute_process(${BASEREVCOMMAND}
-            WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
-            OUTPUT_VARIABLE ANCESTOR_LIST
-        )
-        string(REGEX REPLACE "\n" ";" ANCESTOR_LIST "${ANCESTOR_LIST}")
+# find the names of remotes that are located on the official gromacs
+# git/gerrit servers
+execute_process(COMMAND ${GIT_EXECUTABLE} config --get-regexp
+                "remote\\..*\\.url" "\\.gromacs\\.org[:/].*gromacs(\\.git)?$"
+    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+    OUTPUT_VARIABLE GMX_REMOTES
+    ERROR_VARIABLE EXEC_ERR
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+)
 
-        set(AHEAD 0)
-        set(GMX_GIT_REMOTE_HASH "")
-        foreach(ANCESTOR ${ANCESTOR_LIST})
-            string(REPLACE "\n" "" HASH_AND_REVNAMES "${ANCESTOR}")
-            string(REPLACE " " ";" HASH_AND_REVNAMES "${HASH_AND_REVNAMES}")
-            list(LENGTH HASH_AND_REVNAMES COUNT)
-            # stop and set the hash if we have a hit, otherwise loop and count
-            # how far ahead is the local repo
-            if(COUNT GREATER 1)
-                LIST(GET HASH_AND_REVNAMES 0 GMX_GIT_REMOTE_HASH)
-                break()
-            endif()
-            math(EXPR AHEAD ${AHEAD}+1)
-        endforeach(ANCESTOR)
-        # mark the build "local" if didn't find any commits that are from
-        # remotes/${GMX_REMOTE}/*
-        if("${GMX_GIT_REMOTE_HASH}" STREQUAL "")
-            set(GMX_GIT_REMOTE_HASH "unknown")
-            set(VERSION_STR_SUFFIX "${VERSION_STR_SUFFIX}-local")
-        # don't print the remote hash if there are no local commits
-        elseif("${GMX_GIT_REMOTE_HASH}" STREQUAL "${HEAD_HASH}")
-            set(GMX_GIT_REMOTE_HASH "")
-        else()
-            set(GMX_GIT_REMOTE_HASH "${GMX_GIT_REMOTE_HASH} (${AHEAD} newer local commits)")
-        endif()
+# if there are remotes from the gromacs git servers, try to find ancestor
+# commits of the current HEAD from this remote;
+# otherwise, label the build "unknown"
+if("${GMX_REMOTES}" STREQUAL "")
+    if (NOT DEFINED VERSION_NO_REMOTE_HASH)
+        set(VERSION_STR_SUFFIX "${VERSION_STR_SUFFIX}-unknown")
     endif()
-
-    # compile final version string
-    set(GMX_PROJECT_VERSION_STR "${PROJECT_VERSION}-${VERSION_STR_SUFFIX}")
+    set(GMX_VERSION_CENTRAL_BASE_HASH "unknown")
 else()
-    # the version has to be defined
-    # set the GIT related information to "unknown"
-    message(WARNING "Source tree seems to be a repository, but no compatible git is available, using hard-coded version string")
-    set(GMX_PROJECT_VERSION_STR "${PROJECT_VERSION}")
-    set(GMX_GIT_HEAD_HASH "unknown")
-    set(GMX_GIT_REMOTE_HASH "unknown")
-endif()
+    string(REPLACE "\n" ";" GMX_REMOTES ${GMX_REMOTES})
+    # construct a command pipeline that produces a reverse-time-ordered
+    # list of commits and their annotated names in GMX_REMOTES
+    # the max-count limit is there to put an upper bound on the execution time
+    set(BASEREVCOMMAND "COMMAND ${GIT_EXECUTABLE} rev-list --max-count=1000 HEAD")
+    foreach(REMOTE ${GMX_REMOTES})
+        string(REGEX REPLACE "remote\\.(.*)\\.url.*" "\\1" REMOTE ${REMOTE})
+        set(BASEREVCOMMAND "${BASEREVCOMMAND} COMMAND ${GIT_EXECUTABLE} name-rev --stdin --refs=refs/remotes/${REMOTE}/*")
+    endforeach(REMOTE)
+    # this is necessary for CMake to properly split the variable into
+    # parameters for execute_process().
+    string(REPLACE " " ";" BASEREVCOMMAND ${BASEREVCOMMAND})
+    # find the first ancestor in the list provided by rev-list (not
+    # necessarily the last though) which is in GMX_REMOTE, extract the
+    # hash and the number of commits HEAD is ahead with
+    execute_process(${BASEREVCOMMAND}
+        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+        OUTPUT_VARIABLE ANCESTOR_LIST
+    )
+    string(REGEX REPLACE "\n" ";" ANCESTOR_LIST "${ANCESTOR_LIST}")
 
-# if we're generating cache variables set these
-# otherwise it's assumed that it's called in script mode to generate a file
-if(GEN_VERSION_INFO_INTERNAL)
-    set(GMX_PROJECT_VERSION_STR ${GMX_PROJECT_VERSION_STR}
-        CACHE STRING "Gromacs version string" FORCE)
-    set(GMX_GIT_HEAD_HASH ${GMX_GIT_HEAD_HASH}${DIRTY_STR}
-        CACHE STRING "Current git HEAD commit object" FORCE)
-    set(GMX_GIT_REMOTE_HASH ${GMX_GIT_REMOTE_HASH}
-        CACHE STRING "Commmit object of the nearest ancestor present in the Gromacs git repository" FORCE)
-    mark_as_advanced(GMX_GIT_HEAD_HASH GMX_GIT_REMOTE_HASH)
-else()
-    if("${VERSION_CMAKEIN}" STREQUAL "")
-        message(FATAL_ERROR "Missing input parameter VERSION_CMAKEIN!")
-    endif()
-    if("${VERSION_OUT}" STREQUAL "")
-        message(FATAL_ERROR "Missing input parameter VERSION_OUT!")
+    set(AHEAD 0)
+    set(GMX_VERSION_CENTRAL_BASE_HASH "")
+    foreach(ANCESTOR ${ANCESTOR_LIST})
+        string(REPLACE "\n" "" HASH_AND_REVNAMES "${ANCESTOR}")
+        string(REPLACE " " ";" HASH_AND_REVNAMES "${HASH_AND_REVNAMES}")
+        list(LENGTH HASH_AND_REVNAMES COUNT)
+        # stop and set the hash if we have a hit, otherwise loop and count
+        # how far ahead is the local repo
+        if(COUNT GREATER 1)
+            LIST(GET HASH_AND_REVNAMES 0 GMX_VERSION_CENTRAL_BASE_HASH)
+            break()
+        endif()
+        math(EXPR AHEAD ${AHEAD}+1)
+    endforeach(ANCESTOR)
+    # mark the build "local" if didn't find any commits that are from
+    # remotes/${GMX_REMOTE}/*
+    if("${GMX_VERSION_CENTRAL_BASE_HASH}" STREQUAL "")
+        set(GMX_VERSION_CENTRAL_BASE_HASH "unknown")
+        set(VERSION_STR_SUFFIX "${VERSION_STR_SUFFIX}-local")
+    # don't print the remote hash if there are no local commits
+    elseif("${GMX_VERSION_CENTRAL_BASE_HASH}" STREQUAL "${HEAD_HASH}")
+        set(GMX_VERSION_CENTRAL_BASE_HASH "")
+    else()
+        set(GMX_VERSION_CENTRAL_BASE_HASH "${GMX_VERSION_CENTRAL_BASE_HASH} (${AHEAD} newer local commits)")
     endif()
-    # Generate the output file.
-    configure_file(${VERSION_CMAKEIN} ${VERSION_OUT})
 endif()
+
+# Compile final version string.
+set(GMX_VERSION_STRING_FULL "${PROJECT_VERSION}-${VERSION_STR_SUFFIX}")
+
+# Generate the output file.
+configure_file(${VERSION_CMAKEIN} ${VERSION_OUT})
diff --git a/cmake/gmxVersionInfo.cmake b/cmake/gmxVersionInfo.cmake
new file mode 100644 (file)
index 0000000..3e6ed3f
--- /dev/null
@@ -0,0 +1,408 @@
+#
+# This file is part of the GROMACS molecular simulation package.
+#
+# Copyright (c) 2014, by the GROMACS development team, led by
+# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+# and including many others, as listed in the AUTHORS file in the
+# top-level source directory and at http://www.gromacs.org.
+#
+# GROMACS is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1
+# of the License, or (at your option) any later version.
+#
+# GROMACS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with GROMACS; if not, see
+# http://www.gnu.org/licenses, or write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+#
+# If you want to redistribute modifications to GROMACS, please
+# consider that scientific software is very special. Version
+# control is crucial - bugs must be traceable. We will be happy to
+# consider code for inclusion in the official distribution, but
+# derived work must not be called official GROMACS. Details are found
+# in the README & COPYING files - if they are missing, get the
+# official version at http://www.gromacs.org.
+#
+# To help us fund GROMACS development, we humbly ask that you cite
+# the research papers on the package. Check out http://www.gromacs.org.
+
+# Sets version information variables and provides CMake functions for
+# generating files based on them
+#
+# This script provides the following basic version variables that need to be
+# maintained manually:
+#   GMX_VERSION_MAJOR      Major version number.
+#   GMX_VERSION_MINOR      Minor version number.
+#   GMX_VERSION_PATCH      Patch version number.
+#       Should always be defined: zero for, e.g., 5.0.
+#   GMX_VERSION_SUFFIX     String suffix to add to numeric version string.
+#       "-dev" is automatically added when not building from a source package,
+#       and does not need to be kept here.
+#   LIBRARY_SOVERSION      so version for the built libraries.
+#       Should be increased for each binary incompatible release (in GROMACS,
+#       the typical policy is to increase it for each major/minor version
+#       change, but not for patch releases, even if the latter may not always
+#       be fully binary compatible).
+#   LIBRARY_VERSION        Full library version.
+#   REGRESSIONTEST_BRANCH  For builds not from source packages, name of the
+#       regressiontests branch at gerrit.gromacs.org whose HEAD can test this
+#       code, *if* this code is recent enough (i.e., contains all changes from
+#       the corresponding code branch that affects the regression test
+#       results).
+# They are collected into a single section below.
+# The following variables are set based on these:
+#   GMX_VERSION            String composed from GMX_VERSION_* numeric variables
+#       above. Example: 4.6.1, 5.0
+#   GMX_VERSION_STRING     String with GMX_VERSION suffixed with the given
+#       suffix and possibly "-dev" for builds not from a source package.
+#   GMX_VERSION_NUMERIC    Numeric version number (e.g., 40601 for 4.6.1).
+#   GMX_API_VERSION        Numeric API version.
+#       This is currently set automatically to GMX_VERSION_NUMERIC, but may
+#       become manually maintained in the future if there will be releases
+#       where the API does not change, but programs/libraries do.
+#       In such a case, this should be the first version where the current API
+#       appeared.
+#   REGRESSIONTEST_VERSION For source packages, version number of the
+#       matching regressiontests tarball.  Not used for builds not from source
+#       packages.
+# The latter two are used to generate gromacs/version.h to allow software
+# written against the GROMACS API to provide some #ifdef'ed code to support
+# multiple GROMACS versions.
+#
+# The following variables are defined without manual intervention:
+#   SOURCE_IS_SOURCE_DISTRIBUTION  The source tree is from a source tarball.
+#   SOURCE_IS_GIT_REPOSITORY       The source tree is a git repository.
+# Note that both can be false if the tree has been extracted, e.g., as a
+# tarball directly from git.
+#
+# This script also declares machinery to generate and obtain version
+# information from a git repository.  This is enabled by default if the source
+# tree is a git, but can be disabled with
+#   GMX_GIT_VERSION_INFO           Advanced CMake variable to disable git
+#                                  version info generation.
+# The main interface to this machinery is the gmx_configure_version_file()
+# CMake function.  The signature is
+#   gmx_configure_version_file(<input> <output>
+#                              [REMOTE_HASH] [SOURCE_FILE]
+#                              [TARGET <target>]
+#                              [COMMENT <comment>])
+#   <input>      Specify the input and output files as for configure_file().
+#   <output>     The configuration is done with configure_file(... @ONLY) with
+#                the following variables defined (as well as all the
+#                GMX_VERSION* variables from above):
+#                  GMX_VERSION_STRING_FULL
+#                  GMX_VERSION_FULL_HASH
+#                  GMX_VERSION_CENTRAL_BASE_HASH
+#                The output file is created during build time, so any dependent
+#                targets should specify it as a dependency.
+#   REMOTE_HASH  Currently, this has no effect, but it signifies that the
+#                <input> file is using the CENTRAL_BASE_HASH variable.
+#                This variable is much more expensive to initialize than the
+#                others, so this allows local changes in this file to only
+#                compute that value when required if that becomes necessary.
+#   SOURCE_FILE  Signals that <output> will be used as a source file.
+#                The function will set properties for the source file
+#                appropriately to signify that it is generated.
+#   TARGET       By default, this function uses add_custom_command() to
+#                generate the output file.  If TARGET is specified, then
+#                add_custom_target() is used to create a target with the given
+#                name <target> that runs this custom command.  Use this if
+#                the same file will be used for multiple downstream targets,
+#                or if the explicit target for the file is otherwise
+#                necessary.
+#   COMMENT      Set a custom comment to be shown when building the rule
+#                (see add_custom_command(... COMMENT <comment>)).
+# As an alternative to using this script, also the following variables are
+# provided (can be useful when generating more complex CMake scripts that do
+# build-time tasks):
+#   VERSION_INFO_CMAKE_SCRIPT
+#       Absolute path to a CMake script that can be included using include()
+#       to declare the GMX_VERSION_* variables documented for
+#       gmx_configure_version_file().
+#   VERSION_INFO_DEPS
+#       If a custom command depends on VERSION_INFO_CMAKE_SCRIPT, then it
+#       should add ${VERSION_INFO_DEPS} to its DEPENDS list to get the
+#       appropriate dependencies.
+# TODO: If someone wants to add a custom target that depends on
+# VERSION_INFO_CMAKE_SCRIPT, a separate variable may be needed for those
+# dependencies.
+#
+# The version string printed by 'gmx -version' (and also printed in the startup
+# header) can provide useful information for, e.g., diagnosing bug reports and
+# identifying what exact version the user was using.  The following formats are
+# possible (with examples given for a particular version):
+#   4.6.1       Plain version number without any suffix signifies a build from
+#               a released source tarball.
+#   4.6.1-dev   '-dev' suffix signifies all other builds. If there is no other
+#               information, either the user built the code outside any git
+#               repository, or disabled the version info generation.
+#   4.6.1-dev-YYYYMMDD-1234abc
+#               The YYYYMMDD part shows the commit date (not author date) of
+#               the HEAD commit from which the code was built.  The abbreviated
+#               hash is the hash of that commit (the full hash is available in
+#               'gmx -version' output).
+#               If the HEAD hash is not identified as coming from branches in
+#               "authoritative" GROMACS repositories, 'gmx -version' will show
+#               the nearest ancestor commit that is identified as such (but see
+#               the '-local' and '-unknown' suffixes below).
+#   4.6.1-dev-YYYYMMDD-1234abc-dirty
+#               As above, but there were local modifications in the source tree
+#               when the code was built.
+#   4.6.1-dev-YYYYMMDD-1234abc-unknown
+#               As above, but there were no remotes in the repository that
+#               could be identified as "authoritative" GROMACS repositories.
+#               This happens if the code is not cloned from git.gromacs.org
+#               or gerrit.gromacs.org.
+#   4.6.1-dev-YYYYMMDD-1234abc-local
+#               As above, but there were no commits in the recent history of
+#               the branch that could be identified as coming from
+#               "authoritative" GROMACS repositories.  This should be
+#               relatively rare.
+#
+# Other variables set here are not intended for use outside this file.
+# The scripts gmxGenerateVersionInfo.cmake and gmxConfigureVersionInfo.cmake
+# are used internally by this machinery, as well as VersionInfo.cmake.cmakein.
+
+#####################################################################
+# Basic nature of the source tree
+
+set(SOURCE_IS_GIT_REPOSITORY OFF)
+set(SOURCE_IS_SOURCE_DISTRIBUTION OFF)
+if (EXISTS "${PROJECT_SOURCE_DIR}/.git")
+    set(SOURCE_IS_GIT_REPOSITORY ON)
+endif()
+# This file is excluded from CPack source packages, but part of the repository,
+# so it should get included everywhere else.
+if (NOT EXISTS "${PROJECT_SOURCE_DIR}/admin/.isreposource")
+    set(SOURCE_IS_SOURCE_DISTRIBUTION ON)
+endif()
+
+#####################################################################
+# Manually maintained version info
+
+# The GROMACS convention is that these are the version number of the next
+# release that is going to be made from this branch.
+set(GMX_VERSION_MAJOR 5)
+set(GMX_VERSION_MINOR 1)
+set(GMX_VERSION_PATCH 0)
+# The suffix, on the other hand, is used mainly for betas and release
+# candidates, where it signifies the last such release from this branch;
+# it will be empty before the first such release, as well as after the
+# final release is out.
+set(GMX_VERSION_SUFFIX "")
+
+set(LIBRARY_SOVERSION 1)
+set(LIBRARY_VERSION ${LIBRARY_SOVERSION}.0.0)
+
+set(REGRESSIONTEST_BRANCH "refs/heads/master")
+
+#####################################################################
+# General version management based on manually set numbers
+
+if (GMX_VERSION_PATCH)
+    set(GMX_VERSION "${GMX_VERSION_MAJOR}.${GMX_VERSION_MINOR}.${GMX_VERSION_PATCH}")
+else()
+    set(GMX_VERSION "${GMX_VERSION_MAJOR}.${GMX_VERSION_MINOR}")
+endif()
+set(GMX_VERSION_STRING "${GMX_VERSION}${GMX_VERSION_SUFFIX}")
+if (NOT SOURCE_IS_SOURCE_DISTRIBUTION)
+    set(GMX_VERSION_STRING "${GMX_VERSION_STRING}-dev")
+endif()
+
+set(REGRESSIONTEST_VERSION "${GMX_VERSION_STRING}")
+
+math(EXPR GMX_VERSION_NUMERIC
+     "${GMX_VERSION_MAJOR}*10000 + ${GMX_VERSION_MINOR}*100 + ${GMX_VERSION_PATCH}")
+set(GMX_API_VERSION ${NUM_VERSION})
+
+#####################################################################
+# git version info management
+
+# There can be clusters where git and CMake can run on nodes where the other is
+# not available, accessing the same source tree.
+# Should be unlikely, but doesn't hurt to check.
+set(_git_info_default OFF)
+if (SOURCE_IS_GIT_REPOSITORY)
+    find_package(Git)
+    if (GIT_FOUND)
+        set(_git_info_default ON)
+    endif()
+endif()
+option(GMX_GIT_VERSION_INFO "Generate git version information" ${_git_info_default})
+mark_as_advanced(GMX_GIT_VERSION_INFO)
+# Detect preconditions for version info generation if it is requested.
+if (GMX_GIT_VERSION_INFO)
+    if (NOT SOURCE_IS_GIT_REPOSITORY)
+        message(FATAL_ERROR
+            "Cannot generate git version information from source tree not under git. "
+            "Set GMX_GIT_VERSION_INFO=OFF to proceed.")
+    endif()
+    # We need at least git v1.5.3 be able to parse git's date output.
+    if (NOT GIT_FOUND OR GIT_VERSION_STRING VERSION_LESS "1.5.3")
+        message(FATAL_ERROR
+            "No compatible git version found (>= 1.5.3 required). "
+            "Won't be able to generate development version information. "
+            "Set GMX_GIT_VERSION_INFO=OFF to proceed.")
+    endif()
+endif()
+
+# The first two are also for use outside this file, encapsulating the details
+# of how to use the generated VersionInfo.cmake.
+set(VERSION_INFO_CMAKE_FILE   ${PROJECT_BINARY_DIR}/VersionInfo.cmake)
+set(VERSION_INFO_DEPS         ${VERSION_INFO_CMAKE_FILE})
+# Capture the location of the necessary files in internal variables for use in
+# the function below.
+set(VERSION_INFO_CMAKEIN_FILE     ${CMAKE_CURRENT_LIST_DIR}/VersionInfo.cmake.cmakein)
+set(VERSION_INFO_CONFIGURE_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/gmxConfigureVersionInfo.cmake)
+
+# Rules to create the VersionInfo.cmake file.
+# For git info, the sequence is:
+#   1. (configure time) VersionInfo.cmake.cmakein -> VersionInfo-partial.cmake.cmakein
+#        - Set all variables that are known at configure time.
+#   2. (build time)     VersionInfo-partial.cmake.cmakein -> VersionInfo.cmake
+#        - Set variables that may change as result of repository state changes
+#          (i.e., everything that requires running git).
+#        - Runs every time as a git-version-info target, but the output file
+#          timestamp only changes if its contents actually change.
+#        - Depending on the native build system, this may run once per build
+#          or once per each time it is required for step 3.
+#   3. (build time)     VersionInfo.cmake -> other files
+#        - Set variables in files specified with gmx_configure_version_file()
+#          using the values generated in step 2.
+#        - Each file runs as a custom command that depends on the previous
+#          steps, and runs only if the VersionInfo.cmake file is newer than the
+#          output file.
+# Without git info, the sequence is:
+#  1. (configure time) VersionInfo.cmake.cmakein -> VersionInfo.cmake
+#        - Everything is known at configure time, so the output is generated
+#          immediately with all variables set (git info will be empty).
+#  2. (build time)     VersionInfo.cmake -> other files
+#        - As with git info, processes files from gmx_configure_version_file().
+#        - These are again custom commands that depend on the output from
+#          step 1, so they get regenerated only when the static version info
+#          changes.
+if (GMX_GIT_VERSION_INFO)
+    # Configure information known at this time into a partially filled
+    # version info file.
+    set(VERSION_INFO_CMAKEIN_FILE_PARTIAL
+        ${PROJECT_BINARY_DIR}/VersionInfo-partial.cmake.cmakein)
+    # Leave these to be substituted by the custom target below.
+    set(GMX_VERSION_STRING_FULL       "\@GMX_VERSION_STRING_FULL\@")
+    set(GMX_VERSION_FULL_HASH         "\@GMX_VERSION_FULL_HASH\@")
+    set(GMX_VERSION_CENTRAL_BASE_HASH "\@GMX_VERSION_CENTRAL_BASE_HASH\@")
+    configure_file(${VERSION_INFO_CMAKEIN_FILE}
+                   ${VERSION_INFO_CMAKEIN_FILE_PARTIAL}
+                   @ONLY)
+    # If generating the version info, create a target that runs on every build
+    # and does the actual git calls, storing the results into a CMake script.
+    # This needs to be run at build time to update the version information
+    # properly when the git hash changes, but the build system does not.
+    # All targets added by gmx_configure_version_file() use the information
+    # from this script to get their variables from, removing the need to run
+    # git multiple times and simplifying reuse for other purposes.
+    #
+    # Ninja requires all generated files mentioned in dependencies of custom
+    # commands (in gmx_configure_version_info()) to be actually mentioned in
+    # the build system, and luckily add_custom_command() makes that possible.
+    # But it seems impossible to create a robust custom command that would be
+    # always run, so other generators that do not have this constraint simply
+    # use an add_custom_target().
+    if (CMAKE_GENERATOR STREQUAL "Ninja")
+        # The second, phony file is never created, so the rule is always
+        # triggered again.  TODO: Figure out why this works, even though ninja
+        # very eagerly complains about missing files.
+        # This unfortunately does not work with the make generator, as
+        # the non-existent second file causes some part of the generated system
+        # erase the first file at the beginning of every build, causing a full
+        # rebuild of the dependencies.
+        add_custom_command(OUTPUT ${VERSION_INFO_CMAKE_FILE} git-version-phony
+            COMMAND ${CMAKE_COMMAND}
+                -D GIT_EXECUTABLE=${GIT_EXECUTABLE}
+                -D PROJECT_VERSION=${GMX_VERSION_STRING}
+                -D PROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}
+                -D VERSION_CMAKEIN=${VERSION_INFO_CMAKEIN_FILE_PARTIAL}
+                -D VERSION_OUT=${VERSION_INFO_CMAKE_FILE}
+                -P ${CMAKE_CURRENT_LIST_DIR}/gmxGenerateVersionInfo.cmake
+            WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+            COMMENT "Generating git version information"
+            VERBATIM)
+        # The generated Ninja build system would probably work fine even
+        # without this target, but CMake requires all custom commands to belong
+        # to a target in the same CMakeLists.txt to generate anything for them.
+        add_custom_target(git-version-info DEPENDS ${VERSION_INFO_CMAKE_FILE})
+    else()
+        # For other generators, a target-level dependency on git-version-info
+        # ensures that VERSION_INFO_CMAKE_FILE is created before the dependent
+        # target's dependencies are even evaluated.
+        add_custom_target(git-version-info
+            COMMAND ${CMAKE_COMMAND}
+                -D GIT_EXECUTABLE=${GIT_EXECUTABLE}
+                -D PROJECT_VERSION=${GMX_VERSION_STRING}
+                -D PROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}
+                -D VERSION_CMAKEIN=${VERSION_INFO_CMAKEIN_FILE_PARTIAL}
+                -D VERSION_OUT=${VERSION_INFO_CMAKE_FILE}
+                -P ${CMAKE_CURRENT_LIST_DIR}/gmxGenerateVersionInfo.cmake
+            WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+            COMMENT "Generating git version information"
+            VERBATIM)
+    endif()
+    list(APPEND VERSION_INFO_DEPS git-version-info)
+else()
+    # If the version info is static, just generate the CMake script with the
+    # version variables during the CMake run.
+    set(GMX_VERSION_STRING_FULL       ${GMX_VERSION_STRING})
+    set(GMX_VERSION_FULL_HASH         "")
+    set(GMX_VERSION_CENTRAL_BASE_HASH "")
+    configure_file(${VERSION_INFO_CMAKEIN_FILE} ${VERSION_INFO_CMAKE_FILE})
+endif()
+unset(GMX_VERSION_STRING_FULL)
+unset(GMX_VERSION_FULL_HASH)
+unset(GMX_VERSION_CENTRAL_BASE_HASH)
+
+# The main user-visible interface to the machinery.
+# See documentation at the top of the script.
+function (gmx_configure_version_file INFILE OUTFILE)
+    include(CMakeParseArguments)
+    set(_options REMOTE_HASH SOURCE_FILE)
+    set(_one_value_args COMMENT TARGET)
+    cmake_parse_arguments(ARG "${_options}" "${_one_value_args}" "" ${ARGN})
+    if (ARG_UNPARSED_ARGUMENTS)
+        message(FATAL_ERROR "Unknown arguments: ${ARG_UNPARSED_ARGUMENTS}")
+    endif()
+    # Some callers may pass partial paths that do not really make sense,
+    # so create a default comment that only contains the actual file name.
+    get_filename_component(_basename ${OUTFILE} NAME)
+    set(_comment "Generating ${_basename}")
+    if (ARG_COMMENT)
+        set(_comment ${ARG_COMMENT})
+    endif()
+    # Mimic configure_file()
+    if (NOT IS_ABSOLUTE ${INFILE})
+        set(INFILE ${CMAKE_CURRENT_SOURCE_DIR}/${INFILE})
+    endif()
+    # The touch command is necessary to ensure that after the target is run,
+    # the timestamp is newer than in the input files.
+    add_custom_command(OUTPUT ${OUTFILE}
+        COMMAND ${CMAKE_COMMAND}
+            -D VERSION_VARIABLES=${VERSION_INFO_CMAKE_FILE}
+            -D VERSION_CMAKEIN=${INFILE}
+            -D VERSION_OUT=${OUTFILE}
+            -P ${VERSION_INFO_CONFIGURE_SCRIPT}
+        COMMAND ${CMAKE_COMMAND} -E touch ${OUTFILE}
+        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+        DEPENDS ${INFILE} ${VERSION_INFO_DEPS} ${VERSION_INFO_CONFIGURE_SCRIPT}
+        COMMENT "${_comment}"
+        VERBATIM)
+    if (ARG_TARGET)
+        add_custom_target(${ARG_TARGET} DEPENDS ${OUTFILE} VERBATIM)
+    endif()
+    if (ARG_SOURCE_FILE)
+        set_source_files_properties(${OUTFILE} PROPERTIES GENERATED true)
+    endif()
+endfunction()
index ba333174b2d443dc510939490671b20754a655cd..7401e9560c5e12c6c0c1183f4e7a37d44bc715b1 100644 (file)
@@ -95,6 +95,8 @@ if (DOXYGEN_FOUND)
 
     FILE(COPY index.html DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
     configure_file(RunDoxygen.cmake.cmakein RunDoxygen.cmake @ONLY)
+    gmx_configure_version_file(Doxyfile-version.cmakein Doxyfile-version
+                               TARGET doxygen-version)
     add_custom_target(doc-full
         ${CMAKE_COMMAND} -DDOCTYPE=full -P RunDoxygen.cmake
         WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
@@ -113,28 +115,10 @@ if (DOXYGEN_FOUND)
         COMMENT "Extracting Doxygen documentation to XML" VERBATIM)
     add_custom_target(doc-all)
     add_dependencies(doc-all doc-full doc-lib doc-user)
-
-    if (GMX_GIT_VERSION_INFO)
-        add_custom_target(doxygen-version
-                COMMAND ${CMAKE_COMMAND}
-                    -D GIT_EXECUTABLE="${GIT_EXECUTABLE}"
-                    -D PROJECT_VERSION="${PROJECT_VERSION}"
-                    -D PROJECT_SOURCE_DIR="${PROJECT_SOURCE_DIR}"
-                    -D VERSION_CMAKEIN="${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile-version.cmakein"
-                    -D VERSION_OUT="${CMAKE_CURRENT_BINARY_DIR}/Doxyfile-version"
-                    -D VERSION_NO_REMOTE_HASH=
-                    -P ${CMAKE_SOURCE_DIR}/cmake/gmxGenerateVersionInfo.cmake
-                WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-                DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile-version.cmakein
-                COMMENT "Generating version information for Doxygen")
-        add_dependencies(doc-full doxygen-version)
-        add_dependencies(doc-lib doxygen-version)
-        add_dependencies(doc-user doxygen-version)
-        add_dependencies(doc-xml doxygen-version)
-    else()
-        set(GMX_PROJECT_VERSION_STR ${PROJECT_VERSION})
-        configure_file(Doxyfile-version.cmakein Doxyfile-version)
-    endif()
+    add_dependencies(doc-full doxygen-version)
+    add_dependencies(doc-lib  doxygen-version)
+    add_dependencies(doc-user doxygen-version)
+    add_dependencies(doc-xml  doxygen-version)
 
     if (USE_PYTHON_SCRIPTS)
         # TODO: Consider whether this is the best name and location for this
index 38549a345fdbbe990e0d3a947354a75ec44dfa56..43e374e9c02c223d491326f5d27f8a191ae864e8 100644 (file)
@@ -1 +1 @@
-PROJECT_NUMBER = @GMX_PROJECT_VERSION_STR@
+PROJECT_NUMBER = @GMX_VERSION_STRING_FULL@
index 8980df6bab5d7d5a758841b218173c93e041fbf9..e646163595f36f782b4429a0e810d5bef0706f7d 100644 (file)
@@ -5,7 +5,7 @@
 set(SRC_DIR "@CMAKE_CURRENT_SOURCE_DIR@")
 set(BIN_DIR "@CMAKE_CURRENT_BINARY_DIR@")
 
-set(PROJECT_VERSION "@PROJECT_VERSION@")
+set(PROJECT_VERSION "@GMX_VERSION_STRING@")
 set(GMX_CMAKE_MINIMUM_REQUIRED_VERSION "@GMX_CMAKE_MINIMUM_REQUIRED_VERSION@")
 set(REQUIRED_CUDA_VERSION "@REQUIRED_CUDA_VERSION@")
 set(REQUIRED_CUDA_COMPUTE_CAPABILITY "@REQUIRED_CUDA_COMPUTE_CAPABILITY@")
index cd24695efbc86e8ea1655bf006ed4e5258f1f746..ed4b53ce251289f9e3f8bbf059b64021464c12f7 100644 (file)
@@ -1,7 +1,7 @@
 %
 % This file is part of the GROMACS molecular simulation package.
 %
-% Copyright (c) 2013, by the GROMACS development team, led by
+% Copyright (c) 2013,2014, by the GROMACS development team, led by
 % Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
 % and including many others, as listed in the AUTHORS file in the
 % top-level source directory and at http://www.gromacs.org.
 \newcommand{\ttw}{4.33cm}  % 1/3 of the textwidth
 \newcommand{\htw}{7.5cm}  % 1/2 of the textwidth
 \newcommand{\ntw}{13cm} % 0.9 of the textwidth
-\newcommand{\gmxver}{@PROJECT_VERSION@}
+\newcommand{\gmxver}{@GMX_VERSION_STRING@}
 \newcommand{\gmxyear}{\the\year}
 \newcommand{\figref}[1]{Fig.~\ref{fig:#1}}
 \newcommand{\figsref}[2]{Figs.~\ref{fig:#1} and ~\ref{fig:#2}}
index a04d1dd0eeaae9d1900f49033d17e59fa1268bcd..21232899a2c6854cd7a9376d6d4472d0e3d59278 100644 (file)
@@ -120,37 +120,26 @@ list(APPEND LIBGROMACS_SOURCES ${GMXLIB_SOURCES} ${MDLIB_SOURCES})
 tmpi_get_source_list(THREAD_MPI_SOURCES ${CMAKE_SOURCE_DIR}/src/external/thread_mpi/src)
 list(APPEND LIBGROMACS_SOURCES ${THREAD_MPI_SOURCES})
 
-file(GLOB LIBGROMACS_HEADERS *.h)
+set(LIBGROMACS_HEADERS
+    analysisdata.h
+    commandline.h
+    options.h
+    selection.h
+    trajectoryanalysis.h
+    utility.h)
 configure_file(version.h.cmakein version.h)
 gmx_install_headers("" ${LIBGROMACS_HEADERS})
 gmx_install_headers("" ${CMAKE_CURRENT_BINARY_DIR}/version.h)
 
-# Add target that generates baseversion-gen.c every time make is run
-# if git version info is requested, or create it statically.
-# This code is here instead of utility/CMakeLists.txt because CMake
-# ignores set_source_file_properties from subdirectories.
-set(GENERATED_VERSION_FILE
-    ${CMAKE_CURRENT_BINARY_DIR}/utility/baseversion-gen.c)
-set(GENERATED_VERSION_FILE_SOURCE
-    ${CMAKE_CURRENT_SOURCE_DIR}/utility/baseversion-gen.c.cmakein)
-if (GMX_GIT_VERSION_INFO)
-    add_custom_target(gmx-version ALL
-            COMMAND ${CMAKE_COMMAND}
-                -D GIT_EXECUTABLE="${GIT_EXECUTABLE}"
-                -D PROJECT_VERSION="${PROJECT_VERSION}"
-                -D PROJECT_SOURCE_DIR="${PROJECT_SOURCE_DIR}"
-                -D VERSION_CMAKEIN=${GENERATED_VERSION_FILE_SOURCE}
-                -D VERSION_OUT=${GENERATED_VERSION_FILE}
-                -P ${CMAKE_SOURCE_DIR}/cmake/gmxGenerateVersionInfo.cmake
-            WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-            DEPENDS ${GENERATED_VERSION_FILE_SOURCE}
-            COMMENT "Generating git version information")
-    set_source_files_properties(${GENERATED_VERSION_FILE}
-                                PROPERTIES GENERATED true)
-else()
-    set(GMX_PROJECT_VERSION_STR ${PROJECT_VERSION})
-    configure_file(${GENERATED_VERSION_FILE_SOURCE} ${GENERATED_VERSION_FILE})
-endif()
+# This code is here instead of utility/CMakeLists.txt, because CMake
+# custom commands and source file properties can only be set in the directory
+# that contains the target that uses them.
+# TODO: Generate a header instead that can be included from baseversion.c.
+# That probably simplifies things somewhat.
+set(GENERATED_VERSION_FILE utility/baseversion-gen.c)
+gmx_configure_version_file(
+    utility/baseversion-gen.c.cmakein ${GENERATED_VERSION_FILE}
+    REMOTE_HASH SOURCE_FILE)
 list(APPEND LIBGROMACS_SOURCES ${GENERATED_VERSION_FILE})
 
 # apply gcc 4.4.x bug workaround
@@ -169,9 +158,6 @@ if (GMX_GPU)
 else()
     add_library(libgromacs ${LIBGROMACS_SOURCES})
 endif()
-if (GMX_GIT_VERSION_INFO)
-    add_dependencies(libgromacs gmx-version)
-endif()
 
 # Recent versions of gcc and clang give warnings on scanner.cpp, which
 # is a generated source file. These are awkward to suppress inline, so
index c88b1cb20a62097be9782aef5031578c402e4bf5..2ef52aa20510461f6d36c612035b56550da1ccc0 100644 (file)
@@ -4,7 +4,7 @@ includedir=@CMAKE_INSTALL_PREFIX@/@INCL_INSTALL_DIR@
 Name: libgromacs@GMX_LIBS_SUFFIX@
 Description: Gromacs library
 URL: http://www.gromacs.org
-Version: @PROJECT_VERSION@
+Version: @GMX_VERSION_STRING@
 Requires: @PKG_FFT@ @PKG_XML@
 Libs.private: @CMAKE_THREAD_LIBS_INIT@ @PKG_DL_LIBS@ @OpenMP_LINKER_FLAGS@
 Libs: -L${libdir} -lgromacs@GMX_LIBS_SUFFIX@ @PKG_FFT_LIBS@ -lm
index 77bb06e56830b305da4fa50ca53a78b3e4480460..7d12ce3db8c80f00e3c75a88b6f2e0e3d137b5ab 100644 (file)
@@ -34,6 +34,6 @@
  */
 #include "gromacs/utility/baseversion-gen.h"
 
-const char _gmx_ver_string[] = "VERSION @GMX_PROJECT_VERSION_STR@";
-const char _gmx_full_git_hash[] = "@GMX_GIT_HEAD_HASH@";
-const char _gmx_central_base_hash[] = "@GMX_GIT_REMOTE_HASH@";
+const char _gmx_ver_string[] = "VERSION @GMX_VERSION_STRING_FULL@";
+const char _gmx_full_git_hash[] = "@GMX_VERSION_FULL_HASH@";
+const char _gmx_central_base_hash[] = "@GMX_VERSION_CENTRAL_BASE_HASH@";
index 179457e8f3abf326a762c799712dee6662dd00a5..667ca1399155cf726d8460b65778c850755f99ef 100644 (file)
@@ -92,7 +92,7 @@
  * For 4.6 and 5.0 (and likely for some time in the future as well), this
  * tracks the exact \Gromacs version.
  */
-#define GMX_API_VERSION @API_VERSION@
+#define GMX_API_VERSION @GMX_API_VERSION@
 
 /*! \brief
  * Exact \Gromacs version of this set of headers.
  * This specifies the version number of the actual \Gromacs library that
  * installed these headers.
  */
-#define GMX_VERSION @NUM_VERSION@
+#define GMX_VERSION @GMX_VERSION_NUMERIC@
 
 #endif
index 589ccc9974a421f9b0e2b85784a934562c744ed6..bcf188a6621a2b05ee543004c2bb995ae5eeead1 100644 (file)
@@ -38,15 +38,15 @@ option(REGRESSIONTEST_DOWNLOAD
     "Automatically download regressiontests. Tests can be run with ctest." OFF)
 
 if(REGRESSIONTEST_DOWNLOAD)
-    if("${PROJECT_VERSION}" MATCHES "-dev")
-      set(REGRESSIONTEST_URL http://gerrit.gromacs.org/snapshot/${REGRESSIONTEST_BRANCH})
-      set(REGRESSIONTEST_PATH "${CMAKE_CURRENT_BINARY_DIR}/regressiontests"
-           CACHE PATH "Path to auto-downloaded regressiontests" FORCE)
+    if (NOT SOURCE_IS_SOURCE_DISTRIBUTION)
+        set(REGRESSIONTEST_URL http://gerrit.gromacs.org/snapshot/${REGRESSIONTEST_BRANCH})
+        set(REGRESSIONTEST_PATH "${CMAKE_CURRENT_BINARY_DIR}/regressiontests"
+            CACHE PATH "Path to auto-downloaded regressiontests" FORCE)
     else()
         set(REGRESSIONTEST_URL http://gerrit.gromacs.org/download/regressiontests-${REGRESSIONTEST_VERSION}.tar.gz)
         set(REGRESSIONTEST_PATH
-           "${CMAKE_CURRENT_BINARY_DIR}/regressiontests-${REGRESSIONTEST_VERSION}"
-           CACHE PATH "Path to auto-downloaded regressiontests" FORCE)
+            "${CMAKE_CURRENT_BINARY_DIR}/regressiontests-${REGRESSIONTEST_VERSION}"
+            CACHE PATH "Path to auto-downloaded regressiontests" FORCE)
     endif()
     set(REGRESSIONTEST_FILE "${CMAKE_CURRENT_BINARY_DIR}/regressiontests.tgz")
     message("Downloading: ${REGRESSIONTEST_URL}")