-
Notifications
You must be signed in to change notification settings - Fork 265
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Incorrect paths for header files #271
Comments
Thank you for reporting this problem, you're right that gcovr
behaviour seems to be completely bonkers in this case. I'll try to
take a look during the weekend.
It would help immensely if you could add the following:
1. the first few lines of all involved gcov files (they contain the
actual source file name; the gcov file name is not reliable)
2. a short hello-world style example to reproduce the issue so that I
can experiment on this myself. I.e. the necessary file contents,
directory layouts, and compiler flags.
|
This issue has not seen any progress in a while, so I am closing it for now. If the problem persists, please add further details so it can be re-opened. If someone else is experiencing a similar issue, please create a new issue. |
Sorry for the late reply, I went on holiday before I got round to updating this! Apologies for the following information dump... Here is a zipfile containing a complete toy problem: Directory layout is as follows:
Also included is Running:
should print:
Here is the output of
Notice that Finally, here is the output of
|
No problems, I hope you had relaxing holidays :)
When you look at the three foo.hxx.gcov files you'll see they all point to
their source file in the first line. Unfortunately this relative path is a
lie and is not relative to the gcov file. Gcovr uses various heuristics to
find the real source file, here they fail to work correctly.
I'll look into your test case more deeply as soon as I find the time. Thank
you for providing really comprehensive information about your scenario! If
you want to experiment a bit you can try whether the --object-directory
option fixes anything, as it switches to a different set of heuristics (but
I don't quite understand that part of the code).
Peter Hill <notifications@github.com> schrieb am Di., 24. Juli 2018, 11:01:
… Sorry for the late reply, I went on holiday before I got round to updating
this! Apologies for the following information dump...
Here is a zipfile containing a complete toy problem:
gcovr-271.zip <https://github.com/gcovr/gcovr/files/2222769/gcovr-271.zip>
Directory layout is as follows:
├── make.config
├── makefile
├── include
│ ├── makefile
│ ├── sys
│ │ └── foo.hxx
│ └── toy.hxx
├── src
│ ├── makefile
│ ├── sys
│ │ ├── foo.cxx
│ │ └── makefile
│ └── toy.cxx
└── test
├── makefile
└── test.cxx
Also included is compile_commands.json.
Running:
make
make check
should print:
thing is : 4
bar
foo
test
Here is the output of gcovr -r . -k -s:
------------------------------------------------------------------------------
GCC Code Coverage Report
Directory: .
------------------------------------------------------------------------------
File Lines Exec Cover Missing
------------------------------------------------------------------------------
src/foo.hxx 2 0 0% 9-10
src/sys/foo.cxx 9 9 100%
src/toy.cxx 10 10 100%
src/toy.hxx 4 4 100%
test/foo.hxx 2 2 100%
test/test.cxx 6 6 100%
------------------------------------------------------------------------------
TOTAL 33 31 93%
------------------------------------------------------------------------------
lines: 93.9% (31 out of 33)
branches: 52.6% (20 out of 38)
Notice that foo.hxx is included twice, once with 0% coverage. Neither
header file (foo.hxx, toy.hxx) is under include/. The makefile has a
code-coverage-capture target that uses lcov, which reports everything
correctly, so I don't think it's something fundamentally wrong with our
setup. Unfortunately, lcov automatically cleans up the gcov files it
generates, with no option to keep them, so it's not possible to directly
compare them. I have a suspicion it's something to do with our
recursive-make build system and needing to run gcov in the correct
locations, but I'm not certain.
Finally, here is the output of find . -type f -name "*.gcov" | xargs head
(after getting rid of the files from system headers):
==> ./src/sys/foo.cxx.gcov <==
-: 0:Source:foo.cxx
-: 0:Graph:/home/user/gcovr-271/src/sys/foo.gcno
-: 0:Data:/home/user/gcovr-271/src/sys/foo.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include "sys/foo.hxx"
-: 2:
function _ZN3Foo4pushENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE called 3 returned 100% blocks executed 100%
3: 3:void Foo::push(std::string str) {
3: 4: stack.push_back(std::move(str));
==> ./src/toy.cxx.gcov <==
-: 0:Source:toy.cxx
-: 0:Graph:/home/user/gcovr-271/src/toy.gcno
-: 0:Data:/home/user/gcovr-271/src/toy.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include "toy.hxx"
-: 2:#include "sys/foo.hxx"
-: 3:
-: 4:#include <iostream>
-: 5:
==> ./src/^#include#sys#foo.hxx.gcov <==
-: 0:Source:../include/sys/foo.hxx
-: 0:Graph:/home/user/gcovr-271/src/toy.gcno
-: 0:Data:/home/user/gcovr-271/src/toy.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#ifndef __FOO_H__
-: 2:#define __FOO_H__
-: 3:
-: 4:#include <string>
-: 5:#include <vector>
==> ./src/^#include#toy.hxx.gcov <==
-: 0:Source:../include/toy.hxx
-: 0:Graph:/home/user/gcovr-271/src/toy.gcno
-: 0:Data:/home/user/gcovr-271/src/toy.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#ifndef __TOY_H__
-: 2:#define __TOY_H__
-: 3:
-: 4:#include <iostream>
-: 5:
==> ./test/test.cxx.gcov <==
-: 0:Source:test.cxx
-: 0:Graph:/home/user/gcovr-271/test/test.gcno
-: 0:Data:/home/user/gcovr-271/test/test.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include "toy.hxx"
-: 2:#include "sys/foo.hxx"
-: 3:
function main called 1 returned 100% blocks executed 67%
1: 4:int main() {
==> ./test/^#include#sys#foo.hxx.gcov <==
-: 0:Source:../include/sys/foo.hxx
-: 0:Graph:/home/user/gcovr-271/test/test.gcno
-: 0:Data:/home/user/gcovr-271/test/test.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#ifndef __FOO_H__
-: 2:#define __FOO_H__
-: 3:
-: 4:#include <string>
-: 5:#include <vector>
==> ./test.cxx.gcov <==
-: 0:Source:test.cxx
-: 0:Graph:/home/user/gcovr-271/test/test.gcno
-: 0:Data:/home/user/gcovr-271/test/test.gcda
-: 0:Runs:1
-: 0:Programs:1
==> ./^#include#sys#foo.hxx.gcov <==
-: 0:Source:../include/sys/foo.hxx
-: 0:Graph:/home/user/gcovr-271/src/toy.gcno
-: 0:Data:/home/user/gcovr-271/src/toy.gcda
-: 0:Runs:1
-: 0:Programs:1
==> ./toy.cxx.gcov <==
-: 0:Source:toy.cxx
-: 0:Graph:/home/user/gcovr-271/src/toy.gcno
-: 0:Data:/home/user/gcovr-271/src/toy.gcda
-: 0:Runs:1
-: 0:Programs:1
==> ./^#include#toy.hxx.gcov <==
-: 0:Source:../include/toy.hxx
-: 0:Graph:/home/user/gcovr-271/src/toy.gcno
-: 0:Data:/home/user/gcovr-271/src/toy.gcda
-: 0:Runs:1
-: 0:Programs:1
==> ./foo.cxx.gcov <==
-: 0:Source:foo.cxx
-: 0:Graph:/home/user/gcovr-271/src/sys/foo.gcno
-: 0:Data:/home/user/gcovr-271/src/sys/foo.gcda
-: 0:Runs:1
-: 0:Programs:1
—
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
<#271 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ABs0jyaUKgs8Y3hOL5q_mgSYZiKOYLCHks5uJuJmgaJpZM4VMxEU>
.
|
It may cause by
now fname is
which should be
without realpath @@ -196,8 +198,13 @@ def guess_source_file_name_heuristics(
if os.path.exists(fname):
return fname
- # 3. Try using the path to the gcda file as the source directory
+ # 3. Try using the path relative to source directory
source_fname_dir = os.path.dirname(source_fname)
+ fname = os.path.join(source_fname_dir, gcovname)
+ if os.path.exists(fname):
+ return os.path.realpath(fname)
+
+ # 4. Try using the path to the gcda file as the source directory
fname = os.path.join(source_fname_dir, os.path.basename(gcovname))
return fname
|
Thank you @lisongmin, you are absolutely right that we should use I am not quite sure whether it is correct to resolve the source code path relative to the gcda file (confusingly called During the last few weeks I've been spending some time on gcovr's path heuristics. There's a lot of weird code around there and I hope to clean some of it up soon. Gcovr tends to make some assumptions about the build process that are not always a good fit in the real world, e.g. either GCC is invoked somewhere in the build directory or from the --root. This recursive-Makefile approach combined with a separate build directory would probably break the heuristics (haven't tested it yet). I am super thankful for this issue because it exposes some of these bad assumptions! |
Be aware symlink may changed via realpath(). This may affect to filter in some case. |
Hi, is there anything that I can help with? I also experience those things. Shall I post outputs similar to the above? |
Also experiencing the same error
Any other info I can give? Edit: Everything works fine when using standard gcov, but I get the error above when using Edit 2: At least in my instance, this exception only seems to appear when I am including a file via a compiler include path, not relative to the file being covered. ie // Include relative path
#include "../../mylib/include/my-header.h" // <-- Works
// Include using predefined compiler include path
#include "my-header.h" // <-- Exception Edit 3: Yeah interestingly the xml report works fine, it's just the html generator that throws an error. The xml report does report the same file multiple times, each with a different path, so this does seem to be a path issue. Interestingly I only get this issue when using clang/llvm-cov. Everything works fine when building with gcc and gcov. |
I now have a bit of time to look at issues again since I completed an important project today. The core problem is that I don't understand what gcov's relative I'll try looking at the gcov source code and at how lcov handles this, sometime over the next few weeks. If someone is quicker than me and can post an explanation here (with sources/references), that would also be most welcome. I'll also try turning @ZedThree's excellent example into an xfail test case. Since the HTML details report has to open the source files in order to display the details, it is the only report that will die due to this issue. |
Thank you for looking into this @latk! Judging from the fact I can hardly find any online resources using gcovr with llvm, I must assume it's not a well used feature. I'm not surprised something got broken by mistake. |
+1 Seeing the issue still with GCC 8.2 |
Same issue with gcc 7.4.0 (gcov alone works)
|
I'm seeing this issue currently with gcc 10.2.0. Recommend changing issue title to "Incorrect paths for Include Path files" since this does not apply to all headers, nor is it restricted to only headers (I'm writing some odd unit tests which are including a Edit First, some background on my environment. This is (the interesting part of) my directory structure: /workspaces/ci-baseline$ tree
.
|-- CMakeLists.txt
|-- build
| |-- CMakeFiles
| | |-- ci-baseline.sample1.test.dir
| | | `-- sample1
| | | `-- test
| | | |-- sample1_unittest.cpp.gcda
| | | |-- sample1_unittest.cpp.gcno
| | | `-- sample1_unittest.cpp.o
| |-- bin
| | `-- ci-baseline.sample1.test
`-- sample1
|-- include
| `-- sample1.h
|-- src
| `-- sample1.cpp
`-- test
`-- sample1_unittest.cpp A note of something unusual I'm doing: my # sample1_unittest.cpp excerpt
// NOTE: Since our test unit contains an `int main` method, we can only test it by putting that into a namesapce.
// In order to do that, we have to include the source file directly, rather than any related header.
// This also ensures that the source is compiled with appropriate debugging symbols, optimizatopms, and gcov support.
namespace sample1 {
#include "sample1.cpp"
} The compile command (generated from CMake, with comments added for clarity) is: # PWD = /workspaces/ci-baseline/build
/bin/g++-10 \
-I../sample1/test `# Location of this target's .cpp files` \
-I../sample1/test/include `# Location of this target's .h files` \
-I../sample1/src `# Location of the unit-under-test's .cpp files` \
-I../sample1/include `# Location of the unit-under-test's .h files` \
-isystem /home/conan/.conan/data/gtest/1.10.0/_/_/package/6f74be7aa0880ac3a032c53631ce97b6e7ac1ed3/include `# Location of system header files` \
-fPIE `# position independent executable` \
-Wall `# enables all the warnings about constructions that some users consider questionable, and that are easy to avoid` \
-Wextra `# enables some extra warning flags that are not enabled by -Wall` \
-g `# Produce debugging information` \
-O0 `# Optimization: Reduce compilation time and make debugging produce the expected results.` \
--coverage `# compile and link code instrumented for coverage analysis.` \
-std=gnu++17 `# Determine the language standard` \
-MD `# generate a rule suitable for make describing the dependencies of the main source file (stored at -MF)` \
-MT CMakeFiles/ci-baseline.sample1.test.dir/sample1/test/sample1_unittest.cpp.o `# change the target name` \
-MF CMakeFiles/ci-baseline.sample1.test.dir/sample1/test/sample1_unittest.cpp.o.d `# set the target dependency file name`\
-o CMakeFiles/ci-baseline.sample1.test.dir/sample1/test/sample1_unittest.cpp.o `# set the output file` \
-c `# Compile or assemble the source files, but do not link` \
`#input file` ../sample1/test/sample1_unittest.cpp
# Link command is next, but isn't interesting. The simplest demonstration of the problem for me is: # PWD=/workspaces/ci-baseline
$ gcovr
------------------------------------------------------------------------------
GCC Code Coverage Report
Directory: .
------------------------------------------------------------------------------
File Lines Exec Cover Missing
------------------------------------------------------------------------------
build/CMakeFiles/ci-baseline.sample1.test.dir/sample1/test/sample1.cpp
15 0 0% 35-38,41,45,47,50,55,57,61,65,69-71
build/CMakeFiles/ci-baseline.sample1.test.dir/sample1/test/sample1_unittest.cpp
39 3 7% 83,86-88,107-108,112-116,123,126-128,132-136,140-145,150-151,153-154,156-157,159-160,165,169
------------------------------------------------------------------------------
TOTAL 54 3 5%
------------------------------------------------------------------------------ There is no error thrown here, but you can see that gcovr has detected invalid file names which do not exist in the filesystem. This is an indication that the The simplest solution is to set gcovr's root (either by the working directory where you execute the command, or the For example: # PWD=doesn't matter since we're using the `--root` parameter.
$ gcovr \
--root "/workspaces/ci-baseline/build" `# The directory where gcc was invoked` \
--filter "/workspaces/ci-baseline" `# The directory which contains our source code since it is not a child of root`;
------------------------------------------------------------------------------
GCC Code Coverage Report
Directory: /workspaces/ci-baseline/build
------------------------------------------------------------------------------
File Lines Exec Cover Missing
------------------------------------------------------------------------------
/workspaces/ci-baseline/sample1/src/sample1.cpp
15 0 0% 35-38,41,45,47,50,55,57,61,65,69-71
/workspaces/ci-baseline/sample1/test/sample1_unittest.cpp
39 3 7% 83,86-88,107-108,112-116,123,126-128,132-136,140-145,150-151,153-154,156-157,159-160,165,169
------------------------------------------------------------------------------
TOTAL 54 3 5%
------------------------------------------------------------------------------ Here you can see the filenames are correct. With those values for |
fix issue gcovr#271, make gcovr to search for the files in all directory.
Did #358 resolve this issue? |
Can you check this with the branch of #597? |
As mentioned in gcovr#271 (comment) is the name source_fname confusing.
* Add test data for gcc-10 * Add test data for gcc-11 * Scan subdirectory because of timeout in test. * Add the directory of the gcov file to the heuristic to fix test shared_lib for gcc-11. gcc-11 creates in the gcda files in a sub directory which results in an error later. The file is used as testApp/test/tmp.cpp but correct is testApp/tmp.cpp. (DEBUG) Running gcov: '/usr/bin/gcov-11 /gcovr/gcovr/tests/shared_lib/testApp/test/a-tmp.gcda --branch-counts --branch-probabilities --demangled-names --hash-filenames --object-directory /gcovr/gcovr/tests/shared_lib/testApp/test' in '/gcovr/gcovr/tests/shared_lib/testApp' (DEBUG) Finding source file corresponding to a gcov data file currdir /gcovr/gcovr/tests/shared_lib gcov_fname /gcovr/gcovr/tests/shared_lib/testApp/tmp.cpp##95fbba3ae32e8157841b28787cf829e3.gcov source_fname /gcovr/gcovr/tests/shared_lib/testApp/test/a-tmp.gcda root /gcovr/gcovr/tests/shared_lib fname /gcovr/gcovr/tests/shared_lib/testApp/test/tmp.cpp (DEBUG) Parsing coverage data for file /gcovr/gcovr/tests/shared_lib/testApp/test/tmp.cpp * Rename source_fname to gcda_fname As mentioned in #271 (comment) is the name source_fname confusing.
Closing because of missing response. If the problem persists, please reopen. |
Header files don't seem to be dealt with correctly:
While
--html-details
throws an error, just runninggcovr
counts each header separately for each directory containing a source file that includes it, so I get stuff like:If I keep the gcov files, I can see they have the correct names, i.e.:
This is with gcovr version 4.1 and gcc 8.1
The text was updated successfully, but these errors were encountered: