mozilla / grcov

Rust tool to collect and aggregate code coverage data for multiple source files
Mozilla Public License 2.0
1.15k stars 148 forks source link

Cannot generate report from Meson's out-of-tree build with GCC's coverage instrumentation #1182

Open detly opened 1 month ago

detly commented 1 month ago

I've been trying to use grcov on a C project that uses Meson as a build system and GCC to compile. Meson does out-of-tree builds where binary artifacts are put in a separate build directory eg. build, possibly within the source tree. GCC seems to generate gcno files with a leading ../. I cannot figure out how to tell grcov how to handle this.

Here is an example project, with an example CI job. Note the warnings:

$ ./grcov . --binary-path build --source-dir . --output-path "$GRCOV_REPORT_DIR" --output-types html --ignore-not-existing
Warning: "../one/src/one.c" cannot be normalized because of "..", so skip it.
Warning: "../test_main.c" cannot be normalized because of "..", so skip it.
Warning: "../one/test/test_one.c" cannot be normalized because of "..", so skip it.

I have tried many combinations of the main path argument, --binary-path, --source-dir, --prefix-dir, changing the current directory to build, using absolute paths wherever possible, etc. At best, I can get coverage for the test_main.c file, but never for one/src/one.c.

The example HTML output looks like this:

Screenshot from 2024-06-06 12-42-27

Frustratingly, the cobertura output sometimes contains perfectly valid paths. They are just not present in the HTML output.

It is possible to generate a proper coverage HTML report with gcovr using the following command:

gcovr --root=. --html --output="$COVERAGE_HTML_DIR" .

...so it is possible to use the coverage information generated by Meson and GCC there:

Screenshot from 2024-06-06 12-46-28

Version information:

$ lsb_release -a
Distributor ID: Debian
Description:    Debian GNU/Linux 12 (bookworm)
Release:    12
Codename:   bookworm
$ ./grcov --version
grcov 0.8.19
$ meson --version
1.4.1

[...]

C compiler for the host machine: cc (gcc 12.2.0 "cc (Debian 12.2.0-14) 12.2.0")
C linker for the host machine: cc ld.bfd 2.40
Host machine cpu family: x86_64
Host machine cpu: x86_64
detly commented 1 month ago

The closest I can get, by the way, is with

grcov . --binary-path build --source-dir . --output-path cov --output-types html --ignore-not-existing --prefix-dir '../'

Then my coverage report looks like:

Screenshot from 2024-06-06 12-54-35

Still no one.c though.

lu-zero commented 1 month ago

If --source-dir is set to build does it resolve correctly?

detly commented 1 month ago

If --source-dir is set to build does it resolve correctly?

Nope, it's completely empty, like in the first screenshot.

detly commented 1 month ago

I am starting to think it's an issue with the HTML renderer and not the input handling. Here's Cobertura output from the following command:

grcov . --binary-path build --source-dir . --output-path cov.xml --output-types cobertura --ignore-not-existing --prefix-dir '../'
```xml /home/jason/Code/meson-grcov ```

All of the appropriate paths are present, and can be joined up to perfectly match the source tree. Why aren't they in the HTML output though?

detly commented 1 month ago

I thought I'd try to work around this by using gcovr to generate lcov data, and consume that with grcov:

$ gcovr --root=. --lcov cov.info --lcov-test-name gcovr
(INFO) Reading coverage data...
(INFO) Writing coverage report...
$ lcov -l cov.info
                           |Lines       |Functions  |Branches    
Filename                   |Rate     Num|Rate    Num|Rate     Num
=================================================================
[/home/jason/Code/meson-grcov/]
one/src/one.c              |50.0%      2| 0.0%     1|    -      0
one/test/test_one.c        |22.2%      9| 0.0%     2|    -      0
test_main.c                |33.3%      3| 0.0%     1|    -      0
=================================================================
                     Total:|28.6%     14| 0.0%     4|    -      0
$ grcov cov.info --binary-path build --source-dir . --output-path cov --output-types html --ignore-not-existing

I still have the missing paths, but now I also have extremely suspicious line hit counts:

Screenshot from 2024-06-06 15-13-19