Skip to content

Commit

Permalink
kcov
Browse files Browse the repository at this point in the history
  • Loading branch information
nim65s committed Sep 7, 2024
1 parent 51a0ab3 commit 181cc39
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 74 deletions.
85 changes: 18 additions & 67 deletions coverage.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 $<$<BOOL:ENABLE_COVERAGE>:--coverage>)
target_link_options(${target} PRIVATE $<$<BOOL:ENABLE_COVERAGE>:--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()
Expand Down
25 changes: 18 additions & 7 deletions test.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 181cc39

Please sign in to comment.