gcovr - Man Page

Name

gcovr — gcovr Documentation

Gcovr provides a utility for managing the use of the GNU gcov <https://gcc.gnu.org/onlinedocs/gcc/Gcov.html> utility and generating summarized code coverage results. This command is inspired by the Python coverage.py <https://coverage.readthedocs.io/> package, which provides a similar utility for Python.

The gcovr command can produce different kinds of coverage reports:

CLI OptionUser GuideDescription
default, --txt <#cmdoption-gcovr-txt>Text Output <#txt-output>compact human-readable summaries
--html <#cmdoption-gcovr-html>HTML Output <#html-output>overview of all files
--html-details <#cmdoption-gcovr-html-details>HTML Output <#html-output>annotated source files
--html-template-dir <#cmdoption-gcovr-html-template-dir>HTML Output <#html-output>use custom set of Jinja2 templates
--csv <#cmdoption-gcovr-csv>CSV Output <#csv-output>CSV report summarizing the coverage of each file
--json <#cmdoption-gcovr-json>JSON Output <#json-output>JSON report with source file structure and coverage
--json-summary <#cmdoption-gcovr-json-summary>JSON Output <#json-output>JSON summary coverage report
--markdown <#cmdoption-gcovr-markdown>Markdown Output <#markdown-output>Markdown coverage report
--markdown-summary <#cmdoption-gcovr-markdown-summary>Markdown Output <#markdown-output>Markdown summary coverage report
--clover <#cmdoption-gcovr-clover>Clover XML Output <#clover-output>machine readable XML reports in Clover <https://bitbucket.org/atlassian/clover/src/master/> format
--cobertura <#cmdoption-gcovr-cobertura>Cobertura XML Output <#cobertura-output>machine readable XML reports in Cobertura <https://github.com/cobertura/cobertura/> format
--coveralls <#cmdoption-gcovr-coveralls>Coveralls JSON Output <#coveralls-output>machine readable JSON report in Coveralls <https://coveralls.io/> format
--jacoco <#cmdoption-gcovr-jacoco>JaCoCo XML Output <#jacoco-output>machine readable XML reports in JaCoCo <https://www.eclemma.org/jacoco/> format
--lcov <#cmdoption-gcovr-lcov>LCOV info Output <#lcov-output>machine readable report in LCOV <https://github.com/linux-test-project/lcov> info format
--sonarqube <#cmdoption-gcovr-sonarqube>SonarQube XML Output <#sonarqube-xml-output>machine readable XML reports in SonarQube <https://www.sonarsource.com/products/sonarqube/> format

Thus, gcovr can be viewed as a command-line alternative to the lcov <https://github.com/linux-test-project/lcov> utility, which runs gcov and generates an HTML-formatted report. The development of gcovr was motivated by the need for text summaries and XML reports.

Quick Links

