1f2483f8bSJoakim Soderberg# 2f2483f8bSJoakim Soderberg# Boost Software License - Version 1.0 - August 17th, 2003 3f2483f8bSJoakim Soderberg# 4f2483f8bSJoakim Soderberg# Permission is hereby granted, free of charge, to any person or organization 5f2483f8bSJoakim Soderberg# obtaining a copy of the software and accompanying documentation covered by 6f2483f8bSJoakim Soderberg# this license (the "Software") to use, reproduce, display, distribute, 7f2483f8bSJoakim Soderberg# execute, and transmit the Software, and to prepare derivative works of the 8f2483f8bSJoakim Soderberg# Software, and to permit third-parties to whom the Software is furnished to 9f2483f8bSJoakim Soderberg# do so, all subject to the following: 10f2483f8bSJoakim Soderberg# 11f2483f8bSJoakim Soderberg# The copyright notices in the Software and this entire statement, including 12f2483f8bSJoakim Soderberg# the above license grant, this restriction and the following disclaimer, 13f2483f8bSJoakim Soderberg# must be included in all copies of the Software, in whole or in part, and 14f2483f8bSJoakim Soderberg# all derivative works of the Software, unless such copies or derivative 15f2483f8bSJoakim Soderberg# works are solely in the form of machine-executable object code generated by 16f2483f8bSJoakim Soderberg# a source language processor. 17f2483f8bSJoakim Soderberg# 18f2483f8bSJoakim Soderberg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19f2483f8bSJoakim Soderberg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20f2483f8bSJoakim Soderberg# FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 21f2483f8bSJoakim Soderberg# SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 22f2483f8bSJoakim Soderberg# FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 23f2483f8bSJoakim Soderberg# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24f2483f8bSJoakim Soderberg# DEALINGS IN THE SOFTWARE. 25f2483f8bSJoakim Soderberg# 26f2483f8bSJoakim Soderberg# 2012-01-31, Lars Bilke 27f2483f8bSJoakim Soderberg# - Enable Code Coverage 28f2483f8bSJoakim Soderberg# 29f2483f8bSJoakim Soderberg# 2013-09-17, Joakim Söderberg 30f2483f8bSJoakim Soderberg# - Added support for Clang. 31f2483f8bSJoakim Soderberg# - Some additional usage instructions. 32f2483f8bSJoakim Soderberg# 33*40fbffc0SAzat Khuzhin# 2016-11-02, Azat Khuzhin 34*40fbffc0SAzat Khuzhin# - Adopt for C compiler only (libevent) 35*40fbffc0SAzat Khuzhin# 36f2483f8bSJoakim Soderberg# USAGE: 37f2483f8bSJoakim Soderberg# 1. Copy this file into your cmake modules path. 38f2483f8bSJoakim Soderberg# 39f2483f8bSJoakim Soderberg# 2. Add the following line to your CMakeLists.txt: 40f2483f8bSJoakim Soderberg# INCLUDE(CodeCoverage) 41f2483f8bSJoakim Soderberg# 42f2483f8bSJoakim Soderberg# 3. Set compiler flags to turn off optimization and enable coverage: 43f2483f8bSJoakim Soderberg# SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") 44f2483f8bSJoakim Soderberg# SET(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") 45f2483f8bSJoakim Soderberg# 46f2483f8bSJoakim Soderberg# 3. Use the function SETUP_TARGET_FOR_COVERAGE to create a custom make target 47f2483f8bSJoakim Soderberg# which runs your test executable and produces a lcov code coverage report: 48f2483f8bSJoakim Soderberg# Example: 49f2483f8bSJoakim Soderberg# SETUP_TARGET_FOR_COVERAGE( 50f2483f8bSJoakim Soderberg# my_coverage_target # Name for custom target. 51f2483f8bSJoakim Soderberg# test_driver # Name of the test driver executable that runs the tests. 52f2483f8bSJoakim Soderberg# # NOTE! This should always have a ZERO as exit code 53f2483f8bSJoakim Soderberg# # otherwise the coverage generation will not complete. 54f2483f8bSJoakim Soderberg# coverage # Name of output directory. 55f2483f8bSJoakim Soderberg# ) 56f2483f8bSJoakim Soderberg# 57f2483f8bSJoakim Soderberg# 4. Build a Debug build: 58f2483f8bSJoakim Soderberg# cmake -DCMAKE_BUILD_TYPE=Debug .. 59f2483f8bSJoakim Soderberg# make 60f2483f8bSJoakim Soderberg# make my_coverage_target 61f2483f8bSJoakim Soderberg# 62f2483f8bSJoakim Soderberg# 63f2483f8bSJoakim Soderberg 64f2483f8bSJoakim Soderberg# Check prereqs 65f2483f8bSJoakim SoderbergFIND_PROGRAM( GCOV_PATH gcov ) 66f2483f8bSJoakim SoderbergFIND_PROGRAM( LCOV_PATH lcov ) 67f2483f8bSJoakim SoderbergFIND_PROGRAM( GENHTML_PATH genhtml ) 68f2483f8bSJoakim SoderbergFIND_PROGRAM( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/tests) 69f2483f8bSJoakim Soderberg 70f2483f8bSJoakim SoderbergIF(NOT GCOV_PATH) 71f2483f8bSJoakim Soderberg MESSAGE(FATAL_ERROR "gcov not found! Aborting...") 72f2483f8bSJoakim SoderbergENDIF() # NOT GCOV_PATH 73f2483f8bSJoakim Soderberg 74*40fbffc0SAzat KhuzhinIF(NOT CMAKE_COMPILER_IS_GNUCC) 75f2483f8bSJoakim Soderberg # Clang version 3.0.0 and greater now supports gcov as well. 76f2483f8bSJoakim Soderberg MESSAGE(WARNING "Compiler is not GNU gcc! Clang Version 3.0.0 and greater supports gcov as well, but older versions don't.") 77f2483f8bSJoakim Soderberg 78*40fbffc0SAzat Khuzhin IF(NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") 79f2483f8bSJoakim Soderberg MESSAGE(FATAL_ERROR "Compiler is not GNU gcc! Aborting...") 80f2483f8bSJoakim Soderberg ENDIF() 81f7805939SJoakim SoderbergENDIF() # NOT CMAKE_COMPILER_IS_GNUCC 82f2483f8bSJoakim Soderberg 83f2483f8bSJoakim SoderbergIF ( NOT CMAKE_BUILD_TYPE STREQUAL "Debug" ) 84f2483f8bSJoakim Soderberg MESSAGE( WARNING "Code coverage results with an optimized (non-Debug) build may be misleading" ) 85f2483f8bSJoakim SoderbergENDIF() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug" 86f2483f8bSJoakim Soderberg 87f2483f8bSJoakim Soderberg 88f2483f8bSJoakim Soderberg# Param _targetname The name of new the custom make target 89f2483f8bSJoakim Soderberg# Param _testrunner The name of the target which runs the tests. 90f2483f8bSJoakim Soderberg# MUST return ZERO always, even on errors. 91f2483f8bSJoakim Soderberg# If not, no coverage report will be created! 92f2483f8bSJoakim Soderberg# Param _outputname lcov output is generated as _outputname.info 93f2483f8bSJoakim Soderberg# HTML report is generated in _outputname/index.html 94f2483f8bSJoakim Soderberg# Optional fourth parameter is passed as arguments to _testrunner 95f2483f8bSJoakim Soderberg# Pass them in list form, e.g.: "-j;2" for -j 2 96f2483f8bSJoakim SoderbergFUNCTION(SETUP_TARGET_FOR_COVERAGE _targetname _testrunner _outputname) 97f2483f8bSJoakim Soderberg 98f2483f8bSJoakim Soderberg IF(NOT LCOV_PATH) 99f2483f8bSJoakim Soderberg MESSAGE(FATAL_ERROR "lcov not found! Aborting...") 100f2483f8bSJoakim Soderberg ENDIF() # NOT LCOV_PATH 101f2483f8bSJoakim Soderberg 102f2483f8bSJoakim Soderberg IF(NOT GENHTML_PATH) 103f2483f8bSJoakim Soderberg MESSAGE(FATAL_ERROR "genhtml not found! Aborting...") 104f2483f8bSJoakim Soderberg ENDIF() # NOT GENHTML_PATH 105f2483f8bSJoakim Soderberg 106f2483f8bSJoakim Soderberg # Setup target 107f2483f8bSJoakim Soderberg ADD_CUSTOM_TARGET(${_targetname} 108f2483f8bSJoakim Soderberg 109f2483f8bSJoakim Soderberg # Cleanup lcov 110f2483f8bSJoakim Soderberg ${LCOV_PATH} --directory . --zerocounters 111f2483f8bSJoakim Soderberg 112f2483f8bSJoakim Soderberg # Run tests 113f2483f8bSJoakim Soderberg COMMAND ${_testrunner} ${ARGV3} 114f2483f8bSJoakim Soderberg 115f2483f8bSJoakim Soderberg # Capturing lcov counters and generating report 116f2483f8bSJoakim Soderberg COMMAND ${LCOV_PATH} --directory . --capture --output-file ${_outputname}.info 117f2483f8bSJoakim Soderberg COMMAND ${LCOV_PATH} --remove ${_outputname}.info 'tests/*' '/usr/*' --output-file ${_outputname}.info.cleaned 118f2483f8bSJoakim Soderberg COMMAND ${GENHTML_PATH} -o ${_outputname} ${_outputname}.info.cleaned 119f2483f8bSJoakim Soderberg COMMAND ${CMAKE_COMMAND} -E remove ${_outputname}.info ${_outputname}.info.cleaned 120f2483f8bSJoakim Soderberg 121f2483f8bSJoakim Soderberg WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 122f2483f8bSJoakim Soderberg COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." 123f2483f8bSJoakim Soderberg ) 124f2483f8bSJoakim Soderberg 125f2483f8bSJoakim Soderberg # Show info where to find the report 126f2483f8bSJoakim Soderberg ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD 127f2483f8bSJoakim Soderberg COMMAND ; 128f2483f8bSJoakim Soderberg COMMENT "Open ./${_outputname}/index.html in your browser to view the coverage report." 129f2483f8bSJoakim Soderberg ) 130f2483f8bSJoakim Soderberg 131f2483f8bSJoakim SoderbergENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE 132f2483f8bSJoakim Soderberg 133f2483f8bSJoakim Soderberg# Param _targetname The name of new the custom make target 134f2483f8bSJoakim Soderberg# Param _testrunner The name of the target which runs the tests 135f2483f8bSJoakim Soderberg# Param _outputname cobertura output is generated as _outputname.xml 136f2483f8bSJoakim Soderberg# Optional fourth parameter is passed as arguments to _testrunner 137f2483f8bSJoakim Soderberg# Pass them in list form, e.g.: "-j;2" for -j 2 138f2483f8bSJoakim SoderbergFUNCTION(SETUP_TARGET_FOR_COVERAGE_COBERTURA _targetname _testrunner _outputname) 139f2483f8bSJoakim Soderberg 140f2483f8bSJoakim Soderberg IF(NOT PYTHON_EXECUTABLE) 141f2483f8bSJoakim Soderberg MESSAGE(FATAL_ERROR "Python not found! Aborting...") 142f2483f8bSJoakim Soderberg ENDIF() # NOT PYTHON_EXECUTABLE 143f2483f8bSJoakim Soderberg 144f2483f8bSJoakim Soderberg IF(NOT GCOVR_PATH) 145f2483f8bSJoakim Soderberg MESSAGE(FATAL_ERROR "gcovr not found! Aborting...") 146f2483f8bSJoakim Soderberg ENDIF() # NOT GCOVR_PATH 147f2483f8bSJoakim Soderberg 148f2483f8bSJoakim Soderberg ADD_CUSTOM_TARGET(${_targetname} 149f2483f8bSJoakim Soderberg 150f2483f8bSJoakim Soderberg # Run tests 151f2483f8bSJoakim Soderberg ${_testrunner} ${ARGV3} 152f2483f8bSJoakim Soderberg 153f2483f8bSJoakim Soderberg # Running gcovr 154f2483f8bSJoakim Soderberg COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} -e '${CMAKE_SOURCE_DIR}/tests/' -o ${_outputname}.xml 155f2483f8bSJoakim Soderberg WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 156f2483f8bSJoakim Soderberg COMMENT "Running gcovr to produce Cobertura code coverage report." 157f2483f8bSJoakim Soderberg ) 158f2483f8bSJoakim Soderberg 159f2483f8bSJoakim Soderberg # Show info where to find the report 160f2483f8bSJoakim Soderberg ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD 161f2483f8bSJoakim Soderberg COMMAND ; 162f2483f8bSJoakim Soderberg COMMENT "Cobertura code coverage report saved in ${_outputname}.xml." 163f2483f8bSJoakim Soderberg ) 164f2483f8bSJoakim Soderberg 165f2483f8bSJoakim SoderbergENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE_COBERTURA 166