代码覆盖率会改变垃圾邮件输出

时间:2017-01-30 13:05:13

标签: c++ cmake code-coverage gcov


在CMake测试配置中,我添加了标志来生成codecoverage

IF( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR
    "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
  SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
  SET(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage ")
endif()

每次我运行测试时 - 我的输出都是垃圾邮件:

  

profiling:/xxxx/xxxxxj/projects/build-xxxxx-CLang-Debug/tests/CMakeFiles/xxxxxxxxxxxxxt_ut.dir/tests/gui/ship_design/ut_ship_stats_header.cpp.gcda:无法合并以前的GCDA文件:计数器数量不匹配(14)

     

谱:   /xxxx/xxxxxx/projects/build-xxxxxxxxxxxxxxx-CLang-Debug/tests/CMakeFiles/xxxxxxxxxxxxxxx_ut.dir/tests/gui/ship_design/ut_ship_stats_header.cpp.gcda:   无法合并以前的GCDA文件:corrupt arc tag(0x2b8e100f)

     

谱:   /xxxx/xxxxxx/projects/build-xxxxxxxxxxxxxxx-CLang-Debug/tests/CMakeFiles/xxxxxxxxxxxxxxx_ut.dir/tests/ut_generate_hex_path.cpp.gcda:   无法合并以前的GCDA文件:corrupt arc tag(0x65646f6e)

我不必说这使得阅读测试运行结果至少很困难。当我删除之前生成的所有gcda文件时,上面的问题就消失了。所以有两种可能的解决方案。

  • 我可能会错过一些有价值的代码覆盖率数据配置(即调用lcov --zerocounters
  

FIND_PROGRAM(LCOV_PATH lcov)

     

COMMAND $ {LCOV_PATH} -z - 目录$ {PROJECT_BINARY_DIR}}

  • 我需要在提交测试运行之前添加自定义目标,删除所有gcda文件。

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

我认为您可能会在工作流程中做一些与众不同的事情,因为您所看到的问题不应该一直发生。但是,我在这里添加的内容可以帮助您解决这个问题,或者完全解决它。

首先,您应该利用CMake的build-types并创建自己的"覆盖类型"。

## coverage flags
set(CMAKE_CXX_FLAGS_COVERAGE "-g -O0 -fprofile-arcs -ftest-coverage" CACHE STRING "Flags used by the C++ compiler during coverage builds.")
set(CMAKE_C_FLAGS_COVERAGE "-g -O0 -fprofile-arcs -ftest-coverage" CACHE STRING "Flags used by the C compiler during coverage builds.")
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "-g -O0 -fprofile-arcs -ftest-coverage" CACHE STRING "Flags used for linking binaries during coverage builds.")
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "-g -O0 -fprofile-arcs -ftest-coverage" CACHE STRING "Flags used by the shared libraries linker during coverage builds.")

mark_as_advanced(
  CMAKE_CXX_FLAGS_COVERAGE
  CMAKE_C_FLAGS_COVERAGE
  CMAKE_EXE_LINKER_FLAGS_COVERAGE
  CMAKE_SHARED_LINKER_FLAGS_COVERAGE)

## Update the documentation string of CMAKE_BUILD_TYPE for GUIs
set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel RelWithAssert Coverage." FORCE)

然后创建一个custom target

## create our "make coverage" target
add_custom_target(coverage
  COMMAND if test ! -d ../output \; then mkdir ../output\; fi
  COMMAND find ${CMAKE_BINARY_DIR} -name \*.gcda -delete
  COMMAND lcov -b CMakeFiles/ -d . -z
  COMMAND lcov -b -d . -c -i -o test_base.info
  COMMAND ./env-shell.sh ctest -j2 || true
  COMMAND lcov -b CMakeFiles/ -d . -c -o test_run.info
  COMMAND lcov -b CMakeFiles/ -d . -a test_base.info -a test_run.info -o test_total.info
  COMMAND lcov -o reports.info -r test_total.info '/usr/include/*' '/usr/local/*' '/cvmfs/*' '*/numpy' '/usr/lib/gcc/*' ${p} '${CMAKE_BINARY_DIR}/CMakeFiles/' '${CMAKE_BINARY_DIR}/steamshovel/*'
  COMMAND genhtml --ignore-errors source --legend -o ../output/`date +%Y-%m-%d` reports.info
)

现在,利用源外构建,在"覆盖范围内运行cmake"与您的源平行的目录。

$ pwd
/home/user/my_project/src
$ mkdir ../coverage
$ cd ../coverage
$ cmake -DCMAKE_BUILD_TYPE=Coverage ../src
[ ... cmake's output here ...]
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/my_project/coverage

$ 

现在,构建您的项目和测试,并运行您的"覆盖范围"目标

$ make
$ make test-bins
$ make coverage
[ ... make's output here ... ]
$ 

我们在CMakeLists.txt中定义的make coverage目标将:

  1. 如果它不存在,请创建"输出"与我们的源和构建目录并行的目录
  2. 查找并删除当前构建目录中的所有*.gcda个文件
  3. 归零并初始化我们的lcov计数器和输出文件
  4. 通过ctest
  5. 运行我们的测试
  6. "编译" lcov输出并生成我们的HTML覆盖率报告
  7. 请注意,您可能需要针对特定​​项目进行调整。

    此时我强烈建议自动完成所有这些操作。将它添加到您的持续集成中,如果您有一些,或甚至设置cron作业,以便在一夜之间运行,并且您有一个全新的覆盖率报告来开始您的一天。 (这些示例来自一个工作项目,该项目执行由buildbot处理的夜间报道报告。)