【C++】统计代码覆盖率(四) - 补充

补充如下内容:

  1. 配置 GCC 环境 支持 C++ 11 regex代码编译

  2. 更换一种 (二) 中 修改编译脚本方式 使用 scons 提供的 SConstruct 编译

一  centos 安装devtoolset-3

该篇幅转自:http://www.openskill.cn/article/372

背景:由于gcc 4.8.2不支持C++11的regex库,故需升到4.9.2。

1  cat /etc/issue,确认服务器 CeotOS 是哪个系列

centos6系列
# wget https://www.softwarecollections.org/repos/rhscl/devtoolset-3/epel-6-x86_64/noarch/rhscl-devtoolset-3-epel-6-x86_64-1-2.noarch.rpm
# rpm -ivh rhscl-devtoolset-3-epel-6-x86_64-1-2.noarch.rpm
# wget https://copr.fedoraproject.org/coprs/rhscl/devtoolset-3/repo/epel-6/rhscl-devtoolset-3-epel-6.repo && mv ./*.repo /etc/yum.repos.d/
centos7系统
# wget https://www.softwarecollections.org/repos/rhscl/devtoolset-3/epel-7-x86_64/noarch/rhscl-devtoolset-3-epel-7-x86_64-1-2.noarch.rpm
# rpm -ivh rhscl-devtoolset-3-epel-7-x86_64-1-2.noarch.rpm

2 安装命令如下

yum --disablerepo='*' --enablerepo='rhscl-devtoolset-3' install devtoolset-3-gcc devtoolset-3-gcc-c++ devtoolset-3-toolchain -y
# 如果报错见 报错与解决 部分

3 启用该版本GCC

scl enable devtoolset-3 bash #类似于python虚拟环境,不影响其他版本使用者
或者如下:
find / -name "devtoolset-3" # 找到 devtoolset-3 的安装目录
[root@105 /opt/rh]$ source devtoolset-3/enable # 激活
[root@105 /opt/rh]$ gcc -v
Using built-in specs.
...
gcc version 4.9.2 20150212 (Red Hat 4.9.2-6) (GCC)

4 替换编译文件变量

# export CC=/opt/rh/devtoolset-3/root/usr/bin/gcc
# export CPP=/opt/rh/devtoolset-3/root/usr/bin/cpp
# export CXX=/opt/rh/devtoolset-3/root/usr/bin/c++

 5 问题与解决

①在步骤2安装中,报错:

[/opt/xiaoming/workspace/src]$ yum --disablerepo='*' --enablerepo='rhscl-devtoolset-3' install devtoolset-3-gcc devtoolset-3-gcc-c++ devtoolset-3-toolchain -y
Loaded plugins: fastestmirror, security

Error getting repository data for rhscl-devtoolset-3, repository not found

原因:不知道,没查

解决:替换安装命令为 yum install devtoolset-3-toolchain

 

二 使用 scons 提供的 SConstruct 编译

scons是linux下的自动构建工具,类似cmake。该命令可执行的条件  python 命令可执行 && 安装 scons 工具

1 安装 scons 工具

   yum install scons

2 配置 SConstruct 文件 

utest = ARGUMENTS.get('utest', 'true')
if utest == 'true':
   env['CXXFLAGS'] += ['-DUTEST']
   env['CXXFLAGS'] += ['-fprofile-arcs']
   env['CXXFLAGS'] += ['-ftest-coverage']
   env.Append(dynamic_libs='-Lartifacts/lib -lcares -Wl,-Bdynamic -lgcov -lm -lc -lrt -ldl')   #主要是这几句
else:
   env.Append(dynamic_libs='-Lartifacts/lib -lcares -Wl,-Bdynamic -lm -lc -lrt -ldl')

3 scons -D . 编译文件

4 检查源码文件夹,包含以下文件

-rw-r--r--. 1 root root  172K Jun  8 10:19 fb.gcno   #源文件,与gcda合并可统计到覆盖率
-rw-r--r--. 1 root root  1.3M Jun  8 10:19 fb.o
-rwxr-xr-x. 1 root root   42M Jun  8 10:22 fb        # 可执行文件

5 生成gcda文件

  没实际应用,使用./fb 启动文件即可在目录下生成对应 gcda 文件

  正常执行用例应该也能生成,但是有同学反馈没有生成,由于担心环境冲突影响,我没有试。

6 合并 gcda 和 gcno

artifacts/bin/lcov/usr/bin/lcov -b ./ --capture --directory src --gcov-tool gcov --output-file alla.info
lcov命令装在了 artifacts...目录下
-b 指定 base directory,后面的文件需要在这个目录内
--capture Capture coverage data 捕获

三 统计与集成

同【C++】统计代码覆盖率(三)一致

四 错误与解决

① 使用 scons -D . 命令编译报错

   解决:注意此处报错需要的python版本是 python27。因此要到python27执行  pip install gevent-1.1.2-cp27-cp27mu-manylinux1_x86_64.whl。

   该问题实际没解决,但未影响编译,奇奇怪怪。

