Detailed guide on using gcov with CMake/CDash?
Asked Answered
H

4

62

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 https://gitlab.kitware.com/cmake/community/-/wikis/doc/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.

Hydrometer answered 29/10, 2012 at 5:48 Comment(1)
The link seems broken.Disjunct
S
60

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.

Selffulfillment answered 14/5, 2013 at 6:22 Comment(14)
Linking to gcov isn't really necessary. Gcc does that automatically anyway, and it will not work with Clang for instance which instead should link againt libprofile_rtRearmost
I'll add a note that I'm using clang on OSX and besides a warning in CodeCoverage.cmake, this solution worked perfectly.Gymnasiarch
@Selffulfillment Will that aggregate the coverage results for all of your tests? Or do you need to setup_target_for_coverage for every test target?Bandylegged
Can one exclude directories using this approach? I don't see any options in the tool itself.Affusion
You can add exclusion rules in the CodeCoverage.cmakefile (or pass it via a variable), set line 145, the --remove option of lcov.Selffulfillment
How does one set a custom gcov version using this plugin?Affusion
@Affusion My first guess would be to set the GCOV_PATH variable. See line 71 of github.com/bilke/cmake-modules/blob/master/CodeCoverage.cmakeSelffulfillment
How come make my_project_coverage works? CodeCoverage.cmake adds a custom target, but in my experience those are only put in subdir makefiles which is very inconvenient... Is there a trick you can share?Pohai
Clang support was added to CodeCoverage.cmake on 2013-09-17!Alaster
The line regarding setup_target_for_coverage is incorrect; it should be setup_target_for_coverage(NAME ${PROJECT_NAME} ....; (I've edited the answer, but it was rejected).Tenebrific
Anybody has a recent example github project that I can take a look at? As @PhilippLudwig said, I am not sure if the above answer is correct anymore.Guiana
Can this be adapted for clang?Unparalleled
Also - this doesn't work for me. The modules says " Compiler is not GNU gcc! Aborting..." - even though I'm using GCC.Unparalleled
@Unparalleled The current code specifically checks that CMAKE_COMPILER_IS_GNUCXX — IOW, it wants to see g++ enabled. If you have a C-only project, you might consider adjusting that, or you can add CXX to your project LANGUAGES.Allodium
T
12

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 ../ .
Thinkable answered 15/9, 2017 at 6:23 Comment(2)
I know that this is in the documentation however I found it pretty handy gcovr -r . --html --html-details -o example-html-details.htmlDurante
I kept getting failure by -r . until I found your command is -r .. . !Umont
A
11

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.

Atabrine answered 4/7, 2020 at 14:39 Comment(0)
I
8

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

Inaccurate answered 2/1, 2019 at 9:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.