# gcovr: turning gcov output into the report your CI expects

> gcovr is a Python tool that manages the use of the GNU gcov utility and produces summarised code coverage results in many output formats, from plain text to Cobertura XML, JaCoCo, Clover, LCOV and SonarQube. It suits a C or C++ project that already compiles with coverage flags and wants a report a dashboard can read.

**gcovr/gcovr** — Generate code coverage reports with gcc/gcov

- Repository: https://github.com/gcovr/gcovr
- Website: https://gcovr.com/
- Stars: 995 · Forks: 292
- Language: Python
- License: NOASSERTION
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/gcovr-gcovr

## A wrapper around gcov, not a coverage tool

Gcovr provides a utility for managing the use of the GNU gcov utility and generating summarised code coverage results. That one sentence is the whole architecture, and it matters for how you position the tool.

gcov is the part of GCC that reads the note files a coverage-instrumented build leaves behind and produces per-file line and branch counts. It works, and it has worked for decades, but its native output is a set of per-file .gcov files with raw counts, and reading those directly is unpleasant. gcovr is the layer that runs gcov, merges the results, applies filters, and renders something a person or a service can read.

The project describes itself as inspired by the Python coverage.py package, which provides a similar utility for Python, and the framing is fair: coverage.py is the reference implementation of the same idea in a different language, and gcovr is the equivalent for C and C++.

It also describes itself as a command-line alternative to the lcov utility, which runs gcov and generates an HTML-formatted report, and states that the development of gcovr was motivated by the need for text summaries and XML reports. So the historical framing is lcov for HTML, gcovr for everything else, and that is still roughly the right mental model for picking between them.

The package manifest says Development Status :: 5 - Production/Stable, requires Python 3.10 or newer, and supports 3.10 through 3.14, on MacOS, Windows, POSIX and Unix. The homepage is gcovr.com, and the last push to the main branch was on 2026-10-19 with release 8.7 published on 2026-10-16.

## Fourteen output formats, and the ones that matter in a pipeline

The format list is the reason to use gcovr rather than lcov, and it is worth reading in two groups.

The human-facing formats come first. The default option produces compact human-readable summaries, and there is a text output option for the same thing in a different shape. HTML gives an overview of all files, HTML details gives annotated source files, and HTML template directory lets you supply your own set of Jinja2 templates. CSV is a report summarising the coverage of each file, and JSON gives a report with source file structure and coverage, with a JSON summary variant that is the flat version.

The machine-readable formats are the second group, and they are the reason the project was written. Clover produces machine readable XML in Clover format, Cobertura produces machine readable XML in Cobertura format, JaCoCo produces machine readable XML in JaCoCo format, and SonarQube produces machine readable XML in SonarQube format. There is an LCOV option for a machine readable report in LCOV info format, and a Coveralls option for a machine readable JSON report in Coveralls format.

The distinction between the machine-readable and the human-readable outputs is the useful part of the design. Cobertura and JaCoCo are XML schemas that Java ecosystem tools already understand, so a C++ project can publish coverage to a service that expects a Java project. LCOV is the lcov format, which is what many C and C++ CI pipelines already parse. Coveralls is the JSON that a specific hosted service consumes. SonarQube is the XML that SonarQube imports.

So the answer to which format to pick is not a matter of taste, it is a matter of what consumes the report downstream. The documentation links a separate page per output, and the JSON and Cobertura shapes are the two you are most likely to get wrong by assuming they are the same thing, since the two formats describe coverage with different structures.

## The dependency list, and what each one is for

The runtime dependencies in the project manifest are few, and each one maps to a specific capability.

Jinja2 is the template engine, and it is what makes the HTML template directory option work, letting you supply your own set of templates for the report. lxml is the XML parser, which is the dependency behind the XML output formats. Pygments is the syntax highlighter, pinned at 2.13.0 or newer, and it is what the annotated source in the HTML details output uses to colour the code. colorlog provides coloured log output. tomli and typing_extensions are conditional dependencies for Python versions below 3.11, with a comment that typing_extensions needs to be installed manually.

That last detail is the kind of thing that catches people. The manifest carries the comment that typing_extensions needs to be installed manually, and the two conditional dependencies exist only for Python below 3.11. On 3.11 and newer, all of that comes from the standard library.

The build system is hatchling with three pinned build requirements, hatchling, hatch-vcs and hatch-fancy-pypi-readme, and the version and readme are declared dynamic, so they are derived from the repository rather than written in the file. The project uses a BSD-3-Clause licence with LICENSE.txt named in the licence-files field, although the licence reported for the repository is one GitHub cannot classify, so the file itself is the authority.

The repository layout is a modern Python project: pyproject.toml, a src/ directory, tests/, doc/, scripts/, admin/, a noxfile.py for task automation, a .pre-commit-config.yaml, and a cspell.json for spell checking.

