本文介绍如何获取大型c++项目在运行时(不用停止)获取覆盖率数据
对于简单的c++覆盖率获取,可参考http://blog.youkuaiyun.com/zm_21/article/details/37820257,以了解gcc的代码覆盖率统计,并安装相关环境。
正常来说,当项目正常运行结束,才会触发gcc的gcov_flush方法,如果想在项目运行中输出覆盖率数据(即gcda文件),则需要加代码,手工调用gcov_flush方法输出。
官方样例:http://www.osadl.org/Dumping-gcov-data-at-runtime-simple-ex.online-coverage-analysis.0.html
先编写gentle-exit.cpp
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
extern "C" void __gcov_flush();
void sighandler( int signo)
{
printf("received signal pid=%d\n",getpid());
__gcov_flush(); /* dump coverage data on receiving SIGUSR1 */
printf("__gcov_flush()---time----\n");
}
__attribute__ ((constructor))
void initializer(){
struct sigaction new_action, old_action;
/* setup signal hander */
new_action.sa_handler = sighandler;
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction(SIGUSR1, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction (SIGUSR1, &new_action, NULL);
}
然后使用命令g++ -c gentle-exit.cpp,把gentle-exit.cpp编译成gentle-exit.o,该文件就是要嵌入项目里的代码,用于接收信号并输出覆盖率数据。
改造大型c++项目
1,找到根目录下的Makefile.inc
在CXXFLAG和LINK_CXXFLAG里加上-g3 -O0 -fprofile-arcs -ftest-coverage,如果原来里面已经有-O1(O2、O3等等)参数的,要改成-O0,以防止编译器优化代码。
当然,可以设置一下参数,当使用make传入指定参数时,才进行加覆盖率编译。如
ifeq ($(coverage),yes)
CFLAG = -g3 -O0 -fprofile-arcs -ftest-coverage 其它参数
else
CFLAG = 其它参数
endif
进行make时,使用make coverage=yes编译
2、在具体进程项目里找到makefile文件(也就是编译成单独进程的目录),在编译成可执行文件那里后面加上gentle-exit.o,样例如下
all: music_appmonitor_m
music_appmonitor_m:$(OBJ_COMM)
$(CXX32) -W -pg -o $@ $(MCXXFLAG) $(INCLUDE) $(OBJ_COMM) $(COMM_LIB) $(LIB) ../bin/libthrift.so.0.0.0_061 -L../bin ../lib/mapi4dbcommon2.a ../lib/libbase.a ../gentle-exit.o
其中music_appmonitor_m会生成一个可执行文件
3、make coverage=yes编译、运行
4、当测试完成后,命令kill -s SIGUSR1 pid去输出代码覆盖结果,把输出的.gcda文件和编译时产生的.gcno和源码放在一起,若要测试指定时间内的代码覆盖率,先输出一次覆盖率结果,删除*.gcda文件,作为开始统计时间节点,下次输出覆盖率数据,就是这段时间内的覆盖率数据。
5、lcov -c -d ./ -o app.info 把.gcda数据转成.info数据
6、genhtml app.info -o result生成可视化html页面
注意:生成的gcda文件不一定在当前目录,具体位置可能与项目的包路径有关,我也不清楚