Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
Prepare for major information dump! If this question has already been asked, please let me know. I tried looking for anything related to this, with no luck, but definitely point me in the right direction if I missed it!
For my project, my build directory is separate from my source directory, and I also need the .gcda files in a separate directory. The reason for this is my source and build directories are located on a shared filesystem, and I have workers that will each test the executable and then run gcovr. If the .gcda, .gcov, and output files aren't in different locations for each worker, then I'll have a race condition because the workers run in parallel.
Here is an example file structure. I'm working with a larger project, so there are actually more subdirectories, but I think this gets the point across:
Now, where the problem exists, I'm running the following gcovr command:
I expected this to check
The output for that gcov command is:
And when I run this command, the output is as I expect, with the proper coverage percentages as well.
Is this expected behavior?
That's a detailed question! That behaviour of gcovr is kind of expected. I'm not sure whether it can be fixed without breaking lots of existing workflows.
What is gcovr doing?
(I'm writing this up partially for my own benefit, as the behaviour is mildly WTF.)
Gcovr looks in any search paths that you specify as positional arguments. If none are given, gcovr falls back to the root path and any --object-dir. If you specify both search paths and --object-dir, the --object-dir path will be ignored. (It could make sense to change this part, I'm not sure).
Gcovr then searches for all .gcda and .gcno files under the selected search paths (but discards .gcno if there's a corresponding .gcda).
Next, gcovr tries to guess from which directory gcov should be invoked to process that coverage data. There are a couple of organically grown heuristics, and they are all bad. I don't really understand them.
It has been suggested that these heuristics could be removed entirely, but I don't understand gcov sufficiently well.
Finally gcovr tries to run gcov in all the directories suggested by the heuristics and sees what sticks. This is …slow. Gcov is given the base directory of the .gcda file as the --object-directory arguments, since the .gcno file should be right next to it.
The takeaway is that there are few or no reasons to continue using the --object-directory option. Historically, the --object-directory option is older (and the search paths weren't documented for a long time).
At no point are the actual .o object files of interest, only the .gcno files that are generated during compilation.
In your case the .gcda and .gcno files are not next to each other. The simplest way to fix this is to copy the .gcno files into your coverage target directory structure.
The less simple way is to give me (a series of) pull requests that:
If you (or anyone else) would like to tackle this, please see the contribution guide for general advice and how to set up a development environment. For this kind of option it would also be really important to include a test case; a simplified version of this scenario with only one source file would do. That test case would be great anyway because it has related problems as cross-profiling, compare #259 (comment).
Thanks for such a detailed response!
I'd be interested in pursuing the
For now, I'll copy the gcno files to the location of the gcda files. Here's a semi-related question- does gcovr care about the relative paths between the source dir and the build dir? I.e. is anything dependent on their locations relative to one another?
I'll be glad for a pull request if and when you get around to it! Could also be a small project for a student assistant?
Unfortunately, yes, the relative path between the .gcda/.gcno files and the source files can matter.
I did some further digging during the weekend:
Your options seem to be:
I am now closing this issue because any of those approaches is out of scope for gcovr.