Code Coverage with SonarQube#
This guide explains how to build the project with gcov instrumentation, run the unit tests, and feed the resulting coverage data into SonarQube.
Prerequisites#
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 gcovrsonar-scanner (for uploading results to SonarQube)
Quick Start#
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/TensorRT
The TRT_PACKAGE_DIR can also be supplied as an environment variable:
export TRT_PACKAGE_DIR=/usr/local/TensorRT-10.x.x
./scripts/run_coverage.sh
After the script completes, coverage data is available in build_coverage/
and SonarQube can be run immediately with sonar-scanner.
Script Options#
Flag |
Description |
Default |
|---|---|---|
|
Path to TensorRT installation (required unless |
— |
|
CUDA version to use |
|
|
Build output directory |
|
|
Google Test filter expression |
|
|
Parallel build jobs |
|
Manual Workflow#
If you need finer control you can run each step individually.
1. Configure#
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/TensorRT
The key CMake options for coverage are:
Option |
Description |
Default |
|---|---|---|
|
Enable gcov instrumentation ( |
|
|
Build the Google Test unit test binary |
|
|
Must be |
— |
|
Generate |
|
Note:
ENABLE_COVERAGEwarns at configure time ifCMAKE_BUILD_TYPEis notDebug, because compiler optimizations can cause misleading coverage results.
2. Build#
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.
3. Clear Stale Data#
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' -delete
4. Run Tests#
ctest --test-dir build_coverage --output-on-failure --parallel $(nproc) \
--output-junit build_coverage/test_results.xml
Running 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_coverage
5. Generate Reports#
Use 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.html
Open build_coverage/coverage.html in a browser for a quick local overview.
SonarQube Integration#
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.xml
sonar.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-scanner
Tip: 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
What Gets Instrumented#
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.
CI Integration Example#
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.xml
Troubleshooting#
gcov not found during CMake configure
gcov is part of the GCC toolchain. Install it with:
sudo apt install gcc
No .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).