[root@localhost# scons -D .
...
gevent-1.1.2-cp27-cp27mu-manylinux1_x86_64.whl is not a supported wheel on this platform.
usage: easy_install [options] requirement_or_url ...
   or: easy_install --help

 ② 当前环境不支持 --user 安装

Can not perform a '--user' install. User site-packages are not visible in this virtualenv.

原因:--user 的目的与 虚拟环境相同,因此不支持这种使用。但是非常奇怪,因为 python3 是支持的。

解决:没解决,②和①报的是一个问题的错误,忽略对编译结果没影响。

③ 执行编译时报错   #先忽略了其他错误

[root@105 ...]$ scons -D . 
...
cc1plus: error: -fsanitize=address and -fsanitize=kernel-address are incompatible with -fsanitize=thread
scons: *** [src/***.o] Error 1
scons: building terminated because of errors.

原因:GNU GCC提供的关于sanitize的编译选项之一 -fsanitize=address

当ASAN_OPTIONS环境变量设置为help=1时(如:ASAN_OPTIONS=help=1),所有可用的选项将在将在程序启用时显示。ASAN_OPTIONS环境变量不能结合-fsanitize=thread使用。

解决:在编译文件 SConstruct 中注释掉 env['CXXFLAGS'] += ['-fsanitize=thread'] 即可,实际也没用,开发估计瞎写

④ 在 GCC V4.9.2 编译报错

/opt/xiaoming/workspace/tool/workspace/tool.cpp:152: undefined reference to `__asan_before_dynamic_init'
/opt/xiaoming/workspace/tool.cpp:15: undefined reference to `__ubsan_handle_type_mismatch'
/opt/xiaoming/workspace/tool.cpp:15: undefined reference to `__ubsan_handle_add_overflow'
/opt/xiaoming/workspace/tool.cpp:15: undefined reference to `__ubsan_handle_type_mismatch'

原因:使用 ubsan 检测代码时的问题?一般需要忽略一些东西,比如添加 '-fsanitize=undefined',但实际未生效,可能原因如下:

https://www.codenong.com/31803705/

1 我已经安装了 libubsan0 和 lib64ubsan0 并添加了 -lubsan 选项,并且我的应用程序已成功编译!
2 "GCC recently (version 4.9) gained Undefined Behavior Sanitizer (ubsan), a run-time checker for the C and C++ languages. In order to check your program with ubsan, compile and link the program with -fsanitize=undefined option."
将-fsanitize=undefined传递给了meson.add_project_arguments(),但是 那些只交给编译器; 我还需要将其传递给meson.add_project_link_arguments()。 添加之后,错误消失了,程序链接了。

实际解决:注释掉了代码中的如下部分,编译成功了,怀疑开发并实际编译时也是注释掉该部分并没有解决问题。

build_type = ARGUMENTS.get('build', 'debug')
if build_type.lower() == 'debug':
  env['CXXFLAGS'] += ['-g']
  #env['CXXFLAGS'] += ['-fsanitize=address']  
  #env['CXXFLAGS'] += ['-fsanitize=thread']    #注释掉以防编译冲突
  #env['CXXFLAGS'] += ['-fno-omit-frame-pointer']
  #env['CXXFLAGS'] += ['-fsanitize=leak']
  #env['CXXFLAGS'] += ['-fsanitize=undefined']
else:
  env['CXXFLAGS'] += ['-O3']

⑤ 生成 info 文件时报错

[root@105 /opt/xiaoming/workspace]$ artifacts/bin/lcov/usr/bin/lcov -b ./ --capture --directory src --gcov-tool /usr/bin/gcov --output-file alla.info
Capturing coverage data from src
Found gcov version: 4.4.7
Scanning src for .gcda files ...
Found 49 data files in src
Processing ssp_service_v2/preload_session.gcda
Auto-detected compatibility mode for split checksum .gcno file format
/opt/xiaoming/***.gcno:version '409R', prefer '404R'

out of memory allocating 25868243408 bytes after a total of 14941280 bytes    # 报错
geninfo: ERROR: GCOV failed for /opt/xiaoming/***.gcda!

原因:gcc 和 gcov 版本对不上所致

解决:/usr/bin/gcov --version 是4.4.7,gcc 4.9.2;试了下gcov 版本4.9.2是可以生成info文件了。

⑥ 编译后启动服务报错 

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::program_options::unknown_option> >'
  what():  unrecognised option
Aborted (core dumped)

原因:不知道,很奇怪。

a 启动命令中有 redis 密码等 会识别不了,加'' ok,报错误b

b 报贴出来的图样错误,据说是对应代码需要调整,开发同学调整后 ok

⑦其他问题

问题:鉴于有多个模块共用一个 git 地址,且各模块归属不同的开发负责,经常在统计 html 报告时由于模块 A 部署分支,没有模块B编译时的源码文件等问题导致html报告生成失败( xml 不会失败)

建议:基于以上问题,有以下几种处理方式

  1. 统计分离:git目录只用来拉取代码,拷贝模块的源码文件到其他目录编译统计(同时对通用模块common改动,可手动更新)
  2. 提测分支统一:推动开发解决 -- 此时要保证提测时拉取的分支从 master 拉取
  3. 不解决,单独部署模块,单独查看覆盖率 -- 鉴于自动化用例是全量执行,还是不建议该措施

综上,最推荐方式1,因为想要指望开发是没用的,测试要时刻靠自己。

 

posted @ 2020-06-03 14:48  KK_Yolanda  阅读(1175)  评论(0编辑  收藏  举报