Commit 89975e51e766954d7044f0af1ed99f0256654c24

Authored by Henry Fredrick Schreiner
Committed by Henry Schreiner
1 parent 952f2913

Updating coverage

.codecov.yml
1 1
2 ignore: 2 ignore:
3 - "tests" 3 - "tests"
  4 + - "examples"
CMakeLists.txt
@@ -61,11 +61,6 @@ include(CMakeDependentOption) @@ -61,11 +61,6 @@ include(CMakeDependentOption)
61 # Allow IDE's to group targets into folders 61 # Allow IDE's to group targets into folders
62 set_property(GLOBAL PROPERTY USE_FOLDERS ON) 62 set_property(GLOBAL PROPERTY USE_FOLDERS ON)
63 63
64 -if(CMAKE_BUILD_TYPE STREQUAL Coverage)  
65 - include(CodeCoverage)  
66 - setup_target_for_coverage(CLI11_coverage ctest coverage)  
67 -endif()  
68 -  
69 file(GLOB CLI11_headers "${CMAKE_CURRENT_SOURCE_DIR}/include/CLI/*") 64 file(GLOB CLI11_headers "${CMAKE_CURRENT_SOURCE_DIR}/include/CLI/*")
70 # To see in IDE, must be listed for target 65 # To see in IDE, must be listed for target
71 66
cmake/CodeCoverage.cmake
1 -# Copyright (c) 2012 - 2015, Lars Bilke 1 +# Copyright (c) 2012 - 2017, Lars Bilke
2 # All rights reserved. 2 # All rights reserved.
3 # 3 #
4 # Redistribution and use in source and binary forms, with or without modification, 4 # Redistribution and use in source and binary forms, with or without modification,
@@ -26,7 +26,7 @@ @@ -26,7 +26,7 @@
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 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. 27 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 # 28 #
29 -# 29 +# CHANGES:
30 # 30 #
31 # 2012-01-31, Lars Bilke 31 # 2012-01-31, Lars Bilke
32 # - Enable Code Coverage 32 # - Enable Code Coverage
@@ -35,164 +35,210 @@ @@ -35,164 +35,210 @@
35 # - Added support for Clang. 35 # - Added support for Clang.
36 # - Some additional usage instructions. 36 # - Some additional usage instructions.
37 # 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 +#
38 # USAGE: 45 # USAGE:
39 -  
40 -# 0. (Mac only) If you use Xcode 5.1 make sure to patch geninfo as described here:  
41 -# http://stackoverflow.com/a/22404544/80480  
42 # 46 #
43 # 1. Copy this file into your cmake modules path. 47 # 1. Copy this file into your cmake modules path.
44 # 48 #
45 # 2. Add the following line to your CMakeLists.txt: 49 # 2. Add the following line to your CMakeLists.txt:
46 -# INCLUDE(CodeCoverage) 50 +# include(CodeCoverage)
47 # 51 #
48 -# 3. Set compiler flags to turn off optimization and enable coverage:  
49 -# SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")  
50 -# SET(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") 52 +# 3. Append necessary compiler flags:
  53 +# APPEND_COVERAGE_COMPILER_FLAGS()
51 # 54 #
52 -# 3. Use the function SETUP_TARGET_FOR_COVERAGE to create a custom make target  
53 -# which runs your test executable and produces a lcov code coverage report: 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.
54 # Example: 57 # Example:
55 -# SETUP_TARGET_FOR_COVERAGE(  
56 -# my_coverage_target # Name for custom target.  
57 -# test_driver # Name of the test driver executable that runs the tests.  
58 -# # NOTE! This should always have a ZERO as exit code  
59 -# # otherwise the coverage generation will not complete.  
60 -# coverage # Name of output directory.  
61 -# ) 58 +# set(COVERAGE_EXCLUDES 'dir1/*' 'dir2/*')
62 # 59 #
63 -# 4. Build a Debug build:  
64 -# cmake -DCMAKE_BUILD_TYPE=Debug ..  
65 -# make  
66 -# make my_coverage_target 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.
67 # 62 #
  63 +# 6. Build a Debug build:
  64 +# cmake -DCMAKE_BUILD_TYPE=Debug ..
  65 +# make
  66 +# make my_coverage_target
