annotate and export public symbols (#1321)

This commit is contained in:
Sergiu Deitsch 2022-02-14 11:48:53 +01:00 committed by GitHub
parent 6e51dcbcc3
commit 9e47d070fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 466 additions and 92 deletions

View File

@ -10,7 +10,7 @@ jobs:
# TODO: add coverage build (requires lcov)
# TODO: add clang + libc++ builds for ubuntu
job:
name: ${{ matrix.os }}.${{ matrix.build_type }}.${{ matrix.compiler }}
name: ${{ matrix.os }}.${{ matrix.build_type }}.${{ matrix.lib }}.${{ matrix.compiler }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
@ -18,28 +18,39 @@ jobs:
os: [ubuntu-latest, ubuntu-20.04, macos-latest]
build_type: ['Release', 'Debug']
compiler: [g++, clang++]
include:
- displayTargetName: windows-latest-release
os: windows-latest
build_type: 'Release'
- displayTargetName: windows-latest-debug
os: windows-latest
build_type: 'Debug'
lib: ['shared', 'static']
steps:
- uses: actions/checkout@v2
- name: create build environment
run: cmake -E make_directory ${{ runner.workspace }}/_build
- name: setup cmake initial cache
run: touch compiler-cache.cmake
- name: setup lto
# Workaround for enabling -flto on old GCC versions
if: matrix.build_type == 'Release' && startsWith(matrix.compiler, 'g++') && matrix.os != 'macos-latest'
run: >
echo 'set (CMAKE_CXX_FLAGS -flto CACHE STRING "")' >> compiler-cache.cmake;
echo 'set (CMAKE_RANLIB /usr/bin/gcc-ranlib CACHE FILEPATH "")' >> compiler-cache.cmake;
echo 'set (CMAKE_AR /usr/bin/gcc-ar CACHE FILEPATH "")' >> compiler-cache.cmake;
echo 'set (CMAKE_NM /usr/bin/gcc-nm CACHE FILEPATH "")' >> compiler-cache.cmake;
- name: configure cmake
env:
CXX: ${{ matrix.compiler }}
shell: bash
working-directory: ${{ runner.workspace }}/_build
run: >
cmake $GITHUB_WORKSPACE
cmake -C ${{ github.workspace }}/compiler-cache.cmake
$GITHUB_WORKSPACE
-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON
-DBUILD_SHARED_LIBS=${{ matrix.lib == 'shared' }}
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
-DCMAKE_CXX_VISIBILITY_PRESET=hidden
-DCMAKE_VISIBILITY_INLINES_HIDDEN=ON
- name: build
shell: bash
@ -51,6 +62,57 @@ jobs:
working-directory: ${{ runner.workspace }}/_build
run: ctest -C ${{ matrix.build_type }} -VV
msvc:
name: ${{ matrix.os }}.${{ matrix.build_type }}.${{ matrix.lib }}.${{ matrix.msvc }}
runs-on: ${{ matrix.os }}
defaults:
run:
shell: powershell
strategy:
fail-fast: false
matrix:
msvc:
- VS-16-2019
- VS-17-2022
arch:
- x64
build_type:
- Debug
- Release
lib:
- shared
- static
include:
- msvc: VS-16-2019
os: windows-2019
generator: 'Visual Studio 16 2019'
- msvc: VS-17-2022
os: windows-2022
generator: 'Visual Studio 17 2022'
steps:
- uses: actions/checkout@v2
- name: configure cmake
run: >
cmake -S . -B _build/
-A ${{ matrix.arch }}
-G "${{ matrix.generator }}"
-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON
-DBUILD_SHARED_LIBS=${{ matrix.lib == 'shared' }}
- name: build
run: cmake --build _build/ --config ${{ matrix.build_type }}
- name: setup test environment
# Make sure gmock and benchmark DLLs can be found
run: >
echo "$((Get-Item .).FullName)/_build/bin/${{ matrix.build_type }}" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append;
echo "$((Get-Item .).FullName)/_build/src/${{ matrix.build_type }}" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append;
- name: test
run: ctest --test-dir _build/ -C ${{ matrix.build_type }} -VV
ubuntu-16_04:
name: ubuntu-16.04.${{ matrix.build_type }}.${{ matrix.compiler }}
runs-on: [ubuntu-latest]
@ -71,15 +133,34 @@ jobs:
- name: create build environment
run: cmake -E make_directory $GITHUB_WORKSPACE/_build
- name: setup cmake initial cache
run: touch compiler-cache.cmake
- name: setup lto
# Workaround for enabling -flto on old GCC versions
# -Wl,--no-as-needed is needed to avoid the following linker error:
#
# /usr/lib/gcc/x86_64-linux-gnu/5/libstdc++.so: undefined reference to `pthread_create'
#
if: matrix.build_type == 'Release' && startsWith(matrix.compiler, 'g++')
run: >
echo 'set (CMAKE_CXX_FLAGS "-Wl,--no-as-needed -flto" CACHE STRING "")' >> compiler-cache.cmake;
echo 'set (CMAKE_RANLIB "/usr/bin/gcc-ranlib" CACHE FILEPATH "")' >> compiler-cache.cmake;
echo 'set (CMAKE_AR "/usr/bin/gcc-ar" CACHE FILEPATH "")' >> compiler-cache.cmake;
echo 'set (CMAKE_NM "/usr/bin/gcc-nm" CACHE FILEPATH "")' >> compiler-cache.cmake;
- name: configure cmake
env:
CXX: ${{ matrix.compiler }}
shell: bash
working-directory: ${{ github.workspace }}/_build
run: >
cmake $GITHUB_WORKSPACE
cmake -C ../compiler-cache.cmake ..
-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON
-DBUILD_SHARED_LIBS=${{ matrix.lib == 'shared' }}
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
-DCMAKE_CXX_VISIBILITY_PRESET=hidden
-DCMAKE_VISIBILITY_INLINES_HIDDEN=ON
- name: build
shell: bash
@ -126,16 +207,38 @@ jobs:
- name: create build environment
run: cmake -E make_directory $GITHUB_WORKSPACE/_build
- name: setup cmake initial cache
run: touch compiler-cache.cmake
- name: setup lto
# Workaround for enabling -flto on old GCC versions
# -Wl,--no-as-needed is needed to avoid the following linker error:
#
# /usr/lib/gcc/x86_64-linux-gnu/6/libstdc++.so: undefined reference to `pthread_create'
#
if: matrix.build_type == 'Release' && startsWith(matrix.compiler, 'g++')
run: >
COMPILER=${{ matrix.compiler }};
VERSION=${COMPILER#g++-};
PREFIX=/usr/bin/gcc;
echo "set (CMAKE_CXX_FLAGS \"-Wl,--no-as-needed -flto\" CACHE STRING \"\")" >> compiler-cache.cmake;
echo "set (CMAKE_RANLIB \"$PREFIX-ranlib-$VERSION\" CACHE FILEPATH \"\")" >> compiler-cache.cmake;
echo "set (CMAKE_AR \"$PREFIX-ar-$VERSION\" CACHE FILEPATH \"\")" >> compiler-cache.cmake;
echo "set (CMAKE_NM \"$PREFIX-nm-$VERSION\" CACHE FILEPAT \"\")" >> compiler-cache.cmake;
- name: configure cmake
env:
CXX: ${{ matrix.compiler }}
shell: bash
working-directory: ${{ github.workspace }}/_build
run: >
cmake $GITHUB_WORKSPACE
-DBENCHMARK_ENABLE_TESTING=${{ matrix.run_tests }}
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
cmake -C ../compiler-cache.cmake ..
-DBENCHMARK_DOWNLOAD_DEPENDENCIES=${{ matrix.run_tests }}
-DBENCHMARK_ENABLE_TESTING=${{ matrix.run_tests }}
-DBUILD_SHARED_LIBS=${{ matrix.lib == 'shared' }}
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
-DCMAKE_CXX_VISIBILITY_PRESET=hidden
-DCMAKE_VISIBILITY_INLINES_HIDDEN=ON
- name: build
shell: bash

View File

@ -1,5 +1,22 @@
licenses(["notice"])
load(
"@com_github_google_benchmark//tools:workspace/generate_export_header.bzl",
"generate_export_header",
)
posix_copts = [
"-fvisibility=hidden",
"-fvisibility-inlines-hidden",
]
# Generate header to provide ABI export symbols
generate_export_header(
out = "include/benchmark/export.h",
lib = "benchmark",
static_define = "BENCHMARK_STATIC_DEFINE",
)
config_setting(
name = "qnx",
constraint_values = ["@platforms//os:qnx"],
@ -27,13 +44,20 @@ cc_library(
],
exclude = ["src/benchmark_main.cc"],
),
hdrs = ["include/benchmark/benchmark.h"],
hdrs = [
"include/benchmark/benchmark.h",
"include/benchmark/export.h", # From generate_export_header
],
linkopts = select({
":windows": ["-DEFAULTLIB:shlwapi.lib"],
"//conditions:default": ["-pthread"],
}),
strip_include_prefix = "include",
visibility = ["//visibility:public"],
copts = select({
":windows": [],
"//conditions:default": posix_copts,
}),
)
cc_library(
@ -43,6 +67,10 @@ cc_library(
strip_include_prefix = "include",
visibility = ["//visibility:public"],
deps = [":benchmark"],
copts = select({
":windows": [],
"//conditions:default": posix_copts,
}),
)
cc_library(

View File

@ -50,7 +50,10 @@ option(BENCHMARK_USE_BUNDLED_GTEST "Use bundled GoogleTest. If disabled, the fin
option(BENCHMARK_ENABLE_LIBPFM "Enable performance counters provided by libpfm" OFF)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
# Export only public symbols
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
if(MSVC)
# As of CMake 3.18, CMAKE_SYSTEM_PROCESSOR is not set properly for MSVC and
# cross-compilation (e.g. Host=x86_64, target=aarch64) requires using the
@ -123,10 +126,11 @@ set(GENERIC_LIB_VERSION ${VERSION})
string(SUBSTRING ${VERSION} 0 1 GENERIC_LIB_SOVERSION)
# Import our CMake modules
include(CheckCXXCompilerFlag)
include(AddCXXCompilerFlag)
include(CXXFeatureCheck)
include(CheckCXXCompilerFlag)
include(CheckLibraryExists)
include(CXXFeatureCheck)
include(GenerateExportHeader)
check_library_exists(rt shm_open "" HAVE_LIB_RT)

View File

@ -1,5 +1,7 @@
// Benchmark for Python.
#include "benchmark/benchmark.h"
#include <map>
#include <string>
#include <vector>
@ -9,8 +11,6 @@
#include "pybind11/stl.h"
#include "pybind11/stl_bind.h"
#include "benchmark/benchmark.h"
PYBIND11_MAKE_OPAQUE(benchmark::UserCounters);
namespace {

View File

@ -187,6 +187,8 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
#include <utility>
#include <vector>
#include "benchmark/export.h"
#if defined(BENCHMARK_HAS_CXX11)
#include <atomic>
#include <initializer_list>
@ -280,23 +282,29 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
#define BENCHMARK_OVERRIDE
#endif
#if defined(_MSC_VER)
#pragma warning(push)
// C4251: <symbol> needs to have dll-interface to be used by clients of class
#pragma warning(disable : 4251)
#endif
namespace benchmark {
class BenchmarkReporter;
void Initialize(int* argc, char** argv);
void Shutdown();
BENCHMARK_EXPORT void Initialize(int* argc, char** argv);
BENCHMARK_EXPORT void Shutdown();
// Report to stdout all arguments in 'argv' as unrecognized except the first.
// Returns true there is at least on unrecognized argument (i.e. 'argc' > 1).
bool ReportUnrecognizedArguments(int argc, char** argv);
BENCHMARK_EXPORT bool ReportUnrecognizedArguments(int argc, char** argv);
// Returns the current value of --benchmark_filter.
std::string GetBenchmarkFilter();
BENCHMARK_EXPORT std::string GetBenchmarkFilter();
// Creates a default display reporter. Used by the library when no display
// reporter is provided, but also made available for external use in case a
// custom reporter should respect the `--benchmark_format` flag as a fallback
BenchmarkReporter* CreateDefaultDisplayReporter();
BENCHMARK_EXPORT BenchmarkReporter* CreateDefaultDisplayReporter();
// Generate a list of benchmarks matching the specified --benchmark_filter flag
// and if --benchmark_list_tests is specified return after printing the name
@ -314,18 +322,19 @@ BenchmarkReporter* CreateDefaultDisplayReporter();
// 'file_reporter' is ignored.
//
// RETURNS: The number of matching benchmarks.
size_t RunSpecifiedBenchmarks();
size_t RunSpecifiedBenchmarks(std::string spec);
BENCHMARK_EXPORT size_t RunSpecifiedBenchmarks();
BENCHMARK_EXPORT size_t RunSpecifiedBenchmarks(std::string spec);
size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter);
size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
std::string spec);
BENCHMARK_EXPORT size_t
RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter);
BENCHMARK_EXPORT size_t
RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, std::string spec);
size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
BenchmarkReporter* file_reporter);
size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
BenchmarkReporter* file_reporter,
std::string spec);
BENCHMARK_EXPORT size_t RunSpecifiedBenchmarks(
BenchmarkReporter* display_reporter, BenchmarkReporter* file_reporter);
BENCHMARK_EXPORT size_t
RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
BenchmarkReporter* file_reporter, std::string spec);
// If a MemoryManager is registered (via RegisterMemoryManager()),
// it can be used to collect and report allocation metrics for a run of the
@ -374,9 +383,11 @@ class MemoryManager {
// Register a MemoryManager instance that will be used to collect and report
// allocation measurements for benchmark runs.
BENCHMARK_EXPORT
void RegisterMemoryManager(MemoryManager* memory_manager);
// Add a key-value pair to output as part of the context stanza in the report.
BENCHMARK_EXPORT
void AddCustomContext(const std::string& key, const std::string& value);
namespace internal {
@ -384,14 +395,15 @@ class Benchmark;
class BenchmarkImp;
class BenchmarkFamilies;
BENCHMARK_EXPORT
void UseCharPointer(char const volatile*);
// Take ownership of the pointer and register the benchmark. Return the
// registered benchmark.
Benchmark* RegisterBenchmarkInternal(Benchmark*);
BENCHMARK_EXPORT Benchmark* RegisterBenchmarkInternal(Benchmark*);
// Ensure that the standard streams are properly initialized in every TU.
int InitializeStreams();
BENCHMARK_EXPORT int InitializeStreams();
BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams();
} // namespace internal
@ -573,7 +585,7 @@ enum AggregationReportMode
// State is passed to a running Benchmark and contains state for the
// benchmark to use.
class State {
class BENCHMARK_EXPORT State {
public:
struct StateIterator;
friend struct StateIterator;
@ -904,7 +916,7 @@ typedef void(Function)(State&);
// be called on this object to change the properties of the benchmark.
// Each method returns "this" so that multiple method calls can
// chained into one expression.
class Benchmark {
class BENCHMARK_EXPORT Benchmark {
public:
virtual ~Benchmark();
@ -1097,7 +1109,6 @@ class Benchmark {
protected:
explicit Benchmark(const char* name);
Benchmark(Benchmark const&);
void SetName(const char* name);
int ArgsCnt() const;
@ -1127,7 +1138,17 @@ class Benchmark {
callback_function setup_;
callback_function teardown_;
Benchmark& operator=(Benchmark const&);
Benchmark(Benchmark const&)
#if defined(BENCHMARK_HAS_CXX11)
= delete
#endif
;
Benchmark& operator=(Benchmark const&)
#if defined(BENCHMARK_HAS_CXX11)
= delete
#endif
;
};
} // namespace internal
@ -1146,12 +1167,12 @@ internal::Benchmark* RegisterBenchmark(const char* name, Lambda&& fn);
// Remove all registered benchmarks. All pointers to previously registered
// benchmarks are invalidated.
void ClearRegisteredBenchmarks();
BENCHMARK_EXPORT void ClearRegisteredBenchmarks();
namespace internal {
// The class used to hold all Benchmarks created from static function.
// (ie those created using the BENCHMARK(...) macros.
class FunctionBenchmark : public Benchmark {
class BENCHMARK_EXPORT FunctionBenchmark : public Benchmark {
public:
FunctionBenchmark(const char* name, Function* func)
: Benchmark(name), func_(func) {}
@ -1444,22 +1465,14 @@ class Fixture : public internal::Benchmark {
#endif
// Helper macro to create a main routine in a test that runs the benchmarks
#define BENCHMARK_MAIN() \
int main(int argc, char** argv) { \
::benchmark::Initialize(&argc, argv); \
if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1; \
::benchmark::RunSpecifiedBenchmarks(); \
::benchmark::Shutdown(); \
return 0; \
} \
int main(int, char**)
#define BENCHMARK_MAIN() BENCHMARK_EXPORT int main(int argc, char** argv)
// ------------------------------------------------------
// Benchmark Reporters
namespace benchmark {
struct CPUInfo {
struct BENCHMARK_EXPORT CPUInfo {
struct CacheInfo {
std::string type;
int level;
@ -1483,7 +1496,7 @@ struct CPUInfo {
};
// Adding Struct for System Information
struct SystemInfo {
struct BENCHMARK_EXPORT SystemInfo {
std::string name;
static const SystemInfo& Get();
@ -1495,7 +1508,7 @@ struct SystemInfo {
// BenchmarkName contains the components of the Benchmark's name
// which allows individual fields to be modified or cleared before
// building the final name using 'str()'.
struct BenchmarkName {
struct BENCHMARK_EXPORT BenchmarkName {
std::string function_name;
std::string args;
std::string min_time;
@ -1514,7 +1527,7 @@ struct BenchmarkName {
// can control the destination of the reports by calling
// RunSpecifiedBenchmarks and passing it a custom reporter object.
// The reporter object must implement the following interface.
class BenchmarkReporter {
class BENCHMARK_EXPORT BenchmarkReporter {
public:
struct Context {
CPUInfo const& cpu_info;
@ -1525,7 +1538,7 @@ class BenchmarkReporter {
Context();
};
struct Run {
struct BENCHMARK_EXPORT Run {
static const int64_t no_repetition_index = -1;
enum RunType { RT_Iteration, RT_Aggregate };
@ -1670,7 +1683,7 @@ class BenchmarkReporter {
// Simple reporter that outputs benchmark data to the console. This is the
// default reporter used by RunSpecifiedBenchmarks().
class ConsoleReporter : public BenchmarkReporter {
class BENCHMARK_EXPORT ConsoleReporter : public BenchmarkReporter {
public:
enum OutputOptions {
OO_None = 0,
@ -1695,7 +1708,7 @@ class ConsoleReporter : public BenchmarkReporter {
bool printed_header_;
};
class JSONReporter : public BenchmarkReporter {
class BENCHMARK_EXPORT JSONReporter : public BenchmarkReporter {
public:
JSONReporter() : first_report_(true) {}
virtual bool ReportContext(const Context& context) BENCHMARK_OVERRIDE;
@ -1708,7 +1721,7 @@ class JSONReporter : public BenchmarkReporter {
bool first_report_;
};
class BENCHMARK_DEPRECATED_MSG(
class BENCHMARK_EXPORT BENCHMARK_DEPRECATED_MSG(
"The CSV Reporter will be removed in a future release") CSVReporter
: public BenchmarkReporter {
public:
@ -1760,11 +1773,17 @@ inline double GetTimeUnitMultiplier(TimeUnit unit) {
// CreateRange(0, 100, /*multi=*/4),
// CreateDenseRange(0, 4, /*step=*/1),
// });
BENCHMARK_EXPORT
std::vector<int64_t> CreateRange(int64_t lo, int64_t hi, int multi);
// Creates a list of integer values for the given range and step.
BENCHMARK_EXPORT
std::vector<int64_t> CreateDenseRange(int64_t start, int64_t limit, int step);
} // namespace benchmark
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#endif // BENCHMARK_BENCHMARK_H_

View File

@ -22,10 +22,15 @@ add_library(benchmark::benchmark ALIAS benchmark)
set_target_properties(benchmark PROPERTIES
OUTPUT_NAME "benchmark"
VERSION ${GENERIC_LIB_VERSION}
SOVERSION ${GENERIC_LIB_SOVERSION}
SOVERSION 2
)
target_include_directories(benchmark PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>)
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
)
generate_export_header(benchmark
EXPORT_FILE_NAME ${PROJECT_BINARY_DIR}/include/benchmark/export.h)
# libpfm, if available
if (HAVE_LIBPFM)
@ -59,7 +64,8 @@ add_library(benchmark::benchmark_main ALIAS benchmark_main)
set_target_properties(benchmark_main PROPERTIES
OUTPUT_NAME "benchmark_main"
VERSION ${GENERIC_LIB_VERSION}
SOVERSION ${GENERIC_LIB_SOVERSION}
SOVERSION 2
DEFINE_SYMBOL benchmark_EXPORTS
)
target_link_libraries(benchmark_main PUBLIC benchmark::benchmark)
@ -107,6 +113,7 @@ if (BENCHMARK_ENABLE_INSTALL)
install(
DIRECTORY "${PROJECT_SOURCE_DIR}/include/benchmark"
"${PROJECT_BINARY_DIR}/include/benchmark"
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.*h")

View File

@ -126,7 +126,7 @@ BM_DEFINE_int32(v, 0);
namespace internal {
std::map<std::string, std::string>* global_context = nullptr;
BENCHMARK_EXPORT std::map<std::string, std::string>* global_context = nullptr;
// FIXME: wouldn't LTO mess this up?
void UseCharPointer(char const volatile*) {}

View File

@ -76,6 +76,7 @@ bool FindBenchmarksInternal(const std::string& re,
bool IsZero(double n);
BENCHMARK_EXPORT
ConsoleReporter::OutputOptions GetOutputOptions(bool force_no_color = false);
} // end namespace internal

View File

@ -15,3 +15,13 @@
#include "benchmark/benchmark.h"
BENCHMARK_MAIN();
// MSVC does not allow the definition of dllimport. Thus, define it here instead
// inline in a macro.
int main(int argc, char** argv) {
::benchmark::Initialize(&argc, argv);
if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1;
::benchmark::RunSpecifiedBenchmarks();
::benchmark::Shutdown();
return 0;
}

11
src/check.cc Normal file
View File

@ -0,0 +1,11 @@
#include "check.h"
namespace benchmark {
namespace internal {
static AbortHandlerT* handler = &std::abort;
AbortHandlerT*& GetAbortHandler() { return handler; }
} // namespace internal
} // namespace benchmark

View File

@ -5,6 +5,7 @@
#include <cstdlib>
#include <ostream>
#include "benchmark/export.h"
#include "internal_macros.h"
#include "log.h"
@ -13,10 +14,8 @@ namespace internal {
typedef void(AbortHandlerT)();
inline AbortHandlerT*& GetAbortHandler() {
static AbortHandlerT* handler = &std::abort;
return handler;
}
BENCHMARK_EXPORT
AbortHandlerT*& GetAbortHandler();
BENCHMARK_NORETURN inline void CallAbortHandler() {
GetAbortHandler()();

View File

@ -5,28 +5,33 @@
#include <map>
#include <string>
#include "benchmark/export.h"
// Macro for referencing flags.
#define FLAG(name) FLAGS_##name
// Macros for declaring flags.
#define BM_DECLARE_bool(name) extern bool FLAG(name)
#define BM_DECLARE_int32(name) extern int32_t FLAG(name)
#define BM_DECLARE_double(name) extern double FLAG(name)
#define BM_DECLARE_string(name) extern std::string FLAG(name)
#define BM_DECLARE_bool(name) BENCHMARK_EXPORT extern bool FLAG(name)
#define BM_DECLARE_int32(name) BENCHMARK_EXPORT extern int32_t FLAG(name)
#define BM_DECLARE_double(name) BENCHMARK_EXPORT extern double FLAG(name)
#define BM_DECLARE_string(name) BENCHMARK_EXPORT extern std::string FLAG(name)
#define BM_DECLARE_kvpairs(name) \
extern std::map<std::string, std::string> FLAG(name)
BENCHMARK_EXPORT extern std::map<std::string, std::string> FLAG(name)
// Macros for defining flags.
#define BM_DEFINE_bool(name, default_val) \
bool FLAG(name) = benchmark::BoolFromEnv(#name, default_val)
BENCHMARK_EXPORT bool FLAG(name) = benchmark::BoolFromEnv(#name, default_val)
#define BM_DEFINE_int32(name, default_val) \
int32_t FLAG(name) = benchmark::Int32FromEnv(#name, default_val)
BENCHMARK_EXPORT int32_t FLAG(name) = \
benchmark::Int32FromEnv(#name, default_val)
#define BM_DEFINE_double(name, default_val) \
double FLAG(name) = benchmark::DoubleFromEnv(#name, default_val)
BENCHMARK_EXPORT double FLAG(name) = \
benchmark::DoubleFromEnv(#name, default_val)
#define BM_DEFINE_string(name, default_val) \
std::string FLAG(name) = benchmark::StringFromEnv(#name, default_val)
#define BM_DEFINE_kvpairs(name, default_val) \
std::map<std::string, std::string> FLAG(name) = \
BENCHMARK_EXPORT std::string FLAG(name) = \
benchmark::StringFromEnv(#name, default_val)
#define BM_DEFINE_kvpairs(name, default_val) \
BENCHMARK_EXPORT std::map<std::string, std::string> FLAG(name) = \
benchmark::KvPairsFromEnv(#name, default_val)
namespace benchmark {
@ -35,6 +40,7 @@ namespace benchmark {
//
// If the variable exists, returns IsTruthyFlagValue() value; if not,
// returns the given default value.
BENCHMARK_EXPORT
bool BoolFromEnv(const char* flag, bool default_val);
// Parses an Int32 from the environment variable corresponding to the given
@ -42,6 +48,7 @@ bool BoolFromEnv(const char* flag, bool default_val);
//
// If the variable exists, returns ParseInt32() value; if not, returns
// the given default value.
BENCHMARK_EXPORT
int32_t Int32FromEnv(const char* flag, int32_t default_val);
// Parses an Double from the environment variable corresponding to the given
@ -49,6 +56,7 @@ int32_t Int32FromEnv(const char* flag, int32_t default_val);
//
// If the variable exists, returns ParseDouble(); if not, returns
// the given default value.
BENCHMARK_EXPORT
double DoubleFromEnv(const char* flag, double default_val);
// Parses a string from the environment variable corresponding to the given
@ -56,6 +64,7 @@ double DoubleFromEnv(const char* flag, double default_val);
//
// If variable exists, returns its value; if not, returns
// the given default value.
BENCHMARK_EXPORT
const char* StringFromEnv(const char* flag, const char* default_val);
// Parses a set of kvpairs from the environment variable corresponding to the
@ -63,6 +72,7 @@ const char* StringFromEnv(const char* flag, const char* default_val);
//
// If variable exists, returns its value; if not, returns
// the given default value.
BENCHMARK_EXPORT
std::map<std::string, std::string> KvPairsFromEnv(
const char* flag, std::map<std::string, std::string> default_val);
@ -75,40 +85,47 @@ std::map<std::string, std::string> KvPairsFromEnv(
//
// On success, stores the value of the flag in *value, and returns
// true. On failure, returns false without changing *value.
BENCHMARK_EXPORT
bool ParseBoolFlag(const char* str, const char* flag, bool* value);
// Parses a string for an Int32 flag, in the form of "--flag=value".
//
// On success, stores the value of the flag in *value, and returns
// true. On failure, returns false without changing *value.
BENCHMARK_EXPORT
bool ParseInt32Flag(const char* str, const char* flag, int32_t* value);
// Parses a string for a Double flag, in the form of "--flag=value".
//
// On success, stores the value of the flag in *value, and returns
// true. On failure, returns false without changing *value.
BENCHMARK_EXPORT
bool ParseDoubleFlag(const char* str, const char* flag, double* value);
// Parses a string for a string flag, in the form of "--flag=value".
//
// On success, stores the value of the flag in *value, and returns
// true. On failure, returns false without changing *value.
BENCHMARK_EXPORT
bool ParseStringFlag(const char* str, const char* flag, std::string* value);
// Parses a string for a kvpairs flag in the form "--flag=key=value,key=value"
//
// On success, stores the value of the flag in *value and returns true. On
// failure returns false, though *value may have been mutated.
BENCHMARK_EXPORT
bool ParseKeyValueFlag(const char* str, const char* flag,
std::map<std::string, std::string>* value);
// Returns true if the string matches the flag.
BENCHMARK_EXPORT
bool IsFlag(const char* str, const char* flag);
// Returns true unless value starts with one of: '0', 'f', 'F', 'n' or 'N', or
// some non-alphanumeric character. Also returns false if the value matches
// one of 'no', 'false', 'off' (case-insensitive). As a special case, also
// returns true if value is the empty string.
BENCHMARK_EXPORT
bool IsTruthyFlagValue(const std::string& value);
} // end namespace benchmark

View File

@ -29,6 +29,12 @@
#include <unistd.h>
#endif
#if defined(_MSC_VER)
#pragma warning(push)
// C4251: <symbol> needs to have dll-interface to be used by clients of class
#pragma warning(disable : 4251)
#endif
namespace benchmark {
namespace internal {
@ -68,7 +74,7 @@ class PerfCounterValues {
// Collect PMU counters. The object, once constructed, is ready to be used by
// calling read(). PMU counter collection is enabled from the time create() is
// called, to obtain the object, until the object's destructor is called.
class PerfCounters final {
class BENCHMARK_EXPORT PerfCounters final {
public:
// True iff this platform supports performance counters.
static const bool kSupported;
@ -125,7 +131,7 @@ class PerfCounters final {
};
// Typical usage of the above primitives.
class PerfCountersMeasurement final {
class BENCHMARK_EXPORT PerfCountersMeasurement final {
public:
PerfCountersMeasurement(const std::vector<std::string>& counter_names);
~PerfCountersMeasurement();
@ -184,4 +190,8 @@ BENCHMARK_UNUSED static bool perf_init_anchor = PerfCounters::Initialize();
} // namespace internal
} // namespace benchmark
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#endif // BENCHMARK_PERF_COUNTERS_H

View File

@ -25,12 +25,17 @@ namespace benchmark {
// Return a vector containing the mean, median and standard devation information
// (and any user-specified info) for the specified list of reports. If 'reports'
// contains less than two non-errored runs an empty vector is returned
BENCHMARK_EXPORT
std::vector<BenchmarkReporter::Run> ComputeStats(
const std::vector<BenchmarkReporter::Run>& reports);
BENCHMARK_EXPORT
double StatisticsMean(const std::vector<double>& v);
BENCHMARK_EXPORT
double StatisticsMedian(const std::vector<double>& v);
BENCHMARK_EXPORT
double StatisticsStdDev(const std::vector<double>& v);
BENCHMARK_EXPORT
double StatisticsCV(const std::vector<double>& v);
} // end namespace benchmark

View File

@ -5,6 +5,7 @@
#include <string>
#include <utility>
#include "benchmark/export.h"
#include "internal_macros.h"
namespace benchmark {
@ -13,6 +14,7 @@ void AppendHumanReadable(int n, std::string* str);
std::string HumanReadableNumber(double n, double one_k = 1024.0);
BENCHMARK_EXPORT
#if defined(__MINGW32__)
__attribute__((format(__MINGW_PRINTF_FORMAT, 1, 2)))
#elif defined(__GNUC__)
@ -38,6 +40,7 @@ inline std::string StrCat(Args&&... args) {
return ss.str();
}
BENCHMARK_EXPORT
std::vector<std::string> StrSplit(const std::string& str, char delim);
// Disable lint checking for this block since it re-implements C functions.

View File

@ -23,6 +23,7 @@ string(TOUPPER "${CMAKE_CXX_COMPILER_ID}" ASM_TEST_COMPILER)
macro(add_filecheck_test name)
cmake_parse_arguments(ARG "" "" "CHECK_PREFIXES" ${ARGV})
add_library(${name} OBJECT ${name}.cc)
target_link_libraries(${name} PRIVATE benchmark::benchmark)
set_target_properties(${name} PROPERTIES COMPILE_FLAGS "-S ${ASM_TEST_FLAGS}")
set(ASM_OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/${name}.s")
add_custom_target(copy_${name} ALL

View File

@ -50,9 +50,8 @@ cc_library(
"//:benchmark",
"//:benchmark_internal_headers",
"@com_google_googletest//:gtest",
] + (
["@com_google_googletest//:gtest_main"] if (test_src[-len("gtest.cc"):] == "gtest.cc") else []
),
"@com_google_googletest//:gtest_main",
]
# FIXME: Add support for assembly tests to bazel.
# See Issue #556
# https://github.com/google/benchmark/issues/556

View File

@ -1,5 +1,7 @@
# Enable the tests
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
include(CheckCXXCompilerFlag)
@ -35,10 +37,11 @@ if (DEFINED BENCHMARK_CXX_LINKER_FLAGS)
endif()
add_library(output_test_helper STATIC output_test_helper.cc output_test.h)
target_link_libraries(output_test_helper PRIVATE benchmark::benchmark)
macro(compile_benchmark_test name)
add_executable(${name} "${name}.cc")
target_link_libraries(${name} benchmark::benchmark ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(${name} benchmark::benchmark_main ${CMAKE_THREAD_LIBS_INIT})
endmacro(compile_benchmark_test)
macro(compile_benchmark_test_with_main name)
@ -48,7 +51,7 @@ endmacro(compile_benchmark_test_with_main)
macro(compile_output_test name)
add_executable(${name} "${name}.cc" output_test.h)
target_link_libraries(${name} output_test_helper benchmark::benchmark
target_link_libraries(${name} output_test_helper benchmark::benchmark_main
${BENCHMARK_CXX_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
endmacro(compile_output_test)
@ -158,8 +161,8 @@ add_test(NAME user_counters_thousands_test COMMAND user_counters_thousands_test
compile_output_test(memory_manager_test)
add_test(NAME memory_manager_test COMMAND memory_manager_test --benchmark_min_time=0.01)
check_cxx_compiler_flag(-std=c++03 BENCHMARK_HAS_CXX03_FLAG)
if (BENCHMARK_HAS_CXX03_FLAG)
# MSVC does not allow to set the language standard to C++98/03.
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
compile_benchmark_test(cxx03_test)
set_target_properties(cxx03_test
PROPERTIES
@ -170,11 +173,17 @@ if (BENCHMARK_HAS_CXX03_FLAG)
# causing the test to fail to compile. To prevent this we explicitly disable
# the warning.
check_cxx_compiler_flag(-Wno-odr BENCHMARK_HAS_WNO_ODR)
if (BENCHMARK_ENABLE_LTO AND BENCHMARK_HAS_WNO_ODR)
set_target_properties(cxx03_test
PROPERTIES
LINK_FLAGS "-Wno-odr")
check_cxx_compiler_flag(-Wno-lto-type-mismatch BENCHMARK_HAS_WNO_LTO_TYPE_MISMATCH)
# Cannot set_target_properties multiple times here because the warnings will
# be overwritten on each call
set (DISABLE_LTO_WARNINGS "")
if (BENCHMARK_HAS_WNO_ODR)
set(DISABLE_LTO_WARNINGS "${DISABLE_LTO_WARNINGS} -Wno-odr")
endif()
if (BENCHMARK_HAS_WNO_LTO_TYPE_MISMATCH)
set(DISABLE_LTO_WARNINGS "${DISABLE_LTO_WARNINGS} -Wno-lto-type-mismatch")
endif()
set_target_properties(cxx03_test PROPERTIES LINK_FLAGS "${DISABLE_LTO_WARNINGS}")
add_test(NAME cxx03 COMMAND cxx03_test --benchmark_min_time=0.01)
endif()

View File

@ -8,7 +8,7 @@
namespace benchmark {
namespace internal {
extern std::map<std::string, std::string>* global_context;
BENCHMARK_EXPORT extern std::map<std::string, std::string>* global_context;
namespace {

View File

@ -0,0 +1,148 @@
#
# Originl file is located at:
# https://github.com/RobotLocomotion/drake/blob/bad032aeb09b13c7f8c87ed64b624c8d1e9adb30/tools/workspace/generate_export_header.bzl
#
# All components of Drake are licensed under the BSD 3-Clause License
# shown below. Where noted in the source code, some portions may
# be subject to other permissive, non-viral licenses.
#
# Copyright 2012-2016 Robot Locomotion Group @ CSAIL
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer. Redistributions
# in binary form must reproduce the above copyright notice, this list of
# conditions and the following disclaimer in the documentation and/or
# other materials provided with the distribution. Neither the name of
# the Massachusetts Institute of Technology nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# -*- python -*-
def _make_identifier(s):
result = ""
for i in range(len(s)):
result += s[i] if s[i].isalnum() else "_"
return result
# Defines the implementation actions to generate_export_header.
def _generate_export_header_impl(ctx):
output = ctx.outputs.out
guard = _make_identifier(output.basename.upper())
content = [
"#ifndef %s" % guard,
"#define %s" % guard,
"",
"#ifdef %s" % ctx.attr.static_define,
"# define %s" % ctx.attr.export_macro_name,
"# define %s" % ctx.attr.no_export_macro_name,
"#else",
"# define %s __attribute__((visibility(\"default\")))" % ctx.attr.export_macro_name, # noqa
"# define %s __attribute__((visibility(\"hidden\")))" % ctx.attr.no_export_macro_name, # noqa
"#endif",
"",
"#ifndef %s" % ctx.attr.deprecated_macro_name,
"# define %s __attribute__ ((__deprecated__))" % ctx.attr.deprecated_macro_name, # noqa
"#endif",
"",
"#ifndef %s" % ctx.attr.export_deprecated_macro_name,
"# define %s %s %s" % (ctx.attr.export_deprecated_macro_name, ctx.attr.export_macro_name, ctx.attr.deprecated_macro_name), # noqa
"#endif",
"",
"#ifndef %s" % ctx.attr.no_export_deprecated_macro_name,
"# define %s %s %s" % (ctx.attr.no_export_deprecated_macro_name, ctx.attr.no_export_macro_name, ctx.attr.deprecated_macro_name), # noqa
"#endif",
"",
"#endif",
]
ctx.actions.write(output = output, content = "\n".join(content) + "\n")
# Defines the rule to generate_export_header.
_generate_export_header_gen = rule(
attrs = {
"out": attr.output(mandatory = True),
"export_macro_name": attr.string(),
"deprecated_macro_name": attr.string(),
"export_deprecated_macro_name": attr.string(),
"no_export_macro_name": attr.string(),
"no_export_deprecated_macro_name": attr.string(),
"static_define": attr.string(),
},
output_to_genfiles = True,
implementation = _generate_export_header_impl,
)
def generate_export_header(
lib = None,
name = None,
out = None,
export_macro_name = None,
deprecated_macro_name = None,
export_deprecated_macro_name = None,
no_export_macro_name = None,
no_export_deprecated_macro_name = None,
static_define = None,
**kwargs):
"""Creates a rule to generate an export header for a named library. This
is an incomplete implementation of CMake's generate_export_header. (In
particular, it assumes a platform that uses
__attribute__((visibility("default"))) to decorate exports.)
By default, the rule will have a mangled name related to the library name,
and will produce "<lib>_export.h".
The CMake documentation of the generate_export_header macro is:
https://cmake.org/cmake/help/latest/module/GenerateExportHeader.html
"""
if name == None:
name = "__%s_export_h" % lib
if out == None:
out = "%s_export.h" % lib
if export_macro_name == None:
export_macro_name = "%s_EXPORT" % lib.upper()
if deprecated_macro_name == None:
deprecated_macro_name = "%s_DEPRECATED" % lib.upper()
if export_deprecated_macro_name == None:
export_deprecated_macro_name = "%s_DEPRECATED_EXPORT" % lib.upper()
if no_export_macro_name == None:
no_export_macro_name = "%s_NO_EXPORT" % lib.upper()
if no_export_deprecated_macro_name == None:
no_export_deprecated_macro_name = \
"%s_DEPRECATED_NO_EXPORT" % lib.upper()
if static_define == None:
static_define = "%s_STATIC_DEFINE" % lib.upper()
_generate_export_header_gen(
name = name,
out = out,
export_macro_name = export_macro_name,
deprecated_macro_name = deprecated_macro_name,
export_deprecated_macro_name = export_deprecated_macro_name,
no_export_macro_name = no_export_macro_name,
no_export_deprecated_macro_name = no_export_deprecated_macro_name,
static_define = static_define,
**kwargs
)