Skip to content

Instantly share code, notes, and snippets.

@madebr
Last active August 19, 2023 20:10
Show Gist options
  • Save madebr/07ebd0de59e789cd819643b58db25df9 to your computer and use it in GitHub Desktop.
Save madebr/07ebd0de59e789cd819643b58db25df9 to your computer and use it in GitHub Desktop.
Simple CTest coverage project + script
cmake_minimum_required(VERSION 3.9)
project(cmake_coverage)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.c" "int main() {return 0;}")
add_executable(main
main.c
)
target_compile_options(main
PUBLIC
"-O0"
"-fprofile-arcs"
"-ftest-coverage"
)
target_link_libraries(main
gcov
)
include(CTest)
enable_testing()
add_test(NAME test
COMMAND main
)
set(CTEST_PROJECT_NAME "Simple ctest_coverage project")
# This command succeeds
$ ls && mkdir build && cd build && cmake .. && make && make test && make ExperimentalCoverage && cd ..
CMakeLists.txt CTestConfig.cmake test.ctest
-- The C compiler identification is GNU 7.2.1
-- The CXX compiler identification is GNU 7.2.1
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/maarten/programming/minumum_examples/cmake_coverage/build
Scanning dependencies of target main
[ 50%] Building C object CMakeFiles/main.dir/main.c.o
[100%] Linking C executable main
[100%] Built target main
Running tests...
Test project /home/maarten/programming/minumum_examples/cmake_coverage/build
Start 1: test
1/1 Test #1: test ............................. Passed 0.00 sec
100% tests passed, 0 tests failed out of 1
Total Test time (real) = 0.00 sec
Scanning dependencies of target ExperimentalCoverage
Site: maarten-acer
Build name: Linux-c++
Create new tag: 20171028-0543 - Experimental
Performing coverage
Processing coverage (each . represents one file):
.
Accumulating results (each . represents one file):
.
Covered LOC: 1
Not covered LOC: 0
Total LOC: 1
Percentage Coverage: 100.00%
Built target ExperimentalCoverage
# This command fails
$ ctest -S test.ctest
Each . represents 1024 bytes of output
. Size of output: 0K
Each symbol represents 1024 bytes of output.
'!' represents an error and '*' a warning.
. Size of output: 0K
Cannot find file: /home/maarten/programming/minumum_examples/cmake_coverage/build/ctest/Testing/CoverageInfo/main.c
# Why is that?
set(CTEST_SOURCE_DIRECTORY "${CTEST_SCRIPT_DIRECTORY}")
set(CTEST_BINARY_DIRECTORY "${CTEST_SCRIPT_DIRECTORY}/build/ctest")
ctest_empty_binary_directory("${CTEST_BINARY_DIRECTORY}")
set(CTEST_SITE "${CMAKE_SYSTEM_NAME}")
set(CTEST_BUILD_NAME "experimental build")
set(CTEST_CMAKE_GENERATOR "Ninja")
set(CTEST_COVERAGE_COMMAND "gcov")
ctest_start("Experimental")
ctest_configure()
ctest_build()
ctest_test()
ctest_coverage()
@ldouville
Copy link

Hi,
Have you found a solution to this problem ?
I have something really similar.
My temporary solution was creating a symbolic link in the CoverageInfo folder to the sources.
It works well but that's not the right way to do it. How did you ?

@Kamilcuk
Copy link

Kamilcuk commented Apr 9, 2020

The problem is ninja: set(CTEST_CMAKE_GENERATOR "Ninja")
In my case removing -Gninja from cmake configure removed the issue.

@madebr
Copy link
Author

madebr commented Apr 9, 2020

Indeed, gcov creates intermediate files in common folders that fail when building in parallel.
ninja -j1 would also work fine.

@bfueldner
Copy link

I stumbled over the same problem. Solution is a real out-of-tree build, no build in a source subdirectory:
set(CTEST_SOURCE_DIRECTORY "/home/user/testproject")
set(CTEST_BINARY_DIRECTORY "/home/user/testproject_build")

The step ctest_coverage() is executed sequentially after ctest_build() (and other steps) are finished. So it doesn't matter, if the build step with Ninja uses multiple jobs parallel or only one.

@xakod
Copy link

xakod commented Oct 12, 2021

Hello, I try to follow your example. But i use cmake+ninja instead of make so I use cmake commands instead of plain make commands:

ls
mkdir build
cd build
cmake -GNinja .. 
cmake --build . --target all

cmake test

[0/1] Running tests...
Test project /home/ubuntu/sources/gcov_coverage/build
    Start 1: test
1/1 Test #1: test .............................   Passed    0.00 sec

100% tests passed, 0 tests failed out of 1

Total Test time (real) =   0.00 sec

cmake --build . --target ExperimentalCoverage

[0/1] cd /home/ubuntu/sources/gcov_coverage/build && /usr/bin/ctest -D ExperimentalCoverage
   Site: ubuntu
   Build name: Linux-c++
Performing coverage
   Processing coverage (each . represents one file):
    .
   Accumulating results (each . represents one file):
    .Cannot find file: /home/ubuntu/sources/gcov_coverage/build/Testing/CoverageInfo/main.c

        Covered LOC:         0
        Not covered LOC:     0
        Total LOC:           0
        Percentage Coverage: 0.00%

Your example works with plain make commands but it's not useful if u dont use make. So i tried to use cmake cmds. What I do wrong? Can you help?

@madebr
Copy link
Author

madebr commented Nov 18, 2021

Is this still a problem?

@xakod
Copy link

xakod commented Nov 19, 2021

Yep, i couldn't find solution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment