编译PHP扩展时libtool链接阶段删除*.gcno,如何获取代码覆盖率?
解决PHP扩展编译时libtool删除*.gcno文件的代码覆盖率问题
我之前在类似的PHP DEBUG环境下调试扩展代码覆盖率时,也碰到过libtool自动清理gcno文件的坑,结合你的PHP 7.2.2 NTS DEBUG版和gcc 5.4环境,给你几个实用的解决思路:
1. 调整libtool参数,强制保留gcno文件
在你的configure命令中添加LIBTOOLFLAGS参数,直接干预libtool的清理行为:
CXX=gcc \ CFLAGS="--coverage -fprofile-arcs -ftest-coverage $CFLAGS" \ LDFLAGS="--coverage $LDFLAGS" \ LIBTOOLFLAGS="--preserve-dup-deps --no-clean" \ ./configure --enable-your-extension
--preserve-dup-deps会让libtool保留覆盖率相关的依赖文件,--no-clean则避免它在链接阶段自动清理中间目标文件,这样gcno就能留在编译目录里。
2. 手动从libtool归档文件中提取gcno
如果上面的参数不生效,libtool通常会把编译生成的.o和对应的.gcno打包到.libs目录下的静态库中,你可以用ar命令提取这些文件:
# 进入扩展编译目录 cd /path/to/your/extension # 从静态库中提取所有目标文件及关联的gcno ar x .libs/your_extension_name.a
提取完成后,当前目录会出现对应的.o和.gcno文件,后续运行测试生成.gcda后,就能正常用gcov生成覆盖率报告。
3. 修改Makefile的清理规则
phpize生成的Makefile里可能包含清理gcno的命令,你可以手动编辑调整:
- 找到
clean目标,删除所有包含*.gcno或*.gcda的删除语句 - 或者在Makefile末尾添加自定义目标,自动备份gcno文件:
preserve-gcno: cp .libs/*.gcno ./
编译完成后执行make preserve-gcno,就能把.libs里的gcno复制到当前目录,避免被清理。
4. 改用动态链接模式编译扩展
如果你的扩展支持动态编译,在configure时加上--enable-shared(多数PHP扩展默认支持),动态链接时libtool通常不会清理gcno文件:
CXX=gcc \ CFLAGS="--coverage -fprofile-arcs -ftest-coverage $CFLAGS" \ LDFLAGS="--coverage $LDFLAGS" \ ./configure --enable-your-extension --enable-shared
编译出的.so扩展文件会保留覆盖率所需的符号,gcno文件也会直接留在编译目录中。
最后提醒:运行测试后,确保.gcda和.gcno文件在同一目录,再用gcov生成报告,比如:
gcov -o .libs/ your_extension_source.c
内容的提问来源于stack exchange,提问作者Aleksander Wons
相关产品推荐
相关产品推荐

