xref: /src/contrib/libevent/cmake/CodeCoverage.cmake (revision b50261e21f39a6c7249a49e7b60aa878c98512a8)
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