本文将解决上一篇中的一个问题 1)为什么C 项目扫出来缺陷、安全漏洞都是0?覆盖率也是0%?
C 代码扫描方案
本文主要内容如下:
扫描内容
一般来讲,我们主要是对代码进行静态扫描,如果有执行单元测试或者集成测试的话,可以把测试结果以及覆盖率统计结果也一并扫描并上报给SonarQube服务器。
工具链 - 编译构建gcc/make
假定我们是在Linux下使用gcc进行C 代码的编译,并且使用make进行构建管理。
工具链 - 覆盖率统计gcov
C 代码的覆盖率可以采用gcc自带的gcov来实现了。具体的原理和使用过程可以参见其它文章。
工具链 - 覆盖率报告lcov/gcovr
gcov生成的覆盖率结果文件可读性很差,一般都需要额外的工具对gcov的结果文件进行解析和进一步优化,生成可读性更好的xml或者html文件。 lcov和gcovr是两个比较流行的gcov报告解析器。其中lcov的功能更为强大一些,有覆盖率结果累加等功能,但是只提供了html报告。而gcovr比lcov更好的一个场景是提供了cobetura兼容格式的xml报告,从而可以让sonar来解析c 的覆盖率报告。 覆盖率检测这项工作除了简单的代码插桩--用例执行--结果获取这几步之外,实际的工程中还存在更为复杂的场景,如收集分布式系统或者是多环境并行执行测试的结果,这需要对多个执行结果进行合并。又例如需要知道增量覆盖的情况, 需要基于之前的覆盖率结果,对现有结果进行减法,得到增量部分。如果关注C 覆盖率统计的同学,可以阅读gcov/gcovr/lcov等工具的说明文档,以了解这些高阶应用。
工具链-单元测试gtest/gmock
对于C 的单元测试来说,推荐Goole Test, 简称gTest以及配套的gMock。具体的用例编写,也不是本文的范围,读者可自行了解。
工具链-扫描插件sonar-cxx
SonarQube社区版是不带有C 语言支持的。通过搜索,了解到有人根据原厂自行开发并开源了一个兼容的c 插件。[SonarQube C plugin Community] (https://github.com/SonarOpenCommunity/sonar-cxx#sonarqube-c-plugin-community) 根据官宣,做得还是非常不错的。
- 支持C/C 多种编码标准
- 支持windows/Linux
- 提供了多种传感器: 如cppcheck/gcc/valgrind等等
- 提供了对单元测试/覆盖率数据的分析功能
- 还支持自定义扩展规
部署-sonar-cxx
根据官方文档,部署是非常简单的,只要将下载的jar包放到sonarqube安装目录下的/extensions/plugins目录下,将sonarqube重启即可使用。
工具链-扫描器sonar-scanner
最后在简单说一下扫描器。在Java项目中,一般可以通过Maven来管理代码编译、单元测试、覆盖率检测和静态扫描以及结果上报Sonar的整个过程。 而C 项目采用的是make gcc的方式进行编译管理的,对此Sonar提供的是sonar-scanner来进行扫描。 1)下载并安装sonar-scanner 2)bin纳入PATH 3)conf文件中指定SonarQube的服务器/账号 4)待扫描项目设置projectKey/source 等参数 当然,通用的Sonar Scanner配合上Sonar C plugin,虽然说能实现扫描,但是通常第一次的扫描结果是0缺陷,0违规。这就比较奇怪了,笔者后来通过仔细研读说明文档,原来这个Sonar C plugin只是完成了报告的读取,并没有任何代码分析的功能。任何的结果,都依赖于工具链中前述工具所生成的报告。
工作过程
一个典型的过程是:
- 部署上述工具,形成标准化的编译扫码环境
- 从代码库检出代码,并转换到相应的分支
- 通过cppcheck进行代码扫码
- 通过make进行gcc编译,编译过程中通过gccv进行插桩
- 通过gtest/gmock执行单元测试用例并生成测试报告以及gcc覆盖率报告。如果有valgrind的测试也可以在此处执行。
- 使用gcovr分析gcc覆盖率报告文件,并生成xml格式的cobetura兼容报告。
- 执行sonar-scanner扫码并上报结果
1、sonarqube scanner(绿色版,免安装)
注意: 配置环境变量,将bin路径增加至path。 修改 /conf/sonar-scanner.properties,增加sonarqube服务器的配置:
代码语言:javascript复制sonar.host.url=
sonar.login=
##用token的话,不配sonar.password
2、cppcheck/gcovr
方案一(推荐): 直接执行 yum install cppcheck 安装。gcovr同上 方案二(手工安装)
使用步骤
1、 工程根路径新建sonar-project.properties文件,版本号实时更新(与发布版本号相匹配):
代码语言:javascript复制 sonar.projectKey=
sonar.projectName=
sonar.projectVersion=
sonar.sources=src
sonar.sourceEncoding=GB2312
sonar.language=c
sonar.exclusions=
sonar.cxx.cppcheck.reportPath=reports/cppcheck.xml
sonar.cxx.coverage.reportPath=reports/coverage.xml
2、工程根目录创建文件夹reports,用于存放扫描报告; 3、在工程根目录下,执行代码检查,假设src/source为要扫描的源码路径: cppcheck src/source src/public --enable=all --inconclusive --xml-version=2 . 2> reports/cppcheck.xml 4、在工程根目录下,生成覆盖率检测报告(假设已完成gcov覆盖率检测过程) gcovr -x -r src/source -o report/coverage.xml --xml-pretty 4、运行sonar扫描,将结果上传至服务器 sonar-scanner -Dsonar.branch.name=${branchName}
第一次扫描,先初始化执行****master****分支扫描。
这个在一开始还闹了笑话。笔者以为在sonar-cxx插件安装并执行sonar-scanner之后,自然就有代码静态扫描结果了。然而SonarQube上的数据一直是0个BUG,0个违规。 后来经过仔细查看sonar-cxx的使用说明,原来该插件只是提供了sensor, 也就是只是一个报告解析和上报的功能。如果需要cppcheck代码静态扫码或者其它的扫描结果,得先拿工具扫出来。。。。。。 另外, cppcheck 默认是采用最小规则集进行扫码的,如果没有设置 --enable=all,不要轻易跟老板说cppcheck不好用,扫不出“雷”哦。 【未完待续】 1)如果一个项目中包含C /C#/PLSQL多种语言,如何实施SonarQube扫描?需要扫几次,是几个项目? 2)社区版本的SonarQube没有扫描C /PLSQL等语言的能力,怎么办? 3)如果代码库有多个分支,如何为每个分支产生扫描结果?社区版好像没有这个功能哎,怎么办?