linux-test-project / lcov

LCOV
GNU General Public License v2.0
866 stars 234 forks source link

Build of examples fails if part of path is a softlink #305

Open rael007 opened 2 weeks ago

rael007 commented 2 weeks ago

Running Ubuntu 22.04.4 LTS, bash 5.1.16(1)-release. Just pulled lcov and am trying to build the example. It fails if a part of the path is a softlink. lcov is dropping example files because it thinks they are 'external'.

cd $HOME
ln -s dev doddahdev
cd doddahdev/lcov/example
pwd
/home/me/doddahdev/lcov/example
make
[...]
/home/me/dev/lcov/bin/lcov --branch --capture --directory . --output-file trace_noargs.info --test-name test_noargs --no-external
Capturing coverage data from .
geninfo cmd: '/home/me/dev/lcov/bin/geninfo . --output-filename trace_noargs.info --test-name test_noargs --no-external --branch-coverage'
Found gcov version: 11.4.0
Using intermediate gcov format
Recording 'internal' directories:
    /home/me/dev/lcov/example
Writing temporary data to /tmp/geninfo_datm28U
Scanning . for .gcda files ...
Found 3 data files in .
using: chunkSize: 1, nchunks:3, intervalLength:0
Dropping 'external' file '/home/me/doddahdev/lcov/example/methods/iterate.c'
Dropping 'external' file '/home/me/doddahdev/lcov/example/example.c'
Dropping 'external' file '/home/me/doddahdev/lcov/example/methods/gauss.c'
Finished processing 3 GCDA files
Excluded data for 3 files due to include/exclude options
geninfo: ERROR: (empty) no data generated
    (use "geninfo --ignore-errors empty ..." to bypass this error)
Message summary:
  1 error message:
    empty: 1
make: *** [Makefile:108: test_noargs] Error 1

This works however, if I am in the non-softlinked directory /home/me/dev/lcov/example. From above:

cd $(readlink -f .)
pwd
/home/me/dev/lcov/example
make clean
make
[works just fine]
cesaro commented 3 days ago

I'm also hitting this issue. The problem is that --no-external incorrectly filters out files when they can be accessed via symbolic links.

Here is a simple script that reproduces the problem, in a format that should be easy to adapt for the regression tests, @henry2cox:

#!/bin/bash
set -xe

mkdir -p /tmp/bug
cd /tmp/bug

rm -Rf src src2

mkdir src
ln -s src src2

echo 'int a (int x) { return x + 1; }' > src/a.c
echo 'int b (int x) { return x + 2; }' > src/b.c

gcc -c --coverage src/a.c -o src/a.o
gcc -c --coverage src2/b.c -o src/b.o

lcov -o out -c -i --no-external -d src

You would expect that the call to lcov -c -i records the coverage of both a.c and b.c, but --no-external is incorrectly dropping b.c:

+ lcov -o out -c -i --no-external -d src
Capturing coverage data from src
geninfo cmd: '/path/to/geninfo src --output-filename out --initial --no-external'
Found gcov version: 12.3.0
Using intermediate gcov format
geninfo: WARNING: (usage) branch filter enabled but branch coverage not enabled
        (use "geninfo --ignore-errors usage,usage ..." to suppress this warning)
Recording 'internal' directories:
        /tmp/bug/src
Writing temporary data to /tmp/geninfo_datHcWj
Scanning src for .gcno files ...
Found 2 graph files in src
using: chunkSize: 1, nchunks:2, intervalLength:0
Dropping 'external' file '/tmp/bug/src2/b.c'
Finished processing 2 GCNO files
Excluded data for 1 file due to include/exclude options
Apply filtering..
Finished filter file processing
Finished .info-file creation
Summary coverage rate:
  source files: 1
  lines.......: 0.0% (0 of 1 line)
  functions...: 0.0% (0 of 1 function)
Message summary:
  1 warning message:
    usage: 1

And this is probably happening because /tmp/bug/src/b.gcno refers to the path that uses symbolic links:

$ strings /tmp/bug/src/b.gcno
oncg*32B
/tmp/bug
src2/b.c
src2/b.c
src2/b.c

and because lcov --no-external doesn't canonicalize file path names (see realpath(1)) before comparing them.