This documentation (<https://gcovr.com/>) describes gcovr 8.6.

Installation

Gcovr is available as a Python package that can be installed via pip <https://pip.pypa.io/en/stable>.

Install newest stable gcovr release from PyPI:

pip install gcovr

Install development version from GitHub (needs at least version 21.3 of pip):

pip install git+https://github.com/gcovr/gcovr.git

Which environments does gcovr support?

Python:

3.10+.

The automated tests run on CPython (versions 3.10, 3.11, 3.12, 3.13) and a compatible PyPy3. Gcovr will only run on Python versions with upstream support.

Last gcovr release for old Python versions:

Pythongcovr
2.63.4
2.74.2
3.44.1
3.54.2
3.65.0
3.76.0
3.88.2
3.98.5
Operating System:

Linux, Windows, and macOS.

The automated tests run on:

  • Ubuntu 20.04, 22.04 and 24.04
  • Windows Server 2022 and 2025
  • MacOS 14 and 15.
Compiler:

GCC and Clang. The versions used for development tests are documented in the contribution guide <#development-environment>.

Getting Started

The gcovr command provides a summary of the lines that have been executed in a program.  Code coverage statistics help you discover untested parts of a program, which is particularly important when assessing code quality.  Well-tested code is a characteristic of high quality code, and software developers often assess code coverage statistics when deciding if software is ready for a release.

GCC can instrument the executables to emit coverage data. You need to recompile your code with the following flags:

--coverage -g -O0

Next, run your test suite. This will generate raw coverage files.

Finally, invoke gcovr. This will print a tabular report on the console.

gcovr

You can also generate detailed or nested HTML reports:

gcovr --html-details coverage.html
gcovr --html-nested coverage.html

Gcovr will create one HTML report per source file and for --html-nested also per directory next to the coverage.html summary.

You should run gcovr from the build directory. The -r option should point to the root of your project. This only matters if you have a separate build directory. For example:

cd build; gcovr -r ..

What to read next

The User Guide <#guide> explains how to use the features of gcovr. In particular:

  • Compiling for Coverage <#compiling>
  • Output Formats <#output-formats>
  • Using Filters <#filters>

The Command Line Reference <#manpage> provides an overview of all options.

Specific problems might be addressed in the Cookbook <#cookbook> or the Frequently Asked Questions <#faq>.

User Guide

The user guide describes the various features of gcovr. It assumes you have read the Getting Started <#getting-started> guide.

This User Guide provides the following sections:

Compiling for Coverage

In order to collect coverage data, your software must be “instrumented” by the compiler. That means, you must re-compile your software with special compiler options.

The general workflow is:

  1. compile your software to enable coverage profiling
  2. execute your software to collect coverage profiles
  3. run gcovr to create reports from the collected coverage profiling data

This document explains how you can use GCC or Clang to compile with coverage instrumentation.

If you cannot compile your software with coverage flags, you cannot use gcovr. However, other tools like kcov <https://github.com/SimonKagstrom/kcov> might help.

Example Code

The following example.cpp program is used to illustrate the compilation process:

// example.cpp

int foo(int param)
{
    if (param)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

int main(int argc, char* argv[])
{
    foo(0);

    return 0;
}

This code executes several subroutines in this program, but some lines in the program are not executed.

Compiler Options

We compile example.cpp with the GCC compiler as follows:

g++ -fprofile-arcs -ftest-coverage -fPIC -O0 example.cpp -o program

What do these compiler flags mean?

  • We compile without optimization (-O0), because optimizations may merge lines of code or otherwise change the flow of execution in the program. This can change the measured coverage.

    On the other hand, enabling basic optimizations with -O1 can sometimes produce “better” coverage reports, especially for C++. This is a matter of personal preference, just make sure to avoid comparing coverage metrics across optimization levels.

    If you are having problems with lots of uncovered branches, see: Why does C++ code have so many uncovered branches? <#exception-branches>

  • Either --coverage or  -fprofile-arcs -ftest-coverage are needed so that the compiler produces the information necessary to gather coverage data.

    With these options, the compiler adds logic to the output program that counts how often which part of the code was executed. The compiler will also create a example.gcno file with metadata. The name of the gcno file matches the compilation unit (see below).

Optional compiler flags:

  • You can use other flags like -g or -fPIC as required by your tests. These don't affect the coverage results.
  • Using -fprofile-abs-path (available since GCC 8) can avoid some problems with interpreting the coverage data correctly. By default, the additional coverage files generated by GCC contain relative paths from the working directory to the source files. If there are multiple potential working directories from which you might have run the compiler, gcovr can get confused. Adding this option is more robust.

This examples uses the g++ compiler for C++ code, but any GCC or Clang-based compiler should work.

To use the clang source based code coverage instead of gcov code coverage format you need to compile with -fprofile-instr-generate and -fcoverage-mapping instead of the flags above. In addition you need to configure --llvm-profdata-executable <#cmdoption-gcovr-llvm-profdata-executable> and --llvm-cov-binary <#cmdoption-gcovr-llvm-cov-binary>.

Following format versions of LLVM are supported: - 2.0.0: This version is produced by clang-10. - 2.0.1: This version is produced by clang-11 to clang-20 but the entries differ for several compiler versions:

  • clang-11: Difference to version 2.0.0 is that the segments got an additional flag if a GAP region was entered.
  • clang-12: Branches where added.
  • clang-18: MC/DC coverage is added if code is compiled with -fcoverage-mcdc. gcovr ignores this information in the current version.

If you are using CMake, see Out-of-Source Builds with CMake <#oos-cmake> for information on configuring that build system to compile your software with coverage enabled.

Added in version 8.5: Added support for LLVM source based code coverage.

Running the Program

The above compiler invocation generated a program executable. Now, we have to execute this command:

./program

This will run whatever you designed this program to do. Often, such a program would contain unit tests to exercise your code.

As a side effect, this will create an example.gcda file with the coverage data for our compilation unit. This is a binary file so it needs to be processed first. Together, the .gcda and .gcno files can be used to create coverage reports.

Processing Coverage

Your compiler ships with tools to analyze the coverage data files. For GCC, this is gcov. For Clang, this is llvm-cov. You don't have to call these programs yourself, gcovr will do that for you.

So let's invoke gcovr:

gcovr --txt example_txt.txt

This will search for all your .gcno and .gcda files, run the compiler's gcov tool, and summarize the code coverage statistics into a report. By default, we get a text summary on the command line that shows aggregate statistics for each line:

------------------------------------------------------------------------------
                           GCC Code Coverage Report
Directory: .
------------------------------------------------------------------------------
File                                       Lines     Exec  Cover   Missing
------------------------------------------------------------------------------
example.cpp                                    7        6    85%   7
------------------------------------------------------------------------------
TOTAL                                          7        6    85%
------------------------------------------------------------------------------

Gcovr supports many different Output Formats <#output-formats> that you can generate instead.

Choosing the Right Gcov Executable

If you have multiple compilers installed or if you are using Clang, you will likely need to tell gcovr which gcov executable to use. By default, gcovr just uses the program named gcov. This is fine for the default GCC compiler, e.g. gcc or g++. Otherwise, you must use --gcov-executable <#cmdoption-gcovr-gcov-executable> to tell gcovr what to use.

If you have used a specific GCC version (e.g. gcc-8 or g++-8), then you must name the gcov tool with the corresponding version. For example:

gcovr --gcov-executable gcov-8

If you have used Clang, then you can use its gcov emulation mode. For example:

gcovr --gcov-executable "llvm-cov gcov"

Again, the llvm-cov name may have to include your compiler version.

Working with Multiple Object Files

Code coverage instrumentation works on a per object file basis, which means you have to re-compile your entire project to collect coverage data.

The C/C++ model has a concept of “compilation units”. A large project is typically not compiled in one go, but in separate steps. The result of compiling a compilation unit is a .o object file with the machine code. The object code from multiple compilation units is later linked into the final executable or library. The previous example only had a single compilation unit, so no explicit linking step was necessary.

Because each compilation unit is compiled independently, every one has to be instrumented with coverage counters separately. A common mistake is to add the compiler flags for coverage (e.g. in the CFLAGS or CXXFLAGS variables) but then forgetting to force a re-compile. Depending on the build system, it may be necessary to clear out the old object files that weren't compiled with coverage, e.g. with a  make clean command. Other build systems use a separate build directory when compiling with coverage so that incremental compilation works as expected.

Each object file will have an associated .gcno and .gcda file in the same directory as the .o object file. For example, consider the following compilation process:

# (1) compile to object code
g++ --coverage -c -o a.o a.cpp
g++ --coverage -c -o b.o b.cpp

# (2) link the object files in the program
g++ --coverage -o the-program a.o b.o

# (3) run the program
./the-program
  1. Compiling the object code creates the a.o and b.o object files, but also corresponding a.gcno and b.gcno notes files, one for each compilation unit. The -c option is used to only compile but to not link the code.
  2. Linking the object code produces the final program. This has no effect on coverage processing, except that the --coverage flag makes sure that a compiler-internal gcov support library is linked.
  3. Running the program will increment the in-memory coverage counters for all executed lines. At the end, the counters are written into gcov data files, one for each compilation unit. Here, we would get a.gcda and b.gcda files.

If you only want coverage data for certain source files, it is sufficient to only compile those compilation units with coverage enabled that contain these source files. But this can be tricky to do correctly. For example, header files are often part of multiple compilation units.

GCOV parser

GCOV json output

Starting with gcc-14 the gcov tool can generate a zipped JSON representation of the coverage data. Only version 2 of the intermediate format is supported. The version generated by your installation can be checked with the command gcov --version.

If an unsupported version is generated gcovr is falling back to the GCOV text output.

GCOV text output

Until gcc-13 or if the json output format is unsupported the gcov text output is parsed. The behavior of this parser was informed by the following sources:

Error handling

By default the parser raises an exception on unrecognized gcov output.

There are several known issues with the files generated by gcov which can be handled by --gcov-ignore-parse-errors <#cmdoption-gcovr-gcov-ignore-parse-errors> which are described here. If no value is given to the option the value all is used the whole gcov file is ignored if the output is not recognized.

Negative hit counts

A bug in gcov can produce negative hit values (see gcov comment_negative_hits <https://github.com/gcovr/gcovr/issues/583#issuecomment-1340762818>) which are not accepted by default. This behavior can be changed by using the value --gcov-ignore-parse-errors=negative_hits.warn or --gcov-ignore-parse-errors=negative_hits.warn_once_per_file. The first form warns on every line with a negative value the second one only once per processed file and adds a summary with the overall issues in the file.

Suspicious hit counts

A bug in gcov can produce very high hit values (see gcov issue_suspicious_hits <https://github.com/gcovr/gcovr/issues/898>) which are not accepted by default. A suspicious value is assumed if the counter is greater than the value of --gcov-suspicious-hits-threshold <#cmdoption-gcovr-gcov-suspicious-hits-threshold>. This behavior can be changed by using the value --gcov-ignore-parse-errors=suspicious_hits.warn or --gcov-ignore-parse-errors=suspicious_hits.warn_once_per_file. The first form warns on every line with a suspicious value the second one only once per processed file and adds a summary with the overall issues in the file.

Added in version 8.3: The threshold for detection of suspicious hits can be configured with --gcov-suspicious-hits-threshold <#cmdoption-gcovr-gcov-suspicious-hits-threshold>.

Output Formats

Gcovr supports a variety of output formats that are documented on the following pages.

Text Output

The text output format summarizes coverage in a plain-text table. This is the default output format if no other format is selected. This output format can also be explicitly selected with the --txt <#cmdoption-gcovr-txt> option.

If the given name ends with the suffix .gz the report is compressed by gzip, if it ends with .xz it is compressed by LZMA.

Added in version 5.0: Added explicit --txt <#cmdoption-gcovr-txt> option.

Example output:

------------------------------------------------------------------------------
                           GCC Code Coverage Report
Directory: .
------------------------------------------------------------------------------
File                                       Lines     Exec  Cover   Missing
------------------------------------------------------------------------------
example.cpp                                    7        6    85%   7
------------------------------------------------------------------------------
TOTAL                                          7        6    85%
------------------------------------------------------------------------------

Line Coverage

Running gcovr without any explicit output formats …

gcovr --txt example_txt.txt

generates a text summary of the lines executed:

------------------------------------------------------------------------------
                           GCC Code Coverage Report
Directory: .
------------------------------------------------------------------------------
File                                       Lines     Exec  Cover   Missing
------------------------------------------------------------------------------
example.cpp                                    7        6    85%   7
------------------------------------------------------------------------------
TOTAL                                          7        6    85%
------------------------------------------------------------------------------

The same result can be achieved when explicit --txt <#cmdoption-gcovr-txt> option is set. For example:

gcovr --txt

generates the same text summary.

Each line of this output includes a summary for a given source file, including the number of lines instrumented, the number of lines executed, the percentage of lines executed, and a summary of the line numbers that were not executed.  To improve clarity, gcovr uses an aggressive approach to grouping uncovered lines and will combine uncovered lines separated by "non-code" lines (blank, freestanding braces, and single-line comments) into a single region. As a result, the number of lines listed in the "Missing" list may be greater than the difference of the "Lines" and "Exec" columns.

Note that gcov accumulates statistics by line.  Consequently, it works best with a programming style that places only one statement on each line.

Branch Coverage

The gcovr command can also summarize branch coverage using the -b/--branches <#cmdoption-gcovr-b> option:

gcovr --txt-metric branch --txt example_branches.txt

This generates a tabular output that summarizes the number of branches, the number of branches taken and the branches that were not completely covered:

------------------------------------------------------------------------------
                           GCC Code Coverage Report
Directory: .
------------------------------------------------------------------------------
File                                    Branches    Taken  Cover   Missing
------------------------------------------------------------------------------
example.cpp                                    2        1    50%   5
------------------------------------------------------------------------------
TOTAL                                          2        1    50%
------------------------------------------------------------------------------

The same result can be achieved when the --txt <#cmdoption-gcovr-txt> option is explicitly set. For example:

gcovr --branches --txt

prints the same tabular output.

HTML Output

The gcovr command can generate a simple HTML output using the --html <#cmdoption-gcovr-html> option:

gcovr --html example_html.html

This generates a HTML summary of the lines executed.  In this example, the file example_html.html is generated, which has the following output: [image]

The default behavior of the --html <#cmdoption-gcovr-html> option is to generate HTML for a single webpage that summarizes the coverage for all files.

If the given name ends with the suffix .gz the report is compressed by gzip, if it ends with .xz it is compressed by LZMA. This only make sense for a self contained report with one page.

The --html-details <#cmdoption-gcovr-html-details> option is used to create a separate web page for each file. Each of these web pages includes the contents of the file with annotations that summarize code coverage. Consider the following command:

gcovr --html-details example_html.details.html

This generates the following HTML page for the file example.cpp: [image]

The --html-nested <#cmdoption-gcovr-html-nested> option is used to create a separate web page for each file and directory. Each of these web pages includes the contents of the file with annotations that summarize code coverage. Consider the following command:

gcovr --html-nested example_html.nested.html

Note that the --html <#cmdoption-gcovr-html> and --html-details <#cmdoption-gcovr-html-details> options need a named output, e.g. via the the --output <#cmdoption-gcovr-o> option. For example, if the output is named coverage.html, then the web pages generated for each file will have names of the form coverage.<filename>.html.

The --html-self-contained <#cmdoption-gcovr-html-self-contained> option controls whether assets like CSS styles are bundled into the HTML file. The --html <#cmdoption-gcovr-html> report defaults to self-contained mode, but --html-details <#cmdoption-gcovr-html-details> and --html-nested <#cmdoption-gcovr-html-nested> default to --no-html-self-contained <#cmdoption-gcovr-html-self-contained> in order to avoid problems with the Content Security Policy <https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP> of some servers, especially Jenkins.

The --html-theme <#cmdoption-gcovr-html-theme> option controls the theme and color of HTML report.

[image] --html-theme green <#cmdoption-gcovr-html-theme>, --html-theme default.green <#cmdoption-gcovr-html-theme>.UNINDENT
[image] --html-theme blue <#cmdoption-gcovr-html-theme>, --html-theme default.blue <#cmdoption-gcovr-html-theme>.UNINDENT
[image] --html-theme github.green <#cmdoption-gcovr-html-theme>.UNINDENT
[image] --html-theme github.blue <#cmdoption-gcovr-html-theme>.UNINDENT
[image] --html-theme github.dark-green <#cmdoption-gcovr-html-theme>.UNINDENT
[image] --html-theme github.dark-blue <#cmdoption-gcovr-html-theme>.UNINDENT

The --html-template-dir <#cmdoption-gcovr-html-template-dir> option allows you to use an alternate directory with Jinja2 templates to fully customize the HTML output in detail. If a template is missing from this directory the original is used. It is advised that you start by copying the part you want to modify from the existing default theme templates <https://github.com/gcovr/gcovr/tree/main/src/gcovr/formats/html/default> , the existing github theme templates <https://github.com/gcovr/gcovr/tree/main/src/gcovr/formats/html/github>. or  the existing common templates <https://github.com/gcovr/gcovr/tree/main/src/gcovr/formats/html/common>. Keep in mind the template context data that is passed to these templates MAY change between release versions.

Following templates are referenced from the python code, all other files are referenced in the templates themselves:

  • <theme>/directory_page.html: Template for directory overview pages (used by --html-details <#cmdoption-gcovr-html-details>).
  • <theme>/function_page.html: Template for functions overview page (used by --html-details <#cmdoption-gcovr-html-details>).
  • <theme>/source_page.html: Template for source code details pages (used by --html-details <#cmdoption-gcovr-html-details>).
  • <theme>/style.css: Template for CSS stylesheet (always used).
  • common/gcovr.js: Template for javascript code (always used).
  • common/single_page.html: Template for single page report (used by --html-single-page <#cmdoption-gcovr-html-single-page>).

Note that you do not have to copy every single template and can copy and edit only the templates you wish to customize.

Changed in version 8.5: Added --html-static-report <#cmdoption-gcovr-html-static-report> and remove argument from --html-single-page <#cmdoption-gcovr-html-single-page>.

Changed in version 8.4: The total number of elements now also contain the excluded once because they are also listed.

Added in version 7.0: Added --html-template-dir <#cmdoption-gcovr-html-template-dir>.

Added in version 6.0: Added --html-nested <#cmdoption-gcovr-html-nested> and --html-syntax-highlighting <#cmdoption-gcovr-html-syntax-highlighting>.

Added in version 5.0: Added --html-self-contained <#cmdoption-gcovr-html-self-contained>.

Changed in version 5.0: Default to external CSS file for --html-details <#cmdoption-gcovr-html-details>.

CSV Output

The --csv <#cmdoption-gcovr-csv> option output comma-separated values summarizing the coverage of each file. Consider the following command:

gcovr --csv example_csv.csv

This generates an CSV:

filename,line_total,line_covered,line_percent,branch_total,branch_covered,branch_percent,function_total,function_covered,function_percent
example.cpp,7,6,0.857,2,1,0.5,2,2,1.0

Be careful if you print the output of a CSV to STDOUT and redirect it to a file. According to RFC 4180 <https://datatracker.ietf.org/doc/html/rfc4180.html>, the line endings must be CRLF.

If the given name ends with the suffix .gz the report is compressed by gzip, if it ends with .xz it is compressed by LZMA. The file needs to be unzipped before using as input for other tools.

Added in version 5.0: Added --csv <#cmdoption-gcovr-csv>.

JSON Output

The gcovr command can generate JSON output using the --json <#cmdoption-gcovr-json> and --json-pretty <#cmdoption-gcovr-json-pretty> options:

gcovr --json-pretty --json example_json.json

This generates an indented JSON report:

{
    "gcovr/format_version": "0.14",
    "files": [
        {
            "file": "example.cpp",
            "lines": [
                {
                    "line_number": 3,
                    "function_name": "foo(int)",
                    "count": 1,
                    "branches": [],
                    "gcovr/md5": "2cfc07b9a0f8cdd3eb4553562d5875b6"
                },
                {
                    "line_number": 5,
                    "function_name": "foo(int)",
                    "count": 1,
                    "branches": [
                        {
                            "branchno": 0,
                            "count": 0,
                            "fallthrough": true,
                            "throw": false,
                            "source_block_id": 0
                        },
                        {
                            "branchno": 1,
                            "count": 1,
                            "fallthrough": false,
                            "throw": false,
                            "source_block_id": 0
                        }
                    ],
                    "gcovr/md5": "179a2dbf295aceeef210ce9f81eaf46d"
                },
                {
                    "line_number": 7,
                    "function_name": "foo(int)",
                    "count": 0,
                    "branches": [],
                    "gcovr/md5": "430d88bc33efb4bea3225d844dfe292a"
                },
                {
                    "line_number": 11,
                    "function_name": "foo(int)",
                    "count": 1,
                    "branches": [],
                    "gcovr/md5": "f4705ee5bd3c93d33aa9bbc37dd4e473"
                },
                {
                    "line_number": 15,
                    "function_name": "main",
                    "count": 1,
                    "branches": [],
                    "gcovr/md5": "28a5d2a48b50197171c244de3773ad07"
                },
                {
                    "line_number": 17,
                    "function_name": "main",
                    "count": 1,
                    "branches": [],
                    "calls": [
                        {
                            "callno": 0,
                            "source_block_id": 0,
                            "returned": 1
                        }
                    ],
                    "gcovr/md5": "9c0fe984acbd93ec57bb8fff41871458"
                },
                {
                    "line_number": 19,
                    "function_name": "main",
                    "count": 1,
                    "branches": [],
                    "gcovr/md5": "02abc18c3b46fbd7cfee6bbcd0986b79"
                }
            ],
            "functions": [
                {
                    "demangled_name": "foo(int)",
                    "lineno": 3,
                    "execution_count": 1,
                    "blocks_percent": 75.0
                },
                {
                    "name": "main",
                    "lineno": 15,
                    "execution_count": 1,
                    "blocks_percent": 100.0
                }
            ]
        }
    ]
}

The --json-pretty <#cmdoption-gcovr-json-pretty> option generates an indented JSON output that is easier to read.

If you just need a summary of the coverage information, similar to the tabulated text based output, you can use --json-summary <#cmdoption-gcovr-json-summary> instead (see JSON Summary Output).

Multiple JSON files can be merged into the coverage data with sum of lines and branches execution, see JSON Format merging.

See the JSON Format Reference for a description of the file format.

Changed in version 8.0: Order of keys changed from alphabetical to logical.

JSON Format Reference

The structure of the JSON input/output files is based on the GCC gcov JSON intermediate format, but with additional keys specific to gcovr. Field names use snake_case. Gcovr-specific fields are prefixed with gcovr/.

The GCC gcov JSON format is documented at <https://gcc.gnu.org/onlinedocs/gcc-14.1.0/gcc/Invoking-Gcov.html>.

The top level of the file looks like the following:

{
    "gcovr/format_version": version,
    "files": [file]
}
gcovr/format_version: string

A version number string for the gcovr JSON format. This is versioned independently from gcovr itself. Consumers of gcovr JSON reports should check that they are SemVer-compatible with the declared version. Gcovr itself will only consume input files that match the exact version.

The current version is:

"0.14"

files: list

An unordered list of file entries.

File entries

Each file entry contains coverage data for one source file:

{
    "file": filename,
    "lines": [line],
    "functions": [function],
    "gcovr/data_sources": [data_sources]
}
file: string

Path to the source code file. If the source file is within the gcovr root directory, the path will be relative.

lines: list

An ordered list of line coverage entries.

functions: list

An ordered list of function entries.

gcovr/data_sources: list

A list of files from which the coverage object was populated. This entry is only available if --json-trace-data-source <#cmdoption-gcovr-json-trace-data-source> is given.

Added in version 8.5: Change --verbose <#cmdoption-gcovr-v> to --json-trace-data-source <#cmdoption-gcovr-json-trace-data-source> for gcovr/data_sources.

Added in version 8.3: The gcovr/data_sources is added.

Line entries

Each line entry contains coverage data for one line:

{
    "line_number": line_number,
    "function_name": function_name,
    "block_ids", [block_ids],
    "count": count,
    "branches": [branch],
    "conditions", [condition]
    "gcovr/decision": decision,
    "calls": calls,
    "gcovr/md5": md5,
    "gcovr/excluded": excluded,
    "gcovr/data_sources": [data_sources]
}

The ordering and merge key is (line_number, function_name, number of branches, list of condition counts, list of block ids).

line_number: int

The 1-based line number to which this entry relates.

function_name: str

Contains the name of the function to which the line belongs to. If gcov JSON format is used it is always the mangled name. If the legacy gcov text format is used it contains the demangled name if supported by gcov, else the mangled name. Can be missing for a line with an inlined statement.

block_ids: list

The list of block ids defined in this line.

count: int

How often this line was executed.

branches: list

An ordered list of branch coverage entries.

conditions: list

Only available if GCOV JSON format is used it contains an ordered list of branch coverage entries.

gcovr/decision: object

The decision entry for this line, if any. Absent if there is no decision to report. Requires that --decisions <#cmdoption-gcovr-decisions> coverage analysis was enabled.

calls: object

The call for this line, if any. Absent if there is no call to report.

gcovr/md5: str

The MD5 sum of the line.

gcovr/excluded: boolean

True if coverage data for this line was explicitly excluded, in particular with Exclusion Markers <#exclusion-markers>. May be absent if false.

gcovr/data_sources: list

A list of files from which the coverage object was populated. This entry is only available if --json-trace-data-source <#cmdoption-gcovr-json-trace-data-source> is given.

If there is no line entry for a source code line, it either means that the compiler did not generate any code for that line, or that gcovr ignored this coverage data due to heuristics.

The line entry should be interpreted as follows:

  • if gcovr/excluded is true, the line should not be included in coverage reports.
  • if count is 0, the line is uncovered
  • if count is nonzero, the line is covered

Added in version 8.5: Change --verbose <#cmdoption-gcovr-v> to --json-trace-data-source <#cmdoption-gcovr-json-trace-data-source> for gcovr/data_sources.

Added in version 8.4: The gcovr/data_sources is added.

Added in version 8.0: The conditions is added.

Added in version 8.0: The block_ids is added.

Added in version 8.0: The function_name is added.

Added in version 8.0: The gcovr/md5 is added.

Added in version 6.0: The gcovr/excluded field can be absent if false.

Changed in version 6.0: The gcovr/noncode field was removed. Instead of generating noncode entries, the entire line is skipped.

Branch entries

Each branch provides information about a branch on that line:

{
  "branchno": branchno,
  "count": count,
  "fallthrough": fallthrough,
  "throw": throw,
  "source_block_id": number,
  "destination_block_id": number,
  "gcovr/excluded": excluded,
  "gcovr/data_sources": [data_sources]
}

The ordering and merge key is (branchno, source_block_id, destination_block_id).

This exactly matches the GCC gcov format except branchno.

branchno: int

The branch number is only available if data is parsed from GCC gcov text format.

count: int

How often this branch was taken.

fallthrough: boolean

Whether this is the “fallthrough” branch.

throw: boolean

Whether this is an exception-only branch.

source_block_id: int

The source block of this branch.

destination_block_id: int

The destination block of this branch. Only available if gcov JSON format is used.

gcovr/excluded: boolean

True if coverage data for this line was explicitly excluded, in particular with Exclusion Markers <#exclusion-markers>. May be absent if false.

gcovr/data_sources: list

A list of files from which the coverage object was populated. This entry is only available if --json-trace-data-source <#cmdoption-gcovr-json-trace-data-source> is given.

Added in version 8.5: Change --verbose <#cmdoption-gcovr-v> to --json-trace-data-source <#cmdoption-gcovr-json-trace-data-source> for gcovr/data_sources.

Added in version 8.4: The branchno is added.

Added in version 8.4: The gcovr/excluded is added.

Added in version 8.4: The gcovr/data_sources is added.

Added in version 8.0: Added destination_blockno field.

Added in version 8.3: Added source_block_id field.

Changed in version 8.3: Renamed destination_blockno to destination_block_id field.

Condition entries

Each condition provides information about a condition on that line:

{
  "conditionno": conditionno,
  "count": count,
  "covered": covered,
  "not_covered_false": not_covered_false,
  "not_covered_true": not_covered_true,
  "gcovr/excluded": excluded,
  "gcovr/data_sources": [data_sources]
}

The ordering and merge key is (conditionno, count).

This exactly matches the GCC gcov format except conditionno.

conditionno: int

The index number of the condition in GCC gcov output.

count: int

Number of condition outcomes in this expression.

covered: int

Number of covered condition outcomes in this expression.

not_covered_false: list[int]

Terms, by index, not seen as false in this expression.

not_covered_true: list[int]

Terms, by index, not seen as true in this expression.

gcovr/excluded: boolean

True if coverage data for this line was explicitly excluded, in particular with Exclusion Markers <#exclusion-markers>. May be absent if false.

gcovr/data_sources: list

A list of files from which the coverage object was populated. This entry is only available if --json-trace-data-source <#cmdoption-gcovr-json-trace-data-source> is given.

Added in version 8.5: Change --verbose <#cmdoption-gcovr-v> to --json-trace-data-source <#cmdoption-gcovr-json-trace-data-source> for gcovr/data_sources.

Added in version 8.4: The conditionno is added.

Added in version 8.4: New gcovr/excluded field.

Added in version 8.4: The gcovr/data_sources is added.

Decision entries

Each decision summarizes the line's branch coverage data:

{
  "type": "uncheckable",
  "gcovr/data_sources": [data_sources]
}

{
  "type": "conditional",
  "count_true": count_true,
  "count_false": count_false,
  "gcovr/data_sources": [data_sources]
}

{
  "type": "switch",
  "count": count,
  "gcovr/data_sources": [data_sources]
}
type: string

A tag/discriminator for the type of the decision.

type: "uncheckable"

Control flow was recognized on this line, but cannot be interpreted unambiguously.

No further fields.

type: "conditional"

This line represents simple control flow like an if or while.

count_true: int

How often the decision evaluated to “true”.

count_false: int

How often the decision evaluated to “false”.

Note that the true/false are heuristic guesses, and might also be inverted.

type: "switch"

This line is a switch-case.

count: int

How often this case was taken.

gcovr/data_sources: list

A list of files from which the coverage object was populated. This entry is only available if --json-trace-data-source <#cmdoption-gcovr-json-trace-data-source> is given.

Added in version 8.5: Change --verbose <#cmdoption-gcovr-v> to --json-trace-data-source <#cmdoption-gcovr-json-trace-data-source> for gcovr/data_sources.

Added in version 8.4: The gcovr/data_sources is added.

Call entries

Each call provides information about a call on that line:

{
  "callno": callno,
  "source_block_id": source_block_id,
  "destination_block_id": destination_block_id,
  "returned": returned,
  "gcovr/excluded": excluded,
  "gcovr/data_sources": [data_sources]
}

The ordering and merge key is (callno, source_block_id, destination_block_id).

callno: int

Only available if gcov text format is used.

source_block_id: int

The source block number of the call.

destination_block_id: int

Only available if gcov JSON format is used.

returned: int

How often this call returned, if the value is 0 the call is uncovered.

gcovr/excluded: boolean

True if coverage data for this line was explicitly excluded, in particular with Exclusion Markers <#exclusion-markers>. May be absent if false.

gcovr/data_sources: list

A list of files from which the coverage object was populated. This entry is only available if --json-trace-data-source <#cmdoption-gcovr-json-trace-data-source> is given.

Added in version 8.5: Change --verbose <#cmdoption-gcovr-v> to --json-trace-data-source <#cmdoption-gcovr-json-trace-data-source> for gcovr/data_sources.

Changed in version 8.4: New returned field is replacing the field covered.

Added in version 8.4: New gcovr/excluded field.

Added in version 8.4: The gcovr/data_sources is added.

Function entries

Each function entry describes a line in the source file:

{
  "name": name,
  "demangled_name": demangled_name,
  "lineno": lineno,
  "execution_count": count,
  "blocks_percent": percent,
  "pos": [
    "<start line>:<start column>",
    "<end line>:<end column>"
  ]
  "gcovr/excluded": excluded,
  "gcovr/data_sources": [data_sources]
}

The ordering and merge key is function_name.

name: string

The mangled name of the function if present. Is missing if GCOV text format is used and GCOV tool supports demangled names.

demangled_name: string

The demangled name of the function if present. Is missing if GCOV text format is used and GCOV tool doesn't support demangled names.

lineno: int

The line number (1-based) where this function was defined. Incompatible with GCC gcov JSON.

execution_count: int

How often this function was called. Is absent for <unknown function>.

blocks_percent: float

The branch coverage in percent (0.0 to 100.0). Is absent for <unknown function>.

pos: list

A list with start and end position of function (1-based). Both entries are string with line and column separated by :. Only available if gcov JSON format is used.

gcovr/excluded: boolean

True if coverage data for this function was explicitly excluded, in particular with Exclusion Markers <#exclusion-markers>. May be absent if false.

gcovr/data_sources: list

A list of files from which the coverage object was populated. This entry is only available if --json-trace-data-source <#cmdoption-gcovr-json-trace-data-source> is given.

  • if gcovr/excluded is true, the line should not be included in coverage reports.

Added in version 8.5: Change --verbose <#cmdoption-gcovr-v> to --json-trace-data-source <#cmdoption-gcovr-json-trace-data-source> for gcovr/data_sources.

Added in version 8.5: Key execution_count and blocks_percent are optional.

Added in version 8.4: The gcovr/data_sources is added.

Added in version 8.0: Added pos field.

Changed in version 8.0: The name is changed to contain the mangled name previous content is now available as demangled_name as it is in GCOV JSON format.

Removed in version 8.0: Removed returned_count field because missing in gcov JSON format.

Added in version 7.0: New returned_count and blocks_percent field.

Added in version 6.0: New gcovr/excluded field.

JSON Format merging

You can merge coverage data from multiple runs with --json-add-tracefile <#cmdoption-gcovr-a>.

For each run, generate JSON output:

...  # compile and run first test case
gcovr ... --json run-1.json
...  # compile and run second test case
gcovr ... --json run-2.json

Next, merge the json files and generate the desired report:

gcovr --json-add-tracefile run-1.json --json-add-tracefile run-2.json --html-details coverage.html

You can also use unix style wildcards to merge the json files without duplicating --json-add-tracefile <#cmdoption-gcovr-a>. With this option you have to place your pathnames with wildcards in double quotation marks:

gcovr --json-add-tracefile "run-*.json" --html-details coverage.html

If you want to merge coverage reports generated in different --root <#cmdoption-gcovr-r> directories you can use the --json-base <#cmdoption-gcovr-json-base> to get the same root directory for all reports.

If you have same function names defined on different line the default behavior is to abort. With the --merge-mode-functions <#cmdoption-gcovr-merge-mode-functions> you can change this:

  • strict: Abort if same function is defined on a different line (old behavior).
  • merge-use-line-0: Allow same function on different lines, in this case use line 0.
  • merge-use-line-min: Allow same function on different lines, in this case the minimum line.
  • merge-use-line-max: Allow same function on different lines, in this case use maximum line.
  • separate: Allow same function on different lines. Instead of merging keep the functions separate.

Removed in version 8.4: Removed the option --merge-mode-conditions option.

Added in version 8.3: The --merge-mode-conditions option.

Added in version 6.0: The gcovr --json-base <#cmdoption-gcovr-json-base> option. The gcovr --merge-mode-functions <#cmdoption-gcovr-merge-mode-functions> option.

JSON Summary Output

The --json-summary <#cmdoption-gcovr-json-summary> option output coverage summary in a machine-readable format for additional post processing. The format corresponds to the normal JSON output --json <#cmdoption-gcovr-json> option, but without line-level details and with added aggregated statistics. The --json-summary-pretty <#cmdoption-gcovr-json-summary-pretty> option generates an indented JSON summary output that is easier to read. Consider the following command:

gcovr --json-summary-pretty --json-summary example_json_summary.json

This generates an indented JSON summary:

{
    "root": ".",
    "gcovr/summary_format_version": "0.6",
    "files": [
        {
            "filename": "example.cpp",
            "line_total": 7,
            "line_covered": 6,
            "line_percent": 85.7,
            "function_total": 2,
            "function_covered": 2,
            "function_percent": 100.0,
            "branch_total": 2,
            "branch_covered": 1,
            "branch_percent": 50.0
        }
    ],
    "line_total": 7,
    "line_covered": 6,
    "line_percent": 85.7,
    "function_total": 2,
    "function_covered": 2,
    "function_percent": 100.0,
    "branch_total": 2,
    "branch_covered": 1,
    "branch_percent": 50.0
}

Added in version 5.0: Added --json-summary <#cmdoption-gcovr-json-summary> and --json-summary-pretty <#cmdoption-gcovr-json-summary-pretty>.

JSON Summary Format Reference

The summary format follows the general structure of the JSON Format Reference, but removes line-level information and adds aggregated statistics.

The top-level looks like:

{
  "gcovr/summary_format_version": version,
  "files: [file],
  "root": path,
  ...statistics
}
gcovr/summary_format_version: string

A version number string for the summary format. This is versioned independently from gcovr and the full JSON format. Consumers of gcovr JSON Summary reports should check that they are SemVer-compatible with the declared version.

The current version is:

"0.6"

files: list

List of file summary entries.

root: string

Path to the gcovr root directory, useful for reconstructing the absolute path of source files. This root path is relative to the output file, or to the current working directory if the report is printed to stdout.

...statistics

Project-level aggregated statistics. A NaN percentage (0/0) is reported as zero (0.0).

File summary entries

The file summary looks like:

{
  "filename": path,
  ...statistics
}
filename: string

Path to the source file, relative to the gcovr root directory.

...statistics

File-level aggregated statistics. A NaN percentage (0/0) is reported as null.

Summary statistics

The root and file summaries contain the following additional fields:

...
"branch_covered": ...,
"branch_total": ...,
"branch_percent": ...,

"line_covered": ...,
"line_total": ...,
"line_percent": ...,

"function_covered": ...,
"function_total": ...,
"function_percent": ...,
...

These fields can be described by the glob expression {branch,line,function}_{covered,total,percent}.

ELEMENT_covered: int

How many elements were covered or executed.

ELEMENT_total: int

How many elements there are in total.

ELEMENT_percent: float

Percentage of covered elements (covered/total) in the range 0 to 100. Note that the different contexts differ in their treatment of NaN values.

Markdown Output

Added in version 8.4.

The gcovr command can generate Markdown output using the --markdown <#cmdoption-gcovr-markdown> option:

gcovr --markdown coverage.md

If you just need a summary of the coverage information, you can use --markdown-summary <#cmdoption-gcovr-markdown-summary> instead (see Markdown Summary Output).

If the given name ends with the suffix .gz the report is compressed by gzip, if it ends with .xz it is compressed by LZMA.

Markdown Summary Output

The --markdown-summary <#cmdoption-gcovr-markdown-summary> option outputs coverage summary, without file information.

The --markdown-theme <#cmdoption-gcovr-markdown-theme> option controls the color theme of the markdown report.

--markdown-theme green <#cmdoption-gcovr-markdown-theme>, --markdown-theme default.green <#cmdoption-gcovr-markdown-theme>

--markdown-theme blue <#cmdoption-gcovr-markdown-theme>, --markdown-theme default.blue <#cmdoption-gcovr-markdown-theme>

Clover XML Output

The gcovr command can generate a Clover XML output using the --clover <#cmdoption-gcovr-clover> and --clover-pretty <#cmdoption-gcovr-clover-pretty> options:

gcovr --clover-pretty --clover example_clover.xml

This generates an XML summary of the lines executed:

<?xml version='1.0' encoding='utf-8'?>
<coverage clover="1768331147" generated="1768331147">
  <project timestamp="1768331147">
    <metrics complexity="0" elements="7" coveredelements="6" conditionals="0" coveredconditionals="0" statements="7" coveredstatements="6" methods="0" coveredmethods="0" packages="1" classes="1" files="1"/>
    <package name="root">
      <metrics complexity="0" elements="7" coveredelements="6" conditionals="0" coveredconditionals="0" statements="7" coveredstatements="6" methods="0" coveredmethods="0" classes="1" files="1"/>
      <file name="example.cpp" path="example.cpp">
        <metrics complexity="0" elements="7" coveredelements="6" conditionals="0" coveredconditionals="0" statements="7" coveredstatements="6" methods="0" coveredmethods="0" classes="1"/>
        <class name="id$9597a7a3397b8e3a48116e2a3afb4154">
          <metrics complexity="0" elements="7" coveredelements="6" conditionals="0" coveredconditionals="0" statements="7" coveredstatements="6" methods="0" coveredmethods="0"/>
        </class>
        <line num="3" type="stmt" count="1"/>
        <line num="5" type="stmt" count="1"/>
        <line num="7" type="stmt" count="0"/>
        <line num="11" type="stmt" count="1"/>
        <line num="15" type="stmt" count="1"/>
        <line num="17" type="stmt" count="1"/>
        <line num="19" type="stmt" count="1"/>
      </file>
    </package>
  </project>
  <testproject timestamp="1768331147">
    <metrics complexity="0" elements="0" coveredelements="0" conditionals="0" coveredconditionals="0" statements="0" coveredstatements="0" methods="0" coveredmethods="0"/>
    <package name="dummy">
      <metrics complexity="0" elements="0" coveredelements="0" conditionals="0" coveredconditionals="0" statements="0" coveredstatements="0" methods="0" coveredmethods="0"/>
      <file name="dummy" path="dummy">
        <metrics complexity="0" elements="0" coveredelements="0" conditionals="0" coveredconditionals="0" statements="0" coveredstatements="0" methods="0" coveredmethods="0"/>
        <class name="id$275876e34cf609db118f3d84b799a790">
          <metrics complexity="0" elements="0" coveredelements="0" conditionals="0" coveredconditionals="0" statements="0" coveredstatements="0" methods="0" coveredmethods="0"/>
        </class>
      </file>
    </package>
  </testproject>
</coverage>

This XML format is described in the Clover XML <https://bitbucket.org/atlassian/clover/src/master/etc/schema/clover.xsd> XSD suitable for import and display within the Atlassian Bamboo <https://www.atlassian.com/de/software/bamboo> continuous integration servers.

The --clover <#cmdoption-gcovr-clover> option generates a denser XML output, and the --clover-pretty <#cmdoption-gcovr-clover-pretty> option generates an indented XML output that is easier to read.

If the given name ends with the suffix .gz the report is compressed by gzip, if it ends with .xz it is compressed by LZMA.

Added in version 7.1: Add --clover <#cmdoption-gcovr-clover> and --clover-pretty <#cmdoption-gcovr-clover-pretty>.

Cobertura XML Output

The gcovr command can generate a Cobertura XML output using the --cobertura <#cmdoption-gcovr-cobertura> and --cobertura-pretty <#cmdoption-gcovr-cobertura-pretty> options:

gcovr --cobertura-pretty --cobertura example_cobertura.xml

This generates an XML summary of the lines executed:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE coverage SYSTEM 'http://cobertura.sourceforge.net/xml/coverage-04.dtd'>
<coverage line-rate="0.8571428571428571" branch-rate="0.5" lines-covered="6" lines-valid="7" branches-covered="1" branches-valid="2" complexity="0.0" timestamp="1768331147" version="gcovr 8.6">
  <sources>
    <source>/gcovr/tests/output/examples-example-cobertura</source>
  </sources>
  <packages>
    <package name="" line-rate="0.8571428571428571" branch-rate="0.5" complexity="0.0">
      <classes>
        <class name="example_cpp" filename="example.cpp" line-rate="0.8571428571428571" branch-rate="0.5" complexity="0.0">
          <methods>
            <method name="foo" signature="(int)" line-rate="0.75" branch-rate="0.5" complexity="0.0">
              <lines>
                <line number="3" hits="1" branch="false"/>
                <line number="5" hits="1" branch="true" condition-coverage="50% (1/2)">
                  <conditions>
                    <condition number="0" type="jump" coverage="50%"/>
                  </conditions>
                </line>
                <line number="7" hits="0" branch="false"/>
                <line number="11" hits="1" branch="false"/>
              </lines>
            </method>
            <method name="main" signature="" line-rate="1.0" branch-rate="1.0" complexity="0.0">
              <lines>
                <line number="15" hits="1" branch="false"/>
                <line number="17" hits="1" branch="false"/>
                <line number="19" hits="1" branch="false"/>
              </lines>
            </method>
          </methods>
          <lines>
            <line number="3" hits="1" branch="false"/>
            <line number="5" hits="1" branch="true" condition-coverage="50% (1/2)">
              <conditions>
                <condition number="0" type="jump" coverage="50%"/>
              </conditions>
            </line>
            <line number="7" hits="0" branch="false"/>
            <line number="11" hits="1" branch="false"/>
            <line number="15" hits="1" branch="false"/>
            <line number="17" hits="1" branch="false"/>
            <line number="19" hits="1" branch="false"/>
          </lines>
        </class>
      </classes>
    </package>
  </packages>
</coverage>

This XML format is described in the Cobertura XML DTD <https://github.com/gcovr/gcovr/blob/main/tests/cobertura.coverage-04.dtd> suitable for import and display within the Jenkins <https://www.jenkins.io/> and Hudson <https://projects.eclipse.org/projects/technology.hudson> continuous integration servers using the Jenkins Coverage Plugin <https://github.com/jenkinsci/coverage-plugin>.

The --cobertura <#cmdoption-gcovr-cobertura> option generates a denser XML output, and the --cobertura-pretty <#cmdoption-gcovr-cobertura-pretty> option generates an indented XML output that is easier to read. Note that the XML output contains more information than the tabular summary. The tabular summary shows the percentage of covered lines, while the XML output includes branch statistics and the number of times that each line was covered. Consequently, XML output can be used to support performance optimization in the same manner that gcov does.

If the given name ends with the suffix .gz the report is compressed by gzip, if it ends with .xz it is compressed by LZMA. The file needs to be unzipped before using as input for other tools.

Added in version 5.1: The --cobertura <#cmdoption-gcovr-cobertura> and --cobertura-pretty <#cmdoption-gcovr-cobertura-pretty> options were added as an alias for -x <#cmdoption-gcovr-cobertura>/--xml <#cmdoption-gcovr-cobertura> and --xml-pretty <#cmdoption-gcovr-cobertura-pretty>, respectively. This avoids confusion with other XML output formats like SonarQube XML Output <#sonarqube-xml-output>. The old options remain available for backwards compatibility.

Coveralls JSON Output

If you are using Coveralls, you can get a coverage report in a suitable JSON format via the --coveralls <#cmdoption-gcovr-coveralls> option:

gcovr --coveralls coverage.json

The --coveralls-pretty <#cmdoption-gcovr-coveralls-pretty> option generates an indented JSON output that is easier to read.

If the given name ends with the suffix .gz the report is compressed by gzip, if it ends with .xz it is compressed by LZMA.

Keep in mind that the output contains the checksums of the source files. If you are using different OSes, the line endings shall be the same.

If available, environment variable COVERALLS_REPO_TOKEN will be consumed and baked into the JSON output.

If running in a CI additional variables are used:

  • In Travis CI:

    • TRAVIS_JOB_ID
    • TRAVIS_BUILD_NUMBER
    • TRAVIS_PULL_REQUEST
    • TRAVIS_COMMIT
    • TRAVIS_BRANCH
  • In Appveyor:

    • APPVEYOR_JOB_ID
    • APPVEYOR_JOB_NUMBER
    • APPVEYOR_PULL_REQUEST_NUMBER
    • APPVEYOR_REPO_COMMIT
    • APPVEYOR_REPO_BRANCH
  • In Jenkins CI:

    • JOB_NAME
    • BUILD_ID
    • CHANGE_ID
    • GIT_COMMIT (if available)
    • BRANCH_NAME
  • In GitHub Actions:

    • GITHUB_WORKFLOW
    • GITHUB_RUN_ID
    • GITHUB_SHA
    • GITHUB_HEAD_REF (if available)
    • GITHUB_REF

The Coveralls JSON format is documented at <https://docs.coveralls.io/api-introduction>.

Changed in version 8.0: Order of keys changed from alphabetical to logical.

Added in version 5.0: Added --coveralls <#cmdoption-gcovr-coveralls> and --coveralls-pretty <#cmdoption-gcovr-coveralls-pretty>.

SonarQube XML Output

If you are using SonarQube, you can get a coverage report in a suitable XML format via the --sonarqube <#cmdoption-gcovr-sonarqube> option:

gcovr --sonarqube coverage.xml

If the given name ends with the suffix .gz the report is compressed by gzip, if it ends with .xz it is compressed by LZMA.

The SonarQube XML format is documented at <https://docs.sonarsource.com/sonarqube-server/2025.2/analyzing-source-code/test-coverage/generic-test-data/>.

Coverage Metrics

By default the coverage report contains metrics for line and branch coverage. You can adjust the metrics available in the report with the --sonarqube-metric option. The following options are available:

OptionDescription
--sonarqube-metric=lineThe generated XML contains only line coverage information
--sonarqube-metric=branchThe generated XML contains line and branch coverage information
--sonarqube-metric=conditionThe generated XML contains line and branch coverage information, but the branch coverage is actually condition coverage. Requires GCC 14 or newer and the code to be compiled with -fcondition-coverage.
--sonarqube-metric=decisionThe generated XML contains line and branch coverage information, but the branch coverage is actually decision coverage. Requires the option --decisions to be enabled

JaCoCo XML Output

The gcovr command can generate a JaCoCo XML output using the --jacoco <#cmdoption-gcovr-jacoco> and --jacoco-pretty <#cmdoption-gcovr-jacoco-pretty> options:

gcovr --jacoco-pretty --jacoco example_jacoco.xml

This generates an XML summary of the lines executed:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE report SYSTEM 'https://www.jacoco.org/jacoco/trunk/coverage/report.dtd'>
<report name="GCOVR report">
  <package name="">
    <sourcefile name="example.cpp">
      <line nr="3"/>
      <line nr="5" mb="1" cb="1"/>
      <line nr="7"/>
      <line nr="11"/>
      <line nr="15"/>
      <line nr="17"/>
      <line nr="19"/>
      <counter type="LINE" missed="1" covered="6"/>
      <counter type="BRANCH" missed="1" covered="1"/>
      <counter type="METHOD" missed="0" covered="2"/>
    </sourcefile>
    <counter type="LINE" missed="1" covered="6"/>
    <counter type="BRANCH" missed="1" covered="1"/>
    <counter type="METHOD" missed="0" covered="2"/>
  </package>
  <counter type="LINE" missed="1" covered="6"/>
  <counter type="BRANCH" missed="1" covered="1"/>
  <counter type="METHOD" missed="0" covered="2"/>
</report>

This XML format is described in the JaCoCo XML <https://www.jacoco.org/jacoco/trunk/coverage/report.dtd> DTD.

The --jacoco <#cmdoption-gcovr-jacoco> option generates a denser XML output, and the --jacoco-pretty <#cmdoption-gcovr-jacoco-pretty> option generates an indented XML output that is easier to read. Note that the XML output contains more information than the tabular summary. The tabular summary shows the percentage of covered lines, while the XML output includes branch statistics and the number of times that each line was covered. Consequently, XML output can be used to support performance optimization in the same manner that gcov does.

If the given name ends with the suffix .gz the report is compressed by gzip, if it ends with .xz it is compressed by LZMA.

Added in version 7.0: The --jacoco <#cmdoption-gcovr-jacoco> and --jacoco-pretty <#cmdoption-gcovr-jacoco-pretty>.

LCOV info Output

If you are using tools which handle LCOV info file you can get a coverage report in a suitable info format via the --lcov <#cmdoption-gcovr-lcov> option:

gcovr --lcov coverage.lcov

If the given name ends with the suffix .gz the report is compressed by gzip, if it ends with .xz it is compressed by LZMA.

With the following options you can set user defined fields in the coverage report:

Keep in mind that the output contains the checksums of the source files. If you are using different operating systems, the line endings shall be the same.

The LCOV info format is documented at <https://github.com/linux-test-project/lcov/blob/07a1127c2b4390abf4a516e9763fb28a956a9ce4/man/geninfo.1#L989>.

Added in version 8.5: Added --lcov-format-version <#cmdoption-gcovr-lcov-format-version>.

Deprecated since version 8.5: Deprecated --lcov-format-1.x <#cmdoption-gcovr-lcov-format-1> mapped to --lcov-format-version=1.x <#cmdoption-gcovr-lcov-format-version>.

Added in version 7.0: Added --lcov <#cmdoption-gcovr-lcov>, --lcov-comment <#cmdoption-gcovr-lcov-comment> and --lcov-test-name <#cmdoption-gcovr-lcov-test-name>.

You can use Multiple Output Formats <#multiple-output-formats> at the same time.

Multiple Output Formats

You can write multiple report formats with one gcovr invocation by passing the output filename directly to the report format flag. If no filename is specified for the format, the value from -o/--output <#cmdoption-gcovr-o> is used by default, which itself defaults to stdout.

The following report format flags can take an optional output file name:

If the value given to the output option ends with a path separator (/ or \) it is used a directory which is created first and a default filename depending on the format is used.

Note that --html-details <#cmdoption-gcovr-html-details> and --html-nested <#cmdoption-gcovr-html-nested> override any value of --html <#cmdoption-gcovr-html> if it is present.

Using Filters

Gcovr tries to only report coverage for files within your project, not for your libraries. This is influenced by the following options:

  • -r <#cmdoption-gcovr-r>/--root <#cmdoption-gcovr-r>
  • -f <#cmdoption-gcovr-f>/--filter <#cmdoption-gcovr-f>
  • -e <#cmdoption-gcovr-e>/--exclude <#cmdoption-gcovr-e>
  • --gcov-filter <#cmdoption-gcovr-gcov-filter>
  • --gcov-exclude <#cmdoption-gcovr-gcov-exclude>
  • --gcov-exclude-directory <#cmdoption-gcovr-exclude-directory>
  • (the current working directory where gcovr is invoked)

NOTE: Filters can also be specified in the gcovr configuration file <#configuration>.

These options take filters. A filter is a regular expression that matches a file path. Because filters are regular expressions, you will have to escape “special” characters with a backslash \.

Always use forward slashes / as path separators, even on Windows:

If the filter looks like an absolute path, it is matched against an absolute path. Otherwise, the filter is matched against a relative path, where that path is relative to the current directory or if defined in a configuration file to the directory of the file.

Examples of relative filters:

  • --filter sub-dir/ matches only that subdirectory
  • --filter '\.\./src/' matches a sibling directory ../src. But because a dot . matches any character in a regex, we have to escape it. You have to use additional shell escaping. This example uses single quotes for Bash or POSIX shell.
  • --filter '(.+/)?foo\.c$' matches only files called foo.c. The regex must match from the start of the relative path, so we ignore any leading directory parts with (.+/)?. The $ at the end ensures that the path ends here.

If no -f/--filter <#cmdoption-gcovr-f> is provided, the -r/--root <#cmdoption-gcovr-r> is turned into a default filter. Therefore, files outside of the -r/--root <#cmdoption-gcovr-r> directory are excluded.

To be included in a report, the source file must match any -f/--filter <#cmdoption-gcovr-f>, and must not match any -e/--exclude <#cmdoption-gcovr-e> filter.

The --gcov-filter <#cmdoption-gcovr-gcov-filter> and --gcov-exclude <#cmdoption-gcovr-gcov-exclude> filters apply to the .gcov / .json.gz files created by gcov. This is useful mostly when running gcov yourself, and then invoking gcovr with -g/--gcov-use-existing-files <#cmdoption-gcovr-g>. But these filters also apply when gcov is launched by gcovr.

More examples for filters

Excluding files inside build directory via --exclude <#cmdoption-gcovr-e> with absolute path (Unix only):

gcovr --exclude '/.*/build/'

Excluding files inside build directory via --filter <#cmdoption-gcovr-f> with relative path:

gcovr --filter '\.\./'

Configuration Files

Warning:

Config files are an experimental feature and may be subject to change without prior notice.

Defaults for the command line options can be set in a configuration file. Example:

filter = src/
html-details = yes  # info about each source file
output = build/coverage.html

How the configuration file is found: If a --config <#cmdoption-gcovr-config> option is provided, that file is used. Otherwise, a gcovr.cfg file in the -r/--root <#cmdoption-gcovr-r> directory is used, if that file exists.

Each line contains a key = value pair. Space around the = is optional. The value may be empty. Comments start with a hash # and ignore the rest of the line, but cannot start within a word. Empty lines are also ignored.

The available config keys correspond closely to the command line options, and are parsed similarly. In most cases, the name of a long command line option can be used as a config key. If not, this is documented in the option's help message. For example, --gcov-executable <#cmdoption-gcovr-gcov-executable> can be set via the gcov-executable config key. But -b/--branches <#cmdoption-gcovr-b> is set via txt-branch.

Just like command line options, the config keys can be specified multiple times. Depending on the option the last one wins or a list will be built. For example, -f/--filter <#cmdoption-gcovr-f> can be provided multiple times:

# Only show coverage for files in src/, lib/foo, or for main.cpp files.
filter = src/
filter = lib/foo/
filter = *./main\.cpp

Note that relative filters specified in config files will be interpreted relative to the location of the config file itself.

Option arguments are parsed with the following precedence:

  • First the config file is parsed, if any.
  • Then, all command line arguments are added.
  • Finally, if an option was specified neither in a config file nor on the command line, its documented default value is used.

Therefore, it doesn't matter whether a value is provided in the config file or the command line.

Boolean flags are treated specially. When their config value is yes they are enabled, as if the flag had been provided on the command line. When their value is no, they are explicitly disabled by assigning their default value. The -j <#cmdoption-gcovr-j> flag is special as it takes an optional argument. In the config file, gcov-parallel = yes would refer to the no-argument form, whereas gcov-parallel = 4 would provide an explicit argument.

If the option is a path and is not absolute, the path is used relative to the config file. For the option --json-add-tracefile <#cmdoption-gcovr-a>, the directory of the config file is always prepended.

Some config file syntax is explicitly reserved for future extensions: semicolon comments, INI-style sections, multi-line values, quoted values, variable substitutions, alternative key-value separators, etc.

Exclusion Markers

You can exclude parts of your code from coverage metrics.

  • If GCOVR_EXCL_LINE appears within a line, that line is ignored.
  • If GCOVR_EXCL_START appears within a line, all following lines (including the current line) are ignored until a GCOVR_EXCL_STOP marker is encountered.
  • If GCOVR_EXCL_FUNCTION in the line of the function definition but not in front of the definition, the lines of the function are ignored. This marker needs the gcov JSON format version 2 which is generated by gcc-14 and newer. If the needed info isn't available a warning is printed if the tag is found. Also a warning is printed if no function is defined at the tag location. See also --exclude-function <#cmdoption-gcovr-exclude-function>.
  • If GCOVR_EXCL_BR_* markers are used the same exclusion rules apply as above, with the difference being that they are only taken into account for branch coverage.
  • If GCOVR_EXCL_BR_SOURCE appears within a line, the branches which have one of the block ids of the current line as destination block are excluded from the coverage. This can be used e.g. in a default branch which is used for error handling to exclude the source branch from the coverage.
  • If GCOVR_EXCL_BR_WITHOUT_HIT: uncovered/total appears within a line, the uncovered branches are ignored, e.g. GCOVR_EXCL_BR_WITHOUT_HIT: 2/6 will exclude the 2 uncovered branches out of 6 branches in the line. If the uncovered or total branches doesn't match the branches in the line a error is logged and nothing is excluded.

Instead of GCOVR_*, the markers may also start with GCOV_* or LCOV_*. However, start and stop markers must use the same style. The prefix is configurable with the option --exclude-pattern-prefix <#cmdoption-gcovr-exclude-pattern-prefix>.

The excluded region not includes the line with the stop marker:

code
code
excluded       // GCOVR_EXCL_START
still excluded
...
still excluded
NOT excluded // GCOVR_EXCL_STOP
code
code

In the excluded regions, any coverage is excluded.

Added in version 8.0: If --verbose <#cmdoption-gcovr-v> is used the exclusion ranges are logged.

Added in version 8.0: Comment GCOVR_EXCL_BR_SOURCE.

Added in version 8.4: Comment GCOVR_EXCL_BR_WITHOUT_HIT: uncovered/total.

Reproducible Timestamps

In some cases, it may be desirable to list a specific timestamp in the report. Timestamps are shown in the HTML Output <#html-output>, Coveralls JSON Output <#coveralls-output>, and the Cobertura XML Output <#cobertura-output>. This can be achieved via the --timestamp <#cmdoption-gcovr-timestamp> option or via Using SOURCE_DATE_EPOCH environment variable. This option does not affect the modification times or other filesystem metadata.

Added in version 6.0: Respect environment variable SOURCE_DATE_EPOCH <https://reproducible-builds.org/docs/source-date-epoch/> for default of --timestamp <#cmdoption-gcovr-timestamp>.

Added in version 5.1: The --timestamp <#cmdoption-gcovr-timestamp> option.

Timestamp Syntax

The timestamp option understands different formats: Unix timestamps and RFC-3339 timestamps.

Unix timestamps (also known as Posix time or Epoch) are the number of seconds since 1 Jan 1970. These timestamps are always resolved in the UTC timezone. Example usage:

gcovr --timestamp 1640606727

RFC 3339 <https://datatracker.ietf.org/doc/html/rfc3339.html> specifies a reasonable subset of ISO-8601 timestamps. This is the YYYY-MM-DDThh:mm:ss format, optionally followed by a timezone offset (+hh:mm, or Z for UTC). Example usage without a timezone:

gcovr --timestamp '2021-12-27 13:05:27'

Example usages that show equivalent specifications for UTC timestamps:

gcovr --timestamp '2021-12-27T13:05:27Z'
gcovr --timestamp '2021-12-27T13:05:27+00:00'
gcovr --timestamp '2021-12-27T13:05:27-00:00'

Differences and clarifications with respect to RFC-3339:

  • the time zone may be omitted
  • the date and time parts may be separated by a space character instead of the T
  • the date is parsed in a case insensitive manner
  • sub-second accuracy is not currently supported

Additional formats may be added in the future. To ensure that timestamps are handled in the expected manner, it is possible to select a particular timestamp syntax with a prefix.

  • Epoch timestamps can be selected with a @ or epoch: prefix.
  • RFC-3339 timestamps can be selected with a rfc3339: prefix.

Examples of prefixes:

gcovr --timestamp @1640606727
gcovr --timestamp epoch:1640606727
gcovr --timestamp 'rfc3339:2021-12-27 13:05:27'

Using timestamps from Git commits

As an example of using the timestamp feature, we might want to attribute a coverage report to the time when a Git commit was created. Git lets us extract the commit date from a commit with the git show <https://git-scm.com/docs/git-show> command. For the current HEAD commit:

git show --no-patch --format=%cI HEAD

This can be combined into a Bash one-liner like this:

gcovr --timestamp="$(git show --no-patch --format=%cI HEAD)"

Each Git commit has two dates, the author date and the committer date. This information can be extracted with various format codes, e.g. %aI for the author date and %cI for the committer date. These format codes are also available in different formats. The supported Git formats are:

  • Unix timestamps: %at, %ct
  • "Strict ISO" format: %aI, %cI
  • depending on the --date option: %ad, %cd

Git's --date option is documented in git log <https://git-scm.com/docs/git-log>. The supported settings are:

  • Unix timestamps: --date=unix
  • "Strict ISO" format: --date=iso-strict, --date=iso8601-strict, --date=iso-strict-local, --date=iso8601-strict-local

Using SOURCE_DATE_EPOCH

The Reproducible Builds project defines the SOURCE_DATE_EPOCH variable. Gcovr will use this variable as a default timestamp if no explicit --timestamp <#cmdoption-gcovr-timestamp> is set.

The contents of this variable must be an UTC epoch, without any prefix. No other format is supported. Example usage:

SOURCE_DATE_EPOCH=1640606727 gcovr

For more information on setting and using this variable, see the Reproducible Builds documentation on SOURCE_DATE_EPOCH <https://reproducible-builds.org/docs/source-date-epoch/>.

Related documents:

  • Installation <>
  • Getting Started <>
  • Command Line Reference <>
  • Cookbook <>
  • Frequently Asked Questions <>
  • Contributing <> (includes instructions for bug reports)
  • Change Log <>
  • License <>

Command Line Reference

The gcovr command recursively searches a directory tree to find gcov coverage files, and generates a text summary of the code coverage.  The -h/--help option generates the following summary of the gcovr command line options:

gcovr

A utility to run gcov and summarize the coverage in simple reports.

usage: gcovr [options] [search_paths...]

See <<http://gcovr.com/>> for the full manual.

Options

search_paths

Search paths for coverage files. Defaults to --root and --gcov-object-directory. If path is a file it is used directly. Config key(s): search-path.

-h, --help

Show this help message, then exit.

--version

Print the version number, then exit.

-v, --verbose

Print progress messages. Please include this output in bug reports. Config key(s): verbose.

--no-color

Turn off colored logging. Is also set if environment variable NO_COLOR is present. Ignored if --force-color is used. Config key(s): no-color.

--force-color

Force colored logging, this is the default for a terminal. Is also set if environment variable FORCE_COLOR is present. Has precedence over --no-color. Config key(s): force-color.

-r <root>, --root <root>

The root directory of your source files. Defaults to '.', the current directory. File names are reported relative to this root. The --root is the default --filter. Config key(s): root.

--config <config>

Load that configuration file. Defaults to gcovr.cfg in the --root directory.

--no-markers

Turn off exclusion markers. Any exclusion markers specified in source files will be ignored. Config key(s): no-markers.

--fail-under-line <min>

Exit with a status of 2 if the total line coverage is less than MIN. Can be ORed with exit status of '--fail-under-branch', '--fail-under-decision', and '--fail-under-function' option. Config key(s): fail-under-line.

--fail-under-branch <min>

Exit with a status of 4 if the total branch coverage is less than MIN. Can be ORed with exit status of '--fail-under-line', '--fail-under-decision', and '--fail-under-function' option. Config key(s): fail-under-branch.

--fail-under-decision <min>

Exit with a status of 8 if the total decision coverage is less than MIN. Can be ORed with exit status of '--fail-under-line', '--fail-under-branch', and '--fail-under-function' option. Config key(s): fail-under-decision.

--fail-under-function <min>

Exit with a status of 16 if the total function coverage is less than MIN. Can be ORed with exit status of '--fail-under-line', '--fail-under-branch', and '--fail-under-decision' option. Config key(s): fail-under-function.

--source-encoding <source_encoding>

Select the source file encoding. Defaults to the system default encoding (UTF-8). Config key(s): source-encoding.

--cobertura-add-tracefile <cobertura_tracefile>

Combine the coverage data from Cobertura XML files. When this option is used gcov is not run to collect the new coverage data. Config key(s): cobertura-add-tracefile.

-a <json_tracefile>, --json-add-tracefile <json_tracefile>, --add-tracefile <json_tracefile>

Combine the coverage data from JSON files. Coverage files contains source files structure relative to root directory. Those structures are combined in the output relative to the current root directory. Unix style wildcards can be used to add the pathnames matching a specified pattern. In this case pattern must be set in double quotation marks. Option can be specified multiple times. When option is used gcov is not run to collect the new coverage data. Config key(s): add-tracefile.

--txt-report-covered

Report the covered lines instead of the uncovered. Config key(s): txt-covered.

--exclude-function <exclude_function>

Exclude coverage of functions. If function starts and end with '/' it is treated as a regular expression. This option needs at least GCC 14 with a supported version of JSON output format. Config key(s): exclude-function.

--exclude-lines-by-pattern <exclude_lines_by_pattern>

Exclude lines that match this regex. The regex must match the start of the line. Config key(s): exclude-lines-by-pattern.

--exclude-branches-by-pattern <exclude_branches_by_pattern>

Exclude branches that match this regex. The regex must match the start of the line. Config key(s): exclude-branches-by-pattern.

--exclude-pattern-prefix <exclude_pattern_prefix>

Define the regex prefix used in markers / line exclusions (i.e ..._EXCL_START, ..._EXCL_START, ..._EXCL_STOP) Config key(s): exclude-pattern-prefix.

--warn-excluded-lines-with-hits

Print a warning if a line excluded by comments has a hit counter != 0. Config key(s): warn-excluded-lines-with-hits.

Output Options

Gcovr prints a text report by default, but can switch to XML or HTML.

--medium-threshold <medium>, --html-medium-threshold <medium>

If the coverage is below MEDIUM, the value is marked as low coverage in the report. MEDIUM has to be lower than or equal to value of --high-threshold and greater than 0. If MEDIUM is equal to value of --high-threshold the report has only high and low coverage. Default is 75.0. Config key(s): medium-threshold, html-medium-threshold.

--high-threshold <high>, --html-high-threshold <high>

If the coverage is below HIGH, the value is marked as medium coverage in the report. HIGH has to be greater than or equal to value of --medium-threshold. If HIGH is equal to value of --medium-threshold the report has only high and low coverage. Default is 90.0. Config key(s): high-threshold, html-high-threshold.

--medium-threshold-branch <medium_branch>, --html-medium-threshold-branch <medium_branch>

If the coverage is below MEDIUM_BRANCH, the value is marked as low coverage in the report. MEDIUM_BRANCH has to be lower than or equal to value of --high-threshold-branch and greater than 0. If MEDIUM_BRANCH is equal to value of --medium-threshold-branch the report has only high and low coverage. Default is taken from --medium-threshold. Config key(s): medium-threshold-branch, html-medium-threshold-branch.

--high-threshold-branch <high_branch>, --html-high-threshold-branch <high_branch>

If the coverage is below HIGH_BRANCH, the value is marked as medium coverage in the report. HIGH_BRANCH has to be greater than or equal to value of --medium-threshold-branch. If HIGH_BRANCH is equal to value of --medium-threshold-branch the report has only high and low coverage. Default is taken from --high-threshold. Config key(s): high-threshold-branch, html-high-threshold-branch.

--medium-threshold-line <medium_line>, --html-medium-threshold-line <medium_line>

If the coverage is below MEDIUM_LINE, the value is marked as low coverage in the report. MEDIUM_LINE has to be lower than or equal to value of --high-threshold-line and greater than 0. If MEDIUM_LINE is equal to value of --medium-threshold-line the report has only high and low coverage. Default is taken from --medium-threshold. Config key(s): medium-threshold-line, html-medium-threshold-line.

--high-threshold-line <high_line>, --html-high-threshold-line <high_line>

If the coverage is below HIGH_LINE, the value is marked as medium coverage in the report. HIGH_LINE has to be greater than or equal to value of --medium-threshold-line. If HIGH_LINE is equal to value of --medium-threshold-line the report has only high and low coverage. Default is taken from --high-threshold. Config key(s): high-threshold-line, html-high-threshold-line.

-o <output>, --output <output>

Print output to this filename. Defaults to stdout. Individual output formats can override this. Config key(s): output.

--decisions

Report the decision coverage. For HTML, JSON, and the summary report. Config key(s): decisions.

--calls

Report the calls coverage. For HTML and the summary report. Config key(s): calls.

--sort-branches

Sort entries by branches instead of lines. Can only be used together with '--sort uncovered-number' or '--sort uncovered-percent'. Config key(s): sort-branches.

--sort {filename,uncovered-number,uncovered-percent}

Sort entries by filename, number or percent of uncovered lines or branches(if the option --sort-branches is given). The default order is increasing and can be changed by --sort-reverse. The secondary sort key (if values are identical) is always the filename (ascending order). For CSV, HTML, JSON, LCOV and text report. Config key(s): sort.

-u,  --sort-uncovered

Deprecated, please use '--sort uncovered-number' instead. Config key(s): sort-uncovered.

-p,  --sort-percentage

Deprecated, please use '--sort uncovered-percent' instead. Config key(s): sort-percentage.

--sort-reverse

Sort entries in reverse order (see --sort). Config key(s): sort_reverse.

--clover <output>

Generate a Clover XML report. OUTPUT is optional and defaults to --output. Config key(s): clover.

--clover-pretty

Pretty-print the Clover XML report. Implies --clover. Config key(s): clover-pretty.

--clover-project <clover_project>

The project name for the Clover XML report. Config key(s): clover-project.

--cobertura <output>, -x <output>, --xml <output>

Generate a Cobertura XML report. OUTPUT is optional and defaults to --output. Config key(s): cobertura, xml.

--cobertura-pretty,  --xml-pretty

Pretty-print the Cobertura XML report. Implies --cobertura. Config key(s): cobertura-pretty, xml-pretty.

--coveralls <output>

Generate Coveralls API coverage report in this file name. OUTPUT is optional and defaults to --output. Config key(s): coveralls.

--coveralls-pretty

Pretty-print the coveralls report. Implies --coveralls. Config key(s): coveralls-pretty.

--csv <output>

Generate a CSV summary report. OUTPUT is optional and defaults to --output. Config key(s): csv.

--html <output>

Generate a HTML report. OUTPUT is optional and defaults to --output. Config key(s): html.

--html-details <output>

Add annotated source code reports to the HTML report. Implies --html, can not be used together with --html-nested. OUTPUT is optional and defaults to --output. Config key(s): html-details.

--html-nested <output>

Add annotated source code reports to the HTML report. A page is created for each directory that summarize subdirectories with aggregated statistics. Implies --html, can not be used together with --html-details. OUTPUT is optional and defaults to --output. Config key(s): html-nested.

--html-single-page

Use one single html output file containing all data in the specified mode. If mode is 'js-enabled' (default) and javascript is possible the page is interactive like the normal report. If mode is 'static' all files are shown at once. Config key(s): html-single-page.

--html-static-report

Create a static report without javascript. Config key(s): html-static-report.

--html-self-contained

Control whether the HTML report bundles resources like CSS styles. Self-contained reports can be sent via email, but conflict with the Content Security Policy of some web servers. Defaults to self-contained reports unless --html-details or --html-nested is used without --html-single-page. Negation: --no-html-self-contained. Config key(s): html-self-contained.

--html-block-ids

Add the block ids to the HTML report for debugging the branch coverage. Config key(s): html-block-ids.

--html-template-dir <output>

Override the default Jinja2 template directory for the HTML report. Config key(s): html-template-dir.

--html-syntax-highlighting,  --html-details-syntax-highlighting

Use syntax highlighting in HTML source page. Enabled by default. Negation: --no-html-syntax-highlighting, --no-html-details-syntax-highlighting. Config key(s): html-syntax-highlighting, html-details-syntax-highlighting.

--html-theme {green,blue,github.blue,github.green,github.dark-green,github.dark-blue}

Override the default color theme for the HTML report. Default is green. Config key(s): html-theme.

--html-css <css>

Override the default style sheet for the HTML report. Config key(s): html-css.

--html-title <title>

Use TITLE as title for the HTML report. Default is 'GCC Code Coverage Report'. Config key(s): html-title.

--html-tab-size <html_tab_size>

Used spaces for a tab in a source file. Default is 4 Config key(s): html-tab-size.

--html-absolute-paths

Use absolute paths to link the --html-details reports. Defaults to relative links. Config key(s): html-absolute-paths.

--html-encoding <html_encoding>

Override the declared HTML report encoding. Defaults to UTF-8. See also --source-encoding. Config key(s): html-encoding.

--jacoco <output>

Generate a JaCoCo XML report. OUTPUT is optional and defaults to --output. Config key(s): jacoco.

--jacoco-pretty

Pretty-print the JaCoCo XML report. Implies --jacoco. Config key(s): jacoco-pretty.

--jacoco-report-name <name>

The name used for the JaCoCo report. Default is 'GCOVR report'. Config key(s): jacoco-report-name.

--json <output>

Generate a JSON report. OUTPUT is optional and defaults to --output. Config key(s): json.

--json-pretty

Pretty-print the JSON report. Implies --json. Config key(s): json-pretty.

--json-summary <output>

Generate a JSON summary report. OUTPUT is optional and defaults to --output. Config key(s): json-summary.

--json-summary-pretty

Pretty-print the JSON SUMMARY report. Implies --json-summary. Config key(s): json-summary-pretty.

--json-base <path>

Prepend the given path to all file paths in JSON report. Config key(s): json-base.

--json-trace-data-source

Write the data source to the tracefile. Config key(s): json-trace-data-source.

--lcov <output>

Generate a LCOV info file. OUTPUT is optional and defaults to --output. Config key(s): lcov.

--lcov-format-version {1.x,2.0}

The format version to write. Config key(s): lcov_format_version.

--lcov-format-1.x

Deprecated, please use --lcov-format-version=1.x instead. Config key(s): lcov-format-1.x.

--lcov-comment <comment>

The comment used in LCOV file. Config key(s): lcov-comment.

--lcov-test-name <name>

The name used for TN in LCOV file, must not contain spaces. Default is 'GCOVR_report'. Config key(s): lcov-test-name.

--markdown <output>

Generate a markdown report. OUTPUT is optional and defaults to --output. Config key(s): markdown.

--markdown-summary <output>

Generate a markdown summary report. OUTPUT is optional and defaults to --output. Config key(s): markdown-summary.

--markdown-theme {green,blue}

Override the default color theme for the Markdown report. Default is green. Config key(s): markdown-theme.

--markdown-title <text>

Override the default title of the Markdown report. Default is GCC Code Coverage Report. Config key(s): markdown-title.

--markdown-heading-level <int>

Override the default heading level of the Markdown report. This is useful if the report is embedded in another markdown file. Default is 1. Config key(s): markdown-heading-level.

--markdown-file-link <text>

Link the files using given URL by replacing {file} with the current file. Config key(s): markdown-file-link.

--sonarqube <output>

Generate Sonarqube generic coverage report in this file name. OUTPUT is optional and defaults to --output. Config key(s): sonarqube.

--sonarqube-pretty

Pretty-print the Sonarqube XML report. Implies --sonarqube. Config key(s): sonarqube-pretty.

--sonarqube-metric {line,branch,condition,decision}

The metric type to report. Default is 'branch'. Config key(s): sonarqube-metric.

--txt-metric {line,branch,decision}

The metric type to report. Default is 'line'. Config key(s): txt-metric.

-b,  --txt-branches,  --branches

Deprecated, please use '--txt-metric branch' instead.Report the branch coverage instead of the line coverage in text report. Config key(s): txt-branch.

--txt <output>

Generate a text report. OUTPUT is optional and defaults to --output. Config key(s): txt.

-s,  --txt-summary,  --print-summary

Print a small report to stdout with line & function & branch percentage coverage optional parts are decision & call coverage. This is in addition to other reports.  Config key(s): txt-summary, print-summary.

--timestamp <timestamp>

Override current time for reproducible reports. Can use YYYY-MM-DD hh:mm:ss or epoch notation. Used by HTML, Coveralls, and Cobertura reports. Default is taken from environment variable SOURCE_DATE_EPOCH (see <https://reproducible-builds.org/docs/source-date-epoch>) or current time. Config key(s): timestamp.

Filter Options

Filters decide which files are included in the report. Any filter must match, and no exclude filter must match. A filter is a regular expression that matches a path. Filter paths use forward slashes, even on Windows. If the filter looks like an absolute path it is matched against an absolute path. Otherwise, the filter is matched against a relative path, where that path is relative to the current directory or if defined in a configuration file to the directory of the file.

--gcov-filter <gcov_include_filter>

Keep only gcov data files that match this filter. Can be specified multiple times. Config key(s): gcov-filter.

--gcov-exclude <gcov_exclude_filter>

Exclude gcov data files that match this filter. Can be specified multiple times. Config key(s): gcov-exclude.

-i <include_search_filter>, --include <include_search_filter>

Include source files that match this filter. This is to ensure that files are in report even if no coverage data is found. Files are searched recursive from the --root directory. Can be specified multiple times. Config key(s): include.

-f <include_filter>, --filter <include_filter>

Keep only source files that match this filter. Can be specified multiple times. Relative filters are relative to the current working directory or if defined in a configuration file. If no filters are provided, defaults to --root. Config key(s): filter.

-e <exclude_filter>, --exclude <exclude_filter>

Exclude source files that match this filter. Can be specified multiple times. Config key(s): exclude.

--exclude-directory <exclude_directory>, --gcov-exclude-directory <exclude_directory>, --gcov-exclude-directories <exclude_directory>, --exclude-directories <exclude_directory>

Exclude directories that match this regex while searching raw coverage files. Can be specified multiple times. Config key(s): exclude-directory, gcov-exclude-directory, gcov-exclude-directories, exclude-directories.

--trace-include <trace_include_filter>

Log output for files that match this filter. The output is logged without activating verbose mode. Can be specified multiple times. Config key(s): trace-include.

--trace-exclude <trace_exclude_filter>

Do not log very verbose output for files that match this filter. Can be specified multiple times. Config key(s): trace-exclude.

GCOV Options

The 'gcov' tool turns raw coverage files (.gcda and .gcno) into .gcov files that are then processed by gcovr. The gcno files are generated by the compiler. The gcda files are generated when the instrumented program is executed.

-g,  --gcov-use-existing-files,  --use-gcov-files

Use existing gcov files for analysis. Config key(s): gcov-use-existing-files, use-gcov-files.

--gcov-ignore-errors {all,source_not_found,output_error,no_working_dir_found}

Ignore errors from invoking GCOV command instead of exiting with an error. A report will be shown on stderr. Default is 'None'. Config key(s): gcov-ignore-errors.

--gcov-ignore-parse-errors {all,negative_hits.warn,negative_hits.warn_once_per_file,suspicious_hits.warn,suspicious_hits.warn_once_per_file}

Skip lines with parse errors in GCOV files instead of exiting with an error. A report will be shown on stderr. Default is 'None'. Config key(s): gcov-ignore-parse-errors.

--gcov-suspicious-hits-threshold <gcov_suspicious_hits_threshold>

Set the threshold for detecting suspicious hits in gcov output files. Set to 0 to turn the detection of. Config key(s): gcov-suspicious-hits-threshold.

--gcov-executable <gcov_cmd>

Use a particular gcov executable. Must match the compiler you are using, e.g. 'llvm-cov gcov' for Clang. Can include additional arguments. Defaults to the GCOV environment variable, or 'gcov': 'gcov'. Config key(s): gcov-executable.

--gcov-object-directory <gcov_objdir>, --object-directory <gcov_objdir>

Override normal working directory detection. Gcovr needs to identify the path between gcda files and the directory where the compiler was originally run. Normally, gcovr can guess correctly. This option specifies either the path from gcc to the gcda file (i.e. gcc's '-o' option), or the path from the gcda file to gcc's working directory. Config key(s): gcov-object-directory, object-directory.

-j <gcov_parallel>

Set the number of threads to use in parallel. 0=Number of CPUs, negative number='all but N CPUs'. Config key(s): gcov-parallel.

--merge-lines

Merge line coverage for same line coming from different functions, e.g. template instances. The branches, conditions and calls are merged accordingly. Config key(s): merge-lines.

--exclude-function-lines

Exclude coverage from lines defining a function. Config key(s): exclude-function-lines.

--include-internal-functions

Include function coverage of compiler internal functions (starting with '__' or '_GLOBAL__sub_I_'). Config key(s): include-internal-functions.

--exclude-unreachable-branches

Remove branch coverage from lines without useful source code (often, compiler-generated 'dead' code). Config key(s): exclude-unreachable-branches.

--exclude-noncode-lines

Remove coverage from lines which seem to be non-code. Negation: --no-exclude-noncode-lines. Config key(s): exclude-noncode-lines.

--exclude-throw-branches

For branch coverage, remove branches that the compiler generates for exception handling. This often leads to more 'sensible' coverage reports. Config key(s): exclude-throw-branches.

LLVM Options

The 'llvm-profdata' tool turns raw coverage files (.profraw) into .profdata files which are then exported by 'llvm-cov' into a JSON string.

--llvm-profdata-executable <llvm_profdata_cmd>

Use a particular llvm-profdata executable to convert LLVM profraw files. This switches from searching gcno/gcda files and using gcov to searching profraw files (Source-based Code Coverage) of LLVM. Must match the compiler you are using, e.g. llvm-profdata-13 for clang-13. Defaults to the LLVM_PROFDATA environment variable: 'None'. Config key(s): llvm-profdata-executable.

--llvm-cov-binary <llvm_cov_binaries>

The binary to export the coverage data for. See help of 'llvm-cov export' command. The option can be used multiple times. Config key(s): llvm-cov-binary.

GCOV and LLVM Options

Options which are applicable for GCOV and LLVM processing.

-k,  --keep-intermediate-files,  --keep,  --gcov-keep

Keep gcov/profdata files after processing. This applies both to files that were generated by gcovr, or were supplied via the --gcov-use-existing-files/--llvm-use-existing-files option.  Config key(s): keep-intermediate-files.

-d,  --delete-input-files,  --delete,  --gcov-delete

Delete gcda/profraw files after processing, used gcno files are never deleted. Config key(s): delete-input-files.

--merge-mode-functions {strict,merge-use-line-0,merge-use-line-min,merge-use-line-max,separate}

The merge mode for functions coverage from different gcov files for same sourcefile. Default is 'strict'. Config key(s): merge-mode-functions.

For guide-level explanation on using these options, see the User Guide <#guide>.

Cookbook

This section contains how-to guides on creating code coverage reports for various purposes. For an introduction on using gcovr, see the User Guide <#guide> instead.

Recipes in the cookbook:

How to collect coverage for C extensions in Python

Collecting code coverage data on the C code that makes up a Python extension module is not quite as straightforward as with a regular C program.

As with a normal C project, we have to compile our code with coverage instrumentation. Here, we export CFLAGS="--coverage" and then run python3 -m build build_ext.

Unfortunately, build_ext can rebuild a source file even if the current object file is up to date. If multiple extension modules share the same source code file, gcov will get confused by the different timestamps and report inaccurate coverage. It is nontrivial to adapt the build_ext process to avoid this.

Instead, we can use the ccache utility to make the compilation lazy (works best on Unix systems). Before we invoke the build_ext step, we first export CC="ccache gcc". Ccache works well but isn't absolutely perfect, see the ccache manual <https://ccache.dev/manual/latest.html> for caveats.

A shell session might look like this:

# Set required env vars
export CFLAGS="--coverage"
export CC="ccache gcc"

# clear out build files so we get a fresh compile
rm -rf build/temp.*  # contains old .gcda, .gcno files
rm -rf build/lib.*

# rebuild extensions
python3 -m build build_ext

# run test command i.e. pytest

# run gcovr
rm -rf coverage; mkdir coverage
gcovr --filter src/ --txt-summary --html-details coverage/index.html

Out-of-Source Builds with CMake

Tools such as cmake encourage the use of out-of-source builds, where the code is compiled in a directory other than the one which contains the sources. This is an extra complication for gcov. In order to pass the correct compiler and linker flags, the following commands need to be in CMakeLists.txt:

# This flags are used if cmake is called with -DCMAKE_BUILD_TYPE=PROFILE
set(CMAKE_C_FLAGS_PROFILE --coverage)
set(CMAKE_CXX_FLAGS_PROFILE --coverage)

add_executable(program example.cpp)

The --coverage compiler flag is an alternative to -fprofile-arcs -ftest-coverage for recent version of gcc <https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html>. In versions 3.13 and later of cmake, the target_link_libraries command can be removed and add_link_options("--coverage") added after the add_compile_options command.

We then follow a normal cmake build process:

cd $BLD_DIR
cmake -DCMAKE_BUILD_TYPE=PROFILE $SRC_DIR
cmake --build . --verbose

and run the program:

cd $BLD_DIR
./program

However, invocation of gcovr itself has to change. The assorted .gcno and .gcda files will appear under the CMakeFiles directory in BLD_DIR, rather than next to the sources. Since gcovr requires both, the command we need to run is:

cd $BLD_DIR
gcovr -r $SRC_DIR . --txt ../../example_cmake.txt

Support of Keil uVision format

As mentioned in comment of issue 697 <https://github.com/gcovr/gcovr/issues/697#issuecomment-1336255837> the format of gcov file generated by the Keil uVision compiler is not compatible with the gcov specification. To support coverage data generated by this compiler you have to create the gcov files as documented in Keil uVision documentation <https://developer.arm.com/documentation/101407/0537/Debug-Commands/COVERAGE/COVERAGE-GCOV-Export?lang=en> and process them before running gcov to get the correct format.

Save the following Sed script as fix-gcov.sed:

# fix markers for uncovered code:
# match any of #=%$ repeated 6 times
s/^\([#=%$]\)\(\1\{5\}\)/\2/

# fix branch tags
/^branch/ {
  s/executed 0/never executed/
  s/executed .*/taken 1/
  s/skipped .*/never executed/
}

Then, apply this Sed script to all gcov files before invoking gcovr:

find . -name '*.gcov' -exec sed -i -f fix-gcov.sed {} \;
gcovr --gcov-use-existing-files
Warning:

Untested because we have no access to Keil uVision compiler

How to create a standalone application

To create a standalone application you need to install the test suite (see Test suite <#test-suite>). In this test suite you can build a standalone executable with the command python3 -m nox --session bundle_app. The command creates the application build/gcovr and calls the executable with each format to check if it's working correct.

Frequently Asked Questions

What is the difference between lcov and gcovr?

Both lcov and gcovr are tools to create coverage reports.

Gcovr was originally created as a simple script to provide a convenient command line interface to gcov that produced more easily digestible output similar to Python's coverage utilities.

Later, we added XML output that could be used with the Cobertura plugin of the Jenkins continuous integration server. This gave us nice coverage reports for C/C++ code in Jenkins.

HTML output was added much later. If all you need is HTML, pick whichever one produces the output you like better or integrates easier with your existing workflow.

Lcov is a far older project that is part of the Linux Test Project. It provides some features that gcovr does not have: For example, lcov has explicit support for capturing Linux kernel coverage. Lcov also supports various trace file manipulation functions such as merging trace files from different test runs. You can learn more at the lcov website <https://github.com/linux-test-project/lcov> or the lcov GitHub repository <https://github.com/linux-test-project/lcov>.

Why does C++ code have so many uncovered branches?

Gcovr's branch coverage reports are based on GCC's -fprofile-arcs feature, which uses the compiler's control flow graph (CFG) of each function to determine branches. This is a very low-level view: to understand the branches in a given function, it can help to view the function's assembly, e.g. via the Godbolt Compiler Explorer <https://godbolt.org/>.

What gcovr calls a branch is in fact an arc between basic blocks in the CFG. This means gcovr's reports have many branches that are not caused by if statements! For example:

  • Arcs are caused by C/C++ branching operators: for, if, while, switch/case, &&, ||, ? :. Note that switches are often compiled as a decision tree which introduces extra arcs, not just one per case.
  • (Arcs into another function are not shown.)
  • Arcs are caused when a function that may throw returns: one arc to the next block or statement for normal returns, and one arc to an exception handler for exceptions, if this function contains an exception handler. Every local variable with a destructor is an exception handler as well.
  • Compiler-generated code that deals with exceptions often needs extra branches: throw statements, catch clauses, and destructors.
  • Extra arcs are created for static initialization and destruction.
  • Arcs may be added or removed by compiler optimizations. If you compile without optimizations, some arcs may even be unreachable!

Gcovr is not able to remove any “unwanted” branches because GCC's gcov tool does not make the necessary information available, and because different projects are interested in different kinds of branches. However, gcovr has the following options to reduce unwanted branches:

With the --exclude-unreachable-branches <#cmdoption-gcovr-exclude-unreachable-branches> option, gcovr parses the source code to see whether that line even contains any code. If the line is empty or only contains curly braces, this could be an indication of compiler-generated code that was mis-attributed to that line (such as that for static destruction) and branch coverage will be ignored on that line.

With the --exclude-throw-branches <#cmdoption-gcovr-exclude-throw-branches> option, exception-only branches will be ignored. These are typically arcs from a function call into an exception handler.

Compiling with optimizations will typically remove unreachable branches and remove superfluous branches, but makes the coverage report less exact. For example, branching operators might be optimized away. Decision coverage analysis will be very buggy when compiling with optimizations. See also: Gcov and Optimization <https://gcc.gnu.org/onlinedocs/gcc/Gcov-and-Optimization.html> in the GCC documentation.

Despite these approaches, 100% branch coverage will be impossible for most programs.

With the --decisions <#cmdoption-gcovr-decisions> option, gcovr parses the source code to extract a metric for decision coverage. This metric can be interpreted as the branch coverage on C/C++ level. While the feature is not always able to detect the decisions reliably when the code is written very compact (uncheckable decisions will be marked).

Decision coverage may be an acceptable bandaid for C++ code bases, and may be especially useful for optimistic aggregate metrics (e.g. file-level coverage percentages and for quality gates using the --fail-under-* feature). However, 100% "decision" coverage may still leave substantial uncovered control flow.

Why are uncovered files not reported?

Gcovr does report files that have zero coverage, even when no .gcda file is available for that compilation unit.

However, the gcov tool in some versions of GCC refuses to generate output for uncovered files.

To fix this, upgrade GCC to:

  • version 5.5 or later,
  • version 6.2 or later, or
  • any version since 7.

Note that the compiler may ignore inline functions that are never used. To force files to be included in the report even when they are not instrumented, you can use the --include <#cmdoption-gcovr-i> option.

Which options are used for calling gcov?

The options used for calling gcov depend on the version of gcov.

The following options are always used:

The following options are only used if available:

  • --json-format: Use JSON intermediate format.
  • --demangled-names: Not available for LLVM based gcov.
  • --hash-filenames: Available since GCC 7, as fallback the option --preserve-paths is used.
  • --conditions: Available since GCC 14, additionally requires the compiler to be invoked with -fcondition-coverage.

Contributing

This document contains:

How to report bugs

When reporting a bug, first search our issues <https://github.com/gcovr/gcovr/issues?q=is%3Aissue> to avoid duplicates. In your bug report, please describe what you expected gcovr to do, and what it actually did. Also try to include the following details:

  • how you invoked gcovr, i.e. the exact flags and from which directory
  • your project layout
  • your gcovr version
  • your compiler version
  • your operating system
  • and any other relevant details.

Ideally, you can provide a short script and the smallest possible source file to reproduce the problem.

How to help

If you would like to help out, please take a look at our open issues <https://github.com/gcovr/gcovr/issues> and pull requests <https://github.com/gcovr/gcovr/pulls>. The issues labeled help wanted <https://github.com/gcovr/gcovr/labels/help%20wanted> and needs review <https://github.com/gcovr/gcovr/labels/needs%20review> would have the greatest impact.

There are many ways how you can help:

  • assist other users with their problems
  • share your perspective as a gcovr user in discussions
  • test proposed changes in your real-world projects
  • improve our documentation
  • submit pull requests with bug fixes and enhancements

How to submit a Pull Request

Thank you for helping with gcovr development! Please follow this checklist for your pull request:

  • Is this a good approach? Fixing open issues is always welcome! If you want to implement an enhancement, please discuss it first as a GitHub issue.
  • Does it work? Please run the tests locally:

    python3 -m nox

    (see also: Test suite)

    In any case, the tests will run automatically when you open the pull request. But please prevent unnecessary build failures and run the tests yourself first. If you cannot run the tests locally, you can activate GitHub for your fork, or run the tests with Docker. If there are differences the updated files will be available for download from the CI system (one ZIP for each test environment).

    If you add new features, please try to add a test case.

  • Does it conform to the style guide? The source code should conform to the PEP 8 <https://peps.python.org/pep-0008/> standard. Please check your code:

    python3 -m nox --session lint

    The command python3 -m nox will run the linters, run the tests, and check that the docs can be built.

  • Add yourself as an author. If this is your first contribution to gcovr, please add yourself to the AUTHORS.txt file.
  • One change at a time. Please keep your commits and your whole pull request fairly small, so that the changes are easy to review. Each commit should only contain one kind of change, e.g. refactoring or new functionality.
  • Why is this change necessary? When you open the PR, please explain why we need this change and what your PR does. If this PR fixes an open issue, reference that issue in the pull request description. Add a reference to the issue in the CHANGELOG.rst, if the change should not be visible in the changelog (minor or not of interest), add the following string to a single line in the PR body:

    [no changelog]

Once you submit the PR, it will be automatically tested on Windows and Linux, and code coverage will be collected. Your code will be reviewed. This can take a week. Please fix any issues that are discovered during this process. Feel free to force-push your updates to the pull request branch.

If you need assistance for your pull request, you can

  • chat in our Gitter room <https://gitter.im/gcovr/gcovr>
  • discuss your problem in an issue
  • open an unfinished pull request as a work in progress (WIP), and explain what you've like to get reviewed

How to set up a development environment

For working on gcovr, you will need a supported version of Python 3, GCC or clang version from the list below, make, cmake, ninja and bazel. Please make sure that the tools are in the system PATH. On Windows, you will need to install a GCC toolchain as the tests expect a Unix-like environment. You can use MinGW-W64 or MinGW. An easier way is to run tests with Docker.

  • Check your GCC installation, the binary directory must be added to the PATH environment. If one of the following command groups works everything is OK.

    • gcc-5/g++-5/gcov-5 to gcc-15/g++-15/gcov-15
    • clang-10/clang++-10/llvm-cov to clang-19/clang++-19/llvm-cov

    are available everything is OK. The test suite uses the newest GCC found in the PATH. To use another one you need to set the environment CC=... see run and filter tests. If you only have gcc in your path the version is detected to select the correct reference. You can also create symlinks for the gcc executables with the following steps. You can check the GCC version with gcc --version. If the output says version 8, you should also be able to run gcc-8 --version. Your Linux distribution should have set all of this up already. If you don't have an alias like gcc-8, perform the following steps to create an alias for gcc, this should also work in the MSYS shell under Windows:

    1. Create a directory somewhere, e.g. in your home directory: mkdir ~/bin
    2. Create a symlink in that directory which points to GCC: ln -s $(which gcc) ~/bin/gcc-8
    3. Add this directory to your PATH: export PATH="$HOME/bin:$PATH"
    4. Re-test gcc-8 --version to ensure everything worked.
    5. Create additional symlinks for g++ -> g++-8 and gcov -> gcov-8.
  • (Optional) Fork the project on GitHub.
  • Clone the git repository.
  • (Optional) Set up a virtualenv (e.g. with python3 -m venv .venv)
  • Install gcovr in development mode:

    pip install --upgrade pip
    pip install -e '.[dev]'
    pre-commit install

    You can then run gcovr as gcovr or python3 -m gcovr.

    Run the tests to verify that everything works (see Test suite).

  • (Optional) Activate GitHub Actions for your forked repository, so that the cross-platform compatibility tests get run whenever you push your work to your repository. These tests will also be run when you open a pull request to the main gcovr repository.

Tip: If you have problems getting everything set up, consider looking at these files:

  • for Linux: .github/workflows/gcovr-ci-job.yml and admin/Dockerfile.qa
  • for Windows: .github/workflows/gcovr-ci-job.yml

Project Structure

PathDescription
/project root
/src/the gcovr source code (Python module)
/src/gcovr/__main__.pycommand line interface + top-level behavior
/tests/unit tests + integration test corpus
/noxfile.pyDefinition of tests tasks
/pyproject.tomlPython package and tool configuration
/doc/documentation
/doc/sources/user guide + website
/doc/examples/runnable examples for the user guide

The program entrypoint and command line interface is in gcovr/__main__.py. The coverage data is parsed in the gcovr.formats.gcov module. The HTML, XML, text, and summary reports are in gcovr.formats.html and respective modules.

Test suite

The QA process (python3 -m nox) consists of multiple parts:

  • linting and checking format(python3 -m nox --session lint)
  • tests (python3 -m nox --session tests)

    • unit tests in tests
    • integration tests in tests
    • documentation examples in doc/examples
  • documentation build (python3 -m nox --session doc)

The tests are in the tests directory. You can run the tests with python3 -m nox --session tests for the default GCC version (specified via CC environment variable, defaults to gcc or clang).

There are unit tests for some parts of gcovr, and a comprehensive corpus of example projects for integration tests. Each tests/* directory is one such example project.

You can format files with python3 -m nox --session ruff -- format path/to/file)

To get a list of all available sessions run python3 -m nox -l.

The next sections discuss the structure of integration tests, how to run and filter tests, and how to run tests with Docker.

Changed in version 8.3: black is replaced by ruff.

Changed in version 5.2: If black is called without arguments, all files are reformated instead of checked. To check the format use the session lint.

Structure of integration tests

Each project in the corpus contains a test_*.py, a reference directory and a source directory or file:

tests/some-test/
  reference/
    gcc-5/
  source/
    example.cpp
  test_some_test.py

The test_some_test.py controls how the project is built, and how gcovr should be invoked. The reference directory contains baseline files against which the gcovr output is compared. Tests can be executed even without baseline files.

Each test function uses the fixture gcovr_test_exec which is defined in conftest.py. This fixture creates a temporary output directory for each test and copies the content of source into it. If source contains a sub directory with the test ID (the name of the test function without test_ prefix and _ replaced by -), that directory will be used. If source is a file it must contain the name of the test from which the source should be copied. If there is a test ID, the reference is always used from this sub directory in reference. It provides functions to execute the compiler and linker, run gcovr or other programs and to compare the generated output files with the reference files. After the test function is finished the fixture checks if all files where compared by the test and removes the temporary output directory if option .

Run and filter tests

To run all tests, use python3 -m nox. The tests currently assume that you are using GCC 5 and have set up a development environment. You can select a different GCC version by setting the CC environment variable. Supported versions are:

  • gcc: 5, 6 and 8 to 15
  • clang: 10 and 13 to 19

You can run the tests with additional options by adding -- and then the options to the test invocation. Run all tests after each change is a bit slow, therefore you can limit the tests to a specific test file, example project, or output format. For example:

# run only XML tests
python3 -m nox --session tests -- -k 'xml'

# run the simple1 tests
python3 -m nox --session tests -- -k 'simple1'

# run the simple1 tests only for XML
python3 -m nox --session tests -- -k 'xml and simple1'

To see which tests would be run, add the --collect-only option:

#see which tests would be run
python3 -m nox --session tests -- --collect-only

Sometimes during development you need to create reference files for new test or update the current reference files. To do this you have to add --generate-reference or --update-reference option to the test invocation. By default generated output files are automatically removed after test run. To skip this process you can add --skip-clean option the test invocation. For example:

# run tests and generate references for simple1 example
python3 -m nox --session tests -- -k 'simple1' --generate-reference

# run tests and update xml references for simple1 example
python3 -m nox --session tests -- -k 'xml and simple1' --update-reference

# run only XML tests and do not remove generated files
python3 -m nox --session tests -- -k 'xml' --skip-clean

To update the reference data for all compiler in one call see run tests with Docker.

When the currently generated output reports differ to the reference files you can create a ZIP archive named diff.zip in the tests directory by using --archive-differences option. Currently in gcovr it is used by GitHub CI to create a ZIP file with the differences as an artifact.

# run tests and generate a ZIP archive when there were differences
python3 -m nox --session tests -- --archive-differences

Changed in version 8.5: Replaced _ with - in the options controlling the test suite:

  • --generate_reference is now --generate-reference
  • --update_reference is now --update-reference
  • --archive_differences is now --archive-differences
  • --skip_clean is now --skip-clean

Changed in version 5.1: Change how to start test from make test to python3 -m nox --session tests

Added in version 5.0: Added test options --generate_reference, --update_reference, --skip_clean, --archive_differences and changed way to call tests only by make test.

Run tests with Docker

If you can't set up a toolchain locally, you can run the QA process via Docker. First, build the container images:

python3 -m nox -s docker_build

Then, run the container, which executes nox within the container:

python3 -m nox -s docker_run

Or to build and run the container in one step:

python3 -m nox -s docker

You can select the gcc version to use inside the docker by setting the environment variable CC to gcc-5 (default), gcc-6, gcc-8 to gcc-15, clang-10, clang-13 to clang-19 or you can build and run the container with a specific version:

python3 -m nox -s 'docker_compiler(gcc-9)'

To run a specific session you can use the docker_compiler sessions and give the arguments to the nox executed inside the container after a -- :

python3 -m nox -s 'docker_compiler(gcc-9)' -- -rs tests

You can also use the compiler all to run the tests for all compiler versions, gcc to only use the all GCC versions, or clang to use all Clang/LLVM versions.

If you run the tests session inside the container you can add also additional pytest arguments. A useful command to update all the reference files is:

python3 -m nox -s 'docker_compiler(all)' -- -rs tests -- --update-reference

or only for the tests containing simple in the name:

python3 -m nox -s 'docker_compiler(all)' -- -rs tests -- --update-reference -k 'simple'

or only for the tests for html format:

python3 -m nox -s 'docker_compiler(all)' -- -rs tests -- --update-reference -m 'html'

Use a devcontainer

For developing gcovr you can use whatever editor you want. If the editor supports Devcontainers (e.g. VS Code) you do not need to install the needed tools on your local system. You can also use GitHub Codespaces to contribute to the project.

Become a gcovr developer

After you've contributed a bit (whether with discussions, documentation, or code), consider becoming a gcovr developer. As a developer, you can:

  • manage issues and pull requests (label and close them)
  • review pull requests (a developer must approve each PR before it can be merged)
  • participate in votes

Just open an issue that you're interested, and we'll have a quick vote.

Change Log

gcovr Release History and Change Log

8.6 (13 January 2026)

Breaking changes:

New features and notable changes:

Bug fixes and small improvements:

8.5 (08 January 2026)

Known bugs:

  • Merge assertion error for function <unknown function> <#fix-1229>
  • Merge assertion error for functions defined in multiple lines <#fix-1231>

Breaking changes:

New features and notable changes:

  • Due to added support for LLVM source based code coverage format some configuration file keys got changed. The old gcov named options are still supported but they also affect the LLVM toolchain. (#1188 <https://github.com/gcovr/gcovr/issues/1188>)

    • gcov-exclude-directory is changed to exclude-directory.
    • keep-gcov-files is changed to keep-intermediate-files.
    • delete-gcov-files is changed to delete-input-files.

Bug fixes and small improvements:

Internal changes:

8.4 (27 September 2025)

Known bugs:

  • Multiple counters for same line are not merged in coveralls report <#fix-1165>
  • Branch exclusion comments remove the branches complete and do not affect conditions <#fix-1171-1>
  • Excluded branches ar still reported in LCOV report <#fix-1171-2>
  • Exclusion filter for existing GCOV files doesn't work <#fix-1176>
  • Detection of version mismatch between gcc and gcov doesn't work <#fix-1187>
  • Line coverage missing if template functions are used <#fix-1189>
  • TypeError in text report for covered decisions <#fix-1192>
  • Drastic increase of runtime with large projects <#fix-1194-1>
  • Data source in JSON report can contain wrong information <#fix-1194-2>
  • Nested HTML report without data can't be generated <#fix-1197>
  • Fix excluded functions in HTML report <#fix-1206-1>
  • Fix LCOV report if function is defined in multiple lines <#fix-1206-2>

Breaking changes:

  • Improve data model to have several coverage information per line. (#1069 <https://github.com/gcovr/gcovr/issues/1069>)

    • Option --merge-mode-conditions is removed.
    • Property function_name for a line in JSON report is now always set.
    • JSON report can now have several entries per line also with legacy text parser.
    • Cobertura and HTML report now contain function coverage also for older GCC versions.
  • Add excluded metrics to HTML report. The total numbers in the report contain now also the excluded elements. (#1153 <https://github.com/gcovr/gcovr/issues/1153>)

New features and notable changes:

Bug fixes and small improvements:

Documentation:

Internal changes:

8.3 (19 January 2025)

Known bugs:

  • Wrong log message: Deprecated config key None used, please use ... <#fix-1066>
  • Missing excluded property for condition in JSON report <#fix-1080>
  • Multiple functions with same name in Cobertura report <#fix-1085>
  • JaCoCo report does not follow the DTD schema <#fix-1089>
  • Error if conditions for the same line are reported different across GCOV data files <#fix-1092>
  • Wrong handling of functions with specialization <#fix-1126>
  • Files without functions and lines are added to report <#fix-1130>
  • Wrong data used in clover report <#fix-1138>
  • Branch exclusion comments remove the branches complete and do not affect conditions <#fix-1171-1>
  • Exclusion filter for existing GCOV files doesn't work <#fix-1176>
  • Nested HTML report without data can't be generated <#fix-1197>

Breaking changes:

New features and notable changes:

Bug fixes and small improvements:

Documentation:

Internal changes:

8.2 (13 October 2024)

Known bugs:

  • Excluded lines are added to LCOV report <#fix-1012>
  • Overall summary in JaCoCo report is wrong <#fix-1022>
  • Wrong source root in Cobertura report <#fix-1037>
  • Negative counters in GCOV JSON intermediate file are not handled <#fix-1048>
  • JaCoCo report does not follow the DTD schema <#fix-1089>.
  • Wrong handling of functions with specialization <#fix-1126>.
  • Files without functions and lines are added to report <#fix-1130>
  • Wrong data used in clover report <#fix-1138>
  • Branch exclusion comments remove the branches complete and do not affect conditions <#fix-1171-1>
  • Nested HTML report without data can't be generated <#fix-1197>

Breaking changes:

New features and notable changes:

Bug fixes and small improvements:

Documentation:

  • Fix documentation build issue.

Internal changes:

8.1 (13 October 2024)

Known bugs:

  • Overall summary in JaCoCo report is wrong <#fix-1022>
  • Wrong source root in Cobertura report <#fix-1037>
  • Negative counters in GCOV JSON intermediate file are not handled <#fix-1048>
  • JaCoCo report does not follow the DTD schema <#fix-1089>
  • Error if conditions for the same line are reported different across GCOV data files <#fix-1092>
  • Files without functions and lines are added to report <#fix-1130>
  • Wrong data used in clover report <#fix-1138>
  • Branch exclusion comments remove the branches complete and do not affect conditions <#fix-1171-1>
  • Nested HTML report without data can't be generated <#fix-1197>

Breaking changes:

New features and notable changes:

Bug fixes and small improvements:

Documentation:

Internal changes:

8.0 (07 October 2024)

Known bugs:

  • Exclusion of internal function raises a KeyError <#fix-987>
  • Overall summary in JaCoCo report is wrong <#fix-1022>
  • Wrong source root in Cobertura report <#fix-1037>
  • Negative counters in GCOV JSON intermediate file are not handled <#fix-1048>
  • JaCoCo report does not follow the DTD schema <#fix-1089>
  • Error if conditions for the same line are reported different across GCOV data files <#fix-1092>
  • Files without functions and lines are added to report <#fix-1130>
  • Wrong data used in clover report <#fix-1138>
  • Branch exclusion comments remove the branches complete and do not affect conditions <#fix-1171-1>
  • Nested HTML report without data can't be generated <#fix-1197>

Breaking changes:

  • Changes related to added support of gcov JSON intermediate format:

    • The function return count is removed from internal data model, HTML and JSON output because missing in gcov JSON intermediate format. (#935 <https://github.com/gcovr/gcovr/issues/935>)
    • Renamed name key in in data model and JSON report to demangled_name. If gcov JSON intermediate format is used the name key will contained the mangled name. The keys are now aligned with the gcov JSON intermediate format. (#974 <https://github.com/gcovr/gcovr/issues/974>)
  • If block information is missing in gcov legacy text format block 0 is assumed. (#976 <https://github.com/gcovr/gcovr/issues/976>)

New features and notable changes:

Bug fixes and small improvements:

Documentation:

Internal changes:

7.2 (24 February 2024)

Fix tagging issue of 7.1, no functional change.

7.1 (24 February 2024)

Known bugs:

  • Overall summary in JaCoCo report is wrong <#fix-1022>
  • Wrong source root in Cobertura report <#fix-1037>
  • JaCoCo report does not follow the DTD schema <#fix-1089>.
  • Wrong data used in clover report <#fix-1138>
  • Nested HTML report without data can't be generated <#fix-1197>

New features and notable changes:

Bug fixes and small improvements:

Documentation:

Internal changes:

7.0 (25 January 2024)

Known bugs:

  • Overall summary in JaCoCo report is wrong <#fix-1022>
  • Wrong source root in Cobertura report <#fix-1037>
  • JaCoCo report does not follow the DTD schema <#fix-1089>
  • Nested HTML report without data can't be generated <#fix-1197>

Breaking changes:

New features and notable changes:

Bug fixes and small improvements:

Documentation:

Internal changes:

6.0 (08 March 2023)

Known bugs:

  • Wrong source root in Cobertura report <#fix-1037>
  • Nested HTML report without data can't be generated <#fix-1197>

Breaking changes:

New features and notable changes:

Bug fixes and small improvements:

Documentation:

Internal changes:

5.2 (06 August 2022)

New features and notable changes:

Bug fixes and small improvements:

Internal changes:

5.1 (26 March 2022)

Breaking changes:

New features and notable changes:

Bug fixes and small improvements:

Documentation:

Internal changes:

5.0 (11 June 2021)

Breaking changes:

  • Dropped support for Python 2 and Python 3.5. From now on, gcovr will only support Python versions that enjoy upstream support.

Improvements and new features:

Documentation:

Internal changes:

4.2 (6 November 2019)

Breaking changes:

  • Dropped support for Python 3.4.
  • Format flag parameters like --xml <#cmdoption-gcovr-cobertura> or --html <#cmdoption-gcovr-html> now take an optional output file name. This potentially changes the interpretation of search paths. In gcovr --xml foo, previous gcovr versions would search the foo directory for coverage data. Now, gcovr will try to write the Cobertura report to the foo file. To keep the old meaning, separate positional arguments like gcovr --xml -- foo.

Improvements and new features:

Known issues:

Documentation:

Internal changes:

4.1 (2 July 2018)

4.0 (17 June 2018)

Breaking changes:

Improvements and new features:

Internal changes:

3.4 (12 February 2018)

3.3 (6 August 2016)

3.2 (5 July 2014)

3.1 (6 December 2013)

  • Change to make the -r/--root options define the root directory for source files.
  • Fix to apply the -p option when the --html option is used.
  • Adding new option, '--exclude-unreachable-branches' that will exclude branches in certain lines from coverage report.
  • Simplifying and standardizing the processing of linked files.
  • Adding tests for deeply nested code, and symbolic links.
  • Add support for multiple --filter <#cmdoption-gcovr-f> options in the same manner as the --exclude <#cmdoption-gcovr-e> option.

3.0 (10 August 2013)

  • Adding the '--gcov-executable' option to specify the name/location of the gcov executable. The command line option overrides the environment variable, which overrides the default 'gcov'.
  • Adding an empty "<methods/>" block to <classes/> in the XML output: this makes out XML compliant with the Cobertura DTD. (#3951)
  • Allow the GCOV environment variable to override the default 'gcov' executable.  The default is to search the PATH for 'gcov' if the GCOV environment variable is not set. (#3950)
  • Adding support for LCOV-style flags for excluding certain lines from coverage analysis. (#3942)
  • Setup additional logic to test with Python 2.5.
  • Added the --html and --html-details options to generate HTML.
  • Sort output for XML to facilitate baseline tests.
  • Added error when the --object-directory option specifies a bad directory.
  • Added more flexible XML testing, which can ignore XML elements that frequently change (e.g. timestamps).
  • Added the '--xml-pretty' option, which is used to generate pretty XML output for the user manual.
  • Many documentation updates

2.4 (13 April 2012)

  • New approach to walking the directory tree that is more robust to symbolic links (#3908)
  • Normalize all reported path names

    • Normalize using the full absolute path (#3921)
    • Attempt to resolve files referenced through symlinks to a common project-relative path
  • Process gcno files when there is no corresponding gcda file to provide coverage information for unexecuted modules (#3887)
  • Windows compatibility fixes

    • Fix for how we parse source: file names (#3913)
    • Better handling od EOL indicators (#3920)
  • Fix so that gcovr cleans up all .gcov files, even those filtered by command line arguments
  • Added compatibility with GCC 4.8 (#3918)
  • Added a check to warn users who specify an empty --root option (see #3917)
  • Force gcov to run with en_US localization, so the gcovr parser runs correctly on systems with non-English locales (#3898, #3902).
  • Segregate warning/error information onto the stderr stream (#3924)
  • Miscellaneous (Python 3.x) portability fixes
  • Added the master svn revision number as part of the version identifier

2.3.1 (6 January 2012)

  • Adding support for Python 3.x

2.3 (11 December 2011)

2.2 (10 December 2011)

  • Added a test driver for gcovr.
  • Improved estimation of the <sources> element when using gcovr with filters.
  • Added revision and date keywords to gcovr so it is easier to identify what version of the script users are using (especially when they are running a snapshot from trunk).
  • Addressed special case mentioned in [comment:ticket:3884:1]: do not truncate the reported file name if the filter does not start matching at the beginning of the string.
  • Overhaul of the --root / --filter logic. This should resolve the issue raised in #3884, along with the more general filter issue raised in [comment:ticket:3884:1]
  • Overhaul of gcovr's logic for determining gcc/g++'s original working directory. This resolves issues introduced in the original implementation of --object-directory (#3872, #3883).
  • Bugfix: gcovr was only including a <sources> element in the XML report if the user specified -r (#3869)
  • Adding timestamp and version attributes to the gcovr XML report (see #3877).  It looks like the standard Cobertura output reports number of seconds since the epoch for the timestamp and a doted decimal version string.  Now, gcovr reports seconds since the epoch and "gcovr ``"+``__version__ (e.g. "gcovr 2.2") to differentiate it from a pure Cobertura report.

2.1 (26 November 2010)

  • Added the --object-directory option, which allows for a flexible specification of the directory that contains the objects generated by gcov.
  • Adding fix to compare the absolute path of a filename to an exclusion pattern.
  • Adding error checking when no coverage results are found. The line and branch counts can be zero.
  • Adding logic to process the -o/--output option (#3870).
  • Adding patch to scan for lines that look like:

    creating `foo'

    as well as

    creating 'foo'
  • Changing the semantics for EOL to be portable for MS Windows.
  • Add attributes to xml format so that it could be used by hudson/bamboo with cobertura plug-in.

2.0 (22 August 2010)

  • Initial release as a separate package.  Earlier versions of gcovr were managed within the 'fast' Python package.

Known Bugs

This list contains bugs for version 6.0 and newer, always check the latest version of this file available here <https://gcovr.com/en/latest/known_bugs.html>.

Merge assertion error for functions defined in multiple lines

Introduced8.5 (08 January 2026) <#release-8-5>
Fixed8.6 (13 January 2026) <#release-8-6>, #1231 <https://github.com/gcovr/gcovr/issues/1231>

The lin number of the first source line which is hit is used for the function definition. Correct is the first source line independent from the content. This was the behavior before #1204 <https://github.com/gcovr/gcovr/issues/1204>.

Merge assertion error for function <unknown function>

Introduced8.5 (08 January 2026) <#release-8-5>
Fixed8.6 (13 January 2026) <#release-8-6>, #1229 <https://github.com/gcovr/gcovr/issues/1229>

Always add the line numbers for the unknown function added with #1204 <https://github.com/gcovr/gcovr/issues/1204> because the lines can be different for different compilation units. E.g.:

gcovr.exceptions.GcovrMergeAssertionError: <file>:<line> Got function <unknown function> on multiple lines: 123, 456.
  You can run gcovr with --merge-mode-functions=MERGE_MODE.
  The available values for MERGE_MODE are described in the documentation.

With the fix we will have two functions in the report:

  • Function: <unknown function 123>
  • Function: <unknown function 456>

Fix excluded functions in HTML report

Introduced8.4 (27 September 2025) <#release-8-4>
Fixed8.5 (08 January 2026) <#release-8-5>, #1206 <https://github.com/gcovr/gcovr/issues/1206>

The excluded functions where marked as not called instead of excluded in the HTML report.

Fix LCOV report if function is defined in multiple lines

Introduced8.4 (27 September 2025) <#release-8-4>
Fixed8.5 (08 January 2026) <#release-8-5>, #1206 <https://github.com/gcovr/gcovr/issues/1206>

The created postfix for FNDA entry always contains the last line of the function.

Snippet of LCOV report

FN:3,foo(int)_3
FN:5,foo(int)_5
FNDA:1,foo(int)_5
FNDA:1,foo(int)_5

Nested HTML report without data can't be generated

Introduced6.0 (08 March 2023) <#release-6-0>
Fixed8.5 (08 January 2026) <#release-8-5>, #1197 <https://github.com/gcovr/gcovr/issues/1197>

When generating a nested HTML report but there is no coverage data for 6.0 (08 March 2023) <#release-6-0> to 8.2 (13 October 2024) <#release-8-2> no root page is generated and no error is raised. Starting with 8.3 (19 January 2025) <#release-8-3> the following error occurs:

(ERROR) Error occurred while printing reports:
Traceback (most recent call last):
  File "/gcovr/src/gcovr/__main__.py", line 426, in main
    gcovr_formats.write_reports(covdata, options)
  File "/gcovr/src/gcovr/formats/__init__.py", line 311, in write_reports
    format_writer(covdata, output.abspath)
  File "/gcovr/src/gcovr/formats/html/__init__.py", line 282, in write_report
    write_report(covdata, output_file, self.options)
  File "/gcovr/src/gcovr/formats/html/write.py", line 484, in write_report
    write_directory_pages(
  File "/gcovr/src/gcovr/formats/html/write.py", line 610, in write_directory_pages
    root_key = next(iter(sorted([d.dirname for d in covdata.directories])))
StopIteration

Drastic increase of runtime with large projects

Introduced8.4 (27 September 2025) <#release-8-4>
Fixed8.5 (08 January 2026) <#release-8-5>, #1194 <https://github.com/gcovr/gcovr/issues/1194>

The runtime of gcovr increased drastically if a project had source files with many lines and functions.

Data source in JSON report can contain wrong information

Introduced8.4 (27 September 2025) <#release-8-4>
Fixed8.5 (08 January 2026) <#release-8-5>, #1194 <https://github.com/gcovr/gcovr/issues/1194>

The set used to store the data source is shared for all items of the input file. Merging data from another source e.g. for a line is adding the data source to all other locations.

TypeError in text report for covered decisions

Introduced8.4 (27 September 2025) <#release-8-4>
Fixed8.5 (08 January 2026) <#release-8-5>, #1192 <https://github.com/gcovr/gcovr/issues/1192>

If text report for covered decisions is created with --txt-report-covered <#cmdoption-gcovr-txt-report-covered> and --txt-metric=decision <#cmdoption-gcovr-txt-metric> following error occurs:

(ERROR) Error occurred while printing reports:
Traceback (most recent call last):
  File "/gcovr/src/gcovr/__main__.py", line 426, in main
    gcovr_formats.write_reports(covdata, options)
  File "/gcovr/src/gcovr/formats/__init__.py", line 311, in write_reports
    format_writer(covdata, output.abspath)
  File "/gcovr/src/gcovr/formats/txt/__init__.py", line 105, in write_report
    write_report(covdata, output_file, self.options)
  File "/gcovr/src/gcovr/formats/txt/write.py", line 82, in write_report
    (stat, txt) = _summarize_file_coverage(covdata[key], options)
  File "/gcovr/src/gcovr/formats/txt/write.py", line 130, in _summarize_file_coverage
    covered_lines = _covered_decisions_str(filecov)
  File "/gcovr/src/gcovr/formats/txt/write.py", line 223, in _covered_decisions_str
    covered_decisions = sorted(
TypeError: 'method' object is not iterable

Line coverage missing if template functions are used

Introduced8.4 (27 September 2025) <#release-8-4>
Fixed8.5 (08 January 2026) <#release-8-5>, #1189 <https://github.com/gcovr/gcovr/issues/1189>

With release 8.4 (27 September 2025) <#release-8-4> we ignored lines without a function name. If template functions are used there are separators in gcov text format before and after the function specialization. The lines after the specialization were ignored because the function name was set to None.

Snippet of gcov file provided in #1168 <https://github.com/gcovr/gcovr/issues/1168>

        -:  844:    const std::unordered_map<Kind, std::function<catena::exception_with_status(const st2138::Value&, Path::Index, const IAuthorizer&)>> validateSetValueMap_ {
       45:  845:        {Kind::kInt32Value, [this](const st2138::Value& protoVal, Path::Index index, const IAuthorizer& authz) {
call    0 returned 2
call    1 returned 15
call    2 returned 1
call    3 returned 1
call    4 returned 16
------------------
catena::common::ParamWithValue<int>::validateSetValueMap_::{lambda(st2138::Value const&, unsigned long, catena::common::IAuthorizer const&)#1}::operator()(st2138::Value const&, unsigned long, catena::common::IAuthorizer const&) const:
function catena::common::ParamWithValue<int>::validateSetValueMap_::{lambda(st2138::Value const&, unsigned long, catena::common::IAuthorizer const&)#1}::operator()(st2138::Value const&, unsigned long, catena::common::IAuthorizer const&) const called 3 returned 100% blocks executed 100%
        3:  845:        {Kind::kInt32Value, [this](const st2138::Value& protoVal, Path::Index index, const IAuthorizer& authz) {
------------------
catena::common::ParamWithValue<std::vector<int, std::allocator<int> > >::validateSetValueMap_::{lambda(st2138::Value const&, unsigned long, catena::common::IAuthorizer const&)#1}::operator()(st2138::Value const&, unsigned long, catena::common::IAuthorizer const&) const:
function catena::common::ParamWithValue<std::vector<int, std::allocator<int> > >::validateSetValueMap_::{lambda(st2138::Value const&, unsigned long, catena::common::IAuthorizer const&)#1}::operator()(st2138::Value const&, unsigned long, catena::common::IAuthorizer const&) const called 7 returned 100% blocks executed 100%
        7:  845:        {Kind::kInt32Value, [this](const st2138::Value& protoVal, Path::Index index, const IAuthorizer& authz) {
------------------
       20:  846:            return this->validateSetValue_(this->get(), protoVal.int32_value(), protoVal, index, authz);
        3:  846-block  0
call    0 returned 3
branch  1 taken 3 (fallthrough)
branch  2 taken 0 (throw)
        3:  846-block  1
call    3 returned 3
call    4 returned 3
branch  5 taken 3 (fallthrough)
branch  6 taken 0 (throw)
        3:  846-block  2
        3:  846-block  3
        7:  846-block  4
call    7 returned 7
branch  8 taken 7 (fallthrough)
branch  9 taken 0 (throw)
        7:  846-block  5
call   10 returned 7
call   11 returned 7
branch 12 taken 7 (fallthrough)
branch 13 taken 0 (throw)
        7:  846-block  6
        7:  846-block  7
        -:  847:        }},

Detection of version mismatch between gcc and gcov doesn't work

Introduced8.4 (27 September 2025) <#release-8-4>
Fixed8.5 (08 January 2026) <#release-8-5>, #1187 <https://github.com/gcovr/gcovr/issues/1187>

The regular version for detecting version mismatch between gcc and gcov didn't match the following strings:

  • ...:version '...', prefer '...'
  • ...:version '...', prefer version '...'

Exclusion filter for existing GCOV files doesn't work

Introduced8.3 (19 January 2025) <#release-8-3>
Fixed8.5 (08 January 2026) <#release-8-5>, #1176 <https://github.com/gcovr/gcovr/issues/1176>

The exclusion filter given by --gcov-exclude <#cmdoption-gcovr-gcov-exclude> isn't applied. The message Excluding gcov file: ... is printed but the file is still used.

Branch exclusion comments remove the branches complete and do not affect conditions

Introduced8.0 (07 October 2024) <#release-8-0>
Fixed8.5 (08 January 2026) <#release-8-5>, #1171 <https://github.com/gcovr/gcovr/issues/1171>

If a line is excluded by comments and contains branches and conditions, the branches and conditions are excluded and the decisions are cleared. If branches are excluded by comments they are removed completely but the conditions are still reported. With the fix the branch exclusion comments exclude both the branches and conditions and clear the decisions as if the line was excluded.

Excluded branches ar still reported in LCOV report

Introduced8.4 (27 September 2025) <#release-8-4>
Fixed8.5 (08 January 2026) <#release-8-5>, #1171 <https://github.com/gcovr/gcovr/issues/1171>

When a line with branches is excluded the branch exclusion flag is ignored and there are still BRDA lines created in the LCOV report.

Multiple counters for same line are not merged in coveralls report

Introduced8.4 (27 September 2025) <#release-8-4>
Fixed8.5 (08 January 2026) <#release-8-5>, #1165 <https://github.com/gcovr/gcovr/issues/1165>

Since version 8.4 there can be several coverage elements for same line. This data isn't merged in coveralls report. The elements are added as several elements to the coverage list in the coveralls report which result in wrong data for the following lines.

Wrong data used in clover report

Introduced7.1 (24 February 2024) <#release-7-1>
Fixed8.4 (27 September 2025) <#release-8-4>, #1138 <https://github.com/gcovr/gcovr/issues/1138>
  • loc contains the highest line number with coverage information instead of lines of the file.
  • ncloc contains the number of reportable lines instead of the lines of the file without comments.
  • statements and coveredstatements are always set to zero but lines of type stmt are added to the report.

Discrepancy between exclusion and removal of coverage data

Introduced8.0 (07 October 2024) <#release-8-0>
Fixed8.4 (27 September 2025) <#release-8-4>, #1137 <https://github.com/gcovr/gcovr/issues/1137>
  • The internal functions where removed but the line coverage was only excluded. Now the line coverage data is also removed.
  • The coverage of a whole line was removed if a function started on this line, even if the line coverage belongs to another function. Now only the data for this function is removed.

Files without functions and lines are added to report

Introduced8.0 (07 October 2024) <#release-8-0>
Fixed8.4 (27 September 2025) <#release-8-4>, #1130 <https://github.com/gcovr/gcovr/issues/1130>

Files without functions and lines from gcov JSON report are added to data model.

Snippet from gcov JSON report

{
  "file": "/path/to/file.h",
  "functions": [],
  "lines": []
}

Wrong handling of functions with specialization

Introduced8.3 (19 January 2025) <#release-8-3>
Fixed8.4 (27 September 2025) <#release-8-4>, #1126 <https://github.com/gcovr/gcovr/issues/1126>
  • With gcc-5, gcc-6 and clang compiler functions with specializations (template functions) use one block in the output which starts with all names. All functions are added to the data model but only the last one has coverage data (of all functions). A debug message is printed for each function which will not contain any line coverage.

    This can't be changed on our side because of missing information.

Template specialization for gcc-5, gcc-6 and clang

function foo() called 1 returned 100% blocks executed 100%
        1:    3:void foo() {
        1:    3-block  0
        1:    4:   std::cout << "Hello from foo()." << std::endl;
        1:    4-block  0
call    0 returned 1
call    1 returned 1
        1:    5:}
        -:    6:
        -:    7:template<typename T>
function void func<double>(double, double) called 2 returned 100% blocks executed 33%
function void func<int>(int, int) called 2 returned 100% blocks executed 100%
        4:    8:void func(T a, T b) {
        2:    8-block  0
        2:    8-block  1
        4:    9:   if (a < b) {
        2:    9-block  0
branch  0 taken 0 (fallthrough)
branch  1 taken 2
        2:    9-block  1
branch  2 taken 1 (fallthrough)
branch  3 taken 1
        1:   10:      std::cout << a << " is less than " << b << std::endl;
    $$$$$:   10-block  0
call    0 never executed
call    1 never executed
call    2 never executed
call    3 never executed
        1:   10-block  1
call    4 returned 1
call    5 returned 1
call    6 returned 1
call    7 returned 1
        -:   11:   }
        4:   12:}
  • For gcc-8 and newer (unless GCOV JSON is used) the output of functions with specialization starts with a block with overall coverage followed by a block for each specialized function. If a normal function was in front of this block the overall counts where added to this function.

    This data is now removed again after detecting the specialization and a debug message is printed.

Template specialization for gcc-8 and newer

        -:    2:
function foo() called 1 returned 100% blocks executed 100%
        1:    3:void foo() {
        1:    4:   std::cout << "Hello from foo()." << std::endl;
        1:    4-block  0
call    0 returned 1
call    1 returned 1
        1:    5:}
        -:    6:
        -:    7:template<typename T>
        4:    8:void func(T a, T b) {
        4:    9:   if (a < b) {
      1*:   10:      std::cout << a << " is less than " << b << std::endl;
        -:   11:   }
        4:   12:}
------------------
void func<double>(double, double):
function void func<double>(double, double) called 2 returned 100% blocks executed 33%
        2:    8:void func(T a, T b) {
        2:    9:   if (a < b) {
        2:    9-block  0
branch  0 taken 0 (fallthrough)
branch  1 taken 2
    #####:   10:      std::cout << a << " is less than " << b << std::endl;
    %%%%%:   10-block  0
call    0 never executed
call    1 never executed
call    2 never executed
call    3 never executed
        -:   11:   }
        2:   12:}
------------------
void func<int>(int, int):
function void func<int>(int, int) called 2 returned 100% blocks executed 100%
        2:    8:void func(T a, T b) {
        2:    9:   if (a < b) {
        2:    9-block  0
branch  0 taken 1 (fallthrough)
branch  1 taken 1
        1:   10:      std::cout << a << " is less than " << b << std::endl;
        1:   10-block  0
call    0 returned 1
call    1 returned 1
call    2 returned 1
call    3 returned 1
        -:   11:   }
        2:   12:}
------------------
  • A forced inline function does not contain a function name in the output. If the function is at the begin of the output it is ignored and a debug message is printed. In the middle of the file it is still added to the previous function.

    This can’t be changed on our side because of missing information.

Forced inline function at file start (ignored by fix)

        -:    0:Source:main.cpp
        -:    0:Graph:./testcase-main.gcno
        -:    0:Data:./testcase-main.gcda
        -:    0:Runs:1
        -:    1:
        -:    2:inline int foo(int x) __attribute__((always_inline));
        -:    3:inline int foo(int x) {
      1*:    4:  return x ? 1 : 0;
    %%%%%:    4-block  0
        1:    4-block  1
        1:    4-block  2
        1:    4-block  3
        -:    5:}
        -:    6:
function main called 1 returned 100% blocks executed 86%
        1:    7:int main() {
        1:    7-block  0
branch  0 taken 0 (fallthrough)
branch  1 taken 1
        1:    8:    return foo(0);
        1:    8-block  0
        -:    9:}

Error if conditions for the same line are reported different across GCOV data files

Introduced8.3 (19 January 2025) <#release-8-3>
Fixed8.4 (27 September 2025) <#release-8-4>, #1092 <https://github.com/gcovr/gcovr/issues/1092>

The number and the order of the items reported by GCOV can differ between the compilation units or between the runs. With the fix the data is merged if they have the same properties instead of the position in the list which failed because of the different properties. The properties taken into account are described in JSON Output <#json-output>

E.g. from a project GCOV reported following data for a line defined in a header.

file.gcov from file_a.gcda

{
    "line_number": 970,
    "count": 0,
    "unexecuted_block": true,
    "block_ids": [
        3
    ],
    "branches": [
        {
            "count": 0,
            "throw": false,
            "fallthrough": true,
            "source_block_id": 3,
            "destination_block_id": 4
        },
        {
            "count": 0,
            "throw": false,
            "fallthrough": false,
            "source_block_id": 3,
            "destination_block_id": 5
        }
    ],
    "calls": [],
    "conditions": [
        {
            "count": 2,
            "covered": 0,
            "not_covered_true": [
                0
            ],
            "not_covered_false": [
                0
            ]
        }
    ]
}

file.gcov from file_b.gcda

{
    "line_number": 970,
    "count": 593,
    "unexecuted_block": true,
    "block_ids": [
        6,
        3
    ],
    "branches": [
        {
            "count": 0,
            "throw": false,
            "fallthrough": true,
            "source_block_id": 6,
            "destination_block_id": 7
        },
        {
            "count": 0,
            "throw": false,
            "fallthrough": false,
            "source_block_id": 6,
            "destination_block_id": 8
        },
        {
            "count": 0,
            "throw": false,
            "fallthrough": true,
            "source_block_id": 3,
            "destination_block_id": 4
        },
        {
            "count": 593,
            "throw": false,
            "fallthrough": false,
            "source_block_id": 3,
            "destination_block_id": 5
        }
    ],
    "calls": [],
    "conditions": [
        {
            "count": 4,
            "covered": 0,
            "not_covered_true": [
                0,
                1
            ],
            "not_covered_false": [
                0,
                1
            ]
        },
        {
            "count": 2,
            "covered": 1,
            "not_covered_true": [],
            "not_covered_false": [
                0
            ]
        }
    ]
}

JaCoCo report does not follow the DTD schema

Introduced7.0 (25 January 2024) <#release-7-0>
Fixed8.4 (27 September 2025) <#release-8-4>, #1089 <https://github.com/gcovr/gcovr/issues/1089>

JaCoCo report does not follow the DTD.

Multiple functions with same name in Cobertura report

Introduced8.3 (19 January 2025) <#release-8-3>
Fixed8.4 (27 September 2025) <#release-8-4>, #1085 <https://github.com/gcovr/gcovr/issues/1085>

Cobertura report contains multiple functions with same name for virtual destructors and const overloads.

Missing excluded property for condition in JSON report

Introduced8.3 (19 January 2025) <#release-8-3>
Fixed8.4 (27 September 2025) <#release-8-4>, #1080 <https://github.com/gcovr/gcovr/issues/1080>

JSON report doesn't contain excluded property for conditions and calls.

Wrong log message: Deprecated config key None used, please use ...

Introduced8.3 (19 January 2025) <#release-8-3>
Fixed8.4 (27 September 2025) <#release-8-4>, #1066 <https://github.com/gcovr/gcovr/issues/1066>

The log message Deprecated config key None used, please use 'txt-metric=branch' instead. is printed even if the mentioned key is used.

Negative counters in GCOV JSON intermediate file are not handled

Introduced8.0 (07 October 2024) <#release-8-0>
Fixed8.3 (19 January 2025) <#release-8-3>, #1048 <https://github.com/gcovr/gcovr/issues/1048>

Because of a bug in GCOV (see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68080>) we can get negative counter values in the GCOV reports. The handling of this negative counters was missing is missing if we use JSON intermediate file.

Wrong source root in Cobertura report

Introduced6.0 (08 March 2023) <#release-6-0>
Fixed8.3 (19 January 2025) <#release-8-3>, #1037 <https://github.com/gcovr/gcovr/issues/1037>

For the source root path in Cobertura report a relative path is used instead of an absolute one. When reading the report the root was ignored.

Overall summary in JaCoCo report is wrong

Introduced7.0 (25 January 2024) <#release-7-0>
Fixed8.3 (19 January 2025) <#release-8-3>, #1022 <https://github.com/gcovr/gcovr/issues/1022>

The overall summary stats in JaCoCo report contains the stats ot the last file in the report.

Excluded lines are added to LCOV report

Introduced8.2 (13 October 2024) <#release-8-2>
Fixed8.3 (19 January 2025) <#release-8-3>, #1012 <https://github.com/gcovr/gcovr/issues/1012>

The excluded lines are added with a count of 0 to the LCOV report.

Exclusion of internal function raises a KeyError

Introduced8.0 (07 October 2024) <#release-8-0>
Fixed8.1 (13 October 2024) <#release-8-1>, #987 <https://github.com/gcovr/gcovr/issues/987>

If internal functions are excluded GCOVR fails with a stack backtrace:

(INFO) Reading coverage data...

Traceback (most recent call last):
  File "gcovr/formats/gcov/workers.py", line 81, in worker
    work(*args, **kwargs)
  File "gcovr/formats/gcov/read.py", line 566, in process_datafile
    done = run_gcov_and_process_files(
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "gcovr/formats/gcov/read.py", line 922, in run_gcov_and_process_files
    process_gcov_json_data(gcov_filename, covdata, options)
  File "gcovr/formats/gcov/read.py", line 294, in process_gcov_json_data
    apply_all_exclusions(file_cov, lines=encoded_source_lines, options=options)
  File "gcovr/exclusions/__init__.py", line 109, in apply_all_exclusions
    remove_internal_functions(filecov)
  File "gcovr/exclusions/__init__.py", line 136, in remove_internal_functions
    filecov.functions.pop(function.demangled_name)
KeyError: '__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > config::skip_list<__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >(__gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >)'

License

License Terms

BSD 3-Clause License

Copyright (c) 2013-2026 the gcovr authors
Copyright (c) 2013 Sandia Corporation.
Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
the U.S. Government retains certain rights in this software.

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
   contributors may be used to endorse or promote products derived from
   this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Acknowledgements

Gcovr is maintained by:

Lukas Atkinson and Michael Förderer.

The following developers contributed to gcovr (ordered alphabetically):

alex43dm, Andrew Stone, Antonio Quarta, Armandas Jarušauskas, Arvin Schnell, Attie Grande, Bernhard Breinbauer, Carlos Jenkins, Cary Converse, Cezary Gapiński, Cheng-Yeh(Ken) Chung, Christian Granzin, Christian Taedcke, Dave George, David Legault, Davide Pesavento, Dom Postorivo, ebmmy, Elektrobit Automotive GmbH, Ensky Lin, Frank Ullrich, Frank Wiles, Fredrik Hoxell, Glenn Töws, Grégoire Roussel, goriy, Irfan Adilovic, ja11sop, James Reynolds, Jeremy Fixemer, Jessica Levine, Joachim Kuebart, Joel Klinghed, Johan Bertrand, John Siirola, Jörg Kreuzberger, Jordi Sabater, Josef Barnes, Julien Marrec, Kai Blaschke, Kevin Broselge, Kevin Cai, Klaus Weinbauer, Leon Ma, libPhipp, Lukas Atkinson, Lukas Baischer, Luke Woydziak, Marc Font Freixa, Marek Kurdej, Martin Mraz, Matsumoto Taichi, Matthew Stadelman, Matthias Schmieder, Matthieu Darbois, Matthieu Eyraud, Michael Förderer, Michał Pszona, Mikael Salson, Mikk Leini, Nikolaj Schumacher, Oleksiy Pikalo, Pablo Martín, Phil Clapham, Piotr Dziwinski, Reto Schneider, Richard Kjerstadius, Robert Rosengren, Sebastian Weigand, Songmin Li, Steven Myint, Sylvestre Ledru, TFA-N, Thibault Gasc, Tilo Wiedera, trillian, Tsche, Tyler W. Mace, Tyler Voskuilen, trapzero, Will Thompson, William Hart, Zachary J. Fields, Zachary P. Hensley, and possibly others.

The development of Gcovr has been partially supported by Sandia National Laboratories. Sandia National Laboratories is a multi-program laboratory managed and operated by Sandia Corporation, a wholly owned subsidiary of Lockheed Martin Corporation, for the U.S.  Department of Energy's National Nuclear Security Administration under contract DE-AC04-94AL85000.

Gcovr development moved to this repository in September, 2013 from Sandia National Laboratories.

Author

the gcovr authors

Info

Feb 20, 2026 8.6