Skip to content

Commit

Permalink
Add codecov.io coverage tracking
Browse files Browse the repository at this point in the history
* Every Linux build tracks coverage when running Debug mode
* OS X not supported yet (Future WIP)
* Our own unit tests, non-default reporters and Clara are ignored
  • Loading branch information
horenmar committed Nov 27, 2017
1 parent db44964 commit e344984
Show file tree
Hide file tree
Showing 7 changed files with 892 additions and 26 deletions.
69 changes: 43 additions & 26 deletions .travis.yml
Expand Up @@ -17,15 +17,15 @@ matrix:
addons:
apt:
sources: *all_sources
packages: ['valgrind', 'clang-3.5']
packages: ['valgrind', 'lcov', 'clang-3.5']
env: COMPILER='clang++-3.5' VALGRIND=1

- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['valgrind', 'clang-3.6']
packages: ['valgrind', 'lcov', 'clang-3.6']
env: COMPILER='clang++-3.6' VALGRIND=1

# Travis's containers do not seem to have Clang 3.7 in apt, no matter what sources I add.
Expand All @@ -42,31 +42,31 @@ matrix:
addons:
apt:
sources: *all_sources
packages: ['valgrind', 'clang-3.8']
packages: ['valgrind', 'lcov', 'clang-3.8']
env: COMPILER='clang++-3.8' VALGRIND=1

- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['clang-3.9', 'valgrind']
packages: ['clang-3.9', 'valgrind', 'lcov']
env: COMPILER='clang++-3.9' VALGRIND=1

- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['clang-4.0', 'valgrind']
packages: ['clang-4.0', 'valgrind', 'lcov']
env: COMPILER='clang++-4.0' VALGRIND=1

- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['clang-5.0', 'valgrind']
packages: ['clang-5.0', 'valgrind', 'lcov']
env: COMPILER='clang++-5.0' VALGRIND=1

# 2/ Linux GCC Builds
Expand All @@ -75,47 +75,47 @@ matrix:
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['valgrind', 'g++-4.8']
packages: ['valgrind', 'lcov', 'g++-4.8']
env: COMPILER='g++-4.8' VALGRIND=1

- os: linux
compiler: gcc
addons:
apt:
sources: *all_sources
packages: ['valgrind', 'g++-4.9']
packages: ['valgrind', 'lcov', 'g++-4.9']
env: COMPILER='g++-4.9' VALGRIND=1

- os: linux
compiler: gcc
addons:
apt:
sources: *all_sources
packages: ['valgrind', 'g++-5']
packages: ['valgrind', 'lcov', 'g++-5']
env: COMPILER='g++-5' VALGRIND=1

- os: linux
compiler: gcc
addons: &gcc6
apt:
sources: *all_sources
packages: ['valgrind', 'g++-6']
packages: ['valgrind', 'lcov', 'g++-6']
env: COMPILER='g++-6' VALGRIND=1

- os: linux
compiler: gcc
addons: &gcc7
apt:
sources: *all_sources
packages: ['valgrind', 'g++-7']
packages: ['valgrind', 'lcov', 'g++-7']
env: COMPILER='g++-7' VALGRIND=1

# 3b/ Linux C++14 Clang builds
- os: linux
compiler: clang
addons:
apt:
packages: ['clang-3.8', 'valgrind', 'libstdc++-6-dev']
packages: ['clang-3.8', 'valgrind', 'lcov', 'libstdc++-6-dev']
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty
Expand All @@ -126,23 +126,23 @@ matrix:
addons:
apt:
sources: *all_sources
packages: ['clang-3.9', 'valgrind', 'libstdc++-6-dev']
packages: ['clang-3.9', 'valgrind', 'lcov', 'libstdc++-6-dev']
env: COMPILER='clang++-3.9' CPP14=1 VALGRIND=1

- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['clang-4.0', 'valgrind', 'libstdc++-6-dev']
packages: ['clang-4.0', 'valgrind', 'lcov', 'libstdc++-6-dev']
env: COMPILER='clang++-4.0' CPP14=1 VALGRIND=1

