How to use gcovr with source files outside the current/build/run directory?

Viewed 10821
mkdir -p /tmp/build &&
cd /tmp/build &&
mkdir -p /tmp/src &&
echo "int main(){return 0;}" > /tmp/src/prog.c &&
gcc --coverage -o prog /tmp/src/prog.c &&
./prog &&
gcovr -v -r .

will output an empty report.

Scanning directory . for gcda/gcno files...
Found 2 files (and will process 1)
Processing file: /tmp/build/prog.gcda
Running gcov: 'gcov /tmp/build/prog.gcda --branch-counts --branch-probabilities --preserve-paths --object-directory /tmp/build' in '/tmp/build'
Finding source file corresponding to a gcov data file
  currdir      /tmp/build
  gcov_fname   #tmp#src#prog.c.gcov
               ['        -', '    0', 'Source', '/tmp/src/prog.c\n']
  source_fname /tmp/build/prog.gcda
  root         /tmp/build
  fname        /tmp/src/prog.c
Parsing coverage data for file /tmp/src/prog.c
  Filtering coverage data for file /tmp/src/prog.c
Gathered coveraged data for 0 files
------------------------------------------------------------------------------
                           GCC Code Coverage Report
Directory: .
------------------------------------------------------------------------------
File                                       Lines    Exec  Cover   Missing
------------------------------------------------------------------------------
------------------------------------------------------------------------------
TOTAL                                          0       0    --%
------------------------------------------------------------------------------

However if I manually run

gcov /tmp/build/prog.gcda --branch-counts --branch-probabilities --preserve-paths --object-directory /tmp/build

I get correct results

File '/tmp/src/prog.c'
Lines executed:100.00% of 1
No branches
No calls
Creating '#tmp#src#prog.c.gcov'

It seems that gcovr did not extract the coverage from the otherwise correct gcov output. This only happens if the source file is outside the current directory (same as build directory, same as output directory, same as run directory), and gcc ics called with an absolute path to the source file.

How can I fix this?

Edit

Fixed in upstream gcovr for relative paths, but looks like a bug for absolute paths.

See https://github.com/gcovr/gcovr/issues/169.

2 Answers

Gcovr only generates reports for source files within your project. This is intended to exclude coverage from library headers etc.

The question is, which files are in your project? This is determined by the -r root path.

If you are in /tmp/build and root is . aka /tmp/build and the source file is /tmp/src/prog.c, then that source file is clearly outside of your project. In the verbose output, gcovr will report Filtering coverage data for file /tmp/src/prog.c.

If you are in /tmp/build and root is .. aka /tmp and the source file is /tmp/src/prog.c, then that source file is within the project.

If you are in /tmp/build and root is . aka /tmp/build and the source file is ../src/prog.c, then gcovr seems to do something questionable: It joins the file name with the current directory and checks that. So we actually see /tmp/build/../src/prog.c. As far as gcovr is concerned, that's within your project. It seems this behaviour is necessary to include code that is symlinked into a project.

You can disable this “is the source within the project?” filter by providing your own, better filter. For example, you can ask gcovr to only report coverage for sources under /tmp/src:

gcovr -r . -f /tmp/src
Related