Skip to content

Commit 75c5ff2

Browse files
committed
Rework ccov-run* coverage targets
Previously, any time a coverage target was called, the executables would always be run. Recently, this was changes so that the executables were run to generate the coverage data and not re-run if the underlying executable had not been changed. This commit change it once again to have both. At a minimum the executables will be run to generate the data, and will not be re-run unless either the dependencies have been changed/updated OR the ccov-run* targets are invoked.
1 parent 0123e29 commit 75c5ff2

File tree

1 file changed

+74
-11
lines changed

1 file changed

+74
-11
lines changed

code-coverage.cmake

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,7 @@ function(target_code_coverage TARGET_NAME)
342342
ccov-clean-${target_code_coverage_COVERAGE_TARGET_NAME})
343343

344344
# Run the executable, generating raw profile data Make the run data
345-
# available for further processing. Separated to allow Windows to run this
346-
# target serially.
345+
# available for further processing.
347346
add_custom_command(
348347
OUTPUT ${target_code_coverage_COVERAGE_TARGET_NAME}.profraw
349348
COMMAND
@@ -363,8 +362,41 @@ function(target_code_coverage TARGET_NAME)
363362
COMMAND ${CMAKE_COMMAND} -E rm -f
364363
${CMAKE_COVERAGE_DATA_DIRECTORY}/ccov-all.profdata
365364
DEPENDS ${TARGET_NAME})
365+
366+
# This is a copy of the above add_custom_command.
367+
#
368+
# Since add_custom_target items are always considered out-of-date, this
369+
# can be used by the user to perform another coverage run, but only when
370+
# invoked directly.
366371
add_custom_target(
367372
ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME}
373+
COMMAND
374+
${CMAKE_COMMAND} -E env ${CMAKE_CROSSCOMPILING_EMULATOR}
375+
${target_code_coverage_PRE_ARGS}
376+
LLVM_PROFILE_FILE=${target_code_coverage_COVERAGE_TARGET_NAME}.profraw
377+
$<TARGET_FILE:${TARGET_NAME}> ${target_code_coverage_ARGS}
378+
COMMAND
379+
${CMAKE_COMMAND} -E echo "-object=$<TARGET_FILE:${TARGET_NAME}>"
380+
${LINKED_OBJECTS} >
381+
${CMAKE_COVERAGE_DATA_DIRECTORY}/objects/${target_code_coverage_COVERAGE_TARGET_NAME}
382+
COMMAND
383+
${CMAKE_COMMAND} -E echo
384+
"${CMAKE_CURRENT_BINARY_DIR}/${target_code_coverage_COVERAGE_TARGET_NAME}.profraw"
385+
>
386+
${CMAKE_COVERAGE_DATA_DIRECTORY}/profraw/${target_code_coverage_COVERAGE_TARGET_NAME}
387+
COMMAND ${CMAKE_COMMAND} -E rm -f
388+
${CMAKE_COVERAGE_DATA_DIRECTORY}/ccov-all.profdata
389+
DEPENDS ${TARGET_NAME})
390+
391+
# As custom targets with COMMANDs are always considered out of date, we
392+
# want the merged/all targets to depend on this, so that we don't
393+
# necessarily re-run the executbale every time, only at a minimum to
394+
# generate the file. If the user want to re-run targets, they can by
395+
# explicitly invoking the ccov-run-TARGET targets.
396+
#
397+
# If the option for a hidden target were possible, this would be.
398+
add_custom_target(
399+
ccov-ran-${target_code_coverage_COVERAGE_TARGET_NAME}
368400
DEPENDS ${target_code_coverage_COVERAGE_TARGET_NAME}.profraw)
369401

370402
# Merge the generated profile data so llvm-cov can process it
@@ -469,7 +501,8 @@ function(target_code_coverage TARGET_NAME)
469501
add_dependencies(ccov-clean
470502
ccov-clean-${target_code_coverage_COVERAGE_TARGET_NAME})
471503

