如何在CMake中使用gcov

8
我在跟随这篇指南(在另一篇帖子中推荐过)时遇到了困难,涉及IT技术。以下是需要翻译的内容:https://github.com/bilke/cmake-modules/blob/master/CodeCoverage.cmake 首先,请将此文件复制到您的cmake模块路径中。如何确定我的cmake模块路径?
使用SETUP_TARGET_FOR_COVERAGE函数创建自定义make目标。这具体是什么意思?我该如何做?具体而言,我需要在哪里输入什么内容?
我被迫使用cmake编译应用程序,否则我会使用gcc进行编译。

CMake模块路径为/usr/share/cmake/Modules或类似路径。您可以从cmake软件包安装文件列表中推断出它:在该目录中有许多.cmake模块。至于其他问题,请阅读您所引用的文件中的“USAGE”部分。简而言之,使用SETUP_TARGET_FOR_COVERAGE创建的目标运行一些工作负载并收集由该目录中的可执行文件产生的覆盖率。如果您只想使用gcov支持编译可执行文件,则仅需要执行第3步(设置编译器标志)。 - Tsyvarev
2个回答

7

您可以通过调用set(CMAKE_MODULE_PATH <path>)来设置cmake模块路径。

cmake模块路径设置告诉cmake在哪里查找像include宏包含的那些cmake模块。

例如,我使用CodeCoverage.cmake所需执行的步骤如下:

  1. Copy CodeCoverage.cmake into my source folder at 'scripts/cmake'.
  2. Add the following to my CMakeLists.txt:

    set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake)
    
    if (CMAKE_BUILD_TYPE STREQUAL "Coverage")
        include(CodeCoverage)
        setup_target_for_coverage(${PROJECT_NAME}_coverage ${TEST_TARGET} coverage)
    
        SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
        SET(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
    endif() #CMAKE_BUILD_TYPE STREQUAL "Coverage"
    
  3. Run cmake with -DCMAKE_BUILD_TYPE=Coverage

  4. Run make

  5. Run make <coverage_target>

请注意:

  • ${TEST_TARGET} 是我在脚本中创建的单元测试目标的名称所设置的变量。
  • <coverage_target> 是由 ${PROJECT_NAME}_coverage 生成的任何字符串。
  • 您不必像我一样使用 if 包装覆盖率创建。
  • 由于我使用的是 AppleClang,因此我不得不修复 CodeCoverage.cmake 脚本以允许它。现在编写的方式仅允许 gcc 和 clang 3.0.0 或更新版本。

2
我在CodeCoverage.cmake中找不到setup_target_for_coverage函数。对我有用的是:setup_target_for_coverage_gcovr_xml(${PROJECT_NAME}_coverage NAME coverage)(然后执行make && make coverage)。 - PJ127
1
1月10日:您链接的Github存储库已更改函数名称setup_target_for_code_coverage为append_coverage_compiler_flags_to_target。 - Mattis Asp

2

使用零行CMake的gcov

除了使用CMake模块进行gcov集成外,还可以完全不修改构建系统来实现。您只需要大约5行shell命令。这是一个适用于规模不太大或复杂的项目的好方法。

按照规范,必须向gcov提供源文件名称列表(不包括头文件)。这基于各种命名和目录约定:gcov假定源文件的名称为foo.cfoo.cpp,相应的对象文件称为foo.o,并且在与源文件相同的目录中。但是CMake默认将它们命名为foo.cpp.o。 gcov会剥离给定源文件名的扩展名,然后添加.gcno.gcda后缀。我们可以利用这些事实,向gcov提供.gcda文件而不是源文件。事实证明,在这种情况下,gcov将在正确的位置查找所有内容。

如何操作

  1. Turn on coverage data in the compiler and linker flags by adding the --coverage flag to CMAKE_C_FLAGS and/or CMAKE_CXX_FLAGS. This makes the compiler generate .gcno files at build time, and it makes executables dump .gcda files on exit.

  2. Make a script for the [run test / generate report / clean coverage data] loop. Here's a barebones Bash example:

    # Ensure we are in the build directory and that coverage was enabled in the compiler
    grep -q -- --coverage CMakeCache.txt || exit 1
    
    # Clean up old runtime data
    find . -name '*.gcda' -exec rm {} \;
    
    # Run test command (specified as script arguments)
    # This can be anything that runs program(s) built by the project 
    "${@}"
    
    # Generate reports (.gcov files). All .gcda files in the build directory are passed as gcov args.
    find . -name '*.gcda' | xargs gcov
    

这种方法的优点

  • 同一个脚本可以被重复使用,无需在每个感兴趣的项目上执行CMake集成
  • 没有复杂的CMake代码
  • 灵活性高,可以轻松更改测试命令。与CMake集成的清除/运行/报告循环通常有一个硬编码命令来运行所有测试,这通常比运行单个测试(速度更慢)不太实用。

缺点

  • 完整路径信息丢失。每个.gcov文件的名称仅包括基本名称(foo.gcov),而通常它会像src#foo#foo.gcov那样编码完整路径。这可能导致报告文件中的名称冲突。
  • 依赖信息未集成到构建系统中意味着您可能会在忘记重新构建时意外使用旧的.gcno文件(如果--coverage被打开然后关闭)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接