【嵌入式】gcov/lcov/gcovr代码覆盖率交叉编译使用解析

介绍一下gcov/lcov/gcovr

  • gcov 是一个测试代码覆盖率的程序,正确地使用它搭配GCC可以分析、帮助你将代码写得更高效。帮助你优化程序。类似于一个profiling tool,使用gcov或者gprof,可以收集到一些基础的性能统计数据。比如:

    • 每一行代码执行的频度
    • 每个代码文件中实际被执行到的行数
    • 每一个代码块执行使用的时间
  • gcov创建一个logfile叫做 源文件名称.gcxx (这里的源文件名称指的是.c或者.cc文件的文件名),表示的是这个 源文件.c 中每一行所被执行的次数。这些文件可以配合gprof使用。 gcov要工作只能用gcc编译这些代码。和其他的profiling 或者 测试代码覆盖率的机制不兼容。

  • lcov 是GCC 测试覆盖率的前端图形展示工具。它通过收集多个源文件的 行、函数和分支的代码覆盖信息, 并且将收集后的信息生成HTML页面。生成HTML需要使用genhtml命令下文会解释。

  • gcovr 也是GCC 测试覆盖率的前端图形展示工具。

  • 代码覆盖率测试工具可以帮助我们发现代码中未被测试的部分,

  • gcov/lcov/gcovr之间的差异:

    • GCOV:与GCC配套,不需要安装,生成纯文本文件
    • LCOV:需要安装,跨平台麻烦,生成HTML页面
    • GCOVR:需要安装,跨平台容易,且指令比LCOV少,生成HTML页面
  • gcov是随gcc一起发布的,并不需要独立安装,设法装上gcc就OK了。
    在这里插入图片描述

如何编译检查代码分支覆盖情况

  • 编译与执行前,若是在交叉编译环境,需要在板端加入如下内容:
export  GCOV_PREFIX=/mnt/xx 表示在板端的目录链接略去编译端前三个目录为 /mnt/xx/workspace
export  GCOV_PREFIX_STRIP=3  表示删去原编译端的目录为 /home/1233/test/workspace
  • 例程 test_gcov.c
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    if (argc >=2) {
        printf("=====argc>=2\n");
        return 0;
    }
    printf("helloworld begin\n");

    if (argc <2){
        printf("=====argc<2\n");
        return 0;
    }
    return 0;
}
  • 使用gcc编译,并加入如下编译选项
(指向特定版本的)gcc -fprofile-arcs -ftest-coverage -g -O0 -o test_gcov test_gcov.c
  • 注意:这里若为交叉编译环境,需要指定对应板端的gcc编译器,如/opt/rkxxx1234/bin/gcc-10.2.1/gcc

  • 我们将得到一个被“改造”过的可执行程序test_gcov ,该程序中包含了一些额外的指令,用于记录程序中每一行被执行的次数。以及一个后缀为.gcno的test_gcov .gcno文件,它是即将被gcov引用的关键数据文件。

  • 编译选项说明:
    -ftest-coverage选项:添加记录单行代码执行次数的指令
    -fprofile-arc选项:添加程序每个分支的检测代码(if或者其它条件语句)

  • 在运行环境,如板端,运行可执行程序之后,我们会得到一个test_gcov.gcda的文件,它和test_gcov .gcno一样是即将被gcov引用的数据文件(代码覆盖率信息文件)。

./test_gcov
  • 通过gcov命令生成代码覆盖率报告
(指定版本和gcc版本一致的)gcov test_gcov.c
File 'test_gcov.c'
Lines executed:86.67% of 15
Creating 'test_gcov.c.gcov'
  • 执行指令后,gcov会引用之前的数据文件生成一个代码覆盖率报告test_gcov.c.gcov,查看该文件可以看到每行的执行次数等信息。
    -:    0:Source:test_gcov.c
    -:    0:Graph:test_gcov.gcno
    -:    0:Data:test_gcov.gcda
    -:    0:Runs:1
    -:    1:#include <stdio.h>
    -:    2:#include <string.h>
    -:    3:
    1:    4:int main(int argc, char *argv[])
    -:    5:{
    1:    6:    if (argc >=2) {
#####:    7:        printf("=====argc>=2\n");
#####:    8:        return 0;
    -:    9:    }
    1:   10:    printf("helloworld begin\n");
    -:   11:
    1:   12:    if (argc <2){
    1:   13:        printf("=====argc<2\n");
    1:   14:        return 0;
    -:   15:    }
#####:   16:    return 0;
    -:   17:}
  • 注意:这里若为交叉编译环境,需要指定gcov与gcc编译版本一致,不一致会导致报错。
  • “#####”所标记的是未被执行的语句。

lcov可视化代码分支覆盖率

  • 在代码编译和链接的时候,需要加上下面两个编译选项。在gcc链接时需要加上gcov链接参数。

    -fprofile-arcs -ftest-coverage
    
  • 使用过程,注意:lcov在执行时会打印出所依赖的版本,要检查是否和编译所使用的gcc版本一致,交叉编译环境下通常存在多个编译器版本,这可能会导致生成相关覆盖率文件时出错。

    • 使用lcov -c -d ./ -o all.info --gcov-tool=arm-linux-gnueabihf-gcov 可以指定gcov版本
    • 初始化并创建基准数据文件, -c 捕获,-i初始化,-d应用目录,-o输出文件
    lcov -c -i -d ./ -o init.info
    
    • 执行编译后的测试文件,交叉编译环境下需要在板端运行
    ./test_gcov
    
    • 收集测试文件运行后产生的覆盖率文件
    lcov -c -d ./ -o cover.info
    
    • 合并基准数据和执行测试文件后生成的覆盖率数据, -a 合并文件
    lcov -a init.info -a cover.info -o total.info
    
    • 过滤不需要关注的源文件路径和信息,–remove 删除统计信息中如下的代码或文件,支持正则
    lcov --remove total.info '*/usr/include/*' '*/usr/lib/*' '*/usr/lib64/*' '*/usr/local/include/*' '*/usr/local/lib/*' '*/usr/local/lib64/*' '*/third/*' 'testa.cpp' -o final.info
    
    • 通过final.info生成html文件
    genhtml -o cover_report --legend --title "${project_name} commit SHA1:${commitId}" --prefix=${curr_path} final.info
    

    -o 生成的html及相关文件的目录名称,–legend 简单的统计信息说明,–title 项目名称,–prefix 将要生成的html文件的路径

    genhtml -o cover_report --legend --title "lcov"  --prefix=./ final.info
    
    • test_gcov.gcda、test_gcov.gcno、test_gcov.gcda、test_gcov就是运行可执行文件后gcov产生的统计信息文件。
    • cover_report目录就是生成的html信息目录。
    • lcov常用的参数:
      -d 项目路径,即.gcda .gcno所在的路径
      -a 合并(归并)多个lcov生成的info文件
      -c 捕获,也即收集代码运行后所产生的统计计数信息
      –external 捕获其它目录产生的统计计数文件
      -i/–initial 初始化所有的覆盖率信息,作为基准数据
      -o 生成处理后的文件
      -r/–remove 移除不需要关注的覆盖率信息文件
      -z 重置所有执行程序所产生的统计信息为0
  • 问题1:
    报错:geninfo: WARNING: /xx/work/3work/test/test_gcov.gcno: Overlong record at end of file!
    /xx/xx/work/3work/test/test_gcov.gcno:version ‘B02*’, prefer ‘A75*’
    /xx/xx/work/3work/test/test_gcov.gcno:no functions found
    解决方法:lcov -v 查看版本,较低的话需要升级版本。
    在这里插入图片描述

gcovr可视化代码分支覆盖率

  • 相比于lcov,gcovr可能更方便一点。lcov有的功能gcovr都有,并且gcovr也是开源的,它是用Python写的,这意味着只要有Python环境都可以使用gcovr,无论是WINDOWS还是LINUX。

  • 安装非常简单

    • Install newest stable gcovr release from PyPI:

      pip install gcovr
      
    • Install development version from GitHub:

      pip install git+https://github.com/gcovr/gcovr.git
      
  • 使用
    GCC可以检测可执行文件以发出覆盖数据。您需要使用以下标志重新编译代码:

    --coverage -g -O0
    

    接下来,运行测试套件。这将生成原始覆盖率文件。
    最后,调用gcovr。这将在控制台上打印一份表格报告。

    gcovr
    

    还可以生成详细的或嵌套的HTML报告:

    gcovr --html-details coverage.html
    gcovr --html-nested coverage.html
    或 gcovr -r . --html --html-details -o coverage.html
    

    gcovr相比lcov指令简单,一句即可生成可视化报告。

  • gcovr工具项目地址:https://github.com/gcovr/gcovr
    在这里插入图片描述

参考资料

1、https://www.cnblogs.com/ChinaHook/p/5508660.html

  • 5
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值