mirror of
https://github.com/google/benchmark.git
synced 2024-12-27 13:00:36 +08:00
* Add possibility to ask for libbenchmark version number (#1004) Add a header which holds the current major, minor, and patch number of the library. The header is auto generated by CMake. * Do not generate unused functions (#1004) * Add support for version number in bazel (#1004) * Fix clang format #1004 * Fix more clang format problems (#1004) * Use git version feature of cmake to determine current lib version * Rename version_config header to version * Bake git version into bazel build * Use same input config header as in cmake for version.h * Adapt the releasing.md to include versioning in bazel
This commit is contained in:
parent
2365c4a603
commit
efadf67a12
2
.bazelrc
Normal file
2
.bazelrc
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Call workspace_status.py when building benchmark to determine current version of the lib
|
||||||
|
build --workspace_status_command "python workspace_status.py --default_version "1.6.1""
|
19
BUILD.bazel
19
BUILD.bazel
@ -1,6 +1,7 @@
|
|||||||
licenses(["notice"])
|
licenses(["notice"])
|
||||||
|
|
||||||
load("//:config/generate_export_header.bzl", "generate_export_header")
|
load("//:config/generate_export_header.bzl", "generate_export_header")
|
||||||
|
load("//:config/generate_version_header.bzl", "generate_version_header")
|
||||||
|
|
||||||
# Generate header to provide ABI export symbols
|
# Generate header to provide ABI export symbols
|
||||||
generate_export_header(
|
generate_export_header(
|
||||||
@ -9,6 +10,23 @@ generate_export_header(
|
|||||||
static_define = "BENCHMARK_STATIC_DEFINE",
|
static_define = "BENCHMARK_STATIC_DEFINE",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Get the git version variables
|
||||||
|
py_binary(
|
||||||
|
name = "get_git_version",
|
||||||
|
srcs = ["config/get_git_version.py"],
|
||||||
|
python_version = "PY3"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Generate version header
|
||||||
|
generate_version_header(
|
||||||
|
name = "generate_version_header",
|
||||||
|
git_version_name = "GIT_VERSION",
|
||||||
|
git_is_dirty_name = "GIT_IS_DIRTY",
|
||||||
|
default_version = "DEFAULT_VERSION",
|
||||||
|
header = "include/benchmark/version.h",
|
||||||
|
src = "include/version.h.in"
|
||||||
|
)
|
||||||
|
|
||||||
config_setting(
|
config_setting(
|
||||||
name = "qnx",
|
name = "qnx",
|
||||||
constraint_values = ["@platforms//os:qnx"],
|
constraint_values = ["@platforms//os:qnx"],
|
||||||
@ -39,6 +57,7 @@ cc_library(
|
|||||||
hdrs = [
|
hdrs = [
|
||||||
"include/benchmark/benchmark.h",
|
"include/benchmark/benchmark.h",
|
||||||
"include/benchmark/export.h", # From generate_export_header
|
"include/benchmark/export.h", # From generate_export_header
|
||||||
|
"include/benchmark/version.h", # From generate_version_header
|
||||||
],
|
],
|
||||||
linkopts = select({
|
linkopts = select({
|
||||||
":windows": ["-DEFAULTLIB:shlwapi.lib"],
|
":windows": ["-DEFAULTLIB:shlwapi.lib"],
|
||||||
|
@ -322,6 +322,9 @@ if (BENCHMARK_ENABLE_LIBPFM)
|
|||||||
find_package(PFM)
|
find_package(PFM)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Generate config file (currently only used for version num but may be expanded if needed.)
|
||||||
|
configure_file(${PROJECT_SOURCE_DIR}/include/version.h.in ${CMAKE_BINARY_DIR}/include/benchmark/version.h)
|
||||||
|
|
||||||
# Set up directories
|
# Set up directories
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/include)
|
include_directories(${PROJECT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
30
config/generate_version_header.bzl
Normal file
30
config/generate_version_header.bzl
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
def _generate_version_header_impl(ctx):
|
||||||
|
|
||||||
|
args = ["--header", ctx.outputs.header.path] + ["--header_input", ctx.file.src.path]\
|
||||||
|
+ ["--volatile_file", ctx.version_file.path, \
|
||||||
|
"--version_variable_name", ctx.attr.git_version_name, "--is_dirty_name",\
|
||||||
|
ctx.attr.git_is_dirty_name, "--default_version", ctx.attr.default_version]
|
||||||
|
|
||||||
|
ctx.actions.run(
|
||||||
|
inputs = [ctx.version_file, ctx.info_file, ctx.file.src],
|
||||||
|
outputs = [ctx.outputs.header],
|
||||||
|
arguments = args,
|
||||||
|
executable = ctx.executable._get_git_version_tool,
|
||||||
|
)
|
||||||
|
|
||||||
|
generate_version_header = rule(
|
||||||
|
implementation = _generate_version_header_impl,
|
||||||
|
attrs = {
|
||||||
|
"_get_git_version_tool": attr.label(
|
||||||
|
executable = True,
|
||||||
|
cfg = "host",
|
||||||
|
allow_files = True,
|
||||||
|
default = Label("//:get_git_version"),
|
||||||
|
),
|
||||||
|
"git_version_name": attr.string(mandatory = True),
|
||||||
|
"git_is_dirty_name": attr.string(mandatory = True),
|
||||||
|
"default_version": attr.string(mandatory = True),
|
||||||
|
"header": attr.output(mandatory = True),
|
||||||
|
"src" : attr.label(allow_single_file = [".in"]),
|
||||||
|
},
|
||||||
|
)
|
99
config/get_git_version.py
Normal file
99
config/get_git_version.py
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
# Before actually starting the build, workspace_status.py should have written
|
||||||
|
# the current git repository status as well as if the repository is dirty
|
||||||
|
# to volatile-status.txt.
|
||||||
|
# This script takes these information and generates the version.h which later is
|
||||||
|
# used by the library to report its version.
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_version(git_version, git_is_dirty):
|
||||||
|
if '-' in git_version:
|
||||||
|
cleaned = re.search('[0-9]+\.[0-9]+\.[0-9]\-[0-9]+', git_version)
|
||||||
|
cleaned_string = cleaned.group(0).replace("-", ".")
|
||||||
|
elif 'v' in git_version:
|
||||||
|
cleaned_string = git_version.replace("v", "")
|
||||||
|
else:
|
||||||
|
cleaned_string = git_version
|
||||||
|
|
||||||
|
# In case the repository is in a dirty state (uncommited changes)
|
||||||
|
# we do tell the user during build by writing to stdout.
|
||||||
|
# That is the way it is done in the CMake Build as well.
|
||||||
|
# Maybe think about adding the -dirty also for the version header.
|
||||||
|
if git_is_dirty == "TRUE":
|
||||||
|
git_version_dirty = git_version+"-dirty"
|
||||||
|
print("git version: " + git_version_dirty +
|
||||||
|
" normalized to " + cleaned_string)
|
||||||
|
|
||||||
|
return cleaned_string
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description='Generate version header')
|
||||||
|
parser.add_argument('--header',
|
||||||
|
required=True,
|
||||||
|
help='output header file')
|
||||||
|
parser.add_argument('--header_input',
|
||||||
|
required=True,
|
||||||
|
help='input header file')
|
||||||
|
parser.add_argument('--volatile_file',
|
||||||
|
required=True,
|
||||||
|
help='file containing the git version variables')
|
||||||
|
parser.add_argument('--version_variable_name',
|
||||||
|
required=True,
|
||||||
|
help='variablename of the hash')
|
||||||
|
parser.add_argument('--is_dirty_name',
|
||||||
|
required=True,
|
||||||
|
help='variablename of the boolean communicating if the workspace has no local changes')
|
||||||
|
parser.add_argument('--default_version',
|
||||||
|
required=True,
|
||||||
|
help='variablename for version which should be used in case git was not executable.')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Read volatile-status.txt file
|
||||||
|
git_version = ""
|
||||||
|
is_dirty = ""
|
||||||
|
try:
|
||||||
|
with open(args.volatile_file, "r") as f:
|
||||||
|
for entry in f.read().split("\n"):
|
||||||
|
if entry:
|
||||||
|
key_value = entry.split(' ', 1)
|
||||||
|
key = key_value[0].strip()
|
||||||
|
if key == args.version_variable_name:
|
||||||
|
git_version = key_value[1].strip()
|
||||||
|
if key == args.is_dirty_name:
|
||||||
|
is_dirty = key_value[1].strip()
|
||||||
|
except:
|
||||||
|
# In case volatile-status cannot be read, exit with an error
|
||||||
|
sys.exit("Cannot open volatile-status.txt")
|
||||||
|
|
||||||
|
if git_version == "" or is_dirty == "":
|
||||||
|
sys.exit("No usable entry in volatile-status.txt")
|
||||||
|
|
||||||
|
git_version = normalize_version(git_version, is_dirty)
|
||||||
|
|
||||||
|
# In case we werent able to determine the current version
|
||||||
|
# use the default set version
|
||||||
|
if git_version == "0.0.0":
|
||||||
|
git_version = args.default_version
|
||||||
|
|
||||||
|
# Notify the user about the version used.
|
||||||
|
print("Version: " + git_version)
|
||||||
|
|
||||||
|
# Write the actual version.h
|
||||||
|
texttosearch = "@VERSION@"
|
||||||
|
|
||||||
|
with open(args.header_input, "r") as f:
|
||||||
|
with open(args.header, "w") as w:
|
||||||
|
for line in f:
|
||||||
|
if texttosearch in line:
|
||||||
|
w.write(line.replace(texttosearch, git_version))
|
||||||
|
else:
|
||||||
|
w.write(line)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
@ -8,8 +8,9 @@
|
|||||||
* `git log $(git describe --abbrev=0 --tags)..HEAD` gives you the list of
|
* `git log $(git describe --abbrev=0 --tags)..HEAD` gives you the list of
|
||||||
commits between the last annotated tag and HEAD
|
commits between the last annotated tag and HEAD
|
||||||
* Pick the most interesting.
|
* Pick the most interesting.
|
||||||
* Create one last commit that updates the version saved in `CMakeLists.txt` and the
|
* Create one last commit that updates the version saved in `CMakeLists.txt`, the
|
||||||
`__version__` variable in `bindings/python/google_benchmark/__init__.py`to the release
|
`__version__` variable in `bindings/python/google_benchmark/__init__.py`
|
||||||
|
and the default version in `.bazelrc` to the release
|
||||||
version you're creating. (This version will be used if benchmark is installed from the
|
version you're creating. (This version will be used if benchmark is installed from the
|
||||||
archive you'll be creating in the next step.)
|
archive you'll be creating in the next step.)
|
||||||
|
|
||||||
@ -17,6 +18,10 @@
|
|||||||
project (benchmark VERSION 1.6.0 LANGUAGES CXX)
|
project (benchmark VERSION 1.6.0 LANGUAGES CXX)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
build --workspace_status_command "python workspace_status.py --default_version "1.6.1""
|
||||||
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# bindings/python/google_benchmark/__init__.py
|
# bindings/python/google_benchmark/__init__.py
|
||||||
|
|
||||||
|
6
include/version.h.in
Normal file
6
include/version.h.in
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef VERSION_H
|
||||||
|
#define VERSION_H
|
||||||
|
// clang-format off
|
||||||
|
#define LIBBENCHMARK_VERSION "@VERSION@"
|
||||||
|
// clang-format on
|
||||||
|
#endif // VERSION_H
|
@ -23,6 +23,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "benchmark/benchmark.h"
|
#include "benchmark/benchmark.h"
|
||||||
|
#include "benchmark/version.h"
|
||||||
#include "complexity.h"
|
#include "complexity.h"
|
||||||
#include "string_util.h"
|
#include "string_util.h"
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
@ -124,6 +125,9 @@ bool JSONReporter::ReportContext(const Context& context) {
|
|||||||
std::string walltime_value = LocalDateTimeString();
|
std::string walltime_value = LocalDateTimeString();
|
||||||
out << indent << FormatKV("date", walltime_value) << ",\n";
|
out << indent << FormatKV("date", walltime_value) << ",\n";
|
||||||
|
|
||||||
|
out << indent << FormatKV("libbenchmark version", LIBBENCHMARK_VERSION)
|
||||||
|
<< ",\n";
|
||||||
|
|
||||||
out << indent << FormatKV("host_name", context.sys_info.name) << ",\n";
|
out << indent << FormatKV("host_name", context.sys_info.name) << ",\n";
|
||||||
|
|
||||||
if (Context::executable_name) {
|
if (Context::executable_name) {
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "benchmark/benchmark.h"
|
#include "benchmark/benchmark.h"
|
||||||
|
#include "benchmark/version.h"
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
#include "string_util.h"
|
#include "string_util.h"
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
@ -43,7 +44,7 @@ void BenchmarkReporter::PrintBasicContext(std::ostream *out,
|
|||||||
|
|
||||||
if (context.executable_name)
|
if (context.executable_name)
|
||||||
Out << "Running " << context.executable_name << "\n";
|
Out << "Running " << context.executable_name << "\n";
|
||||||
|
Out << "libbenchmark version: " << LIBBENCHMARK_VERSION << "\n";
|
||||||
const CPUInfo &info = context.cpu_info;
|
const CPUInfo &info = context.cpu_info;
|
||||||
Out << "Run on (" << info.num_cpus << " X "
|
Out << "Run on (" << info.num_cpus << " X "
|
||||||
<< (info.cycles_per_second / 1000000.0) << " MHz CPU "
|
<< (info.cycles_per_second / 1000000.0) << " MHz CPU "
|
||||||
|
@ -18,12 +18,14 @@ static int AddContextCases() {
|
|||||||
{
|
{
|
||||||
{"^%int-%int-%intT%int:%int:%int[-+]%int:%int$", MR_Default},
|
{"^%int-%int-%intT%int:%int:%int[-+]%int:%int$", MR_Default},
|
||||||
{"Running .*(/|\\\\)reporter_output_test(\\.exe)?$", MR_Next},
|
{"Running .*(/|\\\\)reporter_output_test(\\.exe)?$", MR_Next},
|
||||||
|
{"libbenchmark version: %int\\.%int\\.%int", MR_Next},
|
||||||
{"Run on \\(%int X %float MHz CPU s?\\)", MR_Next},
|
{"Run on \\(%int X %float MHz CPU s?\\)", MR_Next},
|
||||||
});
|
});
|
||||||
AddCases(TC_JSONOut,
|
AddCases(TC_JSONOut,
|
||||||
{{"^\\{", MR_Default},
|
{{"^\\{", MR_Default},
|
||||||
{"\"context\":", MR_Next},
|
{"\"context\":", MR_Next},
|
||||||
{"\"date\": \"", MR_Next},
|
{"\"date\": \"", MR_Next},
|
||||||
|
{"\"libbenchmark version\":", MR_Next},
|
||||||
{"\"host_name\":", MR_Next},
|
{"\"host_name\":", MR_Next},
|
||||||
{"\"executable\": \".*(/|\\\\)reporter_output_test(\\.exe)?\",",
|
{"\"executable\": \".*(/|\\\\)reporter_output_test(\\.exe)?\",",
|
||||||
MR_Next},
|
MR_Next},
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"context": {
|
"context": {
|
||||||
"date": "2016-08-02 17:44:46",
|
"date": "2016-08-02 17:44:46",
|
||||||
|
"libbenchmark_version": "1.6.1",
|
||||||
"num_cpus": 4,
|
"num_cpus": 4,
|
||||||
"mhz_per_cpu": 4228,
|
"mhz_per_cpu": 4228,
|
||||||
"cpu_scaling_enabled": false,
|
"cpu_scaling_enabled": false,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"context": {
|
"context": {
|
||||||
"date": "2016-08-02 17:44:46",
|
"date": "2016-08-02 17:44:46",
|
||||||
|
"libbenchmark_version": "1.6.1",
|
||||||
"num_cpus": 4,
|
"num_cpus": 4,
|
||||||
"mhz_per_cpu": 4228,
|
"mhz_per_cpu": 4228,
|
||||||
"cpu_scaling_enabled": false,
|
"cpu_scaling_enabled": false,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"context": {
|
"context": {
|
||||||
"date": "2016-08-02 17:44:46",
|
"date": "2016-08-02 17:44:46",
|
||||||
|
"libbenchmark_version": "1.6.1",
|
||||||
"num_cpus": 4,
|
"num_cpus": 4,
|
||||||
"mhz_per_cpu": 4228,
|
"mhz_per_cpu": 4228,
|
||||||
"cpu_scaling_enabled": false,
|
"cpu_scaling_enabled": false,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"context": {
|
"context": {
|
||||||
"date": "2016-08-02 17:44:46",
|
"date": "2016-08-02 17:44:46",
|
||||||
|
"libbenchmark_version": "1.6.1",
|
||||||
"num_cpus": 4,
|
"num_cpus": 4,
|
||||||
"mhz_per_cpu": 4228,
|
"mhz_per_cpu": 4228,
|
||||||
"cpu_scaling_enabled": false,
|
"cpu_scaling_enabled": false,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"context": {
|
"context": {
|
||||||
"date": "2016-08-02 17:44:46",
|
"date": "2016-08-02 17:44:46",
|
||||||
|
"libbenchmark_version": "1.6.1",
|
||||||
"num_cpus": 4,
|
"num_cpus": 4,
|
||||||
"mhz_per_cpu": 4228,
|
"mhz_per_cpu": 4228,
|
||||||
"cpu_scaling_enabled": false,
|
"cpu_scaling_enabled": false,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"context": {
|
"context": {
|
||||||
"date": "2016-08-02 17:44:46",
|
"date": "2016-08-02 17:44:46",
|
||||||
|
"libbenchmark_version": "1.6.1",
|
||||||
"num_cpus": 4,
|
"num_cpus": 4,
|
||||||
"mhz_per_cpu": 4228,
|
"mhz_per_cpu": 4228,
|
||||||
"cpu_scaling_enabled": false,
|
"cpu_scaling_enabled": false,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"context": {
|
"context": {
|
||||||
"date": "2016-08-02 17:44:46",
|
"date": "2016-08-02 17:44:46",
|
||||||
|
"libbenchmark_version": "1.6.1",
|
||||||
"num_cpus": 4,
|
"num_cpus": 4,
|
||||||
"mhz_per_cpu": 4228,
|
"mhz_per_cpu": 4228,
|
||||||
"cpu_scaling_enabled": false,
|
"cpu_scaling_enabled": false,
|
||||||
|
69
workspace_status.py
Normal file
69
workspace_status.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# Get the current repository git status.
|
||||||
|
# This means get the current version tag and if the repository is dirty.
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description='')
|
||||||
|
parser.add_argument('--default_version',
|
||||||
|
required=True,
|
||||||
|
help='default version in case git can not be called')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Get the current status of the repository by calling out to git.
|
||||||
|
# In case there is no git executable use the default version.
|
||||||
|
git_version = get_version(".")
|
||||||
|
git_is_dirty = get_git_dirty(".")
|
||||||
|
|
||||||
|
# Write to volatile-status.txt.
|
||||||
|
# This is a bazel thing and the recommended way of
|
||||||
|
# getting version control status into bazel build according
|
||||||
|
# to bazels documentation.
|
||||||
|
print("GIT_VERSION {}".format(git_version))
|
||||||
|
print("GIT_IS_DIRTY {}".format(git_is_dirty))
|
||||||
|
print("DEFAULT_VERSION {}".format(args.default_version))
|
||||||
|
|
||||||
|
|
||||||
|
def get_version(path):
|
||||||
|
try:
|
||||||
|
p = subprocess.Popen(["git", "describe", "--tags", "--match",
|
||||||
|
"v[0-9]*.[0-9]*.[0-9]*", "--abbrev=8"], cwd=path, stdout=subprocess.PIPE)
|
||||||
|
(out, err) = p.communicate()
|
||||||
|
|
||||||
|
if p.returncode != 0:
|
||||||
|
return "v0.0.0"
|
||||||
|
return out.decode()
|
||||||
|
|
||||||
|
except:
|
||||||
|
return "0.0.0"
|
||||||
|
|
||||||
|
|
||||||
|
def get_git_dirty(path):
|
||||||
|
try:
|
||||||
|
p = subprocess.Popen(
|
||||||
|
["git", "update-index", "-q", "--refresh"], cwd=path, stdout=subprocess.PIPE)
|
||||||
|
(out, err) = p.communicate()
|
||||||
|
if p.returncode != 0:
|
||||||
|
return "TRUE"
|
||||||
|
|
||||||
|
p = subprocess.Popen(["git", "diff-index", "--name-only",
|
||||||
|
"HEAD", "--"], cwd=path, stdout=subprocess.PIPE)
|
||||||
|
(out, err) = p.communicate()
|
||||||
|
if p.returncode != 0:
|
||||||
|
return "TRUE"
|
||||||
|
|
||||||
|
if out.decode() != "":
|
||||||
|
return "TRUE"
|
||||||
|
else:
|
||||||
|
return "FALSE"
|
||||||
|
|
||||||
|
except:
|
||||||
|
# Be pessimistic. In case git is not available
|
||||||
|
# assume the repository to be dirty.
|
||||||
|
return "TRUE"
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Reference in New Issue
Block a user