59
59
# relative to the BASE_DIRECTORY (default: PROJECT_SOURCE_DIR)
60
60
# Example:
61
61
# set(COVERAGE_EXCLUDES "dir1/*")
62
- # setup_target_for_coverage_gcovr_html (
62
+ # setup_target_for_coverage_gcovr (
63
63
# NAME coverage
64
64
# EXECUTABLE testrunner
65
+ # FORMAT html-details
65
66
# BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src"
66
67
# EXCLUDE "dir2/*")
67
68
#
@@ -95,7 +96,7 @@ elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
95
96
find_program ( LLVMCOV_PATH llvm-cov )
96
97
endif ()
97
98
if (NOT LLVMCOV_PATH)
98
- message (FATAL_ERROR "llvm-cov tool not found ! Aborting..." )
99
+ message (FATAL_ERROR "Could not find llvm-cov tool! Aborting..." )
99
100
endif ()
100
101
set (GCOV_TOOL "${LLVMCOV_PATH} gcov" )
101
102
elseif ("${CMAKE_CXX_COMPILER_ID} " MATCHES "GNU" )
@@ -104,7 +105,7 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
104
105
endif ()
105
106
106
107
if (NOT GCOV_TOOL)
107
- message (FATAL_ERROR "gcov tool not found ! Aborting..." )
108
+ message (FATAL_ERROR "Could not find gcov or llvm-cov tool ! Aborting..." )
108
109
endif () # NOT GCOV_TOOL
109
110
110
111
# Check supported compiler (Clang, GNU and Flang)
@@ -176,26 +177,35 @@ endif()
176
177
# NOTE! The executable should always have a ZERO as exit code otherwise
177
178
# the coverage generation will not complete.
178
179
#
179
- # setup_target_for_coverage_gcovr_xml (
180
+ # setup_target_for_coverage_gcovr (
180
181
# NAME ctest_coverage # New target name
181
182
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
182
183
# DEPENDENCIES executable_target # Dependencies to build first
183
184
# BASE_DIRECTORY "../" # Base directory for report
184
185
# # (defaults to PROJECT_SOURCE_DIR)
186
+ # FORMAT "cobertura" # Output format, one of:
187
+ # # xml cobertura sonarqube json-summary
188
+ # # json-details coveralls csv txt
189
+ # # html-single html-nested html-details
190
+ # # (xml is an alias to cobertura;
191
+ # # if no format is set, defaults to xml;
192
+ # # if any of the supported formats is
193
+ # # set in GCOVR_ADDITIONAL_ARGS options
194
+ # # it will always take priority)
185
195
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
186
196
# # to BASE_DIRECTORY, with CMake 3.4+)
187
197
# )
188
198
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
189
199
# GCVOR command.
190
- function (setup_target_for_coverage_gcovr_xml )
200
+ function (setup_target_for_coverage_gcovr )
191
201
set (options NONE)
192
- set (oneValueArgs BASE_DIRECTORY NAME )
202
+ set (oneValueArgs BASE_DIRECTORY NAME FORMAT )
193
203
set (multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
194
204
cmake_parse_arguments (Coverage "${options} " "${oneValueArgs} " "${multiValueArgs} " ${ARGN} )
195
205
196
206
if (NOT GCOVR_PATH)
197
- message (FATAL_ERROR "gcovr not found ! Aborting..." )
198
- endif () # NOT GCOVR_PATH
207
+ message (FATAL_ERROR "Could not find gcovr tool ! Aborting..." )
208
+ endif ()
199
209
200
210
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
201
211
if (DEFINED Coverage_BASE_DIRECTORY)
@@ -204,109 +214,87 @@ function(setup_target_for_coverage_gcovr_xml)
204
214
set (BASEDIR ${PROJECT_SOURCE_DIR} )
205
215
endif ()
206
216
207
- # Collect excludes (CMake 3.4+: Also compute absolute paths)
208
- set (GCOVR_EXCLUDES "" )
209
- foreach (EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES} )
210
- if (CMAKE_VERSION VERSION_GREATER 3.4)
211
- get_filename_component (EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR} )
217
+ if ("--txt" IN_LIST GCOVR_ADDITIONAL_ARGS)
218
+ set (Coverage_FORMAT txt)
219
+ elseif ("--csv" IN_LIST GCOVR_ADDITIONAL_ARGS)
220
+ set (Coverage_FORMAT csv)
221
+ elseif (("--cobertura" IN_LIST GCOVR_ADDITIONAL_ARGS)
222
+ OR ("--cobertura-pretty" IN_LIST GCOVR_ADDITIONAL_ARGS)
223
+ OR ("--xml" IN_LIST GCOVR_ADDITIONAL_ARGS)
224
+ OR ("--xml-pretty" IN_LIST GCOVR_ADDITIONAL_ARGS)
225
+ OR ("-x" IN_LIST GCOVR_ADDITIONAL_ARGS))
226
+ set (Coverage_FORMAT cobertura)
227
+ elseif ("--sonarqube" IN_LIST GCOVR_ADDITIONAL_ARGS)
228
+ set (Coverage_FORMAT sonarqube)
229
+ elseif (("--json-summary" IN_LIST GCOVR_ADDITIONAL_ARGS)
230
+ OR ("--json-summary-pretty" IN_LIST GCOVR_ADDITIONAL_ARGS))
231
+ set (Coverage_FORMAT json-summary)
232
+ elseif (("--json" IN_LIST GCOVR_ADDITIONAL_ARGS)
233
+ OR ("--json-pretty" IN_LIST GCOVR_ADDITIONAL_ARGS))
234
+ set (Coverage_FORMAT json-details)
235
+ elseif (("--coveralls" IN_LIST GCOVR_ADDITIONAL_ARGS)
236
+ OR ("--coveralls-pretty" IN_LIST GCOVR_ADDITIONAL_ARGS))
237
+ set (Coverage_FORMAT coveralls)
238
+ elseif (("--html" IN_LIST GCOVR_ADDITIONAL_ARGS)
239
+ OR ("--html-self-contained" IN_LIST GCOVR_ADDITIONAL_ARGS))
240
+ set (Coverage_FORMAT html-single)
241
+ elseif ("--html-details" IN_LIST GCOVR_ADDITIONAL_ARGS)
242
+ set (Coverage_FORMAT html-details)
243
+ elseif ("--html-nested" IN_LIST GCOVR_ADDITIONAL_ARGS)
244
+ set (Coverage_FORMAT html-nested)
245
+ else ()
246
+ if (NOT DEFINED Coverage_FORMAT)
247
+ set (Coverage_FORMAT xml)
212
248
endif ()
213
- list (APPEND GCOVR_EXCLUDES "${EXCLUDE} " )
214
- endforeach ()
215
- list (REMOVE_DUPLICATES GCOVR_EXCLUDES)
216
-
217
- # Combine excludes to several -e arguments
218
- set (GCOVR_EXCLUDE_ARGS "" )
219
- foreach (EXCLUDE ${GCOVR_EXCLUDES} )
220
- list (APPEND GCOVR_EXCLUDE_ARGS "-e" )
221
- list (APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE} " )
222
- endforeach ()
223
-
224
- # Set up commands which will be run to generate coverage data
225
- # Run tests
226
- set (GCOVR_XML_EXEC_TESTS_CMD
227
- ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
228
- )
229
- # Running gcovr
230
- set (GCOVR_XML_CMD
231
- ${GCOVR_PATH}
232
- --gcov-executable ${GCOV_TOOL}
233
- --gcov-ignore -parse-errors=negative_hits.warn_once_per_file
234
- --output ${Coverage_NAME} .xml
235
- --xml
236
- -r ${BASEDIR}
237
- ${GCOVR_ADDITIONAL_ARGS}
238
- ${GCOVR_EXCLUDE_ARGS}
239
- --object-directory =${PROJECT_BINARY_DIR}
240
- )
241
249
242
- if (CODE_COVERAGE_VERBOSE)
243
- message (STATUS "Executed command report" )
244
-
245
- message (STATUS "Command to run tests: " )
246
- string (REPLACE ";" " " GCOVR_XML_EXEC_TESTS_CMD_SPACED "${GCOVR_XML_EXEC_TESTS_CMD} " )
247
- message (STATUS "${GCOVR_XML_EXEC_TESTS_CMD_SPACED} " )
248
-
249
- message (STATUS "Command to generate gcovr XML coverage data: " )
250
- string (REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD} " )
251
- message (STATUS "${GCOVR_XML_CMD_SPACED} " )
250
+ if ((Coverage_FORMAT STREQUAL "cobertura" )
251
+ OR (Coverage_FORMAT STREQUAL "xml" ))
252
+ list (APPEND GCOVR_ADDITIONAL_ARGS --cobertura-pretty)
253
+ set (Coverage_FORMAT cobertura) # overwrite xml
254
+ elseif (Coverage_FORMAT STREQUAL "sonarqube" )
255
+ list (APPEND GCOVR_ADDITIONAL_ARGS --sonarqube)
256
+ elseif (Coverage_FORMAT STREQUAL "json-summary" )
257
+ list (APPEND GCOVR_ADDITIONAL_ARGS --json-summary-pretty)
258
+ elseif (Coverage_FORMAT STREQUAL "json-details" )
259
+ list (APPEND GCOVR_ADDITIONAL_ARGS --json-pretty)
260
+ elseif (Coverage_FORMAT STREQUAL "coveralls" )
261
+ list (APPEND GCOVR_ADDITIONAL_ARGS --coveralls-pretty)
262
+ elseif (Coverage_FORMAT STREQUAL "csv" )
263
+ list (APPEND GCOVR_ADDITIONAL_ARGS --csv)
264
+ elseif (Coverage_FORMAT STREQUAL "txt" )
265
+ list (APPEND GCOVR_ADDITIONAL_ARGS --txt)
266
+ elseif (Coverage_FORMAT STREQUAL "html-single" )
267
+ list (APPEND GCOVR_ADDITIONAL_ARGS --html --html-self-contained)
268
+ elseif (Coverage_FORMAT STREQUAL "html-nested" )
269
+ list (APPEND GCOVR_ADDITIONAL_ARGS --html --html-nested)
270
+ elseif (Coverage_FORMAT STREQUAL "html-details" )
271
+ list (APPEND GCOVR_ADDITIONAL_ARGS --html --html-details)
272
+ else ()
273
+ message (FATAL_ERROR "Unsupported output style ${Coverage_FORMAT} ! Aborting..." )
274
+ endif ()
252
275
endif ()
253
276
254
- add_custom_target (${Coverage_NAME}
255
- COMMAND ${GCOVR_XML_EXEC_TESTS_CMD}
256
- COMMAND ${GCOVR_XML_CMD}
257
-
258
- BYPRODUCTS ${Coverage_NAME} .xml
259
- WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
260
- DEPENDS ${Coverage_DEPENDENCIES}
261
- VERBATIM # Protect arguments to commands
262
- COMMENT "Running gcovr to produce Cobertura code coverage report."
263
- )
264
-
265
- # Show info where to find the report
266
- add_custom_command (TARGET ${Coverage_NAME} POST_BUILD
267
- COMMAND ;
268
- COMMENT "Cobertura code coverage report saved in ${Coverage_NAME} .xml."
269
- )
270
- endfunction () # setup_target_for_coverage_gcovr_xml
271
-
272
- # Defines a target for running and collection code coverage information
273
- # Builds dependencies, runs the given executable and outputs reports.
274
- # NOTE! The executable should always have a ZERO as exit code otherwise
275
- # the coverage generation will not complete.
276
- #
277
- # setup_target_for_coverage_gcovr_html(
278
- # NAME ctest_coverage # New target name
279
- # EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
280
- # DEPENDENCIES executable_target # Dependencies to build first
281
- # BASE_DIRECTORY "../" # Base directory for report
282
- # # (defaults to PROJECT_SOURCE_DIR)
283
- # EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
284
- # # to BASE_DIRECTORY, with CMake 3.4+)
285
- # )
286
- # The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
287
- # GCVOR command.
288
- function (setup_target_for_coverage_gcovr_html)
289
- set (options NONE)
290
- set (oneValueArgs BASE_DIRECTORY NAME )
291
- set (multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
292
- cmake_parse_arguments (Coverage "${options} " "${oneValueArgs} " "${multiValueArgs} " ${ARGN} )
293
-
294
- if (NOT GCOVR_PATH)
295
- message (FATAL_ERROR "gcovr not found! Aborting..." )
296
- endif () # NOT GCOVR_PATH
297
-
298
- # Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
299
- if (DEFINED Coverage_BASE_DIRECTORY)
300
- get_filename_component (BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE )
277
+ if ("--output" IN_LIST GCOVR_ADDITIONAL_ARGS)
278
+ message (FATAL_ERROR "Unsupported --output option detected in GCOVR_ADDITIONAL_ARGS! Aborting..." )
301
279
else ()
302
- set (BASEDIR ${PROJECT_SOURCE_DIR} )
303
- endif ()
304
-
305
- # Optionally set --html-details
306
- if ((NOT "--html-details" IN_LIST GCOVR_ADDITIONAL_ARGS)
307
- AND (NOT "--html-nested" IN_LIST GCOVR_ADDITIONAL_ARGS)
308
- AND (NOT "--html" IN_LIST GCOVR_ADDITIONAL_ARGS))
309
- list (APPEND GCOVR_ADDITIONAL_ARGS --html-details)
280
+ if ((Coverage_FORMAT STREQUAL "html-details" )
281
+ OR (Coverage_FORMAT STREQUAL "html-nested" ))
282
+ set (GCOVR_OUTPUT_FILE ${PROJECT_BINARY_DIR} /${Coverage_NAME} /index.html)
283
+ set (GCOVR_CREATE_FOLDER ${PROJECT_BINARY_DIR} /${Coverage_NAME} )
284
+ elseif (Coverage_FORMAT STREQUAL "html-single" )
285
+ set (GCOVR_OUTPUT_FILE ${Coverage_NAME} .html)
286
+ elseif ((Coverage_FORMAT STREQUAL "json-summary" )
287
+ OR (Coverage_FORMAT STREQUAL "json-details" )
288
+ OR (Coverage_FORMAT STREQUAL "coveralls" ))
289
+ set (GCOVR_OUTPUT_FILE ${Coverage_NAME} .json)
290
+ elseif (Coverage_FORMAT STREQUAL "txt" )
291
+ set (GCOVR_OUTPUT_FILE ${Coverage_NAME} .txt)
292
+ elseif (Coverage_FORMAT STREQUAL "csv" )
293
+ set (GCOVR_OUTPUT_FILE ${Coverage_NAME} .csv)
294
+ else ()
295
+ set (GCOVR_OUTPUT_FILE ${Coverage_NAME} .xml)
296
+ endif ()
297
+ list (APPEND GCOVR_ADDITIONAL_ARGS --output ${GCOVR_OUTPUT_FILE} )
310
298
endif ()
311
299
312
300
# Collect excludes (CMake 3.4+: Also compute absolute paths)
@@ -328,20 +316,23 @@ function(setup_target_for_coverage_gcovr_html)
328
316
329
317
# Set up commands which will be run to generate coverage data
330
318
# Run tests
331
- set (GCOVR_HTML_EXEC_TESTS_CMD
319
+ set (GCOVR_EXEC_TESTS_CMD
332
320
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
333
321
)
322
+
334
323
# Create folder
335
- set (GCOVR_HTML_FOLDER_CMD
336
- ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR} /${Coverage_NAME}
337
- )
324
+ if (DEFINED GCOVR_CREATE_FOLDER)
325
+ set (GCOVR_FOLDER_CMD
326
+ ${CMAKE_COMMAND} -E make_directory ${GCOVR_CREATE_FOLDER} )
327
+ else ()
328
+ set (GCOVR_FOLDER_CMD echo) # dummy
329
+ endif ()
330
+
338
331
# Running gcovr
339
- set (GCOVR_HTML_CMD
332
+ set (GCOVR_CMD
340
333
${GCOVR_PATH}
341
334
--gcov-executable ${GCOV_TOOL}
342
335
--gcov-ignore -parse-errors=negative_hits.warn_once_per_file
343
- --output ${Coverage_NAME} /index.html
344
- --html
345
336
-r ${BASEDIR}
346
337
${GCOVR_ADDITIONAL_ARGS}
347
338
${GCOVR_EXCLUDE_ARGS}
@@ -352,37 +343,38 @@ function(setup_target_for_coverage_gcovr_html)
352
343
message (STATUS "Executed command report" )
353
344
354
345
message (STATUS "Command to run tests: " )
355
- string (REPLACE ";" " " GCOVR_HTML_EXEC_TESTS_CMD_SPACED "${GCOVR_HTML_EXEC_TESTS_CMD } " )
356
- message (STATUS "${GCOVR_HTML_EXEC_TESTS_CMD_SPACED } " )
346
+ string (REPLACE ";" " " GCOVR_EXEC_TESTS_CMD_SPACED "${GCOVR_EXEC_TESTS_CMD } " )
347
+ message (STATUS "${GCOVR_EXEC_TESTS_CMD_SPACED } " )
357
348
358
- message (STATUS "Command to create a folder: " )
359
- string (REPLACE ";" " " GCOVR_HTML_FOLDER_CMD_SPACED "${GCOVR_HTML_FOLDER_CMD} " )
360
- message (STATUS "${GCOVR_HTML_FOLDER_CMD_SPACED} " )
349
+ if (NOT GCOVR_FOLDER_CMD STREQUAL "echo" )
350
+ message (STATUS "Command to create a folder: " )
351
+ string (REPLACE ";" " " GCOVR_FOLDER_CMD_SPACED "${GCOVR_FOLDER_CMD} " )
352
+ message (STATUS "${GCOVR_FOLDER_CMD_SPACED} " )
353
+ endif ()
361
354
362
- message (STATUS "Command to generate gcovr HTML coverage data: " )
363
- string (REPLACE ";" " " GCOVR_HTML_CMD_SPACED "${GCOVR_HTML_CMD } " )
364
- message (STATUS "${GCOVR_HTML_CMD_SPACED } " )
355
+ message (STATUS "Command to generate gcovr coverage data: " )
356
+ string (REPLACE ";" " " GCOVR_CMD_SPACED "${GCOVR_CMD } " )
357
+ message (STATUS "${GCOVR_CMD_SPACED } " )
365
358
endif ()
366
359
367
360
add_custom_target (${Coverage_NAME}
368
- COMMAND ${GCOVR_HTML_EXEC_TESTS_CMD }
369
- COMMAND ${GCOVR_HTML_FOLDER_CMD }
370
- COMMAND ${GCOVR_HTML_CMD }
361
+ COMMAND ${GCOVR_EXEC_TESTS_CMD }
362
+ COMMAND ${GCOVR_FOLDER_CMD }
363
+ COMMAND ${GCOVR_CMD }
371
364
372
- BYPRODUCTS ${PROJECT_BINARY_DIR} / ${Coverage_NAME} /index.html # report directory
365
+ BYPRODUCTS ${GCOVR_OUTPUT_FILE}
373
366
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
374
367
DEPENDS ${Coverage_DEPENDENCIES}
375
368
VERBATIM # Protect arguments to commands
376
- COMMENT "Running gcovr to produce HTML code coverage report."
369
+ COMMENT "Running gcovr to produce code coverage report."
377
370
)
378
371
379
372
# Show info where to find the report
380
373
add_custom_command (TARGET ${Coverage_NAME} POST_BUILD
381
374
COMMAND ;
382
- COMMENT "Open ./ ${Coverage_NAME} /index.html in your browser to view the coverage report. "
375
+ COMMENT "Code coverage report saved in ${GCOVR_OUTPUT_FILE} formatted as ${Coverage_FORMAT} "
383
376
)
384
-
385
- endfunction () # setup_target_for_coverage_gcovr_html
377
+ endfunction () # setup_target_for_coverage_gcovr
386
378
387
379
function (append_coverage_compiler_flags)
388
380
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS} " PARENT_SCOPE)
0 commit comments