You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用GCOVR统计共享库代码覆盖:无GCNO/GCDA文件生成问题

共享库项目代码覆盖率为空(无.gcno/.gcda文件)的解决方案

问题背景

测试项目包含共享库calculator,运行覆盖率目标时生成的XML为空:

  • 共享库未生成.gcno文件
  • 仅单元测试可执行文件生成.gcno
  • 完全没有生成.gcda文件

项目目录结构

ProjectRoot/
|- src/
|  |- calculator/
|  |  |- CMakeLists.txt
|  |  |- Calculator.cpp
|  |  |- Calculator.h
|  |- CMakeLists.txt
|  |- sources.cpp
|  |- sources.h
|- tests/
|  |- CMakeLists.txt
|  |- unit-test1.cpp
|- CMakeLists.txt

现有CMake配置(关键部分)

根目录CMakeLists.txt

cmake_minimum_required (VERSION 3.14)
enable_testing()
project("testProject")

add_subdirectory("src")

if (CMAKE_BUILD_TYPE MATCHES Debug)
    add_subdirectory("tests")
endif()

calculator目录CMakeLists.txt

project("calculator")

add_library(${PROJECT_NAME} SHARED "Calculator.h" "Calculator.cpp")

if (CMAKE_VERSION VERSION_GREATER 3.12)
    set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
endif()

测试目录CMakeLists.txt

set(UNIT-TESTS "unit-tests")
include(CTest)

include(FetchContent)
FetchContent_Declare(
    googletest
    GIT_REPOSITORY https://github.com/google/googletest.git
    GIT_TAG v1.14.0)

set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)

add_executable(${UNIT-TESTS} unit-test1.cpp)
target_link_libraries(${UNIT-TESTS} GTest::gtest_main calculator)

include(GoogleTest)
gtest_discover_tests(${UNIT-TESTS})

set(CMAKE_MODULE_PATH /usr/src/CMake)
include(CodeCoverage)
append_coverage_compiler_flags(${UNIT-TESTS})

set(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -O0")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")

set(GCOVR_PATH "/usr/bin/gcovr")
setup_target_for_coverage_gcovr_xml(
        NAME CoverageXml
        EXECUTABLE ${UNIT-TESTS}
        DEPENDENCIES ${UNIT-TESTS}
        EXECUTABLE_ARGS "--gtest_output=xml:report/"
        EXCLUDE "out/" "tests/")

编译命令

cmake -S ./ -B ./out/build/ -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=clang-16 -DCMAKE_CXX_COMPILER=clang++-16
cmake --build ./out/build/ --parallel 2 --target CoverageXml unit-tests

解决方案(保留共享库架构)

问题核心是共享库未添加覆盖率编译/链接参数,导致无法生成.gcno和.gcda文件。以下是具体修改:

1. 给共享库添加覆盖率编译选项

修改src/calculator/CMakeLists.txt,在Debug模式下为共享库添加覆盖率flags并关闭优化:

project("calculator")

add_library(${PROJECT_NAME} SHARED "Calculator.h" "Calculator.cpp")

if (CMAKE_VERSION VERSION_GREATER 3.12)
    set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
endif()

# 仅在Debug模式下添加覆盖率配置
if (CMAKE_BUILD_TYPE MATCHES Debug)
    # 导入CodeCoverage模块
    set(CMAKE_MODULE_PATH /usr/src/CMake)
    include(CodeCoverage)
    # 为共享库添加覆盖率编译/链接flags
    append_coverage_compiler_flags(${PROJECT_NAME})
    # 强制关闭优化,避免覆盖率统计失真
    target_compile_options(${PROJECT_NAME} PRIVATE -O0)
endif()

2. 优化测试目录的覆盖率配置

修改tests/CMakeLists.txt,确保覆盖率目标能正确扫描共享库的编译产物:

# ... 其他内容不变 ...

include(CodeCoverage)
# 为测试可执行文件添加覆盖率flags
append_coverage_compiler_flags(${UNIT-TESTS})
# 为测试程序关闭优化
target_compile_options(${UNIT-TESTS} PRIVATE -O0)

set(GCOVR_PATH "/usr/bin/gcovr")
setup_target_for_coverage_gcovr_xml(
        NAME CoverageXml
        EXECUTABLE ${UNIT-TESTS}
        DEPENDENCIES ${UNIT-TESTS} calculator  # 依赖共享库,确保先编译共享库
        EXECUTABLE_ARGS "--gtest_output=xml:report/"
        EXCLUDE "out/" "tests/"
        BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src"  # 指定源码根目录,帮助gcovr找到文件
)

3. 验证编译与运行

重新执行编译命令,此时:

  • 共享库calculator会生成对应的.gcno文件
  • 运行测试后会生成.gcda文件
  • CoverageXml目标会生成包含共享库代码的覆盖率XML报告

关键原理

  • 覆盖率统计需要编译时添加-fprofile-arcs -ftest-coverage(GCC)或对应Clang参数,这些由append_coverage_compiler_flags自动添加
  • 共享库和测试程序必须都启用这些参数,否则无法收集共享库的执行数据
  • 优化级别-O0是必须的,否则编译器会优化掉部分代码,导致覆盖率统计不准确

内容的提问来源于stack exchange,提问作者wes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 09:33:20