- os: linux
compiler: clang
addons:
apt:
sources: *all_sources
packages: ['clang-5.0', 'valgrind', 'libstdc++-6-dev']
packages: ['clang-5.0', 'valgrind', 'lcov', 'libstdc++-6-dev']
env: COMPILER='clang++-5.0' CPP14=1 VALGRIND=1


Expand Down Expand Up @@ -183,6 +183,7 @@ matrix:
compiler: clang
env: COMPILER='clang++' USE_CPP14=1


install:
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
- mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
Expand All @@ -192,7 +193,13 @@ install:
mkdir cmake && travis_retry wget --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake
export PATH=${DEPS_DIR}/cmake/bin:${PATH}
elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
which cmake || brew install cmake
for pkg in cmake lcov; do
if brew list -1 | grep -q "^${pkg}\$"; then
brew outdated $pkg || brew upgrade $pkg;
else
brew install $pkg;
fi
done
fi
before_script:
Expand All @@ -201,15 +208,25 @@ before_script:
# Regenerate single header file, so it is tested in the examples...
- python scripts/generateSingleHeader.py

# Use Debug builds for running Valgrind and building examples
- cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DUSE_VALGRIND=${VALGRIND} -DBUILD_EXAMPLES=ON
# Check that we don't miscompile with optimalizations...
- cmake -H. -BBuild-Release -DCMAKE_BUILD_TYPE=Release -Wdev -DUSE_CPP14=${CPP14}
- |
# Use Debug builds for running Valgrind and building examples
cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DUSE_VALGRIND=${VALGRIND} -DBUILD_EXAMPLES=ON -DENABLE_COVERAGE=ON
# Don't bother with release build for coverage build
cmake -H. -BBuild-Release -DCMAKE_BUILD_TYPE=Release -Wdev -DUSE_CPP14=${CPP14}
script:
- cd Build-Debug
- make -j 2
- CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
- cd ../Build-Release
- make -j 2
- CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
- |
cd Build-Debug
make -j 2
CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
# Coverage collection does not work for OS X atm
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
make gcov
make lcov
bash <(curl -s https://codecov.io/bash) -X gcov || echo "Codecov did not collect coverage reports"
fi
# Go to release build
cd ../Build-Release
make -j 2
CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
157 changes: 157 additions & 0 deletions CMake/FindGcov.cmake
@@ -0,0 +1,157 @@
# This file is part of CMake-codecov.
#
# Copyright (c)
# 2015-2017 RWTH Aachen University, Federal Republic of Germany
#
# See the LICENSE file in the package base directory for details
#
# Written by Alexander Haase, alexander.haase@rwth-aachen.de
#


# include required Modules
include(FindPackageHandleStandardArgs)


# Search for gcov binary.
set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET})
set(CMAKE_REQUIRED_QUIET ${codecov_FIND_QUIETLY})

get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach (LANG ${ENABLED_LANGUAGES})
# Gcov evaluation is dependend on the used compiler. Check gcov support for
# each compiler that is used. If gcov binary was already found for this
# compiler, do not try to find it again.
if (NOT GCOV_${CMAKE_${LANG}_COMPILER_ID}_BIN)
get_filename_component(COMPILER_PATH "${CMAKE_${LANG}_COMPILER}" PATH)

