我使用的gcov我的应用程序获取覆盖信息。不过,也有我的应用程序3个实例同时运行创建3个版本的“gcda”文件。有没有一种方法来合并不同版本的同一个“gcda”的文件在我的覆盖率信息文件。
我想借此覆盖信息仅作为一个实例。
我刚才一直在寻找到同样的问题,这里是我发现了什么。 TL; DR是有可能,在最好的情况下,由刚刚被小心编译顺序,并在使用gcov-tool merge
命令最普通的(复杂)的方式,但这不是直的开箱即用,它需要一些专门的设置为了得到它的工作。
在我的例子,我有一个库文件,lib.cpp
,有两个功能:
#include <iostream>
void five(int n) {
if (n > 5) {
std::cout << n << " is greater than five" << std::endl;
} else {
std::cout << n << " is not greater than five" << std::endl;
}
}
void ten(int n) {
if (n > 10) {
std::cout << n << " is greater than ten" << std::endl;
} else {
std::cout << n << " is not greater than ten" << std::endl;
}
}
然后我有两个程序,每个程序的调用它们的功能之一,five.cpp
#include <iostream>
#include "lib.hpp"
int main(int argc, char *argv[]) {
if (argc != 2) {
std::cerr << "usage: " << argv[0] << " <n>" << std::endl;
return 2;
}
int n = std::stoi(argv[1]);
five(n);
return 0;
}
和ten.cpp
#include <iostream>
#include "lib.hpp"
int main(int argc, char *argv[]) {
if (argc != 2) {
std::cerr << "usage: " << argv[0] << " <n>" << std::endl;
return 2;
}
int n = std::stoi(argv[1]);
ten(n);
return 0;
}
假设代码位于一个/tmp/merge-gcov
目录。
启用覆盖捕获能像做
g++ -O0 --coverage -o five five.cpp lib.cpp
这将创造lib.gcno
和five.gcno
文件。当正在运行的程序five
它会创建/tmp/merge-gcov/lib.gcda
和/tmp/merge-gcov/five.gcda
。请注意,那些gcda路径被硬编码到二进制(但以后可以操纵,更多关于这一点)。
./five 1
./five 12 # Results from multiple runs will accumulate in gcda files
mkdir report
gcovr -r . --html --html-details --output report/report.html
firefox report/report.html
到现在为止还挺好。但是,如果我们现在还编译ten
程序以同样的方式
g++ -O0 --coverage -o ten ten.cpp lib.cpp
然后它会创建一个lib.gcno
然后将其比新和不同于lib.gcno
与编译five
。这意味着只要five
或ten
是其他运行后它会检测到lib.gcda
文件没有对应的预期(gcno来源)和复位文件内容,从而丢弃任何积累以前的内容。
这可以通过单独编译lib.cpp
文件第一,例如能够避免
g++ -O0 --coverage -c lib.cpp
g++ -O0 --coverage -o five lib.o five.cpp
g++ -O0 --coverage -o ten lib.o ten.cpp
现在无论five
和ten
将共享相同的lib.gcno
,他们都将积累lib.gcda
。
所以,如果你是细心,所有的共享代码链接的二进制文件的编译前只有一次,你应该是好去累加从多个二进制文件覆盖效果。
但是,如果我们想要的东西,以不同的编译库?也许我们要编译一个版本的调试代码禁用一个与它启用了验证代码工作在两种情况下。然后前面的解决方案不起作用,而是战略是把文件每个二进制到它自己的目录,然后再合并这些目录。
g++ -O0 --coverage -c lib.cpp -DENABLE_DEBUG
g++ -O0 --coverage -o five lib.o five.cpp
mkdir gcov-five
mv *.gcno gcov-five/.
请注意,我说的gcda路径较早前硬编码?您可以只住在一起,运行每个二进制文件,然后移动*.gcda
文件后记。或者你也可以设置环境变量,以使程序使用不同的目录。 GCOV_PREFIX_STRIP将从全路径的开始砍目录,例如GCOV_PREFIX_STRIP=1
和/tmp/merge-gcov/lib.gcda
成为merge-gcov/lib.gcda
。该GCOV_PREFIX变量将被放在路径的前面。
export GCOV_PREFIX=/tmp/merge-gcov/gcov-five
export GCOV_PREFIX_STRIP=2
# Gives /tmp/merge-gcov/gcov-five/lib.gcda
./five 1
./five 12
# Repeat for ten
g++ -O0 --coverage -c lib.cpp -DDISABLE_DEBUG
g++ -O0 --coverage -o ten lib.o ten.cpp
mkdir gcov-ten
mv *.gcno gcov-ten/.
export GCOV_PREFIX=/tmp/merge-gcov/gcov-ten
./ten 1
./ten 12
# Combine
gcov-tool merge --outdir merged gcov-five gcov-ten