This guide explains how to build the project with gcov instrumentation, run the unit tests, and feed the resulting coverage data into SonarQube.
- GCC toolchain with
gcov(installed alongsideg++) - CMake 3.20+
- CUDA 12.x+ and TensorRT 10.x+
- gcovr (required, generates SonarQube coverage reports) — install with
pip install gcovr - sonar-scanner (for uploading results to SonarQube)
A convenience script handles the full workflow — configure, build, test, and report — in a single command:
./scripts/run_coverage.sh --trt-package-dir /path/to/TensorRTThe TRT_PACKAGE_DIR can also be supplied as an environment variable:
export TRT_PACKAGE_DIR=/usr/local/TensorRT-10.x.x
./scripts/run_coverage.shAfter the script completes, coverage data is available in build_coverage/
and SonarQube can be run immediately with sonar-scanner.
| Flag | Description | Default |
|---|---|---|
--trt-package-dir <path> |
Path to TensorRT installation (required unless TRT_PACKAGE_DIR is set) |
— |
--cuda-version <ver> |
CUDA version to use | 12.8 |
--build-dir <dir> |
Build output directory | build_coverage |
--gtest-filter <filter> |
Google Test filter expression | * (all tests) |
--jobs, -j <N> |
Parallel build jobs | $(nproc) |
If you need finer control you can run each step individually.
mkdir -p build_coverage
cmake -S . -B build_coverage \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DBUILD_UNIT_TESTS=ON \
-DENABLE_COVERAGE=ON \
-DTRT_PACKAGE_DIR=/path/to/TensorRTThe key CMake options for coverage are:
| Option | Description | Default |
|---|---|---|
ENABLE_COVERAGE |
Enable gcov instrumentation (--coverage flags) |
OFF |
BUILD_UNIT_TESTS |
Build the Google Test unit test binary | OFF |
CMAKE_BUILD_TYPE |
Must be Debug for accurate coverage |
— |
CMAKE_EXPORT_COMPILE_COMMANDS |
Generate compile_commands.json (required by SonarQube) |
OFF |
Note:
ENABLE_COVERAGEwarns at configure time ifCMAKE_BUILD_TYPEis notDebug, because compiler optimizations can cause misleading coverage results.
Build only the unit test target to keep compile times short:
cmake --build build_coverage --target unitTests -j$(nproc)The build produces .gcno files alongside every object file. These contain the
control-flow graph that gcov needs to map execution counts back to source lines.
If you are re-running tests after a previous coverage run, delete old .gcda
files so results are not accumulated:
find build_coverage -name '*.gcda' -deletectest --test-dir build_coverage --output-on-failure --parallel $(nproc) \
--output-junit build_coverage/test_results.xmlRunning the instrumented binaries produces .gcda files that record how many
times each basic block was executed. Every group writes into the same .gcda
set, so the report is the union of all of them.
To narrow the run, either invoke one group directly or set GTEST_FILTER, which
ctest passes through to each executable:
./build_coverage/unittests/unitTestCommon --gtest_filter="LoggerTest.*"
GTEST_FILTER="LoggerTest.*" ctest --test-dir build_coverageUse gcovr to convert the raw gcov data into reports. The SonarQube generic
coverage XML (--sonarqube) is required for coverage import:
GCOVR_COMMON="--root . \
--filter cpp/ \
--filter unittests/ \
--exclude 3rdParty/ \
--exclude '.*\.cu$' \
--gcov-ignore-errors=no_working_dir_found \
--gcov-ignore-parse-errors=all"
# SonarQube generic coverage format (required for sonar.coverageReportPaths)
gcovr $GCOVR_COMMON \
--sonarqube build_coverage/sonarqube-coverage.xml
# Cobertura XML (optional, for other CI integrations)
gcovr $GCOVR_COMMON \
--xml-pretty \
--output build_coverage/coverage.xml
# HTML with per-file detail (optional, for local viewing)
gcovr $GCOVR_COMMON \
--html-details build_coverage/coverage.htmlOpen build_coverage/coverage.html in a browser for a quick local overview.
The project's sonar-project.properties is pre-configured for coverage:
sonar.cfamily.compile-commands=build_coverage/compile_commands.json
sonar.coverageReportPaths=build_coverage/sonarqube-coverage.xmlsonar.coverageReportPathspoints to the SonarQube generic coverage XML generated bygcovr --sonarqube. This is the format SonarQube uses to import line coverage data.sonar.cfamily.compile-commandspoints to the compilation database so SonarQube can accurately parse the C++ source files.build_coverage/**is not listed insonar.sourcesto prevent SonarQube from scanning build artifacts (object files, HTML reports, etc.) as source code.
After a coverage build and test run, upload results with:
sonar-scannerTip: If your build directory is not
build_coverage, override the properties on the command line:sonar-scanner \ -Dsonar.coverageReportPaths=my_build/sonarqube-coverage.xml \ -Dsonar.cfamily.compile-commands=my_build/compile_commands.json
- C++ source files (
.cpp) — fully instrumented with line and branch coverage. - CUDA files (
.cu) — not instrumented. nvcc generates temporary stub files in/tmp/during compilation that are deleted after the build. The resulting.gcnofiles contain unresolvable source references, which causes gcov and gcovr to fail. Coverage is therefore limited to.cppfiles. - Third-party code (
3rdParty/) — excluded from coverage reports viasonar.exclusionsand gcovr--excludefilters.
Below is a minimal CI job that produces coverage for SonarQube:
coverage:
stage: test
script:
- pip install gcovr
- ./scripts/run_coverage.sh --trt-package-dir $TRT_PACKAGE_DIR
- sonar-scanner
artifacts:
paths:
- build_coverage/sonarqube-coverage.xml
- build_coverage/coverage.xml
- build_coverage/coverage.html
- build_coverage/test_results.xml
reports:
junit: build_coverage/test_results.xmlgcov not found during CMake configure
gcov is part of the GCC toolchain. Install it with:
sudo apt install gccNo .gcda files after running tests
- Verify the binary was built with
ENABLE_COVERAGE=ON(--coverageshould appear in the compile commands). - Ensure the test binary runs to completion (or at least exits normally).
Coverage data is flushed on
exit().
Coverage percentages seem too low
- Use
CMAKE_BUILD_TYPE=Debugto prevent the compiler from optimizing away branches. - Make sure you cleared old
.gcdafiles before the test run so you are not mixing stale data.
SonarQube shows 0% coverage
- Confirm
sonar.coverageReportPathspoints to thesonarqube-coverage.xmlfile generated bygcovr --sonarqube. - Confirm
sonar.cfamily.compile-commandspoints to a validcompile_commands.jsongenerated by the same build. - Run
sonar-scannerfrom the repository root so relative paths insonar-project.propertiesresolve correctly. - Verify the source file paths inside
sonarqube-coverage.xmlmatch the files that SonarQube is analyzing (paths must be relative to the project root or absolute).