Crossprofiling with gcov, but GCOV_PREFIX and GCOV

2020-06-03 06:22发布

问题:

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?

回答1:

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.



回答2:

************ ARRRRGGGGGHHHHH ************

Please, please vote for Mat's answer.

The environment variables are taken into account when you run the code.

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:

/MyProject 
 |-MyApp 
 |--MyLib

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.



标签: c gcc gcov