From 181cc39fce81d108788aec817b3e56dac4f4ac82 Mon Sep 17 00:00:00 2001 From: Guilhem Saurel Date: Fri, 6 Sep 2024 16:51:59 +0200 Subject: [PATCH] kcov --- coverage.cmake | 85 +++++++++++--------------------------------------- test.cmake | 25 ++++++++++----- 2 files changed, 36 insertions(+), 74 deletions(-) diff --git a/coverage.cmake b/coverage.cmake index 55f971ed8..6a626a240 100644 --- a/coverage.cmake +++ b/coverage.cmake @@ -4,9 +4,6 @@ # Author: Guilhem Saurel # -set_property(GLOBAL PROPERTY JRL_CMAKEMODULES_HAS_CPP_COVERAGE OFF) -set_property(GLOBAL PROPERTY JRL_CMAKEMODULES_HAS_PYTHON_COVERAGE OFF) - # .rst: .. ifmode:: internal # # .. variable:: ENABLE_COVERAGE @@ -23,76 +20,30 @@ endif() # # .. command:: enable_coverage # -# Configure a target with --coverage compilation and link flags if the -# ENABLE_COVERAGE option is ON +# Deprecated and useless. function(enable_coverage target) - set_property(GLOBAL PROPERTY JRL_CMAKEMODULES_HAS_CPP_COVERAGE ON) - target_compile_options(${target} - PRIVATE $<$:--coverage>) - target_link_options(${target} PRIVATE $<$:--coverage>) + message( + WARNING + "the 'enable_coverage' CMake function is deprecated and does nothing.") endfunction() -macro(_SETUP_COVERAGE_FINALIZE) - get_property(_CPP_COVERAGE GLOBAL PROPERTY JRL_CMAKEMODULES_HAS_CPP_COVERAGE) - get_property(_PYTHON_COVERAGE GLOBAL - PROPERTY JRL_CMAKEMODULES_HAS_PYTHON_COVERAGE) - - if(ENABLE_COVERAGE AND (_CPP_COVERAGE OR _PYTHON_COVERAGE)) - find_program(GENHTML genhtml) - if(NOT GENHTML) - message(FATAL_ERROR "genhtml is required with ENABLE_COVERAGE=ON") - endif() - - set(_COVERAGE_DIR "coverage") - set(_COVERAGE_HTML ${GENHTML}) - set(_COVERAGE_FILES "") - - if(_CPP_COVERAGE) - find_program(LCOV lcov) - if(NOT LCOV) - message( - FATAL_ERROR - "lcov is required with ENABLE_COVERAGE=ON and enable_coverage() on C/C++ target" - ) - endif() - add_custom_command( - OUTPUT cpp.lcov - COMMAND ${LCOV} --include "${PROJECT_SOURCE_DIR}/\\*" -c -d - ${PROJECT_SOURCE_DIR} -o cpp.lcov - COMMENT "Generating code coverage data for C++") - set(_COVERAGE_HTML ${_COVERAGE_HTML} -p ${PROJECT_SOURCE_DIR}) - set(_COVERAGE_FILES ${_COVERAGE_FILES} cpp.lcov) - message(STATUS "C/C++ coverage will be generated for enabled targets") - endif() - - if(_PYTHON_COVERAGE) - execute_process(COMMAND ${PYTHON_EXECUTABLE} -m coverage - RESULT_VARIABLE _cov_ret) - if(_cov_ret EQUAL 1) - message( - FATAL_ERROR "coverage.py required for python with ENABLE_COVERAGE=ON") - endif() - add_custom_command( - OUTPUT python.lcov - COMMAND ${PYTHON_EXECUTABLE} -m coverage combine - COMMAND ${PYTHON_EXECUTABLE} -m coverage lcov -o python.lcov - BYPRODUCTS .coverage - COMMENT "Generating code coverage data for Python") - set(_COVERAGE_HTML ${_COVERAGE_HTML} -p - ${CMAKE_INSTALL_PREFIX}/${PYTHON_SITELIB}) - set(_COVERAGE_FILES ${_COVERAGE_FILES} python.lcov) - message(STATUS "Python coverage will be generated") - endif() +if(ENABLE_COVERAGE) + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -O0 -g --coverage" + CACHE STRING "coverage flags") + find_program( + KCOV kcov DOC "kcov is required for use with -DENABLE_COVERAGE=ON" REQUIRED) + set(KCOV_DIR "${CMAKE_BINARY_DIR}/kcov") + file(MAKE_DIRECTORY ${KCOV_DIR}) +endif() - if(NOT TARGET coverage) - add_custom_target(coverage - COMMENT "Generating HTML report for code coverage") - endif() +macro(_SETUP_COVERAGE_FINALIZE) + if(NOT TARGET coverage) + add_custom_target(coverage + COMMENT "Generating HTML report for code coverage") add_custom_target( ${PROJECT_NAME}-coverage - COMMAND ${_COVERAGE_HTML} -o ${_COVERAGE_DIR} ${_COVERAGE_FILES} - DEPENDS ${_COVERAGE_FILES} - BYPRODUCTS ${_COVERAGE_DIR} + COMMAND ${KCOV} --merge ${CMAKE_BINARY_DIR}/coverage ${KCOV_DIR}/* COMMENT "Generating HTML report for code coverage") add_dependencies(coverage ${PROJECT_NAME}-coverage) endif() diff --git a/test.cmake b/test.cmake index 9cb9dbb3b..aed79eb32 100644 --- a/test.cmake +++ b/test.cmake @@ -102,7 +102,12 @@ macro(ADD_UNIT_TEST NAME) add_dependencies(build_tests ${NAME}) - add_test(NAME ${NAME} COMMAND ${NAME}) + if(ENABLE_COVERAGE) + add_test(NAME ${NAME} COMMAND ${KCOV} --include-path=${CMAKE_SOURCE_DIR} + ${KCOV_DIR}/${NAME} ${NAME}) + else() + add_test(NAME ${NAME} COMMAND ${NAME}) + endif() # Support definition of DYLD_LIBRARY_PATH for OSX systems if(APPLE) set_tests_properties( @@ -182,22 +187,28 @@ endfunction() # macro(ADD_PYTHON_UNIT_TEST NAME SOURCE) if(ENABLE_COVERAGE) - set_property(GLOBAL PROPERTY JRL_CMAKEMODULES_HAS_PYTHON_COVERAGE ON) - set(PYTHONPATH "${CMAKE_INSTALL_PREFIX}/${PYTHON_SITELIB}") + # run this python test to gather C++ coverage of python bindings add_test( NAME ${NAME} - COMMAND ${PYTHON_EXECUTABLE} -m coverage run --branch -p - --source=${PYTHONPATH} "${PROJECT_SOURCE_DIR}/${SOURCE}" - WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) + COMMAND ${KCOV} --include-path=${CMAKE_SOURCE_DIR} ${KCOV_DIR}/${NAME} + ${PYTHON_EXECUTABLE} "${PROJECT_SOURCE_DIR}/${SOURCE}") + # run this python test again, but this time to gather python coverage + add_test(NAME ${NAME}-pycov + COMMAND ${KCOV} --include-path=${CMAKE_SOURCE_DIR} + ${KCOV_DIR}/${NAME} "${PROJECT_SOURCE_DIR}/${SOURCE}") else() add_test(NAME ${NAME} COMMAND ${PYTHON_EXECUTABLE} "${PROJECT_SOURCE_DIR}/${SOURCE}") - set(PYTHONPATH) endif() set(MODULES "${ARGN}") # ARGN is not a variable + set(PYTHONPATH) compute_pythonpath(ENV_VARIABLES ${MODULES}) set_tests_properties(${NAME} PROPERTIES ENVIRONMENT "${ENV_VARIABLES}") + if(ENABLE_COVERAGE) + set_tests_properties(${NAME}-pycov PROPERTIES ENVIRONMENT + "${ENV_VARIABLES}") + endif() endmacro( ADD_PYTHON_UNIT_TEST NAME