if ("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "GNU")
# Some distributions like OSX (homebrew) ship gcov with the compiler
# version appended as gcov-x. To find this binary we'll build the
# suggested binary name with the compiler version.
string(REGEX MATCH "^[0-9]+" GCC_VERSION
"${CMAKE_${LANG}_COMPILER_VERSION}")

find_program(GCOV_BIN NAMES gcov-${GCC_VERSION} gcov
HINTS ${COMPILER_PATH})

elseif ("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "Clang")
# Some distributions like Debian ship llvm-cov with the compiler
# version appended as llvm-cov-x.y. To find this binary we'll build
# the suggested binary name with the compiler version.
string(REGEX MATCH "^[0-9]+.[0-9]+" LLVM_VERSION
"${CMAKE_${LANG}_COMPILER_VERSION}")

# llvm-cov prior version 3.5 seems to be not working with coverage
# evaluation tools, but these versions are compatible with the gcc
# gcov tool.
if(LLVM_VERSION VERSION_GREATER 3.4)
find_program(LLVM_COV_BIN NAMES "llvm-cov-${LLVM_VERSION}"
"llvm-cov" HINTS ${COMPILER_PATH})
mark_as_advanced(LLVM_COV_BIN)

if (LLVM_COV_BIN)
find_program(LLVM_COV_WRAPPER "llvm-cov-wrapper" PATHS
${CMAKE_MODULE_PATH})
if (LLVM_COV_WRAPPER)
set(GCOV_BIN "${LLVM_COV_WRAPPER}" CACHE FILEPATH "")

# set additional parameters
set(GCOV_${CMAKE_${LANG}_COMPILER_ID}_ENV
"LLVM_COV_BIN=${LLVM_COV_BIN}" CACHE STRING
"Environment variables for llvm-cov-wrapper.")
mark_as_advanced(GCOV_${CMAKE_${LANG}_COMPILER_ID}_ENV)
endif ()
endif ()
endif ()

if (NOT GCOV_BIN)
# Fall back to gcov binary if llvm-cov was not found or is
# incompatible. This is the default on OSX, but may crash on
# recent Linux versions.
find_program(GCOV_BIN gcov HINTS ${COMPILER_PATH})
endif ()
endif ()


if (GCOV_BIN)
set(GCOV_${CMAKE_${LANG}_COMPILER_ID}_BIN "${GCOV_BIN}" CACHE STRING
"${LANG} gcov binary.")

if (NOT CMAKE_REQUIRED_QUIET)
message("-- Found gcov evaluation for "
"${CMAKE_${LANG}_COMPILER_ID}: ${GCOV_BIN}")
endif()

unset(GCOV_BIN CACHE)
endif ()
endif ()
endforeach ()




# Add a new global target for all gcov targets. This target could be used to
# generate the gcov files for the whole project instead of calling <TARGET>-gcov
# for each target.
if (NOT TARGET gcov)
add_custom_target(gcov)
endif (NOT TARGET gcov)



# This function will add gcov evaluation for target <TNAME>. Only sources of
# this target will be evaluated and no dependencies will be added. It will call
# Gcov on any source file of <TNAME> once and store the gcov file in the same
# directory.
function (add_gcov_target TNAME)
set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir)

# We don't have to check, if the target has support for coverage, thus this
# will be checked by add_coverage_target in Findcoverage.cmake. Instead we
# have to determine which gcov binary to use.
get_target_property(TSOURCES ${TNAME} SOURCES)
set(SOURCES "")
set(TCOMPILER "")
foreach (FILE ${TSOURCES})
codecov_path_of_source(${FILE} FILE)
if (NOT "${FILE}" STREQUAL "")
codecov_lang_of_source(${FILE} LANG)
if (NOT "${LANG}" STREQUAL "")
list(APPEND SOURCES "${FILE}")
set(TCOMPILER ${CMAKE_${LANG}_COMPILER_ID})
endif ()
endif ()
endforeach ()

# If no gcov binary was found, coverage data can't be evaluated.
if (NOT GCOV_${TCOMPILER}_BIN)
message(WARNING "No coverage evaluation binary found for ${TCOMPILER}.")
return()
endif ()

set(GCOV_BIN "${GCOV_${TCOMPILER}_BIN}")
set(GCOV_ENV "${GCOV_${TCOMPILER}_ENV}")


set(BUFFER "")
foreach(FILE ${SOURCES})
get_filename_component(FILE_PATH "${TDIR}/${FILE}" PATH)

# call gcov
add_custom_command(OUTPUT ${TDIR}/${FILE}.gcov
COMMAND ${GCOV_ENV} ${GCOV_BIN} ${TDIR}/${FILE}.gcno > /dev/null
DEPENDS ${TNAME} ${TDIR}/${FILE}.gcno
WORKING_DIRECTORY ${FILE_PATH}
)

list(APPEND BUFFER ${TDIR}/${FILE}.gcov)
endforeach()


# add target for gcov evaluation of <TNAME>
add_custom_target(${TNAME}-gcov DEPENDS ${BUFFER})

# add evaluation target to the global gcov target.
add_dependencies(gcov ${TNAME}-gcov)
endfunction (add_gcov_target)

0 comments on commit e344984

Please sign in to comment.