Snap for 6533464 from 98780c6c162e8a7804eb906eb1cda968c98f9791 to sdk-release
Change-Id: Ief1d584c24e2ad55287d685ec3f895eefca5967a
diff --git a/METADATA b/METADATA
index 0eea29b..cfcfea7 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,11 @@
type: GIT
value: "https://github.com/google/benchmark.git"
}
- version: "a77d5f70efaebe2b7e8c10134526a23a7ce7ef35"
+ version: "d3ad0b9d11c190cb58de5fb17c3555def61fdc96"
license_type: NOTICE
last_upgrade_date {
year: 2020
- month: 4
+ month: 5
day: 13
}
}
diff --git a/WORKSPACE b/WORKSPACE
index 8df248a..dc6ea02 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -13,3 +13,18 @@
strip_prefix = "googletest-3f0cf6b62ad1eb50d8736538363d3580dd640c3e",
urls = ["https://github.com/google/googletest/archive/3f0cf6b62ad1eb50d8736538363d3580dd640c3e.zip"],
)
+
+http_archive(
+ name = "pybind11",
+ build_file = "@//bindings/python:pybind11.BUILD",
+ sha256 = "1eed57bc6863190e35637290f97a20c81cfe4d9090ac0a24f3bbf08f265eb71d",
+ strip_prefix = "pybind11-2.4.3",
+ urls = ["https://github.com/pybind/pybind11/archive/v2.4.3.tar.gz"],
+)
+
+new_local_repository(
+ name = "python_headers",
+ build_file = "@//bindings/python:python_headers.BUILD",
+ path = "/usr/include/python3.6", # May be overwritten by setup.py.
+)
+
diff --git a/bindings/python/BUILD b/bindings/python/BUILD
new file mode 100644
index 0000000..9559a76
--- /dev/null
+++ b/bindings/python/BUILD
@@ -0,0 +1,3 @@
+exports_files(glob(["*.BUILD"]))
+exports_files(["build_defs.bzl"])
+
diff --git a/bindings/python/benchmark/BUILD b/bindings/python/benchmark/BUILD
new file mode 100644
index 0000000..49f536e
--- /dev/null
+++ b/bindings/python/benchmark/BUILD
@@ -0,0 +1,38 @@
+load("//bindings/python:build_defs.bzl", "py_extension")
+
+py_library(
+ name = "benchmark",
+ srcs = ["__init__.py"],
+ visibility = ["//visibility:public"],
+ deps = [
+ ":_benchmark",
+ # pip; absl:app
+ ],
+)
+
+py_extension(
+ name = "_benchmark",
+ srcs = ["benchmark.cc"],
+ copts = [
+ "-fexceptions",
+ "-fno-strict-aliasing",
+ ],
+ features = ["-use_header_modules"],
+ deps = [
+ "//:benchmark",
+ "@pybind11",
+ "@python_headers",
+ ],
+)
+
+py_test(
+ name = "example",
+ srcs = ["example.py"],
+ python_version = "PY3",
+ srcs_version = "PY3",
+ visibility = ["//visibility:public"],
+ deps = [
+ ":benchmark",
+ ],
+)
+
diff --git a/bindings/python/benchmark/__init__.py b/bindings/python/benchmark/__init__.py
new file mode 100644
index 0000000..27f76e0
--- /dev/null
+++ b/bindings/python/benchmark/__init__.py
@@ -0,0 +1,62 @@
+# Copyright 2020 Google Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Python benchmarking utilities.
+
+Example usage:
+ import benchmark
+
+ @benchmark.register
+ def my_benchmark(state):
+ ... # Code executed outside `while` loop is not timed.
+
+ while state:
+ ... # Code executed within `while` loop is timed.
+
+ if __name__ == '__main__':
+ benchmark.main()
+"""
+
+from absl import app
+from benchmark import _benchmark
+
+__all__ = [
+ "register",
+ "main",
+]
+
+__version__ = "0.1.0"
+
+
+def register(f=None, *, name=None):
+ if f is None:
+ return lambda f: register(f, name=name)
+ if name is None:
+ name = f.__name__
+ _benchmark.RegisterBenchmark(name, f)
+ return f
+
+
+def _flags_parser(argv):
+ argv = _benchmark.Initialize(argv)
+ return app.parse_flags_with_usage(argv)
+
+
+def _run_benchmarks(argv):
+ if len(argv) > 1:
+ raise app.UsageError('Too many command-line arguments.')
+ return _benchmark.RunSpecifiedBenchmarks()
+
+
+def main(argv=None):
+ return app.run(_run_benchmarks, argv=argv, flags_parser=_flags_parser)
diff --git a/bindings/python/benchmark/benchmark.cc b/bindings/python/benchmark/benchmark.cc
new file mode 100644
index 0000000..ef95559
--- /dev/null
+++ b/bindings/python/benchmark/benchmark.cc
@@ -0,0 +1,47 @@
+// Benchmark for Python.
+
+#include "benchmark/benchmark.h"
+#include "pybind11/pybind11.h"
+#include "pybind11/stl.h"
+
+namespace {
+namespace py = ::pybind11;
+
+std::vector<std::string> Initialize(const std::vector<std::string>& argv) {
+ // The `argv` pointers here become invalid when this function returns, but
+ // benchmark holds the pointer to `argv[0]`. We create a static copy of it
+ // so it persists, and replace the pointer below.
+ static std::string executable_name(argv[0]);
+ std::vector<char*> ptrs;
+ ptrs.reserve(argv.size());
+ for (auto& arg : argv) {
+ ptrs.push_back(const_cast<char*>(arg.c_str()));
+ }
+ ptrs[0] = const_cast<char*>(executable_name.c_str());
+ int argc = static_cast<int>(argv.size());
+ benchmark::Initialize(&argc, ptrs.data());
+ std::vector<std::string> remaining_argv;
+ remaining_argv.reserve(argc);
+ for (int i = 0; i < argc; ++i) {
+ remaining_argv.emplace_back(ptrs[i]);
+ }
+ return remaining_argv;
+}
+
+void RegisterBenchmark(const char* name, py::function f) {
+ benchmark::RegisterBenchmark(name, [f](benchmark::State& state) {
+ f(&state);
+ });
+}
+
+PYBIND11_MODULE(_benchmark, m) {
+ m.def("Initialize", Initialize);
+ m.def("RegisterBenchmark", RegisterBenchmark);
+ m.def("RunSpecifiedBenchmarks",
+ []() { benchmark::RunSpecifiedBenchmarks(); });
+
+ py::class_<benchmark::State>(m, "State")
+ .def("__bool__", &benchmark::State::KeepRunning)
+ .def_property_readonly("keep_running", &benchmark::State::KeepRunning);
+};
+} // namespace
diff --git a/bindings/python/benchmark/example.py b/bindings/python/benchmark/example.py
new file mode 100644
index 0000000..24da127
--- /dev/null
+++ b/bindings/python/benchmark/example.py
@@ -0,0 +1,32 @@
+# Copyright 2020 Google Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Example of Python using C++ benchmark framework."""
+
+import benchmark
+
+
+@benchmark.register
+def empty(state):
+ while state:
+ pass
+
+
+@benchmark.register
+def sum_million(state):
+ while state:
+ sum(range(1_000_000))
+
+
+if __name__ == '__main__':
+ benchmark.main()
diff --git a/bindings/python/build_defs.bzl b/bindings/python/build_defs.bzl
new file mode 100644
index 0000000..45907aa
--- /dev/null
+++ b/bindings/python/build_defs.bzl
@@ -0,0 +1,25 @@
+_SHARED_LIB_SUFFIX = {
+ "//conditions:default": ".so",
+ "//:windows": ".dll",
+}
+
+def py_extension(name, srcs, hdrs = [], copts = [], features = [], deps = []):
+ for shared_lib_suffix in _SHARED_LIB_SUFFIX.values():
+ shared_lib_name = name + shared_lib_suffix
+ native.cc_binary(
+ name = shared_lib_name,
+ linkshared = 1,
+ linkstatic = 1,
+ srcs = srcs + hdrs,
+ copts = copts,
+ features = features,
+ deps = deps,
+ )
+
+ return native.py_library(
+ name = name,
+ data = select({
+ platform: [name + shared_lib_suffix]
+ for platform, shared_lib_suffix in _SHARED_LIB_SUFFIX.items()
+ }),
+ )
diff --git a/bindings/python/pybind11.BUILD b/bindings/python/pybind11.BUILD
new file mode 100644
index 0000000..bc83350
--- /dev/null
+++ b/bindings/python/pybind11.BUILD
@@ -0,0 +1,20 @@
+cc_library(
+ name = "pybind11",
+ hdrs = glob(
+ include = [
+ "include/pybind11/*.h",
+ "include/pybind11/detail/*.h",
+ ],
+ exclude = [
+ "include/pybind11/common.h",
+ "include/pybind11/eigen.h",
+ ],
+ ),
+ copts = [
+ "-fexceptions",
+ "-Wno-undefined-inline",
+ "-Wno-pragma-once-outside-header",
+ ],
+ includes = ["include"],
+ visibility = ["//visibility:public"],
+)
diff --git a/bindings/python/python_headers.BUILD b/bindings/python/python_headers.BUILD
new file mode 100644
index 0000000..9c34cf6
--- /dev/null
+++ b/bindings/python/python_headers.BUILD
@@ -0,0 +1,6 @@
+cc_library(
+ name = "python_headers",
+ hdrs = glob(["**/*.h"]),
+ includes = ["."],
+ visibility = ["//visibility:public"],
+)
diff --git a/bindings/python/requirements.txt b/bindings/python/requirements.txt
new file mode 100644
index 0000000..f5bbe7e
--- /dev/null
+++ b/bindings/python/requirements.txt
@@ -0,0 +1,2 @@
+absl-py>=0.7.1
+
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..f4c0633
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,124 @@
+import os
+import posixpath
+import re
+import shutil
+import sys
+
+from distutils import sysconfig
+import setuptools
+from setuptools.command import build_ext
+
+
+here = os.path.dirname(os.path.abspath(__file__))
+
+
+IS_WINDOWS = sys.platform.startswith('win')
+
+
+def _get_version():
+ """Parse the version string from __init__.py."""
+ with open(os.path.join(here, 'bindings', 'python', 'benchmark', '__init__.py')) as f:
+ try:
+ version_line = next(
+ line for line in f if line.startswith('__version__'))
+ except StopIteration:
+ raise ValueError('__version__ not defined in __init__.py')
+ else:
+ ns = {}
+ exec(version_line, ns) # pylint: disable=exec-used
+ return ns['__version__']
+
+
+def _parse_requirements(path):
+ with open(os.path.join(here, path)) as f:
+ return [
+ line.rstrip() for line in f
+ if not (line.isspace() or line.startswith('#'))
+ ]
+
+
+class BazelExtension(setuptools.Extension):
+ """A C/C++ extension that is defined as a Bazel BUILD target."""
+
+ def __init__(self, name, bazel_target):
+ self.bazel_target = bazel_target
+ self.relpath, self.target_name = (
+ posixpath.relpath(bazel_target, '//').split(':'))
+ setuptools.Extension.__init__(self, name, sources=[])
+
+
+class BuildBazelExtension(build_ext.build_ext):
+ """A command that runs Bazel to build a C/C++ extension."""
+
+ def run(self):
+ for ext in self.extensions:
+ self.bazel_build(ext)
+ build_ext.build_ext.run(self)
+
+ def bazel_build(self, ext):
+ with open('WORKSPACE', 'r') as f:
+ workspace_contents = f.read()
+
+ with open('WORKSPACE', 'w') as f:
+ f.write(re.sub(
+ r'(?<=path = ").*(?=", # May be overwritten by setup\.py\.)',
+ sysconfig.get_python_inc().replace(os.path.sep, posixpath.sep),
+ workspace_contents))
+
+ if not os.path.exists(self.build_temp):
+ os.makedirs(self.build_temp)
+
+ bazel_argv = [
+ 'bazel',
+ 'build',
+ ext.bazel_target,
+ '--symlink_prefix=' + os.path.join(self.build_temp, 'bazel-'),
+ '--compilation_mode=' + ('dbg' if self.debug else 'opt'),
+ ]
+
+ if IS_WINDOWS:
+ # Link with python*.lib.
+ for library_dir in self.library_dirs:
+ bazel_argv.append('--linkopt=/LIBPATH:' + library_dir)
+
+ self.spawn(bazel_argv)
+
+ shared_lib_suffix = '.dll' if IS_WINDOWS else '.so'
+ ext_bazel_bin_path = os.path.join(
+ self.build_temp, 'bazel-bin',
+ ext.relpath, ext.target_name + shared_lib_suffix)
+ ext_dest_path = self.get_ext_fullpath(ext.name)
+ ext_dest_dir = os.path.dirname(ext_dest_path)
+ if not os.path.exists(ext_dest_dir):
+ os.makedirs(ext_dest_dir)
+ shutil.copyfile(ext_bazel_bin_path, ext_dest_path)
+
+
+setuptools.setup(
+ name='google-benchmark',
+ version=_get_version(),
+ url='https://github.com/google/benchmark',
+ description='A library to benchmark code snippets.',
+ author='Google',
+ author_email='benchmark-py@google.com',
+ # Contained modules and scripts.
+ package_dir={'': 'bindings/python'},
+ packages=setuptools.find_packages('bindings/python'),
+ install_requires=_parse_requirements('bindings/python/requirements.txt'),
+ cmdclass=dict(build_ext=BuildBazelExtension),
+ ext_modules=[BazelExtension('benchmark._benchmark', '//bindings/python/benchmark:_benchmark')],
+ zip_safe=False,
+ # PyPI package information.
+ classifiers=[
+ 'Development Status :: 4 - Beta',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Science/Research',
+ 'License :: OSI Approved :: Apache Software License',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Topic :: Software Development :: Testing',
+ 'Topic :: System :: Benchmark',
+ ],
+ license='Apache 2.0',
+ keywords='benchmark',
+)
diff --git a/src/benchmark.cc b/src/benchmark.cc
index b751b9c..1c049f2 100644
--- a/src/benchmark.cc
+++ b/src/benchmark.cc
@@ -284,10 +284,10 @@
}
// Disable deprecated warnings temporarily because we need to reference
-// CSVReporter but don't want to trigger -Werror=-Wdeprecated
+// CSVReporter but don't want to trigger -Werror=-Wdeprecated-declarations
#ifdef __GNUC__
#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated"
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
std::unique_ptr<BenchmarkReporter> CreateReporter(
diff --git a/src/cycleclock.h b/src/cycleclock.h
index 3901da6..179c67c 100644
--- a/src/cycleclock.h
+++ b/src/cycleclock.h
@@ -86,15 +86,15 @@
// This returns a time-base, which is not always precisely a cycle-count.
#if defined(__powerpc64__) || defined(__ppc64__)
int64_t tb;
- asm volatile("mfspr %0, 268" : "=r" (tb));
+ asm volatile("mfspr %0, 268" : "=r"(tb));
return tb;
#else
uint32_t tbl, tbu0, tbu1;
asm volatile(
- "mftbu %0\n"
- "mftbl %1\n"
- "mftbu %2"
- : "=r"(tbu0), "=r"(tbl), "=r"(tbu1));
+ "mftbu %0\n"
+ "mftbl %1\n"
+ "mftbu %2"
+ : "=r"(tbu0), "=r"(tbl), "=r"(tbu1));
tbl &= -static_cast<int32_t>(tbu0 == tbu1);
// high 32 bits in tbu1; low 32 bits in tbl (tbu0 is no longer needed)
return (static_cast<uint64_t>(tbu1) << 32) | tbl;
@@ -179,14 +179,14 @@
// This asm also includes the PowerPC overflow handling strategy, as above.
// Implemented in assembly because Clang insisted on branching.
asm volatile(
- "rdcycleh %0\n"
- "rdcycle %1\n"
- "rdcycleh %2\n"
- "sub %0, %0, %2\n"
- "seqz %0, %0\n"
- "sub %0, zero, %0\n"
- "and %1, %1, %0\n"
- : "=r"(cycles_hi0), "=r"(cycles_lo), "=r"(cycles_hi1));
+ "rdcycleh %0\n"
+ "rdcycle %1\n"
+ "rdcycleh %2\n"
+ "sub %0, %0, %2\n"
+ "seqz %0, %0\n"
+ "sub %0, zero, %0\n"
+ "and %1, %1, %0\n"
+ : "=r"(cycles_hi0), "=r"(cycles_lo), "=r"(cycles_hi1));
return (static_cast<uint64_t>(cycles_hi1) << 32) | cycles_lo;
#else
uint64_t cycles;
diff --git a/src/string_util.cc b/src/string_util.cc
index 39b01a1..ac60b55 100644
--- a/src/string_util.cc
+++ b/src/string_util.cc
@@ -1,6 +1,9 @@
#include "string_util.h"
#include <array>
+#ifdef BENCHMARK_STL_ANDROID_GNUSTL
+#include <cerrno>
+#endif
#include <cmath>
#include <cstdarg>
#include <cstdio>
diff --git a/test/output_test_helper.cc b/test/output_test_helper.cc
index bdb34c8..f99b3a8 100644
--- a/test/output_test_helper.cc
+++ b/test/output_test_helper.cc
@@ -374,10 +374,10 @@
}
// Disable deprecated warnings temporarily because we need to reference
-// CSVReporter but don't want to trigger -Werror=-Wdeprecated
+// CSVReporter but don't want to trigger -Werror=-Wdeprecated-declarations
#ifdef __GNUC__
#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated"
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
void RunOutputTests(int argc, char* argv[]) {
using internal::GetTestCaseList;