使用gcov和lcov做代码覆盖有一段时间了,期间走了一些弯路,算是一些经验教训。
- gcov可以对shared object进行代码覆盖信息收集。
之前的一篇文章说过,gcov不能收集.so的代码覆盖率信息,其实这个是错的。
如果是C++程序,在CXXFLAGS中加入-fprofile-arcs -ftest-coverage 作为编译选项,并且在LDFLAGS中加入-lgcov作为链接选项。如果没有-lgcov选项编译出来的.so文件在动态加载的时候会提示类似 undefined reference to ‘__gcov_merge_add’ 或者 undefined reference to ‘__gcov_init’这样的错误。
如果是C程序,在CFLAGS中加入-fprofile-arcs -ftest-coverage 作为编译选项,也是在LDFLAGS中加入-lgcov作为链接选项,就OK了。跑测试的时候跟正常测试一样,最后把收集到的.gcda文件处理一下就能得到代码覆盖率报告
- 用lcov处理.gcda文件的时候,在处理某些文件的时候hang了。
对于这个问题,不知道根本原因是什么,可能是那个文件的某行代码触发了bug,我对此是workaround了一下。lcov本身是一堆Perl脚本,打开它,通常在这里“/usr/bin/geninfo”,然后找到这行,注释掉
push(@gcov_options, “-a”) if ($gcov_caps->{‘all-blocks’});
- genhtml的一个参数:-f, –frames
Use HTML frames for source code view。这样会在每个结果页的左边生成一个缩略图,review代码的时候很方便。但是,如果你的项目里面用到了一些第三方的库,而那些第三方的库没有提供完整的源代码,那么使用这个参数就会出现问题。
gd-png: fatal libpng error: Image width or height is zero in IHDR
gd-png error: setjmp returns error condition
解决方法可以是1. 尝试找一下源代码;2. 通常这些第三方库,我们都是放在一个单独的文件夹里面的,这样子用lcov处理.gcda文件的时候,可以指定目录,把这些第三方库的目录跳过去
- genhtml的一个参数:–num-spaces NUM
默认值是8,出来的报告看着很费劲,建议换成4,如果代码有很多层,那设成2也是可以的
昨天在linkedin更新上看到你现在在Google工作了。恭喜恭喜!
LikeLike
你好,我的系统使用的是动态库,在编译时没有报错,但启动系统时报了”undefined symbol: __bb_init_func“,我看到有资料说时“dynamic libraries and constructor function __bb_init_func and __bb_fork_func :
If you want to avoid such an error: «Undefined symbol “__bb_init_func”», use static binaries.
Explaination: when compiling using Gcov special flags “- fprofile- arcs” and “- ftest- coverage”, the linking of
dynamic libraries may not perform as expected.” 我不太明白这里static binaries的意思,请问是说要使用静态库吗?
LikeLike
你好
gcov做编译动态库的时候是不会报错的,只是在加载.so文件的时候才发现缺少gcov相关的symbol,我之前在编译动态库的时候,在LDFLAGS中加入-lgcov作为链接选项,能解决这个问题。
你可以看一下你的configure文件里面LDFLAGS有没有包含 -lgcov 选项。如果没有就加上这个选项,然后再重新编译一下那些.so文件试试看
LikeLike
你好,如何使用gcov编译静态库呢,我使用ld链接的时候,总是提示undefined reference to ‘__gcov_init这样的错误
LikeLike
你好,我问下,如果要查看链接进去的静态库的覆盖率的话,应该怎么弄呢
LikeLike
请好,请问有没有办法通过gcda或者gcno或者*.o文件对应的cpp文件?我尝试打开*.gcno文件,但从中得到的cpp文件不是完整的路径,是否有办法得到完整路径?
谢谢
LikeLike
你好,你编译的程序是用debug版本的么?
其实生成的.gcda文件都是相对路径,不是绝对路径。
所以当你拿到.gcda文件以后,这些.gcda文件的结构应该跟你当初编译程序的时候那些.cpp文件的结构是一样的
所以你可以把你编译路径的那些.cpp文件和.gcno文件,还有运行测试完成以后的.gcda文件都放在一起(通常都是一一对应的)。然后运行lcov提取结果。
LikeLike
如果有code是编译成la文件的,发现lcov后的info文件里就不会有这个la对应的cpp文件,这是合理的么,如果我想得到这个la对应的cpp文件的覆盖率,可以解决么
LikeLike
hi~ 我没有用过libtool,所以没有遇到过的您所说的问题。
不过我刚才上网搜了一下,有人说只要把.libs/ 文件夹的文件拷贝到外头,然后再运行gcov就可以了。
或许可以尝试一下,是这个地址: http://www.toofishes.net/blog/using-gcov-code-coverage-testing/
LikeLike
谢谢你的帮助,我的project结构类似于这样:
Dir1: 1.cpp 2.cpp 3.cpp
编译后(CFLAG参数添加了-fprofile-arcs -ftest-coverage), Dir1下文件生成如下:
1.cpp 1.o 1.gcno
2.cpp 2.o 2.lo
3.cpp 3.o 3.lo
.libc/***.a ***.la
但是没有2.gcno 和3.gcno生成,导致无法统计2.cpp和3.cpp的覆盖率,貌似现在的情况是如果是生成lo文件的都没有生成gcno,我比较不明白的是2.o和3.o都生成了却没有对应的gcno文件生成。
LikeLike
hi, 不好意思,这个问题就不清楚了。在网上又搜了一下,不知道这个对你有没有帮助: http://lists.gnu.org/archive/html/libtool/2006-09/msg00080.html
LikeLike
lo和la都是libtool的东西 你看看具体的make执行有没有加入-fprofile-arcs -ftest-coverage参数
或者没啥需要的话 在构建里吧libtool去掉
LikeLike
Hi magus,
我有个问题,麻烦帮忙解答一下。我刚开始研究gcov,和.so相关。编译选项是要在编译.so时加入,还是在编译test code的时候加入啊?我测试的平台是android,那在android上跑test,是会在板子上生成.gcda文件吗?
LikeLike
你好,我好久没搞这个了,所以:1. 已经忘记了;2. 知识没有更新。
不好意思……
LikeLike
恩, 还是谢谢你的回复哈。
LikeLike
那请问你还记得LDFLAGS是干什么的吗?它怎么被使用到呢?
LikeLike
请问,我在使用lcov的时候,遇到下面 问题,该如何解决呢?/Users/kerryzhao/Documents/cover/File.gcno:version ‘404*’, prefer ‘402*’
/Users/kerryzhao/Documents/cover/File.gcda:unknown function ‘22167152’
/Users/kerryzhao/Documents/cover/File.gcda:unknown function ‘22177440’
Processing main.gcda
/Users/kerryzhao/Documents/cover/main.gcno:version ‘404*’, prefer ‘402*’
/Users/kerryzhao/Documents/cover/main.gcda:unknown function ‘22169120’
Processing ViewController.gcda
/Users/kerryzhao/Documents/cover/ViewController.gcno:version ‘404*’, prefer ‘402*’
LikeLike
我也遇到了同样的问题,请问这个问题后来解决了吗?多谢
LikeLike
我也遇到这个问题了 还在解决中
LikeLike
请问你这个问题解决了么?
LikeLike
请问这个问题解决了嘛?我也遇到相同问题了
LikeLike
Hi magus,
我想请教个问题,用gcov是可以查看覆盖率,就是如果合成测试的结果数。比如:第一次执行后生成数据A.cpp.gcov1,第二次生成A.cpp.gcov2。
那么我们怎么把这个数据合并呢。然后知道所有分支都走了。
LikeLike
你好,我已经很久没用了,但是在网上看了一些文章,你可以参考一下
http://stackoverflow.com/questions/3166198/with-gcov-is-it-possible-to-merge-to-gcda-files
http://stackoverflow.com/questions/15612077/is-there-anyway-to-merge-two-gcov-files-into-one
LikeLike