From fc883f674202353d659c13d5f0d7f8ecf5c020dd Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Thu, 30 Apr 2015 14:04:28 +0100 Subject: [PATCH 1/9] Improve the CMake C++ flag checker This checks the flag on the compiler AND linker which allows it to work with flags such as -flto and -fsanitize=address --- cmake/AddCXXCompilerFlag.cmake | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/cmake/AddCXXCompilerFlag.cmake b/cmake/AddCXXCompilerFlag.cmake index 7c0f5a31..870f11ae 100644 --- a/cmake/AddCXXCompilerFlag.cmake +++ b/cmake/AddCXXCompilerFlag.cmake @@ -20,18 +20,17 @@ set(__add_cxx_compiler_flag INCLUDED) include(CheckCXXCompilerFlag) function(add_cxx_compiler_flag FLAG) - if(ARGV1) - set(VARIANT ${ARGV1}) - string(TOLOWER ${VARIANT} VARIANT) - set(VARIANT " ${VARIANT}") - endif() - string(TOUPPER "HAVE_${FLAG}" SANITIZED_FLAG) + string(TOUPPER "HAVE_CXX_FLAG_${FLAG}" SANITIZED_FLAG) + string(REPLACE "+" "X" SANITIZED_FLAG ${SANITIZED_FLAG}) string(REGEX REPLACE "[^A-Za-z_0-9]" "_" SANITIZED_FLAG ${SANITIZED_FLAG}) string(REGEX REPLACE "_+" "_" SANITIZED_FLAG ${SANITIZED_FLAG}) - check_cxx_compiler_flag(${FLAG} ${SANITIZED_FLAG}) + set(CMAKE_REQUIRED_FLAGS "${FLAG}") + check_cxx_compiler_flag("" ${SANITIZED_FLAG}) if(${SANITIZED_FLAG}) - string(REGEX REPLACE "[^A-Za-z_0-9]" "_" VARIANT "${VARIANT}") - string(TOUPPER "${VARIANT}" VARIANT) + set(VARIANT ${ARGV1}) + if(ARGV1) + string(TOUPPER "_${VARIANT}" VARIANT) + endif() set(CMAKE_CXX_FLAGS${VARIANT} "${CMAKE_CXX_FLAGS${VARIANT}} ${FLAG}" PARENT_SCOPE) endif() endfunction() From 7418bbbbacaeebaac4281da075440756ea2c778f Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Thu, 30 Apr 2015 14:10:06 +0100 Subject: [PATCH 2/9] Only warn on errors in release mode This improves development iterations when working in debug mode as you don't have to fix up warnings to get the code to compile. Once a feature is complete you can then run a release build and fix up all the warnings. --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cb57f3ed..65d807d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,8 @@ endif() add_cxx_compiler_flag(-Wall) add_cxx_compiler_flag(-Wextra) add_cxx_compiler_flag(-Wshadow) -add_cxx_compiler_flag(-Werror) +add_cxx_compiler_flag(-Werror RELEASE) +add_cxx_compiler_flag(-pedantic) add_cxx_compiler_flag(-pedantic-errors) add_cxx_compiler_flag(-Wshorten-64-to-32) add_cxx_compiler_flag(-Wfloat-equal) From bb23a9b9f2c32a1557378fd2234273e705789eb9 Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Thu, 30 Apr 2015 14:10:52 +0100 Subject: [PATCH 3/9] Compile with link time optimisation Can provide speed improvements --- CMakeLists.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 65d807d0..6a9a4493 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required (VERSION 2.8.11) project (benchmark) option(BENCHMARK_ENABLE_TESTING "Enable testing of the benchmark library." ON) +option(BENCHMARK_ENABLE_LTO "Enable link time optimisation of the benchmark library." OFF) # Make sure we can import out CMake functions list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") @@ -41,9 +42,25 @@ add_cxx_compiler_flag(-pedantic-errors) add_cxx_compiler_flag(-Wshorten-64-to-32) add_cxx_compiler_flag(-Wfloat-equal) add_cxx_compiler_flag(-Wzero-as-null-pointer-constant) + # Release flags add_cxx_compiler_flag(-fno-strict-aliasing RELEASE) +# Link time optimisation +if (BENCHMARK_ENABLE_LTO) + add_cxx_compiler_flag(-flto) + if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") + find_program(GCC_AR gcc-ar) + if (GCC_AR) + set(CMAKE_AR ${GCC_AR}) + endif() + find_program(GCC_RANLIB gcc-ranlib) + if (GCC_RANLIB) + set(CMAKE_RANLIB ${GCC_RANLIB}) + endif() + endif() +endif() + add_cxx_compiler_flag(-Wthread-safety) if (HAVE_WTHREAD_SAFETY) add_definitions(-DHAVE_WTHREAD_SAFETY) From e44ee2d0054e2f314eef8f135de599aad651ecac Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Thu, 30 Apr 2015 14:14:27 +0100 Subject: [PATCH 4/9] Group common C++ flags --- CMakeLists.txt | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a9a4493..dd9c6354 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,11 @@ add_cxx_compiler_flag(-pedantic-errors) add_cxx_compiler_flag(-Wshorten-64-to-32) add_cxx_compiler_flag(-Wfloat-equal) add_cxx_compiler_flag(-Wzero-as-null-pointer-constant) +add_cxx_compiler_flag(-Wthread-safety) +if (HAVE_WTHREAD_SAFETY) + add_definitions(-DHAVE_WTHREAD_SAFETY) + cxx_feature_check(THREAD_SAFETY_ATTRIBUTES) +endif() # Release flags add_cxx_compiler_flag(-fno-strict-aliasing RELEASE) @@ -61,12 +66,6 @@ if (BENCHMARK_ENABLE_LTO) endif() endif() -add_cxx_compiler_flag(-Wthread-safety) -if (HAVE_WTHREAD_SAFETY) - add_definitions(-DHAVE_WTHREAD_SAFETY) - cxx_feature_check(THREAD_SAFETY_ATTRIBUTES) -endif() - # C++ feature checks cxx_feature_check(STD_REGEX) cxx_feature_check(GNU_POSIX_REGEX) From 8b5016034f2ffa04dbf75718d7fdd8bb20a933f5 Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Thu, 30 Apr 2015 14:31:50 +0100 Subject: [PATCH 5/9] Ignore tests --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index b538747d..f7dcf8f3 100644 --- a/.gitignore +++ b/.gitignore @@ -22,8 +22,7 @@ Makefile # in-source build. bin/ lib/ -/test/benchmark_test -/test/re_test +/test/*_test # exuberant ctags. tags From 3314aa43c215b1543a8d0330af4954f0c29792ae Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Thu, 30 Apr 2015 14:40:37 +0100 Subject: [PATCH 6/9] Allow the user to set the C++ standard to use This is useful to test the library at different standard levels. Currently doesn't search for C++14 in 'auto' mode. Can enable in the future --- CMakeLists.txt | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dd9c6354..4f09ceae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,18 +18,16 @@ message("-- Version: ${VERSION}") set(GENERIC_LIB_VERSION ${VERSION}) string(SUBSTRING ${VERSION} 0 1 GENERIC_LIB_SOVERSION) -# Try and enable C++11. Don't use C++14 because it doesn't work in some -# configurations. +# Import our CMake modules include(CheckCXXCompilerFlag) include(AddCXXCompilerFlag) include(CXXFeatureCheck) -check_cxx_compiler_flag(-std=c++11 HAVE_FLAG_CXX_11) -check_cxx_compiler_flag(-std=c++0x HAVE_FLAG_CXX_0X) -if (HAVE_FLAG_CXX_11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -elseif (HAVE_FLAG_CXX_0X) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") +# Try and enable C++11. Don't use C++14 because it doesn't work in some +# configurations. +add_cxx_compiler_flag(-std=c++11) +if (NOT HAVE_CXX_FLAG_STD_CXX11) + add_cxx_compiler_flag(-std=c++0x) endif() # Turn compiler warnings up to 11 From 36c1eb6975827e89a906e2dae90e92ee4a0f2bfb Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Thu, 30 Apr 2015 14:28:04 +0100 Subject: [PATCH 7/9] Coverage support with LCOV and GCOV This patch adds a `coverage` target that allows coverage statisitics to be retrieved for the project. It requires that lcov and gcov is installed and that the generator is unix makefiles but this can be improved upon in future releases. To make it work use the coverage build type: ``` cmake -DCMAKE_BUILD_TYPE=Coverage . make coverage ``` --- .gitignore | 4 ++++ CMakeLists.txt | 21 +++++++++++++++++++++ test/CMakeLists.txt | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/.gitignore b/.gitignore index f7dcf8f3..3c1b4f21 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,10 @@ *.pyc __pycache__ +# lcov +*.lcov +/lcov + # cmake files. /Testing CMakeCache.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f09ceae..20aec17e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,6 +64,27 @@ if (BENCHMARK_ENABLE_LTO) endif() endif() +# Coverage build type +set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING + "Flags used by the C++ compiler during coverage builds." + FORCE) +set(CMAKE_EXE_LINKER_FLAGS_COVERAGE + "${CMAKE_EXE_LINKER_FLAGS_DEBUG}" CACHE STRING + "Flags used for linking binaries during coverage builds." + FORCE) +set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE + "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE STRING + "Flags used by the shared libraries linker during coverage builds." + FORCE) +mark_as_advanced( + CMAKE_CXX_FLAGS_COVERAGE + CMAKE_EXE_LINKER_FLAGS_COVERAGE + CMAKE_SHARED_LINKER_FLAGS_COVERAGE) +set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING + "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage." + FORCE) +add_cxx_compiler_flag(--coverage COVERAGE) + # C++ feature checks cxx_feature_check(STD_REGEX) cxx_feature_check(GNU_POSIX_REGEX) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7c4eae19..5a63b170 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -43,3 +43,45 @@ compile_benchmark_test(cxx03_test) set_target_properties(cxx03_test PROPERTIES COMPILE_FLAGS "${CXX03_FLAGS}") add_test(cxx03 cxx03_test --benchmark_min_time=0.01) + +# Add the coverage command(s) +string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER) +if (${CMAKE_BUILD_TYPE_LOWER} MATCHES "coverage") + find_program(GCOV gcov) + find_program(LCOV lcov) + find_program(GENHTML genhtml) + find_program(CTEST ctest) + if (GCOV AND LCOV AND GENHTML AND CTEST AND HAVE_CXX_FLAG_COVERAGE) + add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/lcov/index.html + COMMAND ${LCOV} -q -z -d . + COMMAND ${LCOV} -q --no-external -c -b "${CMAKE_SOURCE_DIR}" -d . -o before.lcov -i + COMMAND ${CTEST} --force-new-ctest-process + COMMAND ${LCOV} -q --no-external -c -b "${CMAKE_SOURCE_DIR}" -d . -o after.lcov + COMMAND ${LCOV} -q -a before.lcov -a after.lcov --output-file final.lcov + COMMAND ${LCOV} -q -r final.lcov "'${CMAKE_SOURCE_DIR}/test/*'" -o final.lcov + COMMAND ${GENHTML} final.lcov -o lcov --demangle-cpp --sort -p "${CMAKE_BINARY_DIR}" -t benchmark + DEPENDS filter_test benchmark_test options_test basic_test fixture_test cxx03_test + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Running LCOV" + ) + add_custom_target(coverage + DEPENDS ${CMAKE_BINARY_DIR}/lcov/index.html + COMMENT "LCOV report at lcov/index.html" + ) + message(STATUS "Coverage command added") + else() + if (HAVE_CXX_FLAG_COVERAGE) + set(CXX_FLAG_COVERAGE_MESSAGE supported) + else() + set(CXX_FLAG_COVERAGE_MESSAGE unavailable) + endif() + message(WARNING + "Coverage not available:\n" + " gcov: ${GCOV}\n" + " lcov: ${LCOV}\n" + " genhtml: ${GENHTML}\n" + " ctest: ${CTEST}\n" + " --coverage flag: ${CXX_FLAG_COVERAGE_MESSAGE}") + endif() +endif() From 344775db633aef502a1ec9be967a2730a1e0c631 Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Tue, 5 May 2015 12:13:20 +0100 Subject: [PATCH 8/9] Enable strict aliasing warnings --- CMakeLists.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 20aec17e..911f3096 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,15 +40,16 @@ add_cxx_compiler_flag(-pedantic-errors) add_cxx_compiler_flag(-Wshorten-64-to-32) add_cxx_compiler_flag(-Wfloat-equal) add_cxx_compiler_flag(-Wzero-as-null-pointer-constant) +add_cxx_compiler_flag(-fstrict-aliasing) +if (HAVE_CXX_FLAG_FSTRICT_ALIASING) + add_cxx_compiler_flag(-Wstrict-aliasing) +endif() add_cxx_compiler_flag(-Wthread-safety) if (HAVE_WTHREAD_SAFETY) add_definitions(-DHAVE_WTHREAD_SAFETY) cxx_feature_check(THREAD_SAFETY_ATTRIBUTES) endif() -# Release flags -add_cxx_compiler_flag(-fno-strict-aliasing RELEASE) - # Link time optimisation if (BENCHMARK_ENABLE_LTO) add_cxx_compiler_flag(-flto) From ef479921251d6104ca590ddf0d85c331fdbf803a Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Tue, 12 May 2015 16:17:38 +0100 Subject: [PATCH 9/9] Added coveralls support --- .travis.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.travis.yml b/.travis.yml index 91e82ebe..8b138ce1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,8 @@ language: cpp # travis-ci.org more readable. matrix: include: + - compiler: gcc + env: COMPILER=g++-4.6 STD=c++0x BUILD_TYPE=Coverage - compiler: gcc env: COMPILER=g++-4.6 STD=c++0x BUILD_TYPE=Debug - compiler: gcc @@ -21,7 +23,19 @@ before_script: - source .travis-setup.sh - mkdir build && cd build +install: + - if [ "${BUILD_TYPE}" == "Coverage" -a "${TRAVIS_OS_NAME}" == "linux" ]; then + PATH=~/.local/bin:${PATH}; + pip install --user --upgrade pip; + pip install --user cpp-coveralls; + fi + script: - cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_CXX_FLAGS="-std=${STD}" - make - make CTEST_OUTPUT_ON_FAILURE=1 test + +after_success: + - if [ "${BUILD_TYPE}" == "Coverage" -a "${TRAVIS_OS_NAME}" == "linux" ]; then + coveralls --include src --include include --gcov-options '\-lp' --root .. --build-root .; + fi