BullseyeCoverage Up Contents Search

GCC and Clang

Cross Compiling

BullseyeCoverage recognizes many cross-compiled architectures and automatically selects an appropriate run-time source file to compile and link into your executable. For example, if the compiler option -dumpmachine output contains "linux", BullseyeCoverage compiles and links BullseyeCoverage/run/libcov-posix.c.

You have the option to manually build the run-time library with a special name so that it is linked automatically. This overrides the default behavior described above. The special library name format is:

BullseyeCoverage/lib/libcov-arch.a

The filename component arch is the string printed by the compiler option -dumpmachine. For example, if gcc -dumpmachine outputs aarch64-linux-gnu, then the special library name is BullseyeCoverage/lib/libcov-aarch64-linux-gnu.a.

Example 1

$ gcc -dumpmachine
aarch64-none-elf
$ cd BullseyeCoverage/run
$ gcc -c libcov-printf.c
$ ar -r libcov-aarch64-none-elf.a libcov-printf.o

Example 2

$ gcc -dumpmachine
nios2-elf
$ cd BullseyeCoverage/run
$ gcc -c libcov-userDefined.c
$ ar -r libcov-nios2-elf.a libcov-userDefined.o

If you build your cross-compiled run-time library from run/libcov-posix.c, set the COVFILE environment variable on the target device to the path of your coverage file located on your host system. You must have read and write access to the coverage file. For example:

$ export COVFILE=/host/project/test.cov
$ ./a.out

Precompiled Headers

Precompiled headers are not utilized with BullseyeCoverage because the compiler does not use precompiled headers when invoked for preprocessing (with -E).

Assess the Cost-Benefit

Because of potential complications of using precompiled headers, you may wish to first determine whether precompiled headers provide a significant reduction to your build time (when not using BullseyeCoverage). When BullseyeCoverage is enabled, precompiled headers can provide no benefit.

Recommended Organization

Ideally, when the compiler uses a header.h.gch file, the effect is identical to including the corresponding header.h, merely faster. To achieve this goal, follow the recommendations below.

  1. The .gch filename must match the header filename used to create it. That is, header.h.gch is created from header.h.

    Create .gch precompiled headers only from .h headers and never from .c or .cpp files. For example,

    g++ -x c++-header pch.c -o pch.h.gch    ← Wrong. Name mismatch
    g++ pch.h                               ← Correct. This creates pch.h.gch
    
  2. The source header should be located in the same directory as the .gch. If you use compiler option -o to locate the .gch in your output directory, then you should also link the source file to that location. For example,
    g++ pch.h -o x64/debug/pch.h.gch
    ln -s pch.h x64/debug/pch.hAdd this
    
  3. When creating a .gch file, do not use compiler option -include. Use the #include directive to include all headers during this build step. For example,
    g++ -include extra.h ... pch.h          ← Wrong
    

To verify your build process properly adheres to these recommendations:

  1. Disable BullseyeCoverage
  2. Disable creation of .gch files. To do this, remove compiler commands that:
  3. Perform a clean build. Add -I options to resolve errors due to headers not found until your build is successful.

Automatic Workaround

When BullseyeCoverage encounters a compile command that creates a .gch file in an output directory where the input header file does not exist, a symbolic link to the header is automatically created in the output directory.

g++ pch.h -o x64/debug/pch.h.gch
ln -s pch.h x64/debug/pch.hBullseyeCoverage performs this automatically

Updated: 5 Sep 2024