68 # 67 #
69 68
70 -# Check prereqs 69 +include(CMakeParseArguments)
71 70
72 -FIND_PROGRAM( GCOV_PATH gcov)  
73 -FIND_PROGRAM( LCOV_PATH lcov )  
74 -FIND_PROGRAM( GENHTML_PATH genhtml )  
75 -FIND_PROGRAM( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/tests)  
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 -ELSEIF(NOT CMAKE_COMPILER_IS_GNUCXX)  
86 - MESSAGE(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")  
87 -ENDIF() # CHECK VALID COMPILER  
88 -  
89 -SET(CMAKE_CXX_FLAGS_COVERAGE  
90 - "-g -O0 --coverage" 71 +# Check prereqs
  72 +find_program( GCOV_PATH gcov )
  73 +find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl)
  74 +find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat )
  75 +find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
  76 +find_program( SIMPLE_PYTHON_EXECUTABLE python )
  77 +
  78 +if(NOT GCOV_PATH)
  79 + message(FATAL_ERROR "gcov not found! Aborting...")
  80 +endif() # NOT GCOV_PATH
  81 +
  82 +if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
  83 + if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3)
  84 + message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
  85 + endif()
  86 +elseif(NOT CMAKE_COMPILER_IS_GNUCXX)
  87 + message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
  88 +endif()
  89 +
  90 +set(COVERAGE_COMPILER_FLAGS "-g -O0 --coverage -fprofile-arcs -ftest-coverage"
  91 + CACHE INTERNAL "")
  92 +
  93 +set(CMAKE_CXX_FLAGS_COVERAGE
  94 + ${COVERAGE_COMPILER_FLAGS}
91 CACHE STRING "Flags used by the C++ compiler during coverage builds." 95 CACHE STRING "Flags used by the C++ compiler during coverage builds."
92 FORCE ) 96 FORCE )
93 -SET(CMAKE_C_FLAGS_COVERAGE  
94 - "-g -O0 --coverage" 97 +set(CMAKE_C_FLAGS_COVERAGE
  98 + ${COVERAGE_COMPILER_FLAGS}
95 CACHE STRING "Flags used by the C compiler during coverage builds." 99 CACHE STRING "Flags used by the C compiler during coverage builds."
96 FORCE ) 100 FORCE )
97 -SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE  
98 - "--coverage" 101 +set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
  102 + ""
