Skip to content
Snippets Groups Projects
Unverified Commit ee0062a4 authored by Sam Yates's avatar Sam Yates Committed by GitHub
Browse files

Extend available version information. (#1411)

* Provide defines and variables for version string components: major
version; minor version; patch level version; development suffix.
* Change commit date format to strict ISO.
* Add define/variable for Arbor build configuration.
* Add usage/help info to `git-source-id` script.
* Add define/variable for a full build identification string,
incorporating source info, version, build configuration, feature
options.
* Add documentation for the version and build defines and variables.
* Extend version unit tests to suit.
parent 0d6c0a77
No related branches found
No related tags found
No related merge requests found
......@@ -50,10 +50,12 @@ if(ARB_VECTORIZE)
list(APPEND arb_features VECTORIZE)
endif()
string(TOUPPER "${CMAKE_BUILD_TYPE}" arb_config_str)
add_custom_command(
OUTPUT version.hpp-test
DEPENDS _always_rebuild
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/git-source-id ${FULL_VERSION_STRING} ${ARB_ARCH} ${arb_features} > version.hpp-test
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/git-source-id ${FULL_VERSION_STRING} ${ARB_ARCH} ${arb_config_str} ${arb_features} > version.hpp-test
)
set(version_hpp_path arbor/version.hpp)
......
#!/usr/bin/env bash
# arguments: version-string [feature...]
function usage () {
helpstr="Usage: ${0##*/} version arch config [feature ...]"
if [ -n "$1" ]; then
echo "${0##*/}: $1" >&2
echo "$helpstr" >&2
exit 1
else
echo "$helpstr"
exit 0
fi
}
if [ -z "$1" -o "$1" = "--help" -o "$1" = "-h" ]; then usage; fi
if [ -z "$2" ]; then usage "missing arch"; fi
if [ -z "$3" ]; then usage "missing config"; fi
version="$1"
arch="$2"
shift 2
config="$3"
shift 3
if [[ "$version" =~ ^([0-9]+)\.([0-9]+)(\.([0-9]+))?(-(.*))?$ ]]; then
version_major="${BASH_REMATCH[1]}"
version_minor="${BASH_REMATCH[2]}"
version_patch="${BASH_REMATCH[4]:-0}"
version_dev="${BASH_REMATCH[6]}"
else
usage "bad version format"
fi
if gitlog=$(git log -1 --pretty=format:'%ci %H' 2>/dev/null); then
if gitlog=$(git log -1 --pretty=format:'%cI %H' 2>/dev/null); then
git diff --quiet HEAD 2>/dev/null || gitlog="${gitlog} modified"
else
gitlog='unknown commit'
fi
full_build_id="source_id=${gitlog};version=${version};arch=${arch};config=${config};"
for feature in "$@"; do
full_build_id="${full_build_id}${feature}_ENABLED;"
done
cat << __end__
#pragma once
#define ARB_VERSION "${version}"
#define ARB_SOURCE_ID "${gitlog}"
#define ARB_ARCH "${arch}"
namespace arb {
extern const char version[];
extern const char source_id[];
extern const char arch[];
extern const char* source_id;
extern const char* arch;
extern const char* build_config;
extern const char* version;
extern const char* full_build_id;
constexpr int version_major = ${version_major};
constexpr int version_minor = ${version_minor};
constexpr int version_patch = ${version_patch};
extern const char* version_dev;
}
#define ARB_SOURCE_ID "${gitlog}"
#define ARB_ARCH "${arch}"
#define ARB_BUILD_CONFIG "${config}"
#define ARB_FULL_BUILD_ID "${full_build_id}"
#define ARB_VERSION "${version}"
#define ARB_VERSION_MAJOR ${version_major}
#define ARB_VERSION_MINOR ${version_minor}
#define ARB_VERSION_PATCH ${version_patch}
__end__
if [ -n "$version_dev" ]; then echo "#define ARB_VERSION_DEV \"${version_dev}\""; fi
for feature in "$@"; do
echo "#define ARB_${feature}_ENABLED"
done
......
#include <arbor/version.hpp>
namespace arb {
const char version[] = ARB_VERSION;
const char source_id[] = ARB_SOURCE_ID;
const char arch[] = ARB_ARCH;
const char* source_id = ARB_SOURCE_ID;
const char* arch = ARB_ARCH;
const char* build_config = ARB_BUILD_CONFIG;
const char* version = ARB_VERSION;
#ifdef ARB_VERSION_DEV
const char* version_dev = ARB_VERSION_DEV;
#else
const char* version_dev = "";
#endif
const char* full_build_id = ARB_FULL_BUILD_ID;
}
......@@ -23,3 +23,4 @@ A :cpp:type:`arb::recipe` describes a model, and a :cpp:type:`arb::simulation` i
simulation
profiler
cable_cell
version
.. _cppversion:
Version and build information
=============================
The Arbor library records version and configuration information in
two ways:
* The ``version.hpp`` header has preprocessor defines with the prefix ``ARB_``.
* The library presents this information in variables within the ``arb::`` namespace.
Version information
-------------------
The Arbor version string is in the format MAJOR.MINOR.PATCH,
or for development versions MAJOR.MINOR.PATCH-DEV, where DEV
is a string, usually literally "dev".
:c:macro:`ARB_VERSION`
Full Arbor version string. Available as :cpp:var:`arb::version`.
:c:macro:`ARB_VERSION_MAJOR`
Major version number. Available as :cpp:var:`arb::version_major`.
:c:macro:`ARB_VERSION_MINOR`
Major version number. Available as :cpp:var:`arb::version_minor`.
:c:macro:`ARB_VERSION_PATCH`
Major version number. Available as :cpp:var:`arb::version_patch`.
:c:macro:`ARB_VERSION_DEV`
Development version suffix string. Only defined if Arbor is a development version.
Available as :cpp:var:`arb::version_dev`, which will be an empty string
if :c:macro:`ARB_VERSION_DEV` is not defined.
Source information
------------------
:c:macro:`ARB_SOURCE_ID`
The source id contains the git commit time stamp, the commit hash,
and if there are uncommitted changes in the source tree, a suffix "modified",
e.g. ``"2020-01-02T03:04:05+06:00 b1946ac92492d2347c6235b4d2611184 modified"``.
Available as :cpp:var:`arb::source_id`.
Build information
-----------------
Arbor can be built in the default 'Release' configuration, or in an unoptimized
'Debug' configuration that is useful for development. Additionally, it can be
built for a particular CPU architecture given by the ``ARB_ARCH`` CMake configuration
variable.
:c:macro:`ARB_BUILD_CONFIG`
Configuration string, all uppercase. Will be ``"DEBUG"`` or ``"RELEASE"``.
Available as :cpp:var:`arb::build_config`.
:c:macro:`ARB_ARCH`
Value of the ``ARB_ARCH`` configuration variable, e.g. ``"native"``.
Available as :cpp:var:`arb::arch`.
Features
--------
Configuration-time features are enabled in Arbor via CMake configuration variables
such as ``ARB_WITH_MPI`` and ``ARB_WITH_PYTHON``. Each enabled feature has
a corresponding preprocessor symbol in ``version.hpp`` of the form ``ARB_FEATURENAME_ENABLED``.
Examples include :c:macro:`ARB_MPI_ENABLED`, :c:macro:`ARB_ASSERT_ENABLED`.
Full build information
----------------------
A single string containing all the identification information for an Arbor build
is available in the macro :c:macro:`ARB_FULL_BUILD_ID` and in the variable
:cpp:var:`arb::full_build_id`. This string contains the source id, the full version,
the build configuration, the target architecture, and a list of enabled features.
#include <regex>
#include <string>
#include "../gtest.h"
#include <arbor/version.hpp>
TEST(version, libmatch) {
using std::string;
using namespace std::string_literals;
using std::regex;
using std::regex_search;
using std::string;
using std::to_string;
TEST(version, libmatch) {
string header_version = ARB_VERSION;
string header_source_id = ARB_SOURCE_ID;
string header_arch = ARB_ARCH;
string header_build_config = ARB_BUILD_CONFIG;
string header_full_build_id = ARB_FULL_BUILD_ID;
#ifdef ARB_VERSION_DEV
string header_version_dev = ARB_VERSION_DEV;
EXPECT_FALSE(header_version_dev.empty());
#else
string header_version_dev;
#endif
int header_version_major = ARB_VERSION_MAJOR;
int header_version_minor = ARB_VERSION_MINOR;
int header_version_patch = ARB_VERSION_PATCH;
string lib_version = arb::version;
string lib_source_id = arb::source_id;
string lib_arch = arb::arch;
string lib_build_config = arb::build_config;
string lib_full_build_id = arb::full_build_id;
constexpr int lib_version_major = arb::version_major;
constexpr int lib_version_minor = arb::version_minor;
constexpr int lib_version_patch = arb::version_patch;
string lib_version_dev = arb::version_dev;
EXPECT_EQ(header_version, lib_version);
EXPECT_EQ(header_source_id, lib_source_id);
EXPECT_EQ(header_arch, lib_arch);
EXPECT_EQ(header_build_config, lib_build_config);
EXPECT_EQ(header_full_build_id, lib_full_build_id);
EXPECT_EQ(header_version_major, lib_version_major);
EXPECT_EQ(header_version_minor, lib_version_minor);
EXPECT_EQ(header_version_patch, lib_version_patch);
EXPECT_EQ(header_version_dev, lib_version_dev);
}
TEST(version, sane_config) {
EXPECT_TRUE(arb::build_config=="DEBUG"s || arb::build_config=="RELEASE"s);
}
TEST(version, version_components) {
string dev = arb::version_dev;
if (arb::version_patch>0) {
auto expected = to_string(arb::version_major)+"."+to_string(arb::version_minor)+"."+to_string(arb::version_patch);
expected += dev.empty()? "": "-"+dev;
EXPECT_EQ(expected, ARB_VERSION);
}
else {
auto expected_majmin = to_string(arb::version_major)+"."+to_string(arb::version_minor);
auto expected_suffix = dev.empty()? "": "-"+dev;
EXPECT_TRUE(expected_majmin+expected_suffix==ARB_VERSION || expected_majmin+".0"+expected_suffix==ARB_VERSION);
}
}
TEST(version, full_build_id) {
EXPECT_TRUE(regex_search(arb::full_build_id, regex("(;|^)config=.")));
EXPECT_TRUE(regex_search(arb::full_build_id, regex("(;|^)version=.")));
EXPECT_TRUE(regex_search(arb::full_build_id, regex("(;|^)source_id=.")));
EXPECT_TRUE(regex_search(arb::full_build_id, regex("(;|^)arch=.")));
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment