场景:mytest.cpp main.cpp mytest.h main调用mytest.cpp里的函数
step1: 编译,链接 g++ -c mytest.cpp -ftest-coverage -fprofile-arcs -o mytest.o --->> mytest.gcno mytest.o g++ -c main.cpp -ftest-coverage -fprofile-arcs -o main.o --->> main.gcno main.o g++ -ftest-coverage -fprofile-arcs main.o mytest.o -lgcov -o main.exe --->> main.exestep2: 运行,生成gcda数据 ./main.exe --->>main.gcda mytest.gcdastep3:生成覆盖率数据 gcov -b main.cpp --->> main.cpp.gcov 【实际需要gcno,gcda文件】 gcov -b mytest.cpp --->>mytest.cpp.gcov 【备注】实际上到这里就可以看到覆盖率信息了,并且在调用gcov的时候已经会有部分信息如图 step4:生成info数据,为生成html报表准备 lcov -d ./ -o main.info -c 【-c选项:capture覆盖率数据,请man lcov查看,需要.cpp, gnco,gcda三种数据或文件】 step5:生成html报表 genhtml -o ./result_dir main.info 【输入main.info,输出为result_dir下所有的html及其他文件】参考信息1. .gcda文件目录出错,找不到要创建的目录,这种主要用于跨平台情况。
这个是由于.gcda文件的生成默认保存到.o所在的目录,但是如果.o所在目录不存在,就会出现错误。
设置环境变量可以解决这个问题。
设置GCOV_PREFIX=/target/run 和 GCOV_PREFIX_STRIP=1
则生成的.gcda文件 将会保存到 /target/run/build/foo.gcda。
2. the gcov message “Merge mismatch for summaries”
可以将.gcda全部删除或者对整个文件全部编译,而不是单个改变的文件,这个是由于gcda与gcno不相配导致的,因为两者之间都有个时间戳用来记录是不是相同的。
3. 想改变gcda输出的路径,设置GCOV_PREFIX和GCOV_PREFIX_STRIP环境变量,如默认生成在
/data/hudson/slave/workspace/ABC-test/ABC_dev_branch/build64_debug/
如果设置如下
export GCOV_PREFIX=”/data/cloud_deploy_pkg/abc/”
export GCOV_PREFIX_STRIP=1
则对比生成路径,实际的路径已经改变,并被剥去$GCOV_PREFIX_STRIP级路径
/data/hudson/slave/workspace/ABC-test/ABC_dev_branch/build64_debug/ 原始路径
/data/cloud_deploy_pkg/abc/hudson/slave/workspace/ABC-test/ABC_dev_branch/build64_debug/ 实际路径
------------------------------补充------------------------------
lcov -d ./ -c -o main.info -b ./
genhtml -o report_main/ main.info将重要的头文件gcov_out.h 加入到你的main文件中,这样就可以使用 kill -USR1 来刷新主程序,而不许要使main.exe退出就可以生成gcda数据
/****************************@filename: gcov_out.h@author: peterguo@tencent.com@date: 2011.11.12*****************************/#ifndef __GCOV_OUT_H__#define __GCOV_OUT_H__#include#include #include extern "C" void sighandler(int signo){ extern void __gcov_flush(); __gcov_flush();}extern "C" __attribute__ ((constructor)) void __ctor(){ int sigs[] = { SIGUSR1 }; int i; struct sigaction sa; sa.sa_handler = sighandler;//定义信号处理函数,使用kill -USR1 $pid进行刷新 sigemptyset(&sa.sa_mask); sa.sa_flags = SA_NODEFER; for (i = 0; i < sizeof (sigs)/ sizeof (sigs[0]); ++i) { if (sigaction(sigs[i], &sa, NULL) == -1) { perror("Could not set signal handler"); } }}#endif // end of __GCOV_OUT_H__