【C++】统计代码覆盖率(四) - 补充
补充如下内容:
-
配置 GCC 环境 支持 C++ 11 regex代码编译
-
更换一种 (二) 中 修改编译脚本方式 使用 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 不会失败)
建议:基于以上问题,有以下几种处理方式
- 统计分离:git目录只用来拉取代码,拷贝模块的源码文件到其他目录编译统计(同时对通用模块common改动,可手动更新)
- 提测分支统一:推动开发解决 -- 此时要保证提测时拉取的分支从 master 拉取
- 不解决,单独部署模块,单独查看覆盖率 -- 鉴于自动化用例是全量执行,还是不建议该措施
综上,最推荐方式1,因为想要指望开发是没用的,测试要时刻靠自己。