gpt4 book ai didi

c++ - 如何合并多个版本的gcda文件?

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:53:00 33 4
gpt4 key购买 nike

我正在使用 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.gcnofive.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

多重冲突

到目前为止一切顺利。但是,如果我们现在也以同样的方式编译 10 程序

g++ -O0 --coverage -o ten ten.cpp lib.cpp

然后它将创建一个 lib.gcno,它比 five 编译时使用的 lib.gcno 更新且不同。这意味着每当 fiveten 在另一个之后运行时,它会检测到 lib.gcda 文件不符合其预期(的gcno origin) 并重置文件内容,从而丢弃任何累积的先前内容。

这可以通过先单独编译 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

现在 fiveten 将共享相同的 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

关于c++ - 如何合并多个版本的gcda文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25059435/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com