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