472-
# Run the executable, generating coverage information
504+
# Run the executable, generating raw profile data Make the run data
505+
# available for further processing.
473506
add_custom_command(
474507
OUTPUT ${target_code_coverage_COVERAGE_TARGET_NAME}.ccov-run
475508
COMMAND
@@ -480,8 +513,32 @@ function(target_code_coverage TARGET_NAME)
480513
${CMAKE_COMMAND} -E touch
481514
${target_code_coverage_COVERAGE_TARGET_NAME}.ccov-run
482515
DEPENDS ${TARGET_NAME})
516+
517+
# This is a copy of the above add_custom_command.
518+
#
519+
# Since add_custom_target items are always considered out-of-date, this
520+
# can be used by the user to perform another coverage run, but only when
521+
# invoked directly.
483522
add_custom_target(
484523
ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME}
524+
COMMAND
525+
${CMAKE_CROSSCOMPILING_EMULATOR} ${target_code_coverage_PRE_ARGS}
526+
$<TARGET_FILE:${TARGET_NAME}> ${target_code_coverage_ARGS}
527+
COMMAND # add a dummy file to use as a dependency to indicate the target
528+
# has been run and data collected
529+
${CMAKE_COMMAND} -E touch
530+
${target_code_coverage_COVERAGE_TARGET_NAME}.ccov-run
531+
DEPENDS ${TARGET_NAME})
532+
533+
# As custom targets with COMMANDs are always considered out of date, we
534+
# want the merged/all targets to depend on this, so that we don't
535+
# necessarily re-run the executbale every time, only at a minimum to
536+
# generate the file. If the user want to re-run targets, they can by
537+
# explicitly invoking the ccov-run-TARGET targets.
538+
#
539+
# If the option for a hidden target were possible, this would be.
540+
add_custom_target(
541+
ccov-ran-${target_code_coverage_COVERAGE_TARGET_NAME}
485542
DEPENDS ${target_code_coverage_COVERAGE_TARGET_NAME}.ccov-run)
486543

487544
add_custom_command(
@@ -542,12 +599,15 @@ function(target_code_coverage TARGET_NAME)
542599
if(NOT TARGET ccov-all-run)
543600
message(
544601
FATAL_ERROR
545-
"Calling target_code_coverage with 'ALL' must be after a call to 'add_code_coverage_all_targets'."
602+
"Calling target_code_coverage with 'ALL' must be after a call to 'add_code_coverage_all_targets' to create the 'ccov-all' target set."
546603
)
547604
endif()
548605

549606
add_dependencies(ccov-all-run
550607
ccov-run-${target_code_coverage_COVERAGE_TARGET_NAME})
608+
609+
add_dependencies(ccov-all-ran
610+
ccov-ran-${target_code_coverage_COVERAGE_TARGET_NAME})
551611
endif()
552612
endif()
553613
endfunction()
@@ -592,11 +652,16 @@ function(add_code_coverage_all_targets)
592652
cmake_parse_arguments(add_code_coverage_all_targets "" ""
593653
"${multi_value_keywords}" ${ARGN})
594654

655+
# invoke to re-run all coverage-instrumented executables
656+
add_custom_target(ccov-all-run)
657+
658+
# used to ensure profile data from all targets is available, without forcing a
659+
# re-run of previously run ones
660+
add_custom_target(ccov-all-ran)
661+
595662
if(CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang"
596663
OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?[Cc]lang")
597664

598-
add_custom_target(ccov-all-run)
599-
600665
# Merge the profile data for all of the run targets
601666
if(WIN32)
602667
add_custom_command(
@@ -610,7 +675,7 @@ function(add_code_coverage_all_targets)
610675
${CMAKE_COVERAGE_DATA_DIRECTORY}/all-profraw.list \; llvm-profdata.exe
611676
merge -o ${CMAKE_COVERAGE_DATA_DIRECTORY}/ccov-all.profdata -sparse
612677
$$FILELIST
613-
DEPENDS ccov-all-run)
678+
DEPENDS ccov-all-ran)
614679
else()
615680
add_custom_command(
616681
OUTPUT ${CMAKE_COVERAGE_DATA_DIRECTORY}/ccov-all.profdata
@@ -624,7 +689,7 @@ function(add_code_coverage_all_targets)
624689
${LLVM_PROFDATA_PATH} merge -o
625690
${CMAKE_COVERAGE_DATA_DIRECTORY}/ccov-all.profdata -sparse `cat
626691
${CMAKE_COVERAGE_DATA_DIRECTORY}/all-profraw.list`
627-
DEPENDS ccov-all-run)
692+
DEPENDS ccov-all-ran)
628693
endif()
629694

630695
# Regex exclude only available for LLVM >= 7
@@ -712,8 +777,6 @@ function(add_code_coverage_all_targets)
712777
"GNU")
713778
set(COVERAGE_INFO "${CMAKE_COVERAGE_OUTPUT_DIRECTORY}/ccov-all.info")
714779

715-
add_custom_target(ccov-all-run)
716-
717780
# Exclusion regex string creation
718781
set(EXCLUDE_REGEX)
719782
foreach(EXCLUDE_ITEM ${add_code_coverage_all_targets_EXCLUDE})
@@ -747,7 +810,7 @@ function(add_code_coverage_all_targets)
747810
COMMAND ${LCOV_PATH} --ignore-errors unused --directory
748811
${CMAKE_BINARY_DIR} --capture --output-file ${COVERAGE_INFO}
749812
COMMAND ${EXCLUDE_COMMAND}
750-
DEPENDS ccov-all-run)
813+
DEPENDS ccov-all-ran)
751814
add_custom_target(ccov-all-capture DEPENDS ${COVERAGE_INFO})
752815

753816
# Only generates HTML output of all targets for perusal

0 commit comments

Comments
 (0)