CMake-codecov icon indicating copy to clipboard operation
CMake-codecov copied to clipboard

lcov targets fail with Ninja

Open giacomini opened this issue 4 years ago • 3 comments

The same example provided in issue #6 shows that also the support for lcov is failing when using the Ninja generator.

$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DENABLE_COVERAGE=ON ..
$ ninja -v foo
[1/2] /usr/bin/c++    -g    -O0 -g -fprofile-arcs -ftest-coverage -MD -MT CMakeFiles/foo.dir/test.cc.o -MF CMakeFiles/foo.dir/test.cc.o.d -o CMakeFiles/foo.dir/test.cc.o -c ../test.cc
[2/2] : && /usr/bin/c++  -g  -O0 -g -fprofile-arcs -ftest-coverage CMakeFiles/foo.dir/test.cc.o  -o foo   && :
$ ./foo
Hello World!
$ ninja -v foo-genhtml
[1/8] cd /home/giaco/tmp/lcov-cmake/build && /usr/bin/geninfo --quiet --base-directory /home/giaco/tmp/lcov-cmake --initial --gcov-tool /usr/bin/gcov-7 --output-filename /home/giaco/tmp/lcov-cmake/build/CMakeFiles/foo.dir/test.cc.info.init --no-external /home/giaco/tmp/lcov-cmake/build/CMakeFiles/foo.dir/test.cc.gcno
geninfo: WARNING: could not open /home/giaco/tmp/test.cc
geninfo: WARNING: some exclusion markers may be ignored
[2/8] cd /home/giaco/tmp/lcov-cmake/build && cat /home/giaco/tmp/lcov-cmake/build/CMakeFiles/foo.dir/test.cc.info.init > /home/giaco/tmp/lcov-cmake/build/lcov/data/init/foo.info.raw
[3/8] cd /home/giaco/tmp/lcov-cmake/build && /usr/bin/lcov --quiet -a /home/giaco/tmp/lcov-cmake/build/lcov/data/init/foo.info.raw --output-file /home/giaco/tmp/lcov-cmake/build/lcov/data/init/foo.info --base-directory /home/giaco/tmp/lcov-cmake --initial && /usr/bin/lcov --quiet -r /home/giaco/tmp/lcov-cmake/build/lcov/data/init/foo.info --output-file /home/giaco/tmp/lcov-cmake/build/lcov/data/init/foo.info --initial
FAILED: lcov/data/init/foo.info 
cd /home/giaco/tmp/lcov-cmake/build && /usr/bin/lcov --quiet -a /home/giaco/tmp/lcov-cmake/build/lcov/data/init/foo.info.raw --output-file /home/giaco/tmp/lcov-cmake/build/lcov/data/init/foo.info --base-directory /home/giaco/tmp/lcov-cmake --initial && /usr/bin/lcov --quiet -r /home/giaco/tmp/lcov-cmake/build/lcov/data/init/foo.info --output-file /home/giaco/tmp/lcov-cmake/build/lcov/data/init/foo.info --initial
lcov: ERROR: no valid records found in tracefile /home/giaco/tmp/lcov-cmake/build/lcov/data/init/foo.info.raw
ninja: build stopped: subcommand failed.

At least the first error (geninfo: WARNING: could not open /home/giaco/tmp/test.cc) can be fixed passing ${CMAKE_BINARY_DIR} instead of ${CMAKE_SOURCE_DIR} to the --base-directory option of geninfo. This because Ninja works with paths relative to the binary directory.

Everything works fine with the Makefile generator, which works with absolute paths.

giacomini avatar Jun 17 '20 15:06 giacomini

Could you provide a patch for this issue? I can reproduce the issue, but unfortunately I'm not familiar with ninja.

alehaa avatar Jun 23 '20 17:06 alehaa

Me neither :-) but I'll try. Give me a few days.

giacomini avatar Jun 23 '20 20:06 giacomini

There a number of potential issues with using the CMake-codecov library with Ninja in its current form which you might be encountering. The first is that when you perform in source builds with Ninja via CMake even if you pass paths in absolute form Ninja will convert them to relative form (this is a problem because the library in its current form generated GCov information with relative paths), see details here: https://gitlab.kitware.com/cmake/cmake/-/issues/13894

Craig Scott proposed the correct solution here: https://gitlab.kitware.com/cmake/cmake/-/issues/20001. That is the Gcc supports a flag, -fprofile-abs-path, which ensures that coverage information stores absolute paths in the resulting *.gcno & *.gcda file. See the details of this flag here: https://gcc.gnu.org/onlinedocs/gcc-10.1.0/gcc/Instrumentation-Options.html. This can be tested for and appended to the current coverage flags by testing for support first as is already done within the library:

            set(__coverageFlags --coverage)
            check_cxx_compiler_flag(-fprofile-abs-path HAVE_fprofile_abs_path)
            if(HAVE_fprofile_abs_path)
                list(APPEND __coverageFlags -fprofile-abs-path)
            endif()

The next potential issue and the one it looks like you are encountering here is that geninfo will only generate info for files from the *.gcda files that it finds in the path of the --base-directory passed in when invoking geninfo. The geninfo documentation explicitly mentions this scenario in its documentation and say if this happens to just call geninfo multiple times (with the --ignore-errors flag to silence errors) with different base directories and then to combine using the -a (I assume though it does not say that this part means when calling the lcov executable to append info). One common scenario this happens (and the one I ran into) is where the project created generated files which are written to the binary directory, in which case geninfo must be called again with the binary directory in the --base-directory flag to extract coverage information for generated source files.

If any of this is not clear or you have questions then let me know. It would be great to see these issues resolved in the library.

Twon avatar Apr 12 '21 16:04 Twon