99 CACHE STRING "Flags used for linking binaries during coverage builds." 103 CACHE STRING "Flags used for linking binaries during coverage builds."
100 FORCE ) 104 FORCE )
101 -SET(CMAKE_SHARED_LINKER_FLAGS_COVERAGE  
102 - "--coverage" 105 +set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
  106 + ""
103 CACHE STRING "Flags used by the shared libraries linker during coverage builds." 107 CACHE STRING "Flags used by the shared libraries linker during coverage builds."
104 FORCE ) 108 FORCE )
105 -MARK_AS_ADVANCED( 109 +mark_as_advanced(
106 CMAKE_CXX_FLAGS_COVERAGE 110 CMAKE_CXX_FLAGS_COVERAGE
107 CMAKE_C_FLAGS_COVERAGE 111 CMAKE_C_FLAGS_COVERAGE
108 CMAKE_EXE_LINKER_FLAGS_COVERAGE 112 CMAKE_EXE_LINKER_FLAGS_COVERAGE
109 CMAKE_SHARED_LINKER_FLAGS_COVERAGE ) 113 CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
110 114
111 -IF ( NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "Coverage"))  
112 - MESSAGE( WARNING "Code coverage results with an optimized (non-Debug) build may be misleading" )  
113 -ENDIF() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug"  
114 -  
115 -  
116 -# Param _targetname The name of new the custom make target  
117 -# Param _testrunner The name of the target which runs the tests.  
118 -# MUST return ZERO always, even on errors.  
119 -# If not, no coverage report will be created!  
120 -# Param _outputname lcov output is generated as _outputname.info  
121 -# HTML report is generated in _outputname/index.html  
122 -# Optional fourth parameter is passed as arguments to _testrunner  
123 -# Pass them in list form, e.g.: "-j;2" for -j 2  
124 -FUNCTION(SETUP_TARGET_FOR_COVERAGE _targetname _testrunner _outputname)  
125 -  
126 - IF(NOT LCOV_PATH)  
127 - MESSAGE(FATAL_ERROR "lcov not found! Aborting...")  
128 - ENDIF() # NOT LCOV_PATH  
129 -  
130 - IF(NOT GENHTML_PATH)  
131 - MESSAGE(FATAL_ERROR "genhtml not found! Aborting...")  
132 - ENDIF() # NOT GENHTML_PATH  
133 -  
134 - SET(coverage_info "${CMAKE_BINARY_DIR}/${_outputname}.info")  
135 - SET(coverage_cleaned "${coverage_info}.cleaned")  
136 -  
137 - SEPARATE_ARGUMENTS(test_command UNIX_COMMAND "${_testrunner}")  
138 -  
139 - # Setup target  
140 - ADD_CUSTOM_TARGET(${_targetname}  
141 -  
142 - # Cleanup lcov  
143 - ${LCOV_PATH} --directory . --zerocounters  
144 -  
145 - # Run tests  
146 - COMMAND ${test_command} ${ARGV3}  
147 -  
148 - # Capturing lcov counters and generating report  
149 - COMMAND ${LCOV_PATH} --directory . --capture --output-file ${coverage_info}  
150 - COMMAND ${LCOV_PATH} --remove ${coverage_info} '*/tests/*' '*gtest*' '*gmock*' '/usr/*' --output-file ${coverage_cleaned}  
151 - COMMAND ${GENHTML_PATH} -o ${_outputname} ${coverage_cleaned}  
152 - COMMAND ${CMAKE_COMMAND} -E remove ${coverage_info} ${coverage_cleaned}  
153 -  
154 - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}  
155 - COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."  
156 - )  
157 -  
158 - # Show info where to find the report  
159 - ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD  
160 - COMMAND ;  
161 - COMMENT "Open ./${_outputname}/index.html in your browser to view the coverage report."  
162 - )  
163 -  
164 -ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE  
165 -  
166 -# Param _targetname The name of new the custom make target  
167 -# Param _testrunner The name of the target which runs the tests  
168 -# Param _outputname cobertura output is generated as _outputname.xml  
169 -# Optional fourth parameter is passed as arguments to _testrunner  
170 -# Pass them in list form, e.g.: "-j;2" for -j 2  
171 -FUNCTION(SETUP_TARGET_FOR_COVERAGE_COBERTURA _targetname _testrunner _outputname)  
172 -  
173 - IF(NOT PYTHON_EXECUTABLE)  
174 - MESSAGE(FATAL_ERROR "Python not found! Aborting...")  
175 - ENDIF() # NOT PYTHON_EXECUTABLE  
176 -  
177 - IF(NOT GCOVR_PATH)  
178 - MESSAGE(FATAL_ERROR "gcovr not found! Aborting...")  
179 - ENDIF() # NOT GCOVR_PATH  
180 -  
181 - ADD_CUSTOM_TARGET(${_targetname}  
182 -  
183 - # Run tests  
184 - ${_testrunner} ${ARGV3}  
185 -  
186 - # Running gcovr  
187 - COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} -e '${CMAKE_SOURCE_DIR}/tests/' -o ${_outputname}.xml  
188 - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}  
189 - COMMENT "Running gcovr to produce Cobertura code coverage report."  
190 - )  
191 -  
192 - # Show info where to find the report  
193 - ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD  
194 - COMMAND ;  
195 - COMMENT "Cobertura code coverage report saved in ${_outputname}.xml."  
196 - )  
197 -  
198 -ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE_COBERTURA 115 +if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
  116 + message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
  117 +endif() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug"
  118 +
  119 +if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
  120 + link_libraries(gcov)
  121 +else()
  122 + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
  123 +endif()
  124 +
  125 +# Defines a target for running and collection code coverage information
  126 +# Builds dependencies, runs the given executable and outputs reports.
  127 +# NOTE! The executable should always have a ZERO as exit code otherwise
  128 +# the coverage generation will not complete.
  129 +#
  130 +# SETUP_TARGET_FOR_COVERAGE(
  131 +# NAME testrunner_coverage # New target name
  132 +# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
  133 +# DEPENDENCIES testrunner # Dependencies to build first
  134 +# )
  135 +function(SETUP_TARGET_FOR_COVERAGE)
  136 +
  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 + # Create baseline to make sure untouched files show up in the report
  156 + COMMAND ${LCOV_PATH} -c -i -d . -o ${Coverage_NAME}.base
  157 +
  158 + # Run tests
  159 + COMMAND ${Coverage_EXECUTABLE}
  160 +
  161 + # Capturing lcov counters and generating report
  162 + COMMAND ${LCOV_PATH} --directory . --capture --output-file ${Coverage_NAME}.info
  163 + # add baseline counters
  164 + COMMAND ${LCOV_PATH} -a ${Coverage_NAME}.base -a ${Coverage_NAME}.info --output-file ${Coverage_NAME}.total
  165 + COMMAND ${LCOV_PATH} --remove ${Coverage_NAME}.total ${COVERAGE_EXCLUDES} --output-file ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned
  166 + COMMAND ${GENHTML_PATH} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned
  167 + COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.base ${Coverage_NAME}.total ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned
  168 +
  169 + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
  170 + DEPENDS ${Coverage_DEPENDENCIES}
  171 + COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
  172 + )
  173 +
  174 + # Show where to find the lcov info report
  175 + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
  176 + COMMAND ;
  177 + COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info."
  178 + )
  179 +
  180 + # Show info where to find the report
  181 + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
  182 + COMMAND ;
  183 + COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
  184 + )
  185 +
  186 +endfunction() # SETUP_TARGET_FOR_COVERAGE
  187 +
  188 +# Defines a target for running and collection code coverage information
  189 +# Builds dependencies, runs the given executable and outputs reports.
  190 +# NOTE! The executable should always have a ZERO as exit code otherwise
  191 +# the coverage generation will not complete.
  192 +#
  193 +# SETUP_TARGET_FOR_COVERAGE_COBERTURA(
  194 +# NAME ctest_coverage # New target name
  195 +# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
  196 +# DEPENDENCIES executable_target # Dependencies to build first
  197 +# )
  198 +function(SETUP_TARGET_FOR_COVERAGE_COBERTURA)
  199 +
  200 + set(options NONE)
  201 + set(oneValueArgs NAME)
  202 + set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
  203 + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  204 +
  205 + if(NOT SIMPLE_PYTHON_EXECUTABLE)
  206 + message(FATAL_ERROR "python not found! Aborting...")
  207 + endif() # NOT SIMPLE_PYTHON_EXECUTABLE
  208 +
  209 + if(NOT GCOVR_PATH)
  210 + message(FATAL_ERROR "gcovr not found! Aborting...")
  211 + endif() # NOT GCOVR_PATH
  212 +
  213 + # Combine excludes to several -e arguments
  214 + set(COBERTURA_EXCLUDES "")
  215 + foreach(EXCLUDE ${COVERAGE_EXCLUDES})
  216 + set(COBERTURA_EXCLUDES "-e ${EXCLUDE} ${COBERTURA_EXCLUDES}")
  217 + endforeach()
  218 +
  219 + add_custom_target(${Coverage_NAME}
  220 +
  221 + # Run tests
  222 + ${Coverage_EXECUTABLE}
  223 +
  224 + # Running gcovr
  225 + COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} ${COBERTURA_EXCLUDES}
  226 + -o ${Coverage_NAME}.xml
  227 + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
  228 + DEPENDS ${Coverage_DEPENDENCIES}
  229 + COMMENT "Running gcovr to produce Cobertura code coverage report."
  230 + )
  231 +
  232 + # Show info where to find the report
  233 + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
  234 + COMMAND ;
  235 + COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml."
  236 + )
  237 +
  238 +endfunction() # SETUP_TARGET_FOR_COVERAGE_COBERTURA
  239 +
  240 +function(APPEND_COVERAGE_COMPILER_FLAGS)
  241 + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
  242 + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
  243 + message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
  244 +endfunction() # APPEND_COVERAGE_COMPILER_FLAGS
tests/CMakeLists.txt
@@ -103,3 +103,13 @@ if(Boost_FOUND) @@ -103,3 +103,13 @@ if(Boost_FOUND)
103 target_compile_definitions(OptionalTest PUBLIC CLI11_BOOST_OPTIONAL) 103 target_compile_definitions(OptionalTest PUBLIC CLI11_BOOST_OPTIONAL)
104 endif() 104 endif()
105 105
  106 +if(CMAKE_BUILD_TYPE STREQUAL Coverage)
  107 + include(CodeCoverage)
  108 + setup_target_for_coverage(
  109 + NAME CLI11_coverage
  110 + EXECUTABLE ctest
  111 + DEPENDENCIES
  112 + ${CLI11_TESTS}
  113 + ${CLI11_MULTIONLY_TESTS})
  114 +endif()
  115 +