RWTH-HPC / CMake-codecov

CMake module for code coverage
BSD 3-Clause "New" or "Revised" License
89 stars 34 forks source link

gcov generation fails with Ninja generator #6

Closed gsauthof closed 4 years ago

gsauthof commented 8 years ago

Steps to reproduce:

CMakeLists.txt:

cmake_minimum_required(VERSION 3.4)
project(test CXX)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/codecov/cmake" ${CMAKE_MODULE_PATH})
find_package(codecov)
add_executable(foo test.cc)
add_coverage(foo)

test.cc:

#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
    cout << "Hello World!\n";
    return 0;
}

Setup:

$ git submodule add https://github.com/RWTH-ELP/CMake-codecov.git cmake/codecov
$ mkdir build
$ cd build
$ CXX=clang++ CC=clang cmake -G Ninja .. -DENABLE_COVERAGE=On
$ ninja-build -v foo
$ ./foo
$ ninja-build -v foo-gcov

Actual result:

$ ninja-build -v foo-gcov
[1/1] cd /home/juser/cmake-codecov-test/build/CMakeFiles/foo.dir && LLVM_COV_BIN=/usr/bin/llvm-cov /home/juser/cmake-codecov-test/cmake/codecov/cmake/llvm-cov-wrapper /home/juser/cmake-codecov-test/build/CMakeFiles/foo.dir/test.cc.gcno > /dev/null
../test.cc: No such file or directory
$ ninja-build -v foo-gcov
ninja: no work to do.

Expected result:

A .gcov file under in the build directory, i.e. CMakeFiles/foo.dir/test.cc.gcov.

I tested it on Fedora 23.

When compiling with the CMake makefile generator the gcov report is generated as expected.

mjerabek commented 4 years ago

I looked into this a bit. The difference is that when using the makefile generator, absolute path is used to pass test.cc to the compiler, whereas the ninja generator uses paths relative to the build directory. And the exact path is embedded in the .gcno file.

It turns out that geninfo has a switch for this:

--base-directory directory
    Use directory as base directory for relative paths.

But setting base-directory to PROJECT_BINARY_DIR instead of to PROJECT_SOURCE_DIR has its own consequences, namely it conflicts with --no-external:

--no-external
    Specify whether to capture coverage data for external source files.
    External source files are files which are not located in one of the directories specified by --directory or --base-directory.

The --directory switch looks hopeful, but there is no such thing in geninfo. It might be possible to use --no-external in later phase on lcov, or not use it at all and filter the files via --exclude switch for lcov. I'll investigate that later.

mjerabek commented 4 years ago

So the final solution for me was to replace --base-directory ${PROJECT_SOURCE_DIR} with --base-directory ${PROJECT_BINARY_DIR} in FindLcov.cmake and disable adding the --no-external flag. The external sources may then be manually filtered by setting LCOV_REMOVE_PATTERNS.

alehaa commented 4 years ago

22 should add some compatibility with Ninja.

giacomini commented 4 years ago

I still see the problem with Ninja, which is the default generator for Visual Studio Code. With Makefiles all is fine. I'm no expert, but I think the cause is that Make works with absolute paths whereas Ninja works with paths relative to the binary directory.

I've commented on a closed issue, but I may open a new one if you wish.

alehaa commented 4 years ago

I thought #22 should have changed the path to a relative one?

giacomini commented 4 years ago

Ah, wait, I'm talking about lcov. I assumed they would behave the same. Maybe they don't?

giacomini commented 4 years ago

They don't. The foo-gcov target as per the example in the description works. However the lcov-related targets fail. I'll submit another issue.