如何在当前/构建/运行目录之外的源文件中使用gcovr?

7
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 .

将输出一个空报告。

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    --%
------------------------------------------------------------------------------

然而,如果我手动运行

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

我获得了正确的结果

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

似乎gcovr无法从正确的gcov输出中提取覆盖率。当源文件位于当前目录之外(与构建目录、输出目录、运行目录相同),且使用绝对路径调用gcc时才会出现这种情况。
如何解决?
编辑
针对相对路径,在上游的gcovr中已经修复,但绝对路径仍然存在错误。
请参见https://github.com/gcovr/gcovr/issues/169

你应该在问题中直接解释目录结构,而不是提供所有这些mkdir。解释对象和源文件放置的位置。 - Vikas Tawniya
@Vikas,如果有可运行的代码可以重现问题,我更喜欢它。(至少对于这种“错误或用户错误?”的问题是如此。) - not-a-user
2个回答

6
我理解您的代码中,您已经完成了所有事情并运行了程序,但您仍然停留在生成目录中,其中包含对象文件。

因此,您需要明白的是:

gcovr -v -r <path>

这个 -r 标志需要根目录,也就是源代码和目标目录所在的父目录。因此它可以跟踪它们并生成覆盖数据以及其他你想要的数据。
尝试这样做,它会工作。

为了你的理解:

编译后生成的 .gcno 文件只是特定源文件的流程图数据。
然后,当你执行程序时,每个源文件都会生成一个 .gcda 文件。这个文件包含实际的覆盖数据,但对于 gcovr 来说,这三个文件都是必需的(.gcno、.gcda、sourceFile)。

希望它有所帮助。:)

更新:
回到解决方法
你可以将你的覆盖数据位置作为纯参数(没有选项),并将根目录指向你的源代码。

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

这一定能解决你的问题。
对我在项目上进行覆盖测试非常有效。

.gcno文件已经包含了源代码所在的路径。(在一个.gcno文件上执行strings命令即可查看。) - not-a-user
最佳实践是将源代码和构建目录分开,因此gcovr应该支持这一点。 - not-a-user
是的,我在这里谈论的是根目录。它包含构建和源目录。此外,在路径中最后一个目录名称后始终添加额外的斜杠。 - Vikas Tawniya
我明白,但我想在Makefile中使用gcovr,并且我不想假设我正在构建的位置。(如何计算公共根目录?如果它包含许多其他不相关的源和gcov文件怎么办?这里是“/tmp/”,我真的想将所有“/tmp/”输入gcovr吗?!?)- 在我这样做的同时,lcov似乎是我的问题的更好解决方案。(在构建目录中工作,通过(有效地)检查.gcno文件找到源代码。) - not-a-user
@not-a-user 更新了解决方法的答案,请查看。 :) - Vikas Tawniya
显示剩余5条评论

3
Gcovr仅为项目中的源文件生成报告。这旨在排除库头文件等的覆盖范围。
问题是,哪些文件属于您的项目?这取决于-r根路径。
如果您在/tmp/build中,根目录为“。”即/tmp/build,源文件为“/tmp/src/prog.c”,则该源文件显然不在您的项目之内。在详细输出中,gcovr将报告“过滤文件/tmp/src/prog.c的覆盖数据”。
如果您在/tmp/build中,根目录为“..”即/tmp,源文件为“/tmp/src/prog.c”,则该源文件位于项目内。
如果您在/tmp/build中,根目录为“。”即/tmp/build,源文件为“../src/prog.c”,那么gcovr似乎会做出一些可疑的事情:它将文件名与当前目录连接并检查。因此,我们实际上看到的是“/tmp/build/../src/prog.c”。就gcovr而言,这是在您的项目之内。似乎这种行为对于包含符号链接到项目中的代码是必要的。
您可以通过提供自己的更好的过滤器来禁用此“源是否在项目内”的过滤器。例如,您可以要求gcovr仅报告/tmp/src下的源覆盖范围:
gcovr -r . -f /tmp/src

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接