Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kcov #711

Merged
merged 1 commit into from
Sep 12, 2024
Merged

kcov #711

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading