From: Teemu Murtola Date: Mon, 28 Jul 2014 04:08:19 +0000 (+0300) Subject: Reorganize CMake version information management X-Git-Url: http://biod.pnpi.spb.ru/gitweb/?a=commitdiff_plain;h=643944e7f41c74ce4f0ca7b475fddcdfb241482b;p=alexxy%2Fgromacs.git Reorganize CMake version information management 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 --- diff --git a/.gitignore b/.gitignore index e61ec7a009..e2d9763327 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ lib*.pc .project .cproject CMakeLists.txt.user +/VersionInfo*.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 834693f4e6..4f5678f58d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 index 0000000000..b3f81b4ae1 --- /dev/null +++ b/cmake/VersionInfo.cmake.cmakein @@ -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 index 0000000000..a00e2c3314 --- /dev/null +++ b/cmake/gmxConfigureVersionInfo.cmake @@ -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) diff --git a/cmake/gmxGenerateVersionInfo.cmake b/cmake/gmxGenerateVersionInfo.cmake index 8db1e10400..9c64eb580c 100644 --- a/cmake/gmxGenerateVersionInfo.cmake +++ b/cmake/gmxGenerateVersionInfo.cmake @@ -46,189 +46,157 @@ # 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 index 0000000000..3e6ed3fc63 --- /dev/null +++ b/cmake/gmxVersionInfo.cmake @@ -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( +# [REMOTE_HASH] [SOURCE_FILE] +# [TARGET ] +# [COMMENT ]) +# Specify the input and output files as for configure_file(). +# 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 +# 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 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 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 )). +# 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() diff --git a/doxygen/CMakeLists.txt b/doxygen/CMakeLists.txt index ba333174b2..7401e9560c 100644 --- a/doxygen/CMakeLists.txt +++ b/doxygen/CMakeLists.txt @@ -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 diff --git a/doxygen/Doxyfile-version.cmakein b/doxygen/Doxyfile-version.cmakein index 38549a345f..43e374e9c0 100644 --- a/doxygen/Doxyfile-version.cmakein +++ b/doxygen/Doxyfile-version.cmakein @@ -1 +1 @@ -PROJECT_NUMBER = @GMX_PROJECT_VERSION_STR@ +PROJECT_NUMBER = @GMX_VERSION_STRING_FULL@ diff --git a/install-guide/configure-install-guide.cmake.in b/install-guide/configure-install-guide.cmake.in index 8980df6bab..e646163595 100644 --- a/install-guide/configure-install-guide.cmake.in +++ b/install-guide/configure-install-guide.cmake.in @@ -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@") diff --git a/manual/macros.tex b/manual/macros.tex index cd24695efb..ed4b53ce25 100644 --- a/manual/macros.tex +++ b/manual/macros.tex @@ -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. @@ -138,7 +138,7 @@ \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}} diff --git a/src/gromacs/CMakeLists.txt b/src/gromacs/CMakeLists.txt index a04d1dd0ee..21232899a2 100644 --- a/src/gromacs/CMakeLists.txt +++ b/src/gromacs/CMakeLists.txt @@ -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 diff --git a/src/gromacs/libgromacs.pc.cmakein b/src/gromacs/libgromacs.pc.cmakein index c88b1cb20a..2ef52aa205 100644 --- a/src/gromacs/libgromacs.pc.cmakein +++ b/src/gromacs/libgromacs.pc.cmakein @@ -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 diff --git a/src/gromacs/utility/baseversion-gen.c.cmakein b/src/gromacs/utility/baseversion-gen.c.cmakein index 77bb06e568..7d12ce3db8 100644 --- a/src/gromacs/utility/baseversion-gen.c.cmakein +++ b/src/gromacs/utility/baseversion-gen.c.cmakein @@ -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@"; diff --git a/src/gromacs/version.h.cmakein b/src/gromacs/version.h.cmakein index 179457e8f3..667ca13991 100644 --- a/src/gromacs/version.h.cmakein +++ b/src/gromacs/version.h.cmakein @@ -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. @@ -100,6 +100,6 @@ * 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 diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 589ccc9974..bcf188a662 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -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}")