| # generate test code coverage report |
| |
| # check that coverage tools are available - always use before GEN_COVERAGE |
| macro(GEN_COVERAGE_ENABLE ENABLE_TESTS) |
| # make into normal variable |
| set(TESTS_ENABLED ${ENABLE_TESTS}) |
| |
| set(GEN_COVERAGE_ENABLED ON) |
| if(NOT TESTS_ENABLED) |
| message(WARNING "You cannot generate coverage when tests are disabled. Enable test by additing parameter -DENABLE_TESTS=ON or run cmake with Debug build target.") |
| set(GEN_COVERAGE_ENABLED OFF) |
| endif() |
| |
| if(GEN_COVERAGE_ENABLED) |
| find_program(PATH_GCOV NAMES gcov) |
| if(NOT PATH_GCOV) |
| message(WARNING "gcov executable not found! Disabling building code coverage report.") |
| set(GEN_COVERAGE_ENABLED OFF) |
| endif() |
| endif() |
| |
| if(GEN_COVERAGE_ENABLED) |
| find_program(PATH_LCOV NAMES lcov) |
| if(NOT PATH_LCOV) |
| message(WARNING "lcov executable not found! Disabling building code coverage report.") |
| set(GEN_COVERAGE_ENABLED OFF) |
| endif() |
| endif() |
| |
| if(GEN_COVERAGE_ENABLED) |
| find_program(PATH_GENHTML NAMES genhtml) |
| if(NOT PATH_GENHTML) |
| message(WARNING "genhtml executable not found! Disabling building code coverage report.") |
| set(GEN_COVERAGE_ENABLED OFF) |
| endif() |
| endif() |
| |
| if(GEN_COVERAGE_ENABLED) |
| if(NOT CMAKE_COMPILER_IS_GNUCC) |
| message(WARNING "Compiler is not gcc! Coverage may break the tests!") |
| endif() |
| |
| execute_process( |
| COMMAND bash "-c" "${CMAKE_C_COMPILER} --version | head -n1 | sed \"s/.* (.*) \\([0-9]\\+.[0-9]\\+.[0-9]\\+ .*\\)/\\1/\"" |
| OUTPUT_VARIABLE GCC_VERSION_FULL |
| OUTPUT_STRIP_TRAILING_WHITESPACE |
| ) |
| execute_process( |
| COMMAND bash "-c" "${PATH_GCOV} --version | head -n1 | sed \"s/.* (.*) \\([0-9]\\+.[0-9]\\+.[0-9]\\+ .*\\)/\\1/\"" |
| OUTPUT_VARIABLE GCOV_VERSION_FULL |
| OUTPUT_STRIP_TRAILING_WHITESPACE |
| ) |
| if(NOT GCC_VERSION_FULL STREQUAL GCOV_VERSION_FULL) |
| message(WARNING "gcc and gcov versions do not match! Generating coverage may fail with errors.") |
| endif() |
| |
| # add specific required compile flags |
| set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage -fprofile-arcs -ftest-coverage") |
| endif() |
| endmacro() |
| |
| # tests are always expected to be in ${CMAKE_SOURCE_DIR}/tests |
| function(GEN_COVERAGE MATCH_TEST_REGEX EXCLUDE_TEST_REGEX) |
| if(NOT GEN_COVERAGE_ENABLED) |
| return() |
| endif() |
| |
| # destination |
| set(COVERAGE_DIR "${CMAKE_BINARY_DIR}/code_coverage/") |
| set(COVERAGE_FILE_RAW "${CMAKE_BINARY_DIR}/coverage_raw.info") |
| set(COVERAGE_FILE_CLEAN "${CMAKE_BINARY_DIR}/coverage_clean.info") |
| |
| # test match/exclude |
| if(MATCH_TEST_REGEX) |
| set(MATCH_TEST_ARGS -R \"${MATCH_TEST_REGEX}\") |
| endif() |
| if(EXCLUDE_TEST_REGEX) |
| set(EXCLUDE_TEST_ARGS -E \"${EXCLUDE_TEST_REGEX}\") |
| endif() |
| |
| # coverage target |
| add_custom_target(coverage |
| COMMENT "Generating code coverage..." |
| WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" |
| # Cleanup code counters |
| COMMAND "${PATH_LCOV}" --directory . --zerocounters --quiet |
| |
| # Run tests |
| COMMAND "${CMAKE_CTEST_COMMAND}" --quiet ${MATCH_TEST_ARGS} ${EXCLUDE_TEST_ARGS} |
| |
| # Capture the counters |
| COMMAND "${PATH_LCOV}" |
| --directory . |
| --rc lcov_branch_coverage=1 |
| --rc 'lcov_excl_line=assert' |
| --capture --quiet |
| --output-file "${COVERAGE_FILE_RAW}" |
| # Remove coverage of tests, system headers, etc. |
| COMMAND "${PATH_LCOV}" |
| --remove "${COVERAGE_FILE_RAW}" '${CMAKE_SOURCE_DIR}/tests/*' |
| --rc lcov_branch_coverage=1 |
| --quiet --output-file "${COVERAGE_FILE_CLEAN}" |
| # Generate HTML report |
| COMMAND "${PATH_GENHTML}" |
| --branch-coverage --function-coverage --quiet --title "${PROJECT_NAME}" |
| --legend --show-details --output-directory "${COVERAGE_DIR}" |
| "${COVERAGE_FILE_CLEAN}" |
| # Delete the counters |
| COMMAND "${CMAKE_COMMAND}" -E remove |
| ${COVERAGE_FILE_RAW} ${COVERAGE_FILE_CLEAN} |
| ) |
| |
| add_custom_command(TARGET coverage POST_BUILD |
| WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/tests" |
| COMMENT "To see the code coverage report, open ${COVERAGE_DIR}index.html" |
| COMMAND ; |
| ) |
| endfunction() |