## Reading the report table before you pick a format

The abstract section in the README is laid out as a three column table, and the shape of it is worth parsing because it tells you how the project thinks about its own outputs.

The first column is the CLI option, the second is a link into the user guide, and the third is a one line description of what the format contains. Every row links to a separate page on gcovr.com, so the table is an index into the documentation rather than a summary of it.

The descriptions are more precise than the option names alone would suggest. The HTML option is an overview of all files, and HTML details is annotated source files, which is a different artefact rather than a variation of the same one. The JSON option gives a report with source file structure and coverage, and JSON summary is the flat counterpart. The CSV option is a report summarising the coverage of each file.

That distinction between a structured report and a summary report exists in most of the formats, and it is the practical point. If you are feeding a dashboard, you want the structured form, because a dashboard needs to attribute coverage to a file, a class or a function rather than to a total. If you are putting a number into a build badge or a pull request comment, the summary form is what you want, and most of the formats offer both.

Several of the machine-readable options have no summary variant listed, which is worth noticing if you were hoping for one. The Clover, Cobertura, JaCoCo and SonarQube options are described purely as machine readable XML reports, and the Coveralls option as a machine readable JSON report in Coveralls format. Those are formats defined by what consumes them, so the shape is fixed by the consumer rather than chosen by gcovr.

## Where gcovr sits relative to coverage.py and lcov

The alternatives are worth placing precisely, because the choice is not as obvious as it looks.

Against coverage.py, the difference is the language. coverage.py measures Python code. gcovr measures C and C++, and it does so with the instrumentation that the compiler inserts and gcov reads back. There is no overlap in what they can measure, and a polyglot project needs both.

Against lcov, the difference is the output format and the summary. lcov runs gcov and generates an HTML-formatted report, which the README states as the reason gcovr was developed, since text summaries and XML reports were the gap. In practice, if your pipeline ends in a Cobertura or JaCoCo consumer, gcovr is the tool; if it ends in a bare HTML page that a human opens, lcov may be enough.

There is a third dimension, and it is the one the project is explicit about. gcovr does not replace the compiler flags that produce the coverage data in the first place. A GCC or Clang build still needs the instrumentation, the build still produces the note files, and gcov still converts them. gcovr manages and summarises that output. For a team that already has this working, gcovr is an addition to the pipeline, not a replacement for a step in it.

The topics attached to the repository reflect the spread: c, clang, coverage, coverage-report, cpp, gcc, gcov, gcovr, lcov and python. The project also carries quality and coverage badges from Codacy for its own codebase, and the release history shows a steady cadence, 8.7 in October 2026, 8.6 in January 2026 and 8.5 a few days earlier.

## Conclusion

Adopt gcovr when your C or C++ build already produces gcov data and you need it in a form a CI service or a dashboard understands, because the format coverage is where lcov stops and gcovr does not, with Cobertura, JaCoCo, Clover, Coveralls and SonarQube all available from one tool. Do not adopt it as a coverage collector, since gcov or your compiler's instrumentation still does that work. Before you wire it into a pipeline, check the Python version, since 3.10 or newer is required, and read the output documentation for the format you need, since the JSON and Cobertura shapes are not interchangeable.

## FAQ

### What does gcovr do and how is it different from lcov?

Gcovr provides a utility for managing the use of the GNU gcov utility and generating summarised coverage results, and the README describes it as a command-line alternative to lcov that runs gcov and generates an HTML report. The development of gcovr was motivated by the need for text summaries and XML reports.

### Which output formats does gcovr support?

Text, HTML, HTML details with annotated source files, HTML with custom Jinja2 templates, CSV, JSON, JSON summary, Markdown and Markdown summary, plus machine readable formats in Clover XML, Cobertura XML, JaCoCo XML, Coveralls JSON, LCOV info and SonarQube XML. Each format has its own documentation page linked from the README.

### What does gcovr need to run?

Python 3.10 or newer, with 3.11 and up supported through 3.14. The runtime dependencies are jinja2 for the HTML templates, lxml for the XML output formats, pygments for syntax highlighting in annotated source, and colorlog, plus conditional tomli and typing_extensions for Python below 3.11.

### Does gcovr collect the coverage data itself?

No. Gcovr manages the use of the GNU gcov utility and summarises the results it produces, so the build still has to compile with the compiler's coverage instrumentation and produce the note files. The tool is an addition to the reporting end of the pipeline rather than a replacement for the measurement step.

## Sources

- [gcovr/gcovr on GitHub](https://github.com/gcovr/gcovr)
- [Issues](https://github.com/gcovr/gcovr/issues)
- [Project website](https://gcovr.com/)
- [README](https://github.com/gcovr/gcovr/blob/main/README.md)
- [Releases](https://github.com/gcovr/gcovr/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/gcovr-gcovr
