Reputation: 1350
I'm having difficulties following this guide (that I've seen recommended on another post) on the matter https://github.com/bilke/cmake-modules/blob/master/CodeCoverage.cmake
First:
Copy this file into your cmake modules path.
How do I know what my cmake module path is?
Use the function SETUP_TARGET_FOR_COVERAGE to create a custom make target
What does it mean exactly? How do I do that? Especifically, what do I have to type and where?
I am forced to compile the application with cmake, otherwise I would do it with gcc.
Upvotes: 9
Views: 21225
Reputation: 271
As an alternative to using a CMake module for gcov integration, it is possible to use do it without modifying the build system at all. You only need about 5 lines of shell. This is a nice approach for projects that are not too large or complicated.
By the book, one must feed a list of source file names (excluding headers) to gcov. This is based on various naming and directory conventions: gcov assumes that the source files have a name like foo.c
or foo.cpp
and that the corresponding object file is called foo.o
and is in the same directory as the source file. But CMake, by default, names them like foo.cpp.o
. gcov strips the extension of the given source file name, and then adds the .gcno
and .gcda
suffixes. We can exploit these facts by feeding gcov, instead of source files, the .gcda files. As it turns out, gcov will look for everything in the right places in that case.
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.
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
foo.gcov
), whereas normally it would encode the full path like src#foo#foo.gcov
. This could result in name collisions in report files.--coverage
was turned on and later turned off).Upvotes: 4
Reputation: 570
You set the cmake module path by calling
set(CMAKE_MODULE_PATH <path>)
The cmake module path setting tells cmake where to look for cmake modules like those that are included by the include
macro.
For example, the steps I took to use CodeCoverage.cmake are:
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"
Run cmake
with -DCMAKE_BUILD_TYPE=Coverage
Run make
Run make <coverage_target>
Note that:
${TEST_TARGET}
is a variable I set with the name of my unit testing target that I create earlier in the script.<coverage_target>
is whatever string that is generated by ${PROJECT_NAME}_coverage
. if
like I did.Upvotes: 7