Skip to content

gcovr 使用方式及参数说明

gcovr 是基于 gcov 的覆盖率报告工具。它可以直接生成文本、HTML、XML、Cobertura、SonarQube 等格式,常用于 CI,因为命令相对简洁。

gcovr 与 lcov 的区别

工具 特点
lcov + genhtml 经典组合,HTML 报告清晰,Linux 工程常见
gcovr 单工具生成多格式报告,CI 集成方便

二者都依赖编译器生成覆盖率数据。选择哪一个更多取决于团队习惯和 CI 报告格式要求。

基本命令

gcovr -r . build-coverage
gcovr -r . build-coverage --html --html-details -o coverage.html
gcovr -r . build-coverage --xml-pretty -o coverage.xml

-r . 指定项目根目录。gcovr 会用它决定相对路径,并默认过滤根目录外的文件。

常用参数

参数 说明
-r, --root DIR 指定源码根目录
search_paths... 指定搜索覆盖率数据的路径,通常传构建目录
--filter REGEX 只包含匹配路径
--exclude REGEX 排除匹配路径
--exclude-directories REGEX 搜索覆盖率数据时跳过匹配目录
--gcov-filter REGEX 只处理匹配的 .gcov 数据文件
--gcov-exclude REGEX 排除匹配的 .gcov 数据文件
--gcov-executable CMD 指定 gcov 命令,例如 gcc-13-gcov 或 llvm-cov gcov
--gcov-object-directory DIR 指定 gcov 对象目录,路径推断失败时使用
--gcov-ignore-errors TYPE 忽略 gcov 调用错误
--gcov-ignore-parse-errors TYPE 忽略 gcov 输出解析错误
--keep 保留 gcovr 生成的中间 .gcov 文件
--delete 处理后删除输入覆盖率数据文件
--html 生成 HTML 报告
--html-details 生成带源码详情的 HTML 报告
--html-title TITLE 设置 HTML 报告标题
--html-theme THEME 设置 HTML 主题,具体可用值取决于 gcovr 版本
--xml 生成 Cobertura XML
--xml-pretty 生成格式化 XML
--json 生成 JSON
--json-summary 生成 JSON 摘要
--csv 生成 CSV 摘要
--sonarqube 生成 SonarQube XML
--coveralls 生成 Coveralls JSON
--lcov 输出 lcov info 格式
--txt 生成文本报告
--branches 启用分支覆盖率
--decisions 启用 decision coverage,具体支持取决于版本
--calls 启用调用覆盖率,具体支持取决于版本和 gcov 数据
--print-summary 打印摘要
--fail-under-line N 行覆盖率低于 N 时返回失败
--fail-under-branch N 分支覆盖率低于 N 时返回失败
--fail-under-function N 函数覆盖率低于 N 时返回失败
--config FILE 从配置文件读取选项
--verbose 输出详细调试信息
--version 输出版本
-o FILE 指定输出文件

参数分类

目的 常用参数
搜索数据 search_paths、--root、--gcov-object-directory
过滤源码 --filter、--exclude
加速搜索 --exclude-directories
指定工具链 --gcov-executable
调试 gcov --keep、--verbose、--gcov-ignore-errors
输出报告 --html、--xml-pretty、--json、--csv、--sonarqube
覆盖率门禁 --fail-under-line、--fail-under-branch、--fail-under-function

推荐命令

gcovr \
    --root . \
    build-coverage \
    --exclude '.*tests.*' \
    --exclude '.*_deps.*' \
    --branches \
    --html \
    --html-details \
    --output coverage.html \
    --print-summary

CI 中可以设置覆盖率门禁:

gcovr -r . build-coverage \
    --branches \
    --fail-under-line 80 \
    --fail-under-branch 70 \
    --xml-pretty \
    -o coverage.xml

当覆盖率低于阈值时,gcovr 会返回非零退出码,CI 可以据此失败。

指定 gcov 工具

gcovr 会调用 gcov 把 .gcda、.gcno 转换成可分析数据。如果编译器不是默认 GCC,建议显式指定:

gcovr \
    --root . \
    build-coverage \
    --gcov-executable gcc-13-gcov \
    --html --html-details \
    --output coverage.html

交叉工具链:

gcovr \
    --root . \
    build-coverage \
    --gcov-executable /opt/toolchain/bin/arm-none-eabi-gcov \
    --xml-pretty \
    --output coverage.xml

Clang gcov 兼容模式:

gcovr \
    --root . \
    build-coverage \
    --gcov-executable "llvm-cov gcov" \
    --html --html-details \
    --output coverage.html

--gcov-executable 必须和编译器生成的覆盖率数据格式匹配。gcovr 官方文档也明确建议 Clang 场景使用类似 llvm-cov gcov 的命令。

多格式输出

gcovr 可以一次命令生成一种主要输出。实际脚本中常多次调用 gcovr,分别生成不同格式。

