]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | # Copyright (c) 2012 - 2017, Lars Bilke |
2 | # All rights reserved. | |
3 | # | |
4 | # Redistribution and use in source and binary forms, with or without modification, | |
5 | # are permitted provided that the following conditions are met: | |
6 | # | |
7 | # 1. Redistributions of source code must retain the above copyright notice, this | |
8 | # list of conditions and the following disclaimer. | |
9 | # | |
10 | # 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | # this list of conditions and the following disclaimer in the documentation | |
12 | # and/or other materials provided with the distribution. | |
13 | # | |
14 | # 3. Neither the name of the copyright holder nor the names of its contributors | |
15 | # may be used to endorse or promote products derived from this software without | |
16 | # specific prior written permission. | |
17 | # | |
18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
19 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
20 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | |
22 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
23 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
24 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
25 | # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
28 | # | |
29 | # CHANGES: | |
30 | # | |
31 | # 2012-01-31, Lars Bilke | |
32 | # - Enable Code Coverage | |
33 | # | |
34 | # 2013-09-17, Joakim Söderberg | |
35 | # - Added support for Clang. | |
36 | # - Some additional usage instructions. | |
37 | # | |
38 | # 2016-02-03, Lars Bilke | |
39 | # - Refactored functions to use named parameters | |
40 | # | |
41 | # 2017-06-02, Lars Bilke | |
42 | # - Merged with modified version from github.com/ufz/ogs | |
43 | # | |
44 | # | |
45 | # USAGE: | |
46 | # | |
47 | # 1. Copy this file into your cmake modules path. | |
48 | # | |
49 | # 2. Add the following line to your CMakeLists.txt: | |
50 | # include(CodeCoverage) | |
51 | # | |
52 | # 3. Append necessary compiler flags: | |
53 | # APPEND_COVERAGE_COMPILER_FLAGS() | |
54 | # | |
55 | # 4. If you need to exclude additional directories from the report, specify them | |
56 | # using the COVERAGE_EXCLUDES variable before calling SETUP_TARGET_FOR_COVERAGE. | |
57 | # Example: | |
58 | # set(COVERAGE_EXCLUDES 'dir1/*' 'dir2/*') | |
59 | # | |
60 | # 5. Use the functions described below to create a custom make target which | |
61 | # runs your test executable and produces a code coverage report. | |
62 | # | |
63 | # 6. Build a Debug build: | |
64 | # cmake -DCMAKE_BUILD_TYPE=Debug .. | |
65 | # make | |
66 | # make my_coverage_target | |
67 | # | |
68 | ||
69 | include(CMakeParseArguments) | |
70 | ||
71 | # Check prereqs | |
72 | find_program( GCOV_PATH gcov ) | |
73 | find_program( LCOV_PATH lcov ) | |
74 | find_program( GENHTML_PATH genhtml ) | |
75 | find_program( SIMPLE_PYTHON_EXECUTABLE python ) | |
76 | ||
77 | if(NOT GCOV_PATH) | |
78 | message(FATAL_ERROR "gcov not found! Aborting...") | |
79 | endif() # NOT GCOV_PATH | |
80 | ||
81 | if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") | |
82 | if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3) | |
83 | message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...") | |
84 | endif() | |
85 | list(APPEND COVERAGE_COMPILER_FLAGS -Qunused-arguments) | |
86 | elseif(NOT CMAKE_COMPILER_IS_GNUCXX) | |
87 | message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...") | |
88 | endif() | |
89 | ||
90 | list(APPEND COVERAGE_COMPILER_FLAGS | |
91 | -g -O0 --coverage -fprofile-arcs -ftest-coverage) | |
92 | set(COVERAGE_COMPILER_FLAGS ${COVERAGE_COMPILER_FLAGS} CACHE INTERNAL "") | |
93 | ||
94 | set(CMAKE_CXX_FLAGS_COVERAGE | |
95 | ${COVERAGE_COMPILER_FLAGS} | |
96 | CACHE STRING "Flags used by the C++ compiler during coverage builds." | |
97 | FORCE ) | |
98 | set(CMAKE_C_FLAGS_COVERAGE | |
99 | ${COVERAGE_COMPILER_FLAGS} | |
100 | CACHE STRING "Flags used by the C compiler during coverage builds." | |
101 | FORCE ) | |
102 | set(CMAKE_EXE_LINKER_FLAGS_COVERAGE | |
103 | "" | |
104 | CACHE STRING "Flags used for linking binaries during coverage builds." | |
105 | FORCE ) | |
106 | set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE | |
107 | "" | |
108 | CACHE STRING "Flags used by the shared libraries linker during coverage builds." | |
109 | FORCE ) | |
110 | mark_as_advanced( | |
111 | CMAKE_CXX_FLAGS_COVERAGE | |
112 | CMAKE_C_FLAGS_COVERAGE | |
113 | CMAKE_EXE_LINKER_FLAGS_COVERAGE | |
114 | CMAKE_SHARED_LINKER_FLAGS_COVERAGE ) | |
115 | ||
116 | if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") | |
117 | message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading") | |
118 | endif() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug" | |
119 | ||
120 | if(CMAKE_C_COMPILER_ID STREQUAL "GNU") | |
121 | link_libraries(gcov) | |
122 | else() | |
123 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") | |
124 | endif() | |
125 | ||
126 | # Defines a target for running and collection code coverage information | |
127 | # Builds dependencies, runs the given executable and outputs reports. | |
128 | # NOTE! The executable should always have a ZERO as exit code otherwise | |
129 | # the coverage generation will not complete. | |
130 | # | |
131 | # setup_target_for_coverage( | |
132 | # NAME testrunner_coverage # New target name | |
133 | # EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR | |
134 | # DEPENDENCIES testrunner # Dependencies to build first | |
135 | # ) | |
136 | function(setup_target_for_coverage) | |
137 | set(options NONE) | |
138 | set(oneValueArgs NAME) | |
139 | set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) | |
140 | cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) | |
141 | ||
142 | if(NOT LCOV_PATH) | |
143 | message(FATAL_ERROR "lcov not found! Aborting...") | |
144 | endif() # NOT LCOV_PATH | |
145 | ||
146 | if(NOT GENHTML_PATH) | |
147 | message(FATAL_ERROR "genhtml not found! Aborting...") | |
148 | endif() # NOT GENHTML_PATH | |
149 | ||
150 | # Setup target | |
151 | add_custom_target(${Coverage_NAME} | |
152 | ||
153 | # Cleanup lcov | |
154 | COMMAND ${LCOV_PATH} --directory . --zerocounters | |
155 | ||
156 | # Run tests | |
157 | COMMAND ${Coverage_EXECUTABLE} | |
158 | ||
159 | # Capturing lcov counters and generating report | |
160 | COMMAND ${LCOV_PATH} --base-directory ${CMAKE_SOURCE_DIR} --directory . --capture --output-file ${Coverage_NAME}.info --no-external | |
161 | COMMAND ${LCOV_PATH} --remove ${Coverage_NAME}.info ${COVERAGE_EXCLUDES} --output-file ${Coverage_NAME}.info.cleaned | |
162 | COMMAND ${GENHTML_PATH} --legend --demangle-cpp -o ${Coverage_NAME} ${Coverage_NAME}.info.cleaned | |
163 | COMMAND ${CMAKE_COMMAND} -E rename ${Coverage_NAME}.info.cleaned coverage.info | |
164 | COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.info | |
165 | ||
166 | WORKING_DIRECTORY ${PROJECT_BINARY_DIR} | |
167 | DEPENDS ${Coverage_DEPENDENCIES} | |
168 | COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." | |
169 | ) | |
170 | ||
171 | # Show info where to find the report | |
172 | add_custom_command(TARGET ${Coverage_NAME} POST_BUILD | |
173 | COMMAND ; | |
174 | COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." | |
175 | ) | |
176 | endfunction() # setup_target_for_coverage | |
177 | ||
178 | function(append_coverage_compiler_flags flags_var) | |
179 | set(${flags_var} ${${flags_var}} ${COVERAGE_COMPILER_FLAGS} PARENT_SCOPE) | |
180 | endfunction() # append_coverage_compiler_flags |