#
# 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).
# REGRESSIONTEST_MD5SUM
# The MD5 checksum of the regressiontest tarball. Only used when building
# from a source package.
# 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")
set(REGRESSIONTEST_MD5SUM "a07524afebca5013540d4f2f72df2dce")
#####################################################################
# 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()