Skip to content

Commit f718561

Browse files
authored
[PTI-LIB] Generate Code Coverage Report (#471)
Generate a code coverage report after running our tests using Clang's source-based code coverage. https://clang.llvm.org/docs/SourceBasedCodeCoverage.html Provides a summary, lcov exported data, and html report. Added a Python script for including all the test binaries in the report via `llvm-cov`. Signed-off-by: Schilling, Matthew <[email protected]>
1 parent 29abec8 commit f718561

File tree

4 files changed

+456
-1
lines changed

4 files changed

+456
-1
lines changed

sdk/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,10 @@ if(BUILD_TESTING AND PTI_FUZZ)
293293
add_subdirectory(fuzz)
294294
endif()
295295

296+
if(PROJECT_IS_TOP_LEVEL AND BUILD_TESTING)
297+
include(cmake/coverage.cmake)
298+
endif()
299+
296300
# Targets / Install phase
297301
export(
298302
TARGETS pti_all pti pti_view pti_metrics

sdk/CMakePresets.json

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
"CMAKE_EXE_LINKER_FLAGS": "-Wl,-z,relro,-z,now,-z,noexecstack"
3232
}
3333
},
34-
3534
{
3635
"name": "linux-icpx-debug",
3736
"displayName": "Linux Debug x64 IntelLLVM Ninja Config",
@@ -46,6 +45,22 @@
4645
"PTI_ENABLE_LOGGING": "ON"
4746
}
4847
},
48+
{
49+
"name": "linux-cov",
50+
"displayName": "Linux Code Coverage",
51+
"description": "Linux Source-based Code Coverage Config",
52+
"generator": "Ninja",
53+
"binaryDir": "${sourceDir}/build-${presetName}",
54+
"cacheVariables": {
55+
"CMAKE_BUILD_TYPE": "Coverage",
56+
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/icpx_toolchain.cmake",
57+
"CMAKE_CXX_FLAGS_COVERAGE": "-g3 -O0 -Xarch_host -fprofile-instr-generate -Xarch_host -fcoverage-mapping -Xarch_host -mllvm=-runtime-counter-relocation=true",
58+
"CMAKE_C_FLAGS_COVERAGE": "-g3 -O0 -Xarch_host -fprofile-instr-generate -Xarch_host -fcoverage-mapping -Xarch_host -mllvm=-runtime-counter-relocation=true",
59+
"CMAKE_SHARED_LINKER_FLAGS_COVERAGE": "-Xarch_host -fprofile-instr-generate",
60+
"CMAKE_EXE_LINKER_FLAGS_COVERAGE": "-Xarch_host -fprofile-instr-generate",
61+
"PTI_ENABLE_LOGGING": "ON"
62+
}
63+
},
4964
{
5065
"name": "linux-icpx-make-release",
5166
"inherits": "linux-icpx-release",
@@ -180,6 +195,21 @@
180195
"CMAKE_EXE_LINKER_FLAGS": "/DEPENDENTLOADFLAG:0x2000 /DYNAMICBASE /NXCOMPAT /guard:cf"
181196
}
182197
},
198+
{
199+
"name": "windows-cov",
200+
"displayName": "Windows Code Coverage",
201+
"description": "Windows Source-based Code Coverage Config",
202+
"generator": "Ninja",
203+
"binaryDir": "${sourceDir}/build-${presetName}",
204+
"cacheVariables": {
205+
"CMAKE_BUILD_TYPE": "Coverage",
206+
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/toolchains/icpx_toolchain.cmake",
207+
"CMAKE_CXX_FLAGS_COVERAGE": "/MD /EHcs /fp:precise -Qstd:c++17 /Zi -fprofile-instr-generate -fcoverage-mapping",
208+
"CMAKE_SHARED_LINKER_FLAGS_COVERAGE": "-fprofile-instr-generate",
209+
"CMAKE_EXE_LINKER_FLAGS_COVERAGE": "-fprofile-instr-generate",
210+
"PTI_ENABLE_LOGGING": "ON"
211+
}
212+
},
183213
{
184214
"name": "windows-ci-release",
185215
"displayName": "Windows CI Release Config",
@@ -261,6 +291,11 @@
261291
"configurePreset": "linux-icpx-debug",
262292
"displayName": "Linux Debug x64 IntelLLVM Ninja Build"
263293
},
294+
{
295+
"name": "linux-cov",
296+
"configurePreset": "linux-cov",
297+
"displayName": "Linux Source-Based Code Coverage Build"
298+
},
264299
{
265300
"name": "linux-icpx-make-release",
266301
"configurePreset": "linux-icpx-make-release",
@@ -316,6 +351,11 @@
316351
"displayName": "Windows Release x64 IntelLLVM Build",
317352
"configurePreset": "windows-icx-release"
318353
},
354+
{
355+
"name": "windows-cov",
356+
"configurePreset": "windows-cov",
357+
"displayName": "Windows Source-Based Code Coverage Build"
358+
},
319359
{
320360
"name": "windows-ci-release",
321361
"displayName": "Windows CI Release Build",
@@ -357,6 +397,15 @@
357397
"LD_LIBRARY_PATH": "${sourceDir}/build-${presetName}/lib:$penv{LD_LIBRARY_PATH}"
358398
}
359399
},
400+
{
401+
"name": "linux-cov",
402+
"configurePreset": "linux-cov",
403+
"displayName": "Linux Test With Code Coverage",
404+
"environment": {
405+
"LD_LIBRARY_PATH": "${sourceDir}/build-${presetName}/lib:$penv{LD_LIBRARY_PATH}",
406+
"LLVM_PROFILE_FILE": "${sourceDir}/build-${presetName}/coverage/raw/pti-cov.%p.profraw"
407+
}
408+
},
360409
{
361410
"name": "linux-icpx-make-release",
362411
"configurePreset": "linux-icpx-make-release",
@@ -423,6 +472,15 @@
423472
"displayName": "Windows Release x64 IntelLLVM Test",
424473
"configurePreset": "windows-icx-release"
425474
},
475+
{
476+
"name": "windows-cov",
477+
"configurePreset": "windows-cov",
478+
"displayName": "Windows Test With Code Coverage",
479+
"environment": {
480+
"PATH": "${sourceDir}/build-${presetName}/bin;$penv{PATH}",
481+
"LLVM_PROFILE_FILE": "${sourceDir}/build-${presetName}/coverage/raw/pti-cov.%p.profraw"
482+
}
483+
},
426484
{
427485
"name": "windows-oneAPI-release",
428486
"configurePreset": "windows-oneAPI-release",

sdk/cmake/coverage.cmake

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
RequirePythonInterp()
2+
3+
if(DEFINED PTI_INSTALL)
4+
set(PTI_INSTALL_COVERAGE
5+
${PTI_INSTALL}
6+
CACHE
7+
BOOL
8+
"Option to install coverage artifacts.")
9+
else()
10+
set(PTI_INSTALL_COVERAGE
11+
ON
12+
CACHE
13+
BOOL
14+
"Option to install coverage artifacts.")
15+
endif()
16+
17+
set(DEFAULT_PROFDATA_MERGE_FILENAME
18+
"pti-cov.profdata"
19+
CACHE
20+
STRING
21+
"Default filename of merged data (i.e., output from llvm-profdata)")
22+
23+
#
24+
# Source coverage file structure
25+
#
26+
# <src>
27+
# <src>/<bin>/coverage
28+
# <src>/<bin>/coverage/raw (raw data generated from tests)
29+
# <src>/<bin>/coverage/html (html report)
30+
# <src>/<bin>/coverage/*.info (exported lcov for 3rd party integration)
31+
# <src>/<bin>/coverage/*.profdata (merged raw data use to generate output)
32+
#
33+
34+
if(NOT PTI_COVERAGE_DIR)
35+
set(PTI_COVERAGE_DIR ${PROJECT_BINARY_DIR}/coverage)
36+
set(PTI_COVERAGE_RAW_DIR ${PTI_COVERAGE_DIR}/raw)
37+
endif()
38+
39+
if(NOT PTI_PROFDATA_MERGE_FILENAME)
40+
set(PTI_PROFDATA_MERGE_FILENAME ${DEFAULT_PROFDATA_MERGE_FILENAME})
41+
endif()
42+
43+
set(PTI_PROFDATA_MERGE_OUTPUT
44+
${PTI_COVERAGE_DIR}/${PTI_PROFDATA_MERGE_FILENAME})
45+
46+
set(THIRD_PARTY_SRC_DIR ".*_deps*")
47+
48+
if(FETCHCONTENT_BASE_DIR)
49+
set(THIRD_PARTY_SRC_DIR "${THIRD_PARTY_SRC_DIR}|${FETCHCONTENT_BASE_DIR}/*")
50+
file(TO_NATIVE_PATH "${THIRD_PARTY_SRC_DIR}" THIRD_PARTY_SRC_DIR)
51+
endif()
52+
53+
# CMPLR_ROOT -> prefer Intel oneAPI compiler bundled llvm
54+
if(NOT LLVM_PROFDATA_PROG)
55+
find_program(
56+
LLVM_PROFDATA_PROG llvm-profdata
57+
HINTS ENV CMPLR_ROOT
58+
PATH_SUFFIXES bin bin/compiler)
59+
endif()
60+
61+
if(NOT LLVM_COV_PROG)
62+
find_program(
63+
LLVM_COV_PROG llvm-cov
64+
HINTS ENV CMPLR_ROOT
65+
PATH_SUFFIXES bin bin/compiler)
66+
endif()
67+
68+
if(NOT LLVM_PROFDATA_PROG)
69+
return()
70+
endif()
71+
72+
if(NOT LLVM_COV_PROG)
73+
return()
74+
endif()
75+
76+
add_custom_command(
77+
OUTPUT ${PTI_PROFDATA_MERGE_OUTPUT}
78+
COMMAND ${LLVM_PROFDATA_PROG} merge -output=${PTI_PROFDATA_MERGE_OUTPUT}
79+
${PTI_COVERAGE_RAW_DIR}/*.profraw
80+
DEPENDS ${PTI_COVERAGE_RAW_DIR})
81+
82+
set(CODE_COVERAGE_BASE_CMD
83+
${Python_EXECUTABLE}
84+
${PROJECT_SOURCE_DIR}/cmake/generate_coverage_report.py
85+
--llvm-cov
86+
${LLVM_COV_PROG}
87+
--objects
88+
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
89+
${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
90+
--data
91+
${PTI_PROFDATA_MERGE_OUTPUT}
92+
--sources
93+
${PROJECT_SOURCE_DIR}/include
94+
${PROJECT_SOURCE_DIR}/src
95+
${PROJECT_BINARY_DIR}
96+
--extra=-ignore-filename-regex=${THIRD_PARTY_SRC_DIR})
97+
98+
add_custom_target(
99+
coverage_summary
100+
COMMAND ${CODE_COVERAGE_BASE_CMD} --summary
101+
DEPENDS ${PTI_PROFDATA_MERGE_OUTPUT}
102+
COMMENT "Generate coverage summary"
103+
VERBATIM)
104+
105+
add_custom_target(
106+
coverage_report
107+
COMMAND ${CODE_COVERAGE_BASE_CMD} --lcov ${PTI_COVERAGE_DIR}/coverage.info
108+
COMMAND ${CODE_COVERAGE_BASE_CMD} --output-dir ${PTI_COVERAGE_DIR}/html
109+
DEPENDS ${PTI_PROFDATA_MERGE_OUTPUT}
110+
COMMENT "Generate html coverage report along with lcov export data."
111+
VERBATIM)
112+
113+
if(PTI_INSTALL_COVERAGE)
114+
install(
115+
DIRECTORY "${PTI_COVERAGE_DIR}/"
116+
CONFIGURATIONS Coverage
117+
DESTINATION coverage
118+
COMPONENT Pti_Coverage_Data)
119+
120+
install(
121+
DIRECTORY "${PTI_COVERAGE_DIR}/html"
122+
CONFIGURATIONS Coverage
123+
DESTINATION ${CMAKE_INSTALL_DOCDIR}/coverage
124+
COMPONENT Pti_Coverage_HTML)
125+
endif()

0 commit comments

Comments
 (0)