|
1 | | -find_program(GCOVR gcovr) |
2 | 1 | find_program(LLVM_COV llvm-cov) |
| 2 | +find_program(LLVM_PROFDATA llvm-profdata) |
3 | 3 |
|
4 | | -set(COVERAGE_DIR "${PROJECT_BINARY_DIR}/coverage") |
5 | | -set(COVERAGE_HTML_REPORT "${COVERAGE_DIR}/report.html") |
6 | | -set(COVERAGE_XML_REPORT "${COVERAGE_DIR}/report.xml") |
| 4 | +if(NOT LLVM_COV OR NOT LLVM_PROFDATA) |
| 5 | + message(FATAL_ERROR "Required LLVM coverage tools not found.") |
| 6 | +endif() |
| 7 | + |
| 8 | +set(CODE_COVERAGE_DIR "${PROJECT_BINARY_DIR}/coverage") |
| 9 | +set(CODE_COVERAGE_HTML_REPORT ${CODE_COVERAGE_DIR}/index.html) |
| 10 | +list(APPEND CODE_COVERAGE_FLAGS |
| 11 | + -fcoverage-mapping |
| 12 | + -fprofile-instr-generate |
| 13 | +) |
7 | 14 |
|
8 | | -set(target_name "coverage-report") |
9 | | -if(NOT GCOVR OR NOT LLVM_COV) |
10 | | - set(MSG "${target_name} is a dummy target") |
11 | | - add_custom_target(${target_name} |
12 | | - COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --red ${MSG} |
| 15 | +# Clang Version 18.1.0 was the first release with full, native |
| 16 | +# support for MC/DC coverage analysis using the source-based code |
| 17 | +# coverage feature. |
| 18 | +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND |
| 19 | + CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "18.1") |
| 20 | + list(APPEND CODE_COVERAGE_FLAGS |
| 21 | + -fcoverage-mcdc |
13 | 22 | ) |
14 | | - message(WARNING "Either `gcovr' or `llvm-cov` not found, " |
15 | | - "so ${target_name} target is dummy.") |
16 | | - return() |
17 | 23 | endif() |
18 | 24 |
|
19 | | -# See https://gcovr.com/en/stable/manpage.html. |
20 | | -set(GCOVR_OPTIONS |
21 | | - --txt-metric branch |
22 | | - --cobertura ${COVERAGE_XML_REPORT} |
23 | | - --decisions |
24 | | - --gcov-executable "llvm-cov gcov" |
25 | | - --html |
26 | | - --html-details |
27 | | - --html-title "Code Coverage Report" |
28 | | - -j ${CMAKE_BUILD_PARALLEL_LEVEL} |
29 | | - --output ${COVERAGE_HTML_REPORT} |
30 | | - --print-summary |
31 | | - --root ${LUA_SOURCE_DIR} |
32 | | - --sort-key uncovered-percent |
| 25 | +file(MAKE_DIRECTORY ${CODE_COVERAGE_DIR}) |
| 26 | + |
| 27 | +list(APPEND LLVM_COV_PROFRAW_MASK |
| 28 | + ${PROJECT_BINARY_DIR}/tests/capi/*.profraw |
| 29 | + ${PROJECT_BINARY_DIR}/tests/lapi/*.profraw |
| 30 | +) |
| 31 | +set(LLVM_COV_PROFDATA ${PROJECT_BINARY_DIR}/tests/default.profdata) |
| 32 | + |
| 33 | +list(APPEND LLVM_COV_FLAGS |
| 34 | + -instr-profile=${LLVM_COV_PROFDATA} |
| 35 | + -output-dir=${CODE_COVERAGE_DIR} |
| 36 | + --show-branches=count |
| 37 | + --show-expansions |
| 38 | + --show-mcdc |
| 39 | + --show-mcdc-summary |
33 | 40 | ) |
34 | 41 |
|
| 42 | +# XXX: This variable is defined in BuildLua.cmake and |
| 43 | +# BuildLuaJIT.cmake. However, these modules are included after |
| 44 | +# CodeCoverage.cmake, so not available. |
| 45 | +set(LUA_EXECUTABLE ${PROJECT_BINARY_DIR}/luajit-v2.1/source/src/luajit) |
35 | 46 | if(USE_LUA) |
36 | | - set(GCOVR_OPTIONS ${GCOVR_OPTIONS} --object-directory ${LUA_SOURCE_DIR}) |
37 | | -endif () |
38 | | - |
39 | | -if(IS_LUAJIT) |
40 | | - # Exclude DynASM files, that contain a low-level VM code for CPUs. |
41 | | - set(GCOVR_OPTIONS ${GCOVR_OPTIONS} --exclude ".*\.dasc") |
42 | | - # Exclude buildvm source code, it's a project's build infrastructure. |
43 | | - set(GCOVR_OPTIONS ${GCOVR_OPTIONS} --exclude ".*/host/") |
44 | | - set(GCOVR_OPTIONS ${GCOVR_OPTIONS} --object-directory ${LUA_SOURCE_DIR}/src) |
45 | | -endif () |
| 47 | + set(LUA_EXECUTABLE ${PROJECT_BINARY_DIR}/lua-master/source/lua) |
| 48 | +endif() |
46 | 49 |
|
47 | | -file(MAKE_DIRECTORY ${COVERAGE_DIR}) |
48 | | -add_custom_target(${target_name}) |
49 | | -add_custom_command(TARGET ${target_name} |
50 | | - COMMENT "Building coverage report" |
51 | | - COMMAND ${GCOVR} ${GCOVR_OPTIONS} |
| 50 | +add_custom_target(coverage-report |
| 51 | + COMMAND ${LLVM_PROFDATA} merge -sparse ${LLVM_COV_PROFRAW_MASK} |
| 52 | + -o ${LLVM_COV_PROFDATA} |
| 53 | + COMMAND ${LLVM_COV} show --format=html ${LLVM_COV_FLAGS} ${LUA_EXECUTABLE} |
52 | 54 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} |
| 55 | + COMMENT "Generating HTML code coverage report in ${CODE_COVERAGE_DIR}" |
53 | 56 | ) |
54 | 57 |
|
55 | | -# The .gcda count data file is generated when a program containing |
56 | | -# object files built with the GCC -fprofile-arcs option is executed. |
57 | | -# https://gcc.gnu.org/onlinedocs/gcc/Gcov-Data-Files.html |
58 | | -set(GCDA_FILES "${LUA_SOURCE_DIR}/*.gcda") |
59 | | -if(IS_LUAJIT) |
60 | | - # Files 'src/host/*.gcda' are not removed, because |
61 | | - # CMake cannot remove recursively by globbing. |
62 | | - # Files 'src/host/*.gcda' are not used for building coverage report. |
63 | | - set(GCDA_FILES "${LUA_SOURCE_DIR}/src/*.gcda") |
64 | | -endif() |
65 | 58 | add_custom_target(coverage-reset |
66 | 59 | COMMENT "Reset code coverage counters" |
67 | | - COMMAND ${CMAKE_COMMAND} -E rm -f ${GCDA_FILES} |
| 60 | + COMMAND ${CMAKE_COMMAND} -E rm -f ${LLVM_COV_PROFRAW_MASK} ${LLVM_COV_PROFDATA} |
68 | 61 | ) |
69 | 62 |
|
70 | | -message(STATUS "Code coverage HTML report: ${COVERAGE_HTML_REPORT}") |
71 | | -message(STATUS "Code coverage XML report: ${COVERAGE_XML_REPORT}") |
| 63 | +message(STATUS "Code coverage HTML report: ${CODE_COVERAGE_HTML_REPORT}") |
0 commit comments