使用 gcov 进行交叉分析,但忽略 GCOV_PREFIX 和 GCOV_PREFIX_STRIP
我想使用 GCOV 进行代码覆盖,但测试将在另一台机器上运行。因此可执行文件中 .gcda 文件的硬连线路径将不起作用。
为了更改此默认目录,我可以使用 GCOV_PREFIX 和 GCOV_PREFIX_STRIP 环境变量,正如所说的
这里我使用的命令:
$ export GCOV_PREFIX="/foo/bar"
$ export GCOV_PREFIX_STRIP="3"
$ gcc main.c -fprofile-arcs -ftest-coverage
$ strings a.out | grep gcda
/home/calmarius/blahblah/main.c.gcda
路径保持不变。 有人有这方面的经验吗?
I want to use GCOV to make code coverage but the tests will run on another machine. So the hard wired path to .gcda files in the executable won't work.
In order to change this default directory I can use the GCOV_PREFIX and GCOV_PREFIX_STRIP env vars, as it's said here.
Here my commands I used:
$ export GCOV_PREFIX="/foo/bar"
$ export GCOV_PREFIX_STRIP="3"
$ gcc main.c -fprofile-arcs -ftest-coverage
$ strings a.out | grep gcda
/home/calmarius/blahblah/main.c.gcda
The path remains the same.
Anyone have experience with this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
运行代码时会考虑环境变量。
在运行测试之前,在目标计算机上将它们设置为适当的值,
.gcda
文件将在您想要的位置生成。The environment variables are taken into account when you run the code.
Set them to the appropriate values on the target machine before you run your tests, and the
.gcda
files will be generated where you want them.************ ARRRRGGGGGHHHHH ************
请投票给 Mat 的答案。
我读过的关于如何重新定位输出的每一份文档中显然都缺少这句话!
事实上,请允许我稍微扩展一下这个答案。
GCOV_PREFIX 是一个运行时(与构建时不同)环境变量,它确定写入 gcov 输出文件 (*.gcda) 的根目录。
GCOV_PREFIX_STRIP=X 也是一个运行时变量,具有从目标文件(字符串 XXXX.o)中找到的路径中剥离 X 元素的效果,
这意味着:
当您构建项目时,目标文件将使用完整的内容写入负责嵌入其中的每个目标文件的每个源文件位置的路径。
因此,假设您正在这样的目录结构中编写一个可执行文件 MyApp 和一个库 MyLib:
注意 MyLib 是 MyApp 的子目录
假设 MyApp 有 2 个源文件,MyLib 有 3 个
在使用“-coverage”标志构建之后,您将产生
5 个 .gcno 文件,每个目标文件 1 个。
嵌入 MyApp 的 .o 文件中的绝对路径为 **/MyProject/MyApp/**a_source_file.cpp 同样,嵌入 MyLib 的 .o 文件中的路径为 **/MyProject/MyApp/MyLib/** another_source_file.cpp
现在,假设您像我一样,将这些文件移动到一台完全不同的机器上,其目录结构与它们的构建位置不同。就我而言,目标机器实际上是一个完全不同的架构。我部署到该计算机上的 /some/deploy/path 而不是 /MyProject。
如果您只是运行该应用程序,gcov 数据将尝试将项目中每个对象文件的相应 .gcda 文件写入 /MyProject/MyApp 和 /MyProject/MyApp/MyLib ,因为这是 .o 文件指示的路径,之后all、MyApp 和 MyLib 只是存档在一起的 .o 文件的集合,还有一些其他魔法可以修复函数指针和其他内容。
很可能,这些目录不存在,并且您可能没有以 root 身份运行(是吗?),因此也不会创建这些目录。 Soooo..您不会在部署位置 /my/deploy/path 中看到任何 gcda 文件。
这完全令人困惑,对吧!?!?!?!?!?
这就是 GCOV_PREFIX 和 GCOV_PREFIX_STRIP 发挥作用的地方。
(砰!拳头击中额头)
您需要指示****运行时**** .o 文件中的嵌入路径并不是您真正想要的。您想要“剥离”一些路径,并将其替换为部署目录。
因此,您通过 GCOV_PREFIX=/some/deploy/path 设置部署目录,并且希望从生成的 .gcda 路径中删除 /MyProject,因此您设置 GCOV_PREFIX_STRIP=1
设置这两个环境变量后,运行您的应用程序,然后查看在
/some/deploy/path/MyApp 和 /some/deploy/path/MyApp/MyLib ,你瞧,奇迹般地出现了 5 个 gcda 文件,每个目标文件一个。
注意:如果您进行源代码构建,问题会变得更加复杂。 .o 指向源代码,但 gcda 将相对于构建目录写入。
************ ARRRRGGGGGHHHHH ************
Please, please vote for Mat's answer.
This one sentence is apparently missing from EVERY document I have read regarding how to relocate the output !
In fact , allow me to expand that answer just a bit.
GCOV_PREFIX is a runtime - as apposed to build time - environment variable and determines the root directory where the gcov output files (*.gcda) are written.
GCOV_PREFIX_STRIP=X is also a runtime variable, and has the effect of stripping X elements from the path found in the object files (strings XXXX.o)
What this means is:
When you build your project, the object files are written with the full path to the location of each source file responsible for each object file embedded within them.
So, imagine you are writing an executable MyApp and a library MyLib in a directory stricture like this:
Notice MyLib is a subdirectory of MyApp
Let's say MyApp has 2 source files, and MyLib has 3
After building with the "-coverage" flag, you will have generated
5 .gcno files, 1 for each object file.
Embedded in the .o files for MyApp will be the absolute path **/MyProject/MyApp/**a_source_file.cpp Similarly, embedded in the .o files for MyLib will be the path **/MyProject/MyApp/MyLib/**another_source_file.cpp
Now, let's say you're like me, and move those files onto a completely different machine with a different directory structure from where they got built. In my case the target machine is actually a totally different architecture. I deploy to /some/deploy/path not /MyProject on that machine.
If you simply run the app, gcov data will try to write corresponding .gcda files to /MyProject/MyApp and /MyProject/MyApp/MyLib for each object file in your project, because that's the path indicated by the .o files, and after all, MyApp, and MyLib are simply collections of .o files archived together, with some other magic to fix up funcitons pointers and stuff.
Chances are, those directories don't exist, and you probably aren't running as root (are you?), so those directories won't be created either. Soooo.. you won't see any gcda files within the deploy location /my/deploy/path.
That's totally confusing, right !?!??!?!?!?
Here's where GCOV_PREFIX and GCOV_PREFIX_STRIP come in.
(BAM ! fist hits forehead)
You need to instruct the ****runtime**** that the embedded path in the .o files isn't really what you want. You want to "strip" some of the path off, and replace it with the deploy directory.
So, you set the deploy directory via GCOV_PREFIX=/some/deploy/path and you want to strip the /MyProject from the generated .gcda paths so you set GCOV_PREFIX_STRIP=1
With these two environment variables set, you run your app and then look in
/some/deploy/path/MyApp and /some/deploy/path/MyApp/MyLib and lo and behold, the 5 gcda files miraculously appear, one for each object file.
Note: the problem is compounded if you do out of source builds. The .o points to the source, but the gcda will be written relative to the build directory.