Detailed guide on using gcov with CMake/CDash?

C++TestingCmakeCode CoverageCdash

C++ Problem Overview


I'm using CMake with my project and set up a cdash server for continuous/nightly building. Everything works well and by setting up a crontab, we have hourly/nightly build/test results uploaded to our cdash server automatically.

My next step is to add test coverage report to the build. I find the document here http://www.cmake.org/Wiki/CTest:Coverage but frankly it's a bit far from a practical guide.

Currently I've added the required flag (instead of -fprofile-arcs -ftest-coverage, I find --coverage better), the compilation process generates .gcno files. But then I'm stuck. The command

make NightlyCoverage

doesn't seem to do anything. Could anybody tell me what is the next to do? The result that I want, is by doing make NightlyCoverage, coverage reports are generated and uploaded to cdash server.

C++ Solutions


Solution 1 - C++

I've been using https://github.com/bilke/cmake-modules/blob/master/CodeCoverage.cmake successfully.

Just followed the guidelines: added the files to my CMAKE_MODULE_PATH directory, added

set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules)
if(CMAKE_COMPILER_IS_GNUCXX)
    include(CodeCoverage)
    setup_target_for_coverage(${PROJECT_NAME}_coverage ${PROJECT_TEST_NAME} coverage)
endif()

in my CMakeLists.txt. I also added manually gcov as a dependency for my target:

if(CMAKE_COMPILER_IS_GNUCXX)
    target_link_libraries(${PROJECT_TEST_NAME} gcov)
endif()

With this, I just type

make my_project_coverage

and I get the html report in the coverage directory of my build tree.

Solution 2 - C++

I use gcovr to make a GCC Code Coverage Report without the CodeCoverage.cmake :

$ cd /path/to/your/project
$ mkdir build && cd build && cmake ..
$ make && make test
$ gcovr -r ../ .

Solution 3 - C++

I set up my project 'foo' in the following way. Copied the cmake file from the https://github.com/bilke/cmake-modules/blob/master/CodeCoverage.cmake to a subdirectory 'cmake_modules'. In the CMakeLists.txt file after the add_executable(foo ...) I added the following:

if(CMAKE_COMPILER_IS_GNUCXX)
LIST(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_modules")
include(CodeCoverage)
APPEND_COVERAGE_COMPILER_FLAGS()
set(COVERAGE_LCOV_EXCLUDES 'dir1/*' 'dir2/*') // this is optional if you want to exclude some directory from the report
SETUP_TARGET_FOR_COVERAGE_LCOV(NAME foo_coverage
                              EXECUTABLE foo
                              DEPENDENCIES foo)
endif()

After cmake, build the target make make foo_coverage And open the report with index.html file in the foo_coverage folder in the build folder

Solution 4 - C++

This answer is the same as @rcomblen's answer but its a bit outdated so I'll share my solution. Here's what I did:

  1. created a toy project
(base) ciaran@DESKTOP-K0APGUV:/mnt/d/CoverageTest$ tree -L 2
.
├── CMakeLists.txt
├── cmake
│   └── CodeCoverage.cmake
├── src
│   ├── domath.cpp
│   ├── domath.h
│   └── testdomath.cpp
└── third_party
    └── googletest

Where

// src/domath.h

#ifndef COVERAGETEST_DOMATH_H
#define COVERAGETEST_DOMATH_H


class domath {

public:
    int add(int a, int b);
};


#endif //COVERAGETEST_DOMATH_H

and

// src/domath.cpp

#include "domath.h"

int domath::add(int a, int b) {
    return a + b;
}

and

// src/testdomath.cpp
#include "gtest/gtest.h"
#include "domath.h"


TEST(DoMathTests, testAdd){
    domath m;
    int actual = m.add(4, 6);
    ASSERT_EQ(10, actual);
}
  1. download googletest and put it under third party directory
  2. copy the gist so kindly shared by the other answers on this thread into cmake/CodeCoverage.cmake
  3. install gcovr. This step is vital, because the other answers on this thread no longer work with the version of gcovr that I already had:
(base) ciaran@DESKTOP-K0APGUV:/mnt/d/CoverageTest$ pip install gcovr
(base) ciaran@DESKTOP-K0APGUV:/mnt/d/CoverageTest$ gcovr --version
gcovr 4.2
(base) ciaran@DESKTOP-K0APGUV:/mnt/d/CoverageTest$ which gcovr
/home/ciaran/miniconda3/bin/gcovr

Note, we need the output of which gcovr for the cmake script. 4) Write a cmake script that create a library, a test executable and use the CodeCoverage.cmake module:

cmake_minimum_required(VERSION 3.15)
project(CoverageTest)

set(CMAKE_CXX_STANDARD 14)

# setup googletest
add_subdirectory(third_party/googletest)

# create our library
add_library(DoMath STATIC src/domath.h src/domath.cpp)
add_dependencies(DoMath gtest gtest_main)

# create the test executable
add_executable(TestDoMath src/testdomath.cpp)
target_include_directories(TestDoMath PRIVATE third_party/googletest/googletest)
target_link_libraries(TestDoMath PRIVATE
        DoMath gtest gtest_main)
add_dependencies(TestDoMath DoMath gtest gtest_main)

# now for coverage bits
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
if (CMAKE_COMPILER_IS_GNUCXX)
    include(CodeCoverage)
    append_coverage_compiler_flags()

    # we need to turn off optimization for non-skewed coverage reports
    set(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -O0")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")

    # optional excludes - None needed here
    #    set(COVERAGE_EXCLUDES)

    # importantly, set the path to the gcovr executable that you downladed
    set(GCOVR_PATH "/home/ciaran/miniconda3/bin/gcovr")
    # Works
    setup_target_for_coverage_gcovr_xml(
            NAME TestDoMathCoverageXml
            EXECUTABLE TestDoMath
            DEPENDENCIES TestDoMath DoMath
    )
    # Works
    setup_target_for_coverage_gcovr_html(
            NAME TestDoMathCoverageHtml
            EXECUTABLE TestDoMath
            DEPENDENCIES TestDoMath DoMath
    )
    # This one did not work for me:
    setup_target_for_coverage_lcov(
            NAME TestDoMathCoverageLcov
            EXECUTABLE TestDoMath
            DEPENDENCIES TestDoMath DoMath
    )
endif ()

And thats it. Now just build the new targets.

Good luck.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRalph ZhangView Question on Stackoverflow
Solution 1 - C++rcomblenView Answer on Stackoverflow
Solution 2 - C++yeeView Answer on Stackoverflow
Solution 3 - C++psalongView Answer on Stackoverflow
Solution 4 - C++CiaranWelshView Answer on Stackoverflow