mirror of
https://github.com/google/benchmark.git
synced 2024-12-26 12:30:14 +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"])
|
||||
|
||||
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_export_header(
|
||||
@ -9,6 +10,23 @@ generate_export_header(
|
||||
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(
|
||||
name = "qnx",
|
||||
constraint_values = ["@platforms//os:qnx"],
|
||||
@ -39,6 +57,7 @@ cc_library(
|
||||
hdrs = [
|
||||
"include/benchmark/benchmark.h",
|
||||
"include/benchmark/export.h", # From generate_export_header
|
||||
"include/benchmark/version.h", # From generate_version_header
|
||||
],
|
||||
linkopts = select({
|
||||
":windows": ["-DEFAULTLIB:shlwapi.lib"],
|
||||
|
@ -322,6 +322,9 @@ if (BENCHMARK_ENABLE_LIBPFM)
|
||||
find_package(PFM)
|
||||
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
|
||||
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
|
||||
commits between the last annotated tag and HEAD
|
||||
* Pick the most interesting.
|
||||
* Create one last commit that updates the version saved in `CMakeLists.txt` and the
|
||||
`__version__` variable in `bindings/python/google_benchmark/__init__.py`to the release
|
||||
* Create one last commit that updates the version saved in `CMakeLists.txt`, the
|
||||
`__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
|
||||
archive you'll be creating in the next step.)
|
||||
|
||||
@ -17,6 +18,10 @@
|
||||
project (benchmark VERSION 1.6.0 LANGUAGES CXX)
|
||||
```
|
||||
|
||||
```
|
||||
build --workspace_status_command "python workspace_status.py --default_version "1.6.1""
|
||||
```
|
||||
|
||||
```python
|
||||
# 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 "benchmark/benchmark.h"
|
||||
#include "benchmark/version.h"
|
||||
#include "complexity.h"
|
||||
#include "string_util.h"
|
||||
#include "timers.h"
|
||||
@ -124,6 +125,9 @@ bool JSONReporter::ReportContext(const Context& context) {
|
||||
std::string walltime_value = LocalDateTimeString();
|
||||
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";
|
||||
|
||||
if (Context::executable_name) {
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "benchmark/version.h"
|
||||
#include "check.h"
|
||||
#include "string_util.h"
|
||||
#include "timers.h"
|
||||
@ -43,7 +44,7 @@ void BenchmarkReporter::PrintBasicContext(std::ostream *out,
|
||||
|
||||
if (context.executable_name)
|
||||
Out << "Running " << context.executable_name << "\n";
|
||||
|
||||
Out << "libbenchmark version: " << LIBBENCHMARK_VERSION << "\n";
|
||||
const CPUInfo &info = context.cpu_info;
|
||||
Out << "Run on (" << info.num_cpus << " X "
|
||||
<< (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},
|
||||
{"Running .*(/|\\\\)reporter_output_test(\\.exe)?$", MR_Next},
|
||||
{"libbenchmark version: %int\\.%int\\.%int", MR_Next},
|
||||
{"Run on \\(%int X %float MHz CPU s?\\)", MR_Next},
|
||||
});
|
||||
AddCases(TC_JSONOut,
|
||||
{{"^\\{", MR_Default},
|
||||
{"\"context\":", MR_Next},
|
||||
{"\"date\": \"", MR_Next},
|
||||
{"\"libbenchmark version\":", MR_Next},
|
||||
{"\"host_name\":", MR_Next},
|
||||
{"\"executable\": \".*(/|\\\\)reporter_output_test(\\.exe)?\",",
|
||||
MR_Next},
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"context": {
|
||||
"date": "2016-08-02 17:44:46",
|
||||
"libbenchmark_version": "1.6.1",
|
||||
"num_cpus": 4,
|
||||
"mhz_per_cpu": 4228,
|
||||
"cpu_scaling_enabled": false,
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"context": {
|
||||
"date": "2016-08-02 17:44:46",
|
||||
"libbenchmark_version": "1.6.1",
|
||||
"num_cpus": 4,
|
||||
"mhz_per_cpu": 4228,
|
||||
"cpu_scaling_enabled": false,
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"context": {
|
||||
"date": "2016-08-02 17:44:46",
|
||||
"libbenchmark_version": "1.6.1",
|
||||
"num_cpus": 4,
|
||||
"mhz_per_cpu": 4228,
|
||||
"cpu_scaling_enabled": false,
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"context": {
|
||||
"date": "2016-08-02 17:44:46",
|
||||
"libbenchmark_version": "1.6.1",
|
||||
"num_cpus": 4,
|
||||
"mhz_per_cpu": 4228,
|
||||
"cpu_scaling_enabled": false,
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"context": {
|
||||
"date": "2016-08-02 17:44:46",
|
||||
"libbenchmark_version": "1.6.1",
|
||||
"num_cpus": 4,
|
||||
"mhz_per_cpu": 4228,
|
||||
"cpu_scaling_enabled": false,
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"context": {
|
||||
"date": "2016-08-02 17:44:46",
|
||||
"libbenchmark_version": "1.6.1",
|
||||
"num_cpus": 4,
|
||||
"mhz_per_cpu": 4228,
|
||||
"cpu_scaling_enabled": false,
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"context": {
|
||||
"date": "2016-08-02 17:44:46",
|
||||
"libbenchmark_version": "1.6.1",
|
||||
"num_cpus": 4,
|
||||
"mhz_per_cpu": 4228,
|
||||
"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