From 974cd5a5c5a78e76ebc50961f4dbf3bf6d4ade4e Mon Sep 17 00:00:00 2001 From: Dominic Hamon Date: Thu, 4 Aug 2022 15:33:35 +0100 Subject: [PATCH] Ensure we don't need benchmark installed to pass c++ feature checks (#1456) * Ensure we don't need benchmark installed to pass c++ feature checks Requires removal of some dependencies on benchmark.h from internal low-level headers, which is a good thing. Also added better logging to the feature check cmake module. --- CMakeLists.txt | 2 +- cmake/CXXFeatureCheck.cmake | 11 ++++++----- include/benchmark/benchmark.h | 11 ----------- src/benchmark_register.h | 1 + src/check.h | 17 +++++++++++++++++ src/internal_macros.h | 2 -- src/log.h | 26 ++++++++++++++++++++------ src/string_util.h | 2 ++ test/benchmark_gtest.cc | 7 +++---- 9 files changed, 50 insertions(+), 29 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2058effc..3d636bea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -223,7 +223,7 @@ else() add_cxx_compiler_flag(-wd654) add_cxx_compiler_flag(-Wthread-safety) if (HAVE_CXX_FLAG_WTHREAD_SAFETY) - cxx_feature_check(THREAD_SAFETY_ATTRIBUTES) + cxx_feature_check(THREAD_SAFETY_ATTRIBUTES "-DINCLUDE_DIRECTORIES=${PROJECT_SOURCE_DIR}/include") endif() # On most UNIX like platforms g++ and clang++ define _GNU_SOURCE as a diff --git a/cmake/CXXFeatureCheck.cmake b/cmake/CXXFeatureCheck.cmake index aa67f58e..a96a014f 100644 --- a/cmake/CXXFeatureCheck.cmake +++ b/cmake/CXXFeatureCheck.cmake @@ -27,17 +27,18 @@ function(cxx_feature_check FILE) return() endif() + set(FEATURE_CHECK_CMAKE_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS}) if (ARGC GREATER 1) message(STATUS "Enabling additional flags: ${ARGV1}") - list(APPEND BENCHMARK_CXX_LINKER_FLAGS ${ARGV1}) + list(APPEND FEATURE_CHECK_CMAKE_FLAGS ${ARGV1}) endif() if (NOT DEFINED COMPILE_${FEATURE}) - message(STATUS "Performing Test ${FEATURE}") if(CMAKE_CROSSCOMPILING) + message(STATUS "Cross-compiling to test ${FEATURE}") try_compile(COMPILE_${FEATURE} ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${FILE}.cpp - CMAKE_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS} + CMAKE_FLAGS ${FEATURE_CHECK_CMAKE_FLAGS} LINK_LIBRARIES ${BENCHMARK_CXX_LIBRARIES} OUTPUT_VARIABLE COMPILE_OUTPUT_VAR) if(COMPILE_${FEATURE}) @@ -48,10 +49,10 @@ function(cxx_feature_check FILE) set(RUN_${FEATURE} 1 CACHE INTERNAL "") endif() else() - message(STATUS "Performing Test ${FEATURE}") + message(STATUS "Compiling and running to test ${FEATURE}") try_run(RUN_${FEATURE} COMPILE_${FEATURE} ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${FILE}.cpp - CMAKE_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS} + CMAKE_FLAGS ${FEATURE_CHECK_CMAKE_FLAGS} LINK_LIBRARIES ${BENCHMARK_CXX_LIBRARIES} COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT_VAR) endif() diff --git a/include/benchmark/benchmark.h b/include/benchmark/benchmark.h index a17038c0..f0152e5a 100644 --- a/include/benchmark/benchmark.h +++ b/include/benchmark/benchmark.h @@ -220,22 +220,11 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); #if defined(__GNUC__) || defined(__clang__) #define BENCHMARK_ALWAYS_INLINE __attribute__((always_inline)) -#define BENCHMARK_NOEXCEPT noexcept -#define BENCHMARK_NOEXCEPT_OP(x) noexcept(x) #elif defined(_MSC_VER) && !defined(__clang__) #define BENCHMARK_ALWAYS_INLINE __forceinline -#if _MSC_VER >= 1900 -#define BENCHMARK_NOEXCEPT noexcept -#define BENCHMARK_NOEXCEPT_OP(x) noexcept(x) -#else -#define BENCHMARK_NOEXCEPT -#define BENCHMARK_NOEXCEPT_OP(x) -#endif #define __func__ __FUNCTION__ #else #define BENCHMARK_ALWAYS_INLINE -#define BENCHMARK_NOEXCEPT -#define BENCHMARK_NOEXCEPT_OP(x) #endif #define BENCHMARK_INTERNAL_TOSTRING2(x) #x diff --git a/src/benchmark_register.h b/src/benchmark_register.h index a5a250cc..53367c70 100644 --- a/src/benchmark_register.h +++ b/src/benchmark_register.h @@ -1,6 +1,7 @@ #ifndef BENCHMARK_REGISTER_H #define BENCHMARK_REGISTER_H +#include #include #include diff --git a/src/check.h b/src/check.h index 1129e814..c1cd5e85 100644 --- a/src/check.h +++ b/src/check.h @@ -9,6 +9,23 @@ #include "internal_macros.h" #include "log.h" +#if defined(__GNUC__) || defined(__clang__) +#define BENCHMARK_NOEXCEPT noexcept +#define BENCHMARK_NOEXCEPT_OP(x) noexcept(x) +#elif defined(_MSC_VER) && !defined(__clang__) +#if _MSC_VER >= 1900 +#define BENCHMARK_NOEXCEPT noexcept +#define BENCHMARK_NOEXCEPT_OP(x) noexcept(x) +#else +#define BENCHMARK_NOEXCEPT +#define BENCHMARK_NOEXCEPT_OP(x) +#endif +#define __func__ __FUNCTION__ +#else +#define BENCHMARK_NOEXCEPT +#define BENCHMARK_NOEXCEPT_OP(x) +#endif + namespace benchmark { namespace internal { diff --git a/src/internal_macros.h b/src/internal_macros.h index 72ba54ba..1fe1eb6a 100644 --- a/src/internal_macros.h +++ b/src/internal_macros.h @@ -1,8 +1,6 @@ #ifndef BENCHMARK_INTERNAL_MACROS_H_ #define BENCHMARK_INTERNAL_MACROS_H_ -#include "benchmark/benchmark.h" - /* Needed to detect STL */ #include diff --git a/src/log.h b/src/log.h index 48c071ad..45701667 100644 --- a/src/log.h +++ b/src/log.h @@ -4,7 +4,12 @@ #include #include -#include "benchmark/benchmark.h" +// NOTE: this is also defined in benchmark.h but we're trying to avoid a +// dependency. +// The _MSVC_LANG check should detect Visual Studio 2015 Update 3 and newer. +#if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L) +#define BENCHMARK_HAS_CXX11 +#endif namespace benchmark { namespace internal { @@ -23,7 +28,16 @@ class LogType { private: LogType(std::ostream* out) : out_(out) {} std::ostream* out_; - BENCHMARK_DISALLOW_COPY_AND_ASSIGN(LogType); + + // NOTE: we could use BENCHMARK_DISALLOW_COPY_AND_ASSIGN but we shouldn't have + // a dependency on benchmark.h from here. +#ifndef BENCHMARK_HAS_CXX11 + LogType(const LogType&); + LogType& operator=(const LogType&); +#else + LogType(const LogType&) = delete; + LogType& operator=(const LogType&) = delete; +#endif }; template @@ -47,13 +61,13 @@ inline int& LogLevel() { } inline LogType& GetNullLogInstance() { - static LogType log(nullptr); - return log; + static LogType null_log((std::ostream*)nullptr); + return null_log; } inline LogType& GetErrorLogInstance() { - static LogType log(&std::clog); - return log; + static LogType error_log(&std::clog); + return error_log; } inline LogType& GetLogInstanceForLevel(int level) { diff --git a/src/string_util.h b/src/string_util.h index 41458618..37bdd2e9 100644 --- a/src/string_util.h +++ b/src/string_util.h @@ -4,8 +4,10 @@ #include #include #include +#include #include "benchmark/export.h" +#include "check.h" #include "internal_macros.h" namespace benchmark { diff --git a/test/benchmark_gtest.cc b/test/benchmark_gtest.cc index a6919be3..2c9e555d 100644 --- a/test/benchmark_gtest.cc +++ b/test/benchmark_gtest.cc @@ -3,6 +3,7 @@ #include #include "../src/benchmark_register.h" +#include "benchmark/benchmark.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -135,8 +136,7 @@ TEST(AddRangeTest, Simple8) { } TEST(AddCustomContext, Simple) { - std::map *&global_context = - internal::GetGlobalContext(); + std::map *&global_context = GetGlobalContext(); EXPECT_THAT(global_context, nullptr); AddCustomContext("foo", "bar"); @@ -151,8 +151,7 @@ TEST(AddCustomContext, Simple) { } TEST(AddCustomContext, DuplicateKey) { - std::map *&global_context = - internal::GetGlobalContext(); + std::map *&global_context = GetGlobalContext(); EXPECT_THAT(global_context, nullptr); AddCustomContext("foo", "bar");