gcovr -r . build-coverage --txt -o coverage.txt
gcovr -r . build-coverage --html --html-details -o coverage.html
gcovr -r . build-coverage --xml-pretty -o coverage.xml
gcovr -r . build-coverage --json -o coverage.json
gcovr -r . build-coverage --csv -o coverage.csv
gcovr -r . build-coverage --sonarqube -o sonarqube.xml
gcovr -r . build-coverage --lcov -o coverage.info
输出格式 适用场景
--txt 终端查看和日志留存
--html --html-details 本地人工阅读
--xml-pretty CI 平台 Cobertura 风格解析
--json 自定义工具二次处理
--csv 表格统计
--sonarqube SonarQube 平台
--lcov 转换为 lcov info 格式

CMake 自定义目标示例

find_program(GCOVR_EXECUTABLE gcovr)

if(GCOVR_EXECUTABLE)
    add_custom_target(coverage
        COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure
        COMMAND ${GCOVR_EXECUTABLE}
            --root ${CMAKE_SOURCE_DIR}
            ${CMAKE_BINARY_DIR}
            --exclude ".*tests.*"
            --exclude ".*_deps.*"
            --branches
            --html
            --html-details
            --output ${CMAKE_BINARY_DIR}/coverage.html
        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
        COMMENT "Running tests and generating gcovr coverage report")
endif()

运行:

cmake --build build-coverage --target coverage

使用配置文件

当参数很多时,可以把 gcovr 选项写入配置文件,减少 CI 脚本长度。

gcovr.cfg 示例:

root = .
filter = src/.*
filter = include/.*
exclude = .*tests.*
exclude = .*_deps.*
branches = yes
print-summary = yes
gcov-executable = gcov

执行:

gcovr --config gcovr.cfg build-coverage --html --html-details -o coverage.html

配置文件适合固定项目规则,命令行参数适合 CI 中临时覆盖输出路径和门禁阈值。

过滤规则

gcovr 的过滤和排除通常使用正则表达式。Windows 路径可能包含反斜杠,跨平台工程中建议让 CMake、gcovr 尽量使用统一根目录,并用较宽松的正则。

目标 示例
排除测试目录 --exclude '.*tests.*'
排除第三方依赖 --exclude '.*third_party.*'
只包含 src --filter '.*/src/.*'
排除构建生成文件 --exclude '.*CMakeFiles.*'

filter 与 exclude 的区别

--filter 和 --exclude 作用于源码文件路径。常见策略是先用 --filter 限定产品代码目录,再用 --exclude 排除测试和第三方。

gcovr -r . build-coverage \
    --filter '.*/src/.*' \
    --filter '.*/include/.*' \
    --exclude '.*/tests/.*' \
    --exclude '.*/third_party/.*'

--exclude-directories 作用于搜索覆盖率数据的目录,可用于加速:

gcovr -r . build-coverage \
    --exclude-directories '.*/_deps/.*' \
    --exclude-directories '.*/third_party/.*'

如果构建目录很大,先排除第三方和临时目录能明显减少扫描时间。

路径推断失败

gcovr 通常能自动推断 .gcda 文件与源码、对象文件之间的关系。但复杂构建或交叉编译工程中可能失败,此时可以指定对象目录:

gcovr \
    --root . \
    --gcov-object-directory build-coverage \
    build-coverage \
    --html --html-details \
    --output coverage.html

如果报告为空但 .gcda 文件确实存在,--gcov-object-directory 是优先尝试的参数之一。

排除指定代码片段

gcovr 支持通过源码注释排除某些行或区域。具体标记随版本和配置可能不同,常见思想是用排除标记告诉工具“这段代码不计入覆盖率”。

示例:

void DebugOnlyLog() {
    // GCOVR_EXCL_START
    if (std::getenv("DEBUG_LOG")) {
        std::cerr << "debug log\n";
    }
    // GCOVR_EXCL_STOP
}

排除标记适合不可达防御分支、平台相关分支、调试辅助代码。不要用它隐藏应该测试的业务逻辑。

CI 门禁示例

gcovr -r . build-coverage \
    --branches \
    --fail-under-line 80 \
    --fail-under-branch 70 \
    --fail-under-function 80 \
    --xml-pretty \
    -o coverage.xml

门禁阈值建议循序渐进。老项目可以先记录当前基线,再要求新增代码不降低覆盖率。

常见问题

问题 处理
报告为空 确认测试运行后生成 .gcda,并把构建目录传给 gcovr
路径过滤不生效 检查正则是否匹配 gcovr 输出中的实际路径
CI 无法解析报告 使用 --xml-pretty 或 CI 指定的格式
分支覆盖率为 0 添加 --branches,并确认编译器生成分支数据
gcov 调用失败 使用 --gcov-executable 指定匹配工具
扫描很慢 使用 --exclude-directories 排除第三方和大目录
源码路径解析失败 尝试 --gcov-object-directory
偶发解析错误 先用 --verbose 和 --keep 保留中间文件排查