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

15.3k Views Asked by At
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

There are 2 best solutions below

10
On

What I understood from your code up there is that you made everything and ran the program but you are still inside build directory where the object file resides.

So, what you need to understand is:

gcovr -v -r <path>

this -r flag takes the root directory, which means the parent directory inside which the source and object directory resides. So that it can trace them both and generate coverage data and whatever else you want it to generate.
Try doing that and it will work.

For your understanding:

The .gcno files that gets generated after compilation is just the flowchart kind of data for that particular source file.
Then later when you execute the program, a .gcda file gets generated for each source file. This file contains real coverage data, but for gcovr all these three files are necessary (.gcno, .gcda, sourceFile)

Hope it helped. :)

update:
Back with the work around
You can supply your coverage data location as a pure arg (no option) and point the root to your sources.

gcovr .../path/To/GCDA -r .../path/to/src/ [rest desired flags]

This will solve your problem for sure.
Worked for me in covering my projects.

0
On

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