15223d1d9SCy Schubert# 25223d1d9SCy Schubert# Boost Software License - Version 1.0 - August 17th, 2003 35223d1d9SCy Schubert# 45223d1d9SCy Schubert# Permission is hereby granted, free of charge, to any person or organization 55223d1d9SCy Schubert# obtaining a copy of the software and accompanying documentation covered by 65223d1d9SCy Schubert# this license (the "Software") to use, reproduce, display, distribute, 75223d1d9SCy Schubert# execute, and transmit the Software, and to prepare derivative works of the 85223d1d9SCy Schubert# Software, and to permit third-parties to whom the Software is furnished to 95223d1d9SCy Schubert# do so, all subject to the following: 105223d1d9SCy Schubert# 115223d1d9SCy Schubert# The copyright notices in the Software and this entire statement, including 125223d1d9SCy Schubert# the above license grant, this restriction and the following disclaimer, 135223d1d9SCy Schubert# must be included in all copies of the Software, in whole or in part, and 145223d1d9SCy Schubert# all derivative works of the Software, unless such copies or derivative 155223d1d9SCy Schubert# works are solely in the form of machine-executable object code generated by 165223d1d9SCy Schubert# a source language processor. 175223d1d9SCy Schubert# 185223d1d9SCy Schubert# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 195223d1d9SCy Schubert# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 205223d1d9SCy Schubert# FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 215223d1d9SCy Schubert# SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 225223d1d9SCy Schubert# FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 235223d1d9SCy Schubert# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 245223d1d9SCy Schubert# DEALINGS IN THE SOFTWARE. 255223d1d9SCy Schubert# 265223d1d9SCy Schubert# 2012-01-31, Lars Bilke 275223d1d9SCy Schubert# - Enable Code Coverage 285223d1d9SCy Schubert# 295223d1d9SCy Schubert# 2013-09-17, Joakim Söderberg 305223d1d9SCy Schubert# - Added support for Clang. 315223d1d9SCy Schubert# - Some additional usage instructions. 325223d1d9SCy Schubert# 335223d1d9SCy Schubert# 2016-11-02, Azat Khuzhin 345223d1d9SCy Schubert# - Adopt for C compiler only (libevent) 355223d1d9SCy Schubert# 365223d1d9SCy Schubert# USAGE: 375223d1d9SCy Schubert# 1. Copy this file into your cmake modules path. 385223d1d9SCy Schubert# 395223d1d9SCy Schubert# 2. Add the following line to your CMakeLists.txt: 405223d1d9SCy Schubert# INCLUDE(CodeCoverage) 415223d1d9SCy Schubert# 425223d1d9SCy Schubert# 3. Set compiler flags to turn off optimization and enable coverage: 435223d1d9SCy Schubert# SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") 445223d1d9SCy Schubert# SET(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") 455223d1d9SCy Schubert# 465223d1d9SCy Schubert# 3. Use the function SETUP_TARGET_FOR_COVERAGE to create a custom make target 475223d1d9SCy Schubert# which runs your test executable and produces a lcov code coverage report: 485223d1d9SCy Schubert# Example: 495223d1d9SCy Schubert# SETUP_TARGET_FOR_COVERAGE( 505223d1d9SCy Schubert# my_coverage_target # Name for custom target. 515223d1d9SCy Schubert# test_driver # Name of the test driver executable that runs the tests. 525223d1d9SCy Schubert# # NOTE! This should always have a ZERO as exit code 535223d1d9SCy Schubert# # otherwise the coverage generation will not complete. 545223d1d9SCy Schubert# coverage # Name of output directory. 555223d1d9SCy Schubert# ) 565223d1d9SCy Schubert# 575223d1d9SCy Schubert# 4. Build a Debug build: 585223d1d9SCy Schubert# cmake -DCMAKE_BUILD_TYPE=Debug .. 595223d1d9SCy Schubert# make 605223d1d9SCy Schubert# make my_coverage_target 615223d1d9SCy Schubert# 625223d1d9SCy Schubert# 635223d1d9SCy Schubert 645223d1d9SCy Schubert# Check prereqs 655223d1d9SCy SchubertFIND_PROGRAM( GCOV_PATH gcov ) 665223d1d9SCy SchubertFIND_PROGRAM( LCOV_PATH lcov ) 675223d1d9SCy SchubertFIND_PROGRAM( GENHTML_PATH genhtml ) 685223d1d9SCy SchubertFIND_PROGRAM( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/tests) 695223d1d9SCy Schubert 705223d1d9SCy SchubertIF(NOT GCOV_PATH) 715223d1d9SCy Schubert MESSAGE(FATAL_ERROR "gcov not found! Aborting...") 725223d1d9SCy SchubertENDIF() # NOT GCOV_PATH 735223d1d9SCy Schubert 745223d1d9SCy SchubertIF(NOT CMAKE_COMPILER_IS_GNUCC) 755223d1d9SCy Schubert # Clang version 3.0.0 and greater now supports gcov as well. 765223d1d9SCy Schubert MESSAGE(WARNING "Compiler is not GNU gcc! Clang Version 3.0.0 and greater supports gcov as well, but older versions don't.") 775223d1d9SCy Schubert 785223d1d9SCy Schubert IF(NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") 795223d1d9SCy Schubert MESSAGE(FATAL_ERROR "Compiler is not GNU gcc! Aborting...") 805223d1d9SCy Schubert ENDIF() 815223d1d9SCy SchubertENDIF() # NOT CMAKE_COMPILER_IS_GNUCC 825223d1d9SCy Schubert 835223d1d9SCy SchubertIF ( NOT CMAKE_BUILD_TYPE STREQUAL "Debug" ) 845223d1d9SCy Schubert MESSAGE( WARNING "Code coverage results with an optimized (non-Debug) build may be misleading" ) 855223d1d9SCy SchubertENDIF() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug" 865223d1d9SCy Schubert 875223d1d9SCy Schubert 885223d1d9SCy Schubert# Param _targetname The name of new the custom make target 895223d1d9SCy Schubert# Param _testrunner The name of the target which runs the tests. 905223d1d9SCy Schubert# MUST return ZERO always, even on errors. 915223d1d9SCy Schubert# If not, no coverage report will be created! 925223d1d9SCy Schubert# Param _outputname lcov output is generated as _outputname.info 935223d1d9SCy Schubert# HTML report is generated in _outputname/index.html 945223d1d9SCy Schubert# Optional fourth parameter is passed as arguments to _testrunner 955223d1d9SCy Schubert# Pass them in list form, e.g.: "-j;2" for -j 2 965223d1d9SCy SchubertFUNCTION(SETUP_TARGET_FOR_COVERAGE _targetname _testrunner _outputname) 975223d1d9SCy Schubert 985223d1d9SCy Schubert IF(NOT LCOV_PATH) 995223d1d9SCy Schubert MESSAGE(FATAL_ERROR "lcov not found! Aborting...") 1005223d1d9SCy Schubert ENDIF() # NOT LCOV_PATH 1015223d1d9SCy Schubert 1025223d1d9SCy Schubert IF(NOT GENHTML_PATH) 1035223d1d9SCy Schubert MESSAGE(FATAL_ERROR "genhtml not found! Aborting...") 1045223d1d9SCy Schubert ENDIF() # NOT GENHTML_PATH 1055223d1d9SCy Schubert 1065223d1d9SCy Schubert # Setup target 1075223d1d9SCy Schubert ADD_CUSTOM_TARGET(${_targetname} 1085223d1d9SCy Schubert 1095223d1d9SCy Schubert # Cleanup lcov 1105223d1d9SCy Schubert ${LCOV_PATH} --directory . --zerocounters 1115223d1d9SCy Schubert 1125223d1d9SCy Schubert # Run tests 1135223d1d9SCy Schubert COMMAND ${_testrunner} ${ARGV3} 1145223d1d9SCy Schubert 1155223d1d9SCy Schubert # Capturing lcov counters and generating report 1165223d1d9SCy Schubert COMMAND ${LCOV_PATH} --directory . --capture --output-file ${_outputname}.info 1175223d1d9SCy Schubert COMMAND ${LCOV_PATH} --remove ${_outputname}.info 'tests/*' '/usr/*' --output-file ${_outputname}.info.cleaned 1185223d1d9SCy Schubert COMMAND ${GENHTML_PATH} -o ${_outputname} ${_outputname}.info.cleaned 1195223d1d9SCy Schubert COMMAND ${CMAKE_COMMAND} -E remove ${_outputname}.info ${_outputname}.info.cleaned 1205223d1d9SCy Schubert 1215223d1d9SCy Schubert WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 1225223d1d9SCy Schubert COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." 1235223d1d9SCy Schubert ) 1245223d1d9SCy Schubert 1255223d1d9SCy Schubert # Show info where to find the report 1265223d1d9SCy Schubert ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD 1275223d1d9SCy Schubert COMMAND ; 1285223d1d9SCy Schubert COMMENT "Open ./${_outputname}/index.html in your browser to view the coverage report." 1295223d1d9SCy Schubert ) 1305223d1d9SCy Schubert 1315223d1d9SCy SchubertENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE 1325223d1d9SCy Schubert 1335223d1d9SCy Schubert# Param _targetname The name of new the custom make target 1345223d1d9SCy Schubert# Param _testrunner The name of the target which runs the tests 1355223d1d9SCy Schubert# Param _outputname cobertura output is generated as _outputname.xml 1365223d1d9SCy Schubert# Optional fourth parameter is passed as arguments to _testrunner 1375223d1d9SCy Schubert# Pass them in list form, e.g.: "-j;2" for -j 2 1385223d1d9SCy SchubertFUNCTION(SETUP_TARGET_FOR_COVERAGE_COBERTURA _targetname _testrunner _outputname) 1395223d1d9SCy Schubert 1405223d1d9SCy Schubert IF(NOT PYTHON_EXECUTABLE) 1415223d1d9SCy Schubert MESSAGE(FATAL_ERROR "Python not found! Aborting...") 1425223d1d9SCy Schubert ENDIF() # NOT PYTHON_EXECUTABLE 1435223d1d9SCy Schubert 1445223d1d9SCy Schubert IF(NOT GCOVR_PATH) 1455223d1d9SCy Schubert MESSAGE(FATAL_ERROR "gcovr not found! Aborting...") 1465223d1d9SCy Schubert ENDIF() # NOT GCOVR_PATH 1475223d1d9SCy Schubert 1485223d1d9SCy Schubert ADD_CUSTOM_TARGET(${_targetname} 1495223d1d9SCy Schubert 1505223d1d9SCy Schubert # Run tests 1515223d1d9SCy Schubert ${_testrunner} ${ARGV3} 1525223d1d9SCy Schubert 1535223d1d9SCy Schubert # Running gcovr 1545223d1d9SCy Schubert COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} -e '${CMAKE_SOURCE_DIR}/tests/' -o ${_outputname}.xml 1555223d1d9SCy Schubert WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 1565223d1d9SCy Schubert COMMENT "Running gcovr to produce Cobertura code coverage report." 1575223d1d9SCy Schubert ) 1585223d1d9SCy Schubert 1595223d1d9SCy Schubert # Show info where to find the report 1605223d1d9SCy Schubert ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD 1615223d1d9SCy Schubert COMMAND ; 1625223d1d9SCy Schubert COMMENT "Cobertura code coverage report saved in ${_outputname}.xml." 1635223d1d9SCy Schubert ) 1645223d1d9SCy Schubert 1655223d1d9SCy SchubertENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE_COBERTURA 166