summaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-support/lcov
diff options
context:
space:
mode:
authorAlex Yao <alexyao1@meraki.com>2023-04-25 14:12:06 -0700
committerKhem Raj <raj.khem@gmail.com>2023-04-25 22:56:01 -0700
commit38f13205ea4701b65468b731c4c0934a45f9917a (patch)
treefb1e980faccf6abff0d6c8a6ca6b3642d5dc4817 /meta-oe/recipes-support/lcov
parente66ae31c9522a6acf42720edb7623a93407a983a (diff)
downloadmeta-openembedded-38f13205ea4701b65468b731c4c0934a45f9917a.tar.gz
lcov: Upgrade 1.14 -> 1.16
This upgrades lcov to 1.16 and removes backported patches which are now included since 1.15. This also removes dependencies added from backported patches since the new version removes the need for these dependencies. Signed-off-by: Alex Yao <alexyao1@meraki.com> Signed-off-by: Khem Raj <raj.khem@gmail.com>
Diffstat (limited to 'meta-oe/recipes-support/lcov')
-rw-r--r--meta-oe/recipes-support/lcov/files/0001-geninfo-Add-intermediate-text-format-support.patch898
-rw-r--r--meta-oe/recipes-support/lcov/files/0002-geninfo-Add-intermediate-JSON-format-support.patch247
-rwxr-xr-xmeta-oe/recipes-support/lcov/lcov_1.16.bb (renamed from meta-oe/recipes-support/lcov/lcov_1.14.bb)14
3 files changed, 3 insertions, 1156 deletions
diff --git a/meta-oe/recipes-support/lcov/files/0001-geninfo-Add-intermediate-text-format-support.patch b/meta-oe/recipes-support/lcov/files/0001-geninfo-Add-intermediate-text-format-support.patch
deleted file mode 100644
index 9ac0770f9..000000000
--- a/meta-oe/recipes-support/lcov/files/0001-geninfo-Add-intermediate-text-format-support.patch
+++ /dev/null
@@ -1,898 +0,0 @@
1From ec3e1f411c332cbc2f2bc7ab7e2175ebf918b37a Mon Sep 17 00:00:00 2001
2From: Peter Oberparleiter <oberpar@linux.ibm.com>
3Date: Fri, 24 May 2019 16:56:52 +0200
4Subject: [PATCH 1/2] geninfo: Add intermediate text format support
5
6This change adds support for parsing the output of gcov's intermediate
7text file format as implemented by GCC versions 5 to 8. The use of the
8gcov intermediate format should increase processing speed. It also
9provides branch coverage data when using the --initial command line
10option.
11
12Users can control whether geninfo uses the intermediate format via the
13geninfo_intermediate configuration file option. Valid values are:
14
15 0: Use normal text format
16 1: Use intermediate format
17 auto: Use intermediate format if available. This is the default.
18
19Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
20---
21 bin/geninfo | 567 ++++++++++++++++++++++++++++++++++++++++++++-------
22 lcovrc | 3 +
23 man/lcovrc.5 | 24 +++
24 3 files changed, 521 insertions(+), 73 deletions(-)
25
26Upstream-Status: Backport
27Download URL: https://github.com/linux-test-project/lcov/commit/ebfeb3e179e450c69c3532f98cd5ea1fbf6ccba7
28
29diff --git a/bin/geninfo b/bin/geninfo
30index f41eaec..0276666 100755
31--- a/bin/geninfo
32+++ b/bin/geninfo
33@@ -54,6 +54,8 @@ use warnings;
34 use File::Basename;
35 use File::Spec::Functions qw /abs2rel catdir file_name_is_absolute splitdir
36 splitpath catpath/;
37+use File::Temp qw(tempfile tempdir);
38+use File::Copy qw(copy);
39 use Getopt::Long;
40 use Digest::MD5 qw(md5_base64);
41 use Cwd qw/abs_path/;
42@@ -163,13 +165,13 @@ sub solve_relative_path($$);
43 sub read_gcov_header($);
44 sub read_gcov_file($);
45 sub info(@);
46+sub process_intermediate($$$);
47 sub map_llvm_version($);
48 sub version_to_str($);
49 sub get_gcov_version();
50 sub system_no_output($@);
51 sub read_config($);
52 sub apply_config($);
53-sub get_exclusion_data($);
54 sub apply_exclusion_data($$);
55 sub process_graphfile($$);
56 sub filter_fn_name($);
57@@ -264,6 +266,8 @@ our $gcno_split_crc;
58 our $func_coverage = 1;
59 our $br_coverage = 0;
60 our $rc_auto_base = 1;
61+our $rc_intermediate = "auto";
62+our $intermediate;
63 our $excl_line = "LCOV_EXCL_LINE";
64 our $excl_br_line = "LCOV_EXCL_BR_LINE";
65
66@@ -331,6 +335,7 @@ if ($config || %opt_rc)
67 "geninfo_compat" => \$opt_compat,
68 "geninfo_adjust_src_path" => \$rc_adjust_src_path,
69 "geninfo_auto_base" => \$rc_auto_base,
70+ "geninfo_intermediate" => \$rc_intermediate,
71 "lcov_function_coverage" => \$func_coverage,
72 "lcov_branch_coverage" => \$br_coverage,
73 "lcov_excl_line" => \$excl_line,
74@@ -460,15 +465,38 @@ if (system_no_output(3, $gcov_tool, "--help") == -1)
75 }
76
77 ($gcov_version, $gcov_version_string) = get_gcov_version();
78+$gcov_caps = get_gcov_capabilities();
79+
80+# Determine intermediate mode
81+if ($rc_intermediate eq "0") {
82+ $intermediate = 0;
83+} elsif ($rc_intermediate eq "1") {
84+ $intermediate = 1;
85+} elsif (lc($rc_intermediate) eq "auto") {
86+ # Use intermediate format if supported by gcov
87+ $intermediate = $gcov_caps->{'intermediate-format'} ? 1 : 0;
88+} else {
89+ die("ERROR: invalid value for geninfo_intermediate: ".
90+ "'$rc_intermediate'\n");
91+}
92+
93+if ($intermediate) {
94+ info("Using intermediate gcov format\n");
95+ if ($opt_derive_func_data) {
96+ warn("WARNING: --derive-func-data is not compatible with ".
97+ "intermediate format - ignoring\n");
98+ $opt_derive_func_data = 0;
99+ }
100+}
101
102 # Determine gcov options
103-$gcov_caps = get_gcov_capabilities();
104 push(@gcov_options, "-b") if ($gcov_caps->{'branch-probabilities'} &&
105 ($br_coverage || $func_coverage));
106 push(@gcov_options, "-c") if ($gcov_caps->{'branch-counts'} &&
107 $br_coverage);
108 push(@gcov_options, "-a") if ($gcov_caps->{'all-blocks'} &&
109- $opt_gcov_all_blocks && $br_coverage);
110+ $opt_gcov_all_blocks && $br_coverage &&
111+ !$intermediate);
112 if ($gcov_caps->{'hash-filenames'})
113 {
114 push(@gcov_options, "-x");
115@@ -599,7 +627,7 @@ foreach my $entry (@data_directory) {
116 gen_info($entry);
117 }
118
119-if ($initial && $br_coverage) {
120+if ($initial && $br_coverage && !$intermediate) {
121 warn("Note: --initial does not generate branch coverage ".
122 "data\n");
123 }
124@@ -768,6 +796,7 @@ sub gen_info($)
125 my $prefix;
126 my $type;
127 my $ext;
128+ my $tempdir;
129
130 if ($initial) {
131 $type = "graph";
132@@ -798,16 +827,22 @@ sub gen_info($)
133 $prefix = "";
134 }
135
136+ $tempdir = tempdir(CLEANUP => 1);
137+
138 # Process all files in list
139 foreach $file (@file_list) {
140 # Process file
141- if ($initial) {
142+ if ($intermediate) {
143+ process_intermediate($file, $prefix, $tempdir);
144+ } elsif ($initial) {
145 process_graphfile($file, $prefix);
146 } else {
147 process_dafile($file, $prefix);
148 }
149 }
150
151+ unlink($tempdir);
152+
153 # Report whether files were excluded.
154 if (%excluded_files) {
155 info("Excluded data for %d files due to include/exclude options\n",
156@@ -1058,10 +1093,12 @@ sub process_dafile($$)
157
158 # Try to find base directory automatically if requested by user
159 if ($rc_auto_base) {
160- $base_dir = find_base_from_graph($base_dir, $instr, $graph);
161+ $base_dir = find_base_from_source($base_dir,
162+ [ keys(%{$instr}), keys(%{$graph}) ]);
163 }
164
165- ($instr, $graph) = adjust_graph_filenames($base_dir, $instr, $graph);
166+ adjust_source_filenames($instr, $base_dir);
167+ adjust_source_filenames($graph, $base_dir);
168
169 # Set $object_dir to real location of object files. This may differ
170 # from $da_dir if the graph file is just a link to the "real" object
171@@ -2017,6 +2054,299 @@ sub read_gcov_file($)
172 }
173
174
175+#
176+# read_intermediate_text(gcov_filename, data)
177+#
178+# Read gcov intermediate text format in GCOV_FILENAME and add the resulting
179+# data to DATA in the following format:
180+#
181+# data: source_filename -> file_data
182+# file_data: concatenated lines of intermediate text data
183+#
184+
185+sub read_intermediate_text($$)
186+{
187+ my ($gcov_filename, $data) = @_;
188+ my $fd;
189+ my $filename;
190+
191+ open($fd, "<", $gcov_filename) or
192+ die("ERROR: Could not read $gcov_filename: $!\n");
193+ while (my $line = <$fd>) {
194+ if ($line =~ /^file:(.*)$/) {
195+ $filename = $1;
196+ chomp($filename);
197+ } elsif (defined($filename)) {
198+ $data->{$filename} .= $line;
199+ }
200+ }
201+ close($fd);
202+}
203+
204+
205+#
206+# intermediate_text_to_info(fd, data, srcdata)
207+#
208+# Write DATA in info format to file descriptor FD.
209+#
210+# data: filename -> file_data:
211+# file_data: concatenated lines of intermediate text data
212+#
213+# srcdata: filename -> [ excl, brexcl, checksums ]
214+# excl: lineno -> 1 for all lines for which to exclude all data
215+# brexcl: lineno -> 1 for all lines for which to exclude branch data
216+# checksums: lineno -> source code checksum
217+#
218+# Note: To simplify processing, gcov data is not combined here, that is counts
219+# that appear multiple times for the same lines/branches are not added.
220+# This is done by lcov/genhtml when reading the data files.
221+#
222+
223+sub intermediate_text_to_info($$$)
224+{
225+ my ($fd, $data, $srcdata) = @_;
226+ my $branch_num = 0;
227+ my $c;
228+
229+ return if (!%{$data});
230+
231+ print($fd "TN:$test_name\n");
232+ for my $filename (keys(%{$data})) {
233+ my ($excl, $brexcl, $checksums);
234+
235+ if (defined($srcdata->{$filename})) {
236+ ($excl, $brexcl, $checksums) = @{$srcdata->{$filename}};
237+ }
238+
239+ print($fd "SF:$filename\n");
240+ for my $line (split(/\n/, $data->{$filename})) {
241+ if ($line =~ /^lcount:(\d+),(\d+),?/) {
242+ # lcount:<line>,<count>
243+ # lcount:<line>,<count>,<has_unexecuted_blocks>
244+ if ($checksum && exists($checksums->{$1})) {
245+ $c = ",".$checksums->{$1};
246+ } else {
247+ $c = "";
248+ }
249+ print($fd "DA:$1,$2$c\n") if (!$excl->{$1});
250+
251+ # Intermediate text format does not provide
252+ # branch numbers, and the same branch may appear
253+ # multiple times on the same line (e.g. in
254+ # template instances). Synthesize a branch
255+ # number based on the assumptions:
256+ # a) the order of branches is fixed across
257+ # instances
258+ # b) an instance starts with an lcount line
259+ $branch_num = 0;
260+ } elsif ($line =~ /^function:(\d+),(\d+),([^,]+)$/) {
261+ next if (!$func_coverage || $excl->{$1});
262+
263+ # function:<line>,<count>,<name>
264+ print($fd "FN:$1,$3\n");
265+ print($fd "FNDA:$2,$3\n");
266+ } elsif ($line =~ /^function:(\d+),\d+,(\d+),([^,]+)$/) {
267+ next if (!$func_coverage || $excl->{$1});
268+
269+ # function:<start_line>,<end_line>,<count>,
270+ # <name>
271+ print($fd "FN:$1,$3\n");
272+ print($fd "FNDA:$2,$3\n");
273+ } elsif ($line =~ /^branch:(\d+),(taken|nottaken|notexec)/) {
274+ next if (!$br_coverage || $excl->{$1} ||
275+ $brexcl->{$1});
276+
277+ # branch:<line>,taken|nottaken|notexec
278+ if ($2 eq "taken") {
279+ $c = 1;
280+ } elsif ($2 eq "nottaken") {
281+ $c = 0;
282+ } else {
283+ $c = "-";
284+ }
285+ print($fd "BRDA:$1,0,$branch_num,$c\n");
286+ $branch_num++;
287+ }
288+ }
289+ print($fd "end_of_record\n");
290+ }
291+}
292+
293+
294+sub get_output_fd($$)
295+{
296+ my ($outfile, $file) = @_;
297+ my $fd;
298+
299+ if (!defined($outfile)) {
300+ open($fd, ">", "$file.info") or
301+ die("ERROR: Cannot create file $file.info: $!\n");
302+ } elsif ($outfile eq "-") {
303+ open($fd, ">&STDOUT") or
304+ die("ERROR: Cannot duplicate stdout: $!\n");
305+ } else {
306+ open($fd, ">>", $outfile) or
307+ die("ERROR: Cannot write to file $outfile: $!\n");
308+ }
309+
310+ return $fd;
311+}
312+
313+
314+#
315+# print_gcov_warnings(stderr_file, is_graph, map)
316+#
317+# Print GCOV warnings in file STDERR_FILE to STDERR. If IS_GRAPH is non-zero,
318+# suppress warnings about missing as these are expected. Replace keys found
319+# in MAP with their values.
320+#
321+
322+sub print_gcov_warnings($$$)
323+{
324+ my ($stderr_file, $is_graph, $map) = @_;
325+ my $fd;
326+
327+ if (!open($fd, "<", $stderr_file)) {
328+ warn("WARNING: Could not open GCOV stderr file ".
329+ "$stderr_file: $!\n");
330+ return;
331+ }
332+ while (my $line = <$fd>) {
333+ next if ($is_graph && $line =~ /cannot open data file/);
334+
335+ for my $key (keys(%{$map})) {
336+ $line =~ s/\Q$key\E/$map->{$key}/g;
337+ }
338+
339+ print(STDERR $line);
340+ }
341+ close($fd);
342+}
343+
344+
345+#
346+# process_intermediate(file, dir, tempdir)
347+#
348+# Create output for a single file (either a data file or a graph file) using
349+# gcov's intermediate option.
350+#
351+
352+sub process_intermediate($$$)
353+{
354+ my ($file, $dir, $tempdir) = @_;
355+ my ($fdir, $fbase, $fext);
356+ my $data_file;
357+ my $errmsg;
358+ my %data;
359+ my $fd;
360+ my $base;
361+ my $srcdata;
362+ my $is_graph = 0;
363+ my ($out, $err, $rc);
364+
365+ info("Processing %s\n", abs2rel($file, $dir));
366+
367+ $file = solve_relative_path($cwd, $file);
368+ ($fdir, $fbase, $fext) = split_filename($file);
369+
370+ $is_graph = 1 if (".$fext" eq $graph_file_extension);
371+
372+ if ($is_graph) {
373+ # Process graph file - copy to temp directory to prevent
374+ # accidental processing of associated data file
375+ $data_file = "$tempdir/$fbase$graph_file_extension";
376+ if (!copy($file, $data_file)) {
377+ $errmsg = "ERROR: Could not copy file $file";
378+ goto err;
379+ }
380+ } else {
381+ # Process data file in place
382+ $data_file = $file;
383+ }
384+
385+ # Change directory
386+ if (!chdir($tempdir)) {
387+ $errmsg = "Could not change to directory $tempdir: $!";
388+ goto err;
389+ }
390+
391+ # Run gcov on data file
392+ ($out, $err, $rc) = system_no_output(1 + 2 + 4, $gcov_tool,
393+ $data_file, @gcov_options, "-i");
394+ defined($out) && unlink($out);
395+ if (defined($err)) {
396+ print_gcov_warnings($err, $is_graph, {
397+ $data_file => $file,
398+ });
399+ unlink($err);
400+ }
401+ if ($rc) {
402+ $errmsg = "GCOV failed for $file";
403+ goto err;
404+ }
405+
406+ if ($is_graph) {
407+ # Remove graph file copy
408+ unlink($data_file);
409+ }
410+
411+ # Parse resulting file(s)
412+ for my $gcov_filename (glob("*.gcov")) {
413+ read_intermediate_text($gcov_filename, \%data);
414+ unlink($gcov_filename);
415+ }
416+
417+ if (!%data) {
418+ warn("WARNING: GCOV did not produce any data for $file\n");
419+ return;
420+ }
421+
422+ # Determine base directory
423+ if (defined($base_directory)) {
424+ $base = $base_directory;
425+ } else {
426+ $base = $fdir;
427+
428+ if (is_compat($COMPAT_MODE_LIBTOOL)) {
429+ # Avoid files from .libs dirs
430+ $base =~ s/\.libs$//;
431+ }
432+
433+ # Try to find base directory automatically if requested by user
434+ if ($rc_auto_base) {
435+ $base = find_base_from_source($base, [ keys(%data) ]);
436+ }
437+ }
438+
439+ # Apply base file name to relative source files
440+ adjust_source_filenames(\%data, $base);
441+
442+ # Remove excluded source files
443+ filter_source_files(\%data);
444+
445+ # Get data on exclusion markers and checksums if requested
446+ if (!$no_markers || $checksum) {
447+ $srcdata = get_all_source_data(keys(%data));
448+ }
449+
450+ # Generate output
451+ $fd = get_output_fd($output_filename, $file);
452+ intermediate_text_to_info($fd, \%data, $srcdata);
453+ close($fd);
454+
455+ chdir($cwd);
456+
457+ return;
458+
459+err:
460+ if ($ignore[$ERROR_GCOV]) {
461+ warn("WARNING: $errmsg!\n");
462+ } else {
463+ die("ERROR: $errmsg!\n")
464+ }
465+}
466+
467+
468 # Map LLVM versions to the version of GCC gcov which they emulate.
469
470 sub map_llvm_version($)
471@@ -2151,8 +2481,12 @@ sub int_handler()
472 #
473 # MODE & 1: suppress STDOUT
474 # MODE & 2: suppress STDERR
475+# MODE & 4: redirect to temporary files instead of suppressing
476 #
477-# Return 0 on success, non-zero otherwise.
478+# Return (stdout, stderr, rc):
479+# stdout: path to tempfile containing stdout or undef
480+# stderr: path to tempfile containing stderr or undef
481+# 0 on success, non-zero otherwise
482 #
483
484 sub system_no_output($@)
485@@ -2161,14 +2495,31 @@ sub system_no_output($@)
486 my $result;
487 local *OLD_STDERR;
488 local *OLD_STDOUT;
489+ my $stdout_file;
490+ my $stderr_file;
491+ my $fd;
492
493 # Save old stdout and stderr handles
494 ($mode & 1) && open(OLD_STDOUT, ">>&", "STDOUT");
495 ($mode & 2) && open(OLD_STDERR, ">>&", "STDERR");
496
497- # Redirect to /dev/null
498- ($mode & 1) && open(STDOUT, ">", "/dev/null");
499- ($mode & 2) && open(STDERR, ">", "/dev/null");
500+ if ($mode & 4) {
501+ # Redirect to temporary files
502+ if ($mode & 1) {
503+ ($fd, $stdout_file) = tempfile(UNLINK => 1);
504+ open(STDOUT, ">", $stdout_file) || warn("$!\n");
505+ close($fd);
506+ }
507+ if ($mode & 2) {
508+ ($fd, $stderr_file) = tempfile(UNLINK => 1);
509+ open(STDERR, ">", $stderr_file) || warn("$!\n");
510+ close($fd);
511+ }
512+ } else {
513+ # Redirect to /dev/null
514+ ($mode & 1) && open(STDOUT, ">", "/dev/null");
515+ ($mode & 2) && open(STDERR, ">", "/dev/null");
516+ }
517
518 debug("system(".join(' ', @_).")\n");
519 system(@_);
520@@ -2181,8 +2532,18 @@ sub system_no_output($@)
521 # Restore old handles
522 ($mode & 1) && open(STDOUT, ">>&", "OLD_STDOUT");
523 ($mode & 2) && open(STDERR, ">>&", "OLD_STDERR");
524+
525+ # Remove empty output files
526+ if (defined($stdout_file) && -z $stdout_file) {
527+ unlink($stdout_file);
528+ $stdout_file = undef;
529+ }
530+ if (defined($stderr_file) && -z $stderr_file) {
531+ unlink($stderr_file);
532+ $stderr_file = undef;
533+ }
534
535- return $result;
536+ return ($stdout_file, $stderr_file, $result);
537 }
538
539
540@@ -2260,23 +2621,28 @@ sub apply_config($)
541
542
543 #
544-# get_exclusion_data(filename)
545+# get_source_data(filename)
546 #
547-# Scan specified source code file for exclusion markers and return
548-# linenumber -> 1
549-# for all lines which should be excluded.
550+# Scan specified source code file for exclusion markers and checksums. Return
551+# ( excl, brexcl, checksums ) where
552+# excl: lineno -> 1 for all lines for which to exclude all data
553+# brexcl: lineno -> 1 for all lines for which to exclude branch data
554+# checksums: lineno -> source code checksum
555 #
556
557-sub get_exclusion_data($)
558+sub get_source_data($)
559 {
560 my ($filename) = @_;
561 my %list;
562 my $flag = 0;
563+ my %brdata;
564+ my $brflag = 0;
565+ my %checksums;
566 local *HANDLE;
567
568 if (!open(HANDLE, "<", $filename)) {
569 warn("WARNING: could not open $filename\n");
570- return undef;
571+ return;
572 }
573 while (<HANDLE>) {
574 if (/$EXCL_STOP/) {
575@@ -2287,14 +2653,62 @@ sub get_exclusion_data($)
576 if (/$excl_line/ || $flag) {
577 $list{$.} = 1;
578 }
579+ if (/$EXCL_BR_STOP/) {
580+ $brflag = 0;
581+ } elsif (/$EXCL_BR_START/) {
582+ $brflag = 1;
583+ }
584+ if (/$excl_br_line/ || $brflag) {
585+ $brdata{$.} = 1;
586+ }
587+ if ($checksum) {
588+ chomp();
589+ $checksums{$.} = md5_base64($_);
590+ }
591 }
592 close(HANDLE);
593
594- if ($flag) {
595+ if ($flag || $brflag) {
596 warn("WARNING: unterminated exclusion section in $filename\n");
597 }
598
599- return \%list;
600+ return (\%list, \%brdata, \%checksums);
601+}
602+
603+
604+#
605+# get_all_source_data(filenames)
606+#
607+# Scan specified source code files for exclusion markers and return
608+# filename -> [ excl, brexcl, checksums ]
609+# excl: lineno -> 1 for all lines for which to exclude all data
610+# brexcl: lineno -> 1 for all lines for which to exclude branch data
611+# checksums: lineno -> source code checksum
612+#
613+
614+sub get_all_source_data(@)
615+{
616+ my @filenames = @_;
617+ my %data;
618+ my $failed = 0;
619+
620+ for my $filename (@filenames) {
621+ my @d;
622+ next if (exists($data{$filename}));
623+
624+ @d = get_source_data($filename);
625+ if (@d) {
626+ $data{$filename} = [ @d ];
627+ } else {
628+ $failed = 1;
629+ }
630+ }
631+
632+ if ($failed) {
633+ warn("WARNING: some exclusion markers may be ignored\n");
634+ }
635+
636+ return \%data;
637 }
638
639
640@@ -2318,35 +2732,17 @@ sub apply_exclusion_data($$)
641 {
642 my ($instr, $graph) = @_;
643 my $filename;
644- my %excl_data;
645- my $excl_read_failed = 0;
646+ my $excl_data;
647
648- # Collect exclusion marker data
649- foreach $filename (sort_uniq_lex(keys(%{$graph}), keys(%{$instr}))) {
650- my $excl = get_exclusion_data($filename);
651-
652- # Skip and note if file could not be read
653- if (!defined($excl)) {
654- $excl_read_failed = 1;
655- next;
656- }
657-
658- # Add to collection if there are markers
659- $excl_data{$filename} = $excl if (keys(%{$excl}) > 0);
660- }
661-
662- # Warn if not all source files could be read
663- if ($excl_read_failed) {
664- warn("WARNING: some exclusion markers may be ignored\n");
665- }
666+ ($excl_data) = get_all_source_data(keys(%{$graph}), keys(%{$instr}));
667
668 # Skip if no markers were found
669- return ($instr, $graph) if (keys(%excl_data) == 0);
670+ return ($instr, $graph) if (!%$excl_data);
671
672 # Apply exclusion marker data to graph
673- foreach $filename (keys(%excl_data)) {
674+ foreach $filename (keys(%$excl_data)) {
675 my $function_data = $graph->{$filename};
676- my $excl = $excl_data{$filename};
677+ my $excl = $excl_data->{$filename}->[0];
678 my $function;
679
680 next if (!defined($function_data));
681@@ -2384,9 +2780,9 @@ sub apply_exclusion_data($$)
682 }
683
684 # Apply exclusion marker data to instr
685- foreach $filename (keys(%excl_data)) {
686+ foreach $filename (keys(%$excl_data)) {
687 my $line_data = $instr->{$filename};
688- my $excl = $excl_data{$filename};
689+ my $excl = $excl_data->{$filename}->[0];
690 my $line;
691 my @new_data;
692
693@@ -2468,10 +2864,12 @@ sub process_graphfile($$)
694
695 # Try to find base directory automatically if requested by user
696 if ($rc_auto_base) {
697- $base_dir = find_base_from_graph($base_dir, $instr, $graph);
698+ $base_dir = find_base_from_source($base_dir,
699+ [ keys(%{$instr}), keys(%{$graph}) ]);
700 }
701
702- ($instr, $graph) = adjust_graph_filenames($base_dir, $instr, $graph);
703+ adjust_source_filenames($instr, $base_dir);
704+ adjust_source_filenames($graph, $base_dir);
705
706 if (!$no_markers) {
707 # Apply exclusion marker data to graph file data
708@@ -2767,11 +3165,11 @@ sub parent_dir($)
709 }
710
711 #
712-# find_base_from_graph(base_dir, instr, graph)
713+# find_base_from_source(base_dir, source_files)
714 #
715-# Try to determine the base directory of the graph file specified by INSTR
716-# and GRAPH. The base directory is the base for all relative filenames in
717-# the graph file. It is defined by the current working directory at time
718+# Try to determine the base directory of the object file built from
719+# SOURCE_FILES. The base directory is the base for all relative filenames in
720+# the gcov data. It is defined by the current working directory at time
721 # of compiling the source file.
722 #
723 # This function implements a heuristic which relies on the following
724@@ -2781,16 +3179,16 @@ sub parent_dir($)
725 # - files by the same name are not present in multiple parent directories
726 #
727
728-sub find_base_from_graph($$$)
729+sub find_base_from_source($$)
730 {
731- my ($base_dir, $instr, $graph) = @_;
732+ my ($base_dir, $source_files) = @_;
733 my $old_base;
734 my $best_miss;
735 my $best_base;
736 my %rel_files;
737
738 # Determine list of relative paths
739- foreach my $filename (keys(%{$instr}), keys(%{$graph})) {
740+ foreach my $filename (@$source_files) {
741 next if (file_name_is_absolute($filename));
742
743 $rel_files{$filename} = 1;
744@@ -2829,17 +3227,17 @@ sub find_base_from_graph($$$)
745 }
746
747 #
748-# adjust_graph_filenames(base_dir, instr, graph)
749+# adjust_source_filenames(hash, base_dir)
750 #
751-# Make relative paths in INSTR and GRAPH absolute and apply
752-# geninfo_adjust_src_path setting to graph file data.
753+# Transform all keys of HASH to absolute form and apply requested
754+# transformations.
755 #
756
757-sub adjust_graph_filenames($$$)
758+sub adjust_source_filenames($$$)
759 {
760- my ($base_dir, $instr, $graph) = @_;
761+ my ($hash, $base_dir) = @_;
762
763- foreach my $filename (keys(%{$instr})) {
764+ foreach my $filename (keys(%{$hash})) {
765 my $old_filename = $filename;
766
767 # Convert to absolute canonical form
768@@ -2851,28 +3249,50 @@ sub adjust_graph_filenames($$$)
769 }
770
771 if ($filename ne $old_filename) {
772- $instr->{$filename} = delete($instr->{$old_filename});
773+ $hash->{$filename} = delete($hash->{$old_filename});
774 }
775 }
776+}
777
778- foreach my $filename (keys(%{$graph})) {
779- my $old_filename = $filename;
780
781- # Make absolute
782- # Convert to absolute canonical form
783- $filename = solve_relative_path($base_dir, $filename);
784+#
785+# filter_source_files(hash)
786+#
787+# Remove unwanted source file data from HASH.
788+#
789
790- # Apply adjustment
791- if (defined($adjust_src_pattern)) {
792- $filename =~ s/$adjust_src_pattern/$adjust_src_replace/g;
793+sub filter_source_files($)
794+{
795+ my ($hash) = @_;
796+
797+ foreach my $filename (keys(%{$hash})) {
798+ # Skip external files if requested
799+ goto del if (!$opt_external && is_external($filename));
800+
801+ # Apply include patterns
802+ if (@include_patterns) {
803+ my $keep;
804+
805+ foreach my $pattern (@include_patterns) {
806+ if ($filename =~ (/^$pattern$/)) {
807+ $keep = 1;
808+ last;
809+ }
810+ }
811+ goto del if (!$keep);
812 }
813
814- if ($filename ne $old_filename) {
815- $graph->{$filename} = delete($graph->{$old_filename});
816+ # Apply exclude patterns
817+ foreach my $pattern (@exclude_patterns) {
818+ goto del if ($filename =~ (/^$pattern$/));
819 }
820- }
821+ next;
822
823- return ($instr, $graph);
824+del:
825+ # Remove file data
826+ delete($hash->{$filename});
827+ $excluded_files{$filename} = 1;
828+ }
829 }
830
831 #
832@@ -3784,6 +4204,7 @@ sub get_gcov_capabilities()
833 'c' => 'branch-counts',
834 'f' => 'function-summaries',
835 'h' => 'help',
836+ 'i' => 'intermediate-format',
837 'l' => 'long-file-names',
838 'n' => 'no-output',
839 'o' => 'object-directory',
840diff --git a/lcovrc b/lcovrc
841index 40f364f..bd4bc3b 100644
842--- a/lcovrc
843+++ b/lcovrc
844@@ -134,6 +134,9 @@ genhtml_desc_html=0
845 # when collecting coverage data.
846 geninfo_auto_base = 1
847
848+# Use gcov intermediate format? Valid values are 0, 1, auto
849+geninfo_intermediate = auto
850+
851 # Directory containing gcov kernel files
852 # lcov_gcov_dir = /proc/gcov
853
854diff --git a/man/lcovrc.5 b/man/lcovrc.5
855index f20d273..bf0ce7a 100644
856--- a/man/lcovrc.5
857+++ b/man/lcovrc.5
858@@ -223,6 +223,11 @@ geninfo_compat_libtool = 0
859 geninfo_auto_base = 1
860 .br
861
862+# Use gcov intermediate format? Valid values are 0, 1, auto
863+.br
864+geninfo_intermediate = auto
865+.br
866+
867 # Directory containing gcov kernel files
868 .br
869 lcov_gcov_dir = /proc/gcov
870@@ -789,6 +794,25 @@ located, and in addition, is different between files of the same project.
871 Default is 1.
872 .PP
873
874+.BR geninfo_intermediate " ="
875+.IR 0 | 1 | auto
876+.IP
877+Specify whether to use gcov intermediate format
878+.br
879+
880+Use this option to control whether geninfo should use the gcov intermediate
881+format while collecting coverage data. The use of the gcov intermediate format
882+should increase processing speed. It also provides branch coverage data when
883+using the \-\-initial command line option.
884+.br
885+
886+Valid values are 0 for off, 1 for on, and "auto" to let geninfo automatically
887+use immediate format when supported by gcov.
888+.br
889+
890+Default is "auto".
891+.PP
892+
893 .BR lcov_gcov_dir " ="
894 .I path_to_kernel_coverage_data
895 .IP
896--
8972.17.1
898
diff --git a/meta-oe/recipes-support/lcov/files/0002-geninfo-Add-intermediate-JSON-format-support.patch b/meta-oe/recipes-support/lcov/files/0002-geninfo-Add-intermediate-JSON-format-support.patch
deleted file mode 100644
index 7b180635c..000000000
--- a/meta-oe/recipes-support/lcov/files/0002-geninfo-Add-intermediate-JSON-format-support.patch
+++ /dev/null
@@ -1,247 +0,0 @@
1From e13b2b6f8443da660cafa0679c3b16240843ce9f Mon Sep 17 00:00:00 2001
2From: Peter Oberparleiter <oberpar@linux.ibm.com>
3Date: Fri, 24 May 2019 17:16:56 +0200
4Subject: [PATCH 2/2] geninfo: Add intermediate JSON format support
5
6This change adds support for parsing the output of gcov's intermediate
7JSON file format as implemented by GCC version 9.
8
9Note: The way that the intermediate file format support is implemented
10in geninfo removes the need to parse .gcno files directly. Since geninfo
11does not include support for parsing GCC 9 .gcno files, using the
12intermediate format is the only option for geninfo to collect coverage
13data generated by GCC version 9.
14
15Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
16---
17 bin/geninfo | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++-
18 1 file changed, 160 insertions(+), 2 deletions(-)
19
20Upstream-Status: Backport
21Download URL: https://github.com/linux-test-project/lcov/commit/75fbae1cfc5027f818a0bb865bf6f96fab3202da
22
23diff --git a/bin/geninfo b/bin/geninfo
24index 0276666..cceb782 100755
25--- a/bin/geninfo
26+++ b/bin/geninfo
27@@ -59,6 +59,9 @@ use File::Copy qw(copy);
28 use Getopt::Long;
29 use Digest::MD5 qw(md5_base64);
30 use Cwd qw/abs_path/;
31+use PerlIO::gzip;
32+use JSON qw(decode_json);
33+
34 if( $^O eq "msys" )
35 {
36 require File::Spec::Win32;
37@@ -474,7 +477,8 @@ if ($rc_intermediate eq "0") {
38 $intermediate = 1;
39 } elsif (lc($rc_intermediate) eq "auto") {
40 # Use intermediate format if supported by gcov
41- $intermediate = $gcov_caps->{'intermediate-format'} ? 1 : 0;
42+ $intermediate = ($gcov_caps->{'intermediate-format'} ||
43+ $gcov_caps->{'json-format'}) ? 1 : 0;
44 } else {
45 die("ERROR: invalid value for geninfo_intermediate: ".
46 "'$rc_intermediate'\n");
47@@ -2084,6 +2088,48 @@ sub read_intermediate_text($$)
48 }
49
50
51+#
52+# read_intermediate_json(gcov_filename, data, basedir_ref)
53+#
54+# Read gcov intermediate JSON format in GCOV_FILENAME and add the resulting
55+# data to DATA in the following format:
56+#
57+# data: source_filename -> file_data
58+# file_data: GCOV JSON data for file
59+#
60+# Also store the value for current_working_directory to BASEDIR_REF.
61+#
62+
63+sub read_intermediate_json($$$)
64+{
65+ my ($gcov_filename, $data, $basedir_ref) = @_;
66+ my $fd;
67+ my $text;
68+ my $json;
69+
70+ open($fd, "<:gzip", $gcov_filename) or
71+ die("ERROR: Could not read $gcov_filename: $!\n");
72+ local $/;
73+ $text = <$fd>;
74+ close($fd);
75+
76+ $json = decode_json($text);
77+ if (!defined($json) || !exists($json->{"files"}) ||
78+ ref($json->{"files"} ne "ARRAY")) {
79+ die("ERROR: Unrecognized JSON output format in ".
80+ "$gcov_filename\n");
81+ }
82+
83+ $$basedir_ref = $json->{"current_working_directory"};
84+
85+ for my $file (@{$json->{"files"}}) {
86+ my $filename = $file->{"file"};
87+
88+ $data->{$filename} = $file;
89+ }
90+}
91+
92+
93 #
94 # intermediate_text_to_info(fd, data, srcdata)
95 #
96@@ -2173,6 +2219,104 @@ sub intermediate_text_to_info($$$)
97 }
98
99
100+#
101+# intermediate_json_to_info(fd, data, srcdata)
102+#
103+# Write DATA in info format to file descriptor FD.
104+#
105+# data: filename -> file_data:
106+# file_data: GCOV JSON data for file
107+#
108+# srcdata: filename -> [ excl, brexcl, checksums ]
109+# excl: lineno -> 1 for all lines for which to exclude all data
110+# brexcl: lineno -> 1 for all lines for which to exclude branch data
111+# checksums: lineno -> source code checksum
112+#
113+# Note: To simplify processing, gcov data is not combined here, that is counts
114+# that appear multiple times for the same lines/branches are not added.
115+# This is done by lcov/genhtml when reading the data files.
116+#
117+
118+sub intermediate_json_to_info($$$)
119+{
120+ my ($fd, $data, $srcdata) = @_;
121+ my $branch_num = 0;
122+
123+ return if (!%{$data});
124+
125+ print($fd "TN:$test_name\n");
126+ for my $filename (keys(%{$data})) {
127+ my ($excl, $brexcl, $checksums);
128+ my $file_data = $data->{$filename};
129+
130+ if (defined($srcdata->{$filename})) {
131+ ($excl, $brexcl, $checksums) = @{$srcdata->{$filename}};
132+ }
133+
134+ print($fd "SF:$filename\n");
135+
136+ # Function data
137+ if ($func_coverage) {
138+ for my $d (@{$file_data->{"functions"}}) {
139+ my $line = $d->{"start_line"};
140+ my $count = $d->{"execution_count"};
141+ my $name = $d->{"name"};
142+
143+ next if (!defined($line) || !defined($count) ||
144+ !defined($name) || $excl->{$line});
145+
146+ print($fd "FN:$line,$name\n");
147+ print($fd "FNDA:$count,$name\n");
148+ }
149+ }
150+
151+ # Line data
152+ for my $d (@{$file_data->{"lines"}}) {
153+ my $line = $d->{"line_number"};
154+ my $count = $d->{"count"};
155+ my $c;
156+ my $branches = $d->{"branches"};
157+ my $unexec = $d->{"unexecuted_block"};
158+
159+ next if (!defined($line) || !defined($count) ||
160+ $excl->{$line});
161+
162+ if (defined($unexec) && $unexec && $count == 0) {
163+ $unexec = 1;
164+ } else {
165+ $unexec = 0;
166+ }
167+
168+ if ($checksum && exists($checksums->{$line})) {
169+ $c = ",".$checksums->{$line};
170+ } else {
171+ $c = "";
172+ }
173+ print($fd "DA:$line,$count$c\n");
174+
175+ $branch_num = 0;
176+ # Branch data
177+ if ($br_coverage && !$brexcl->{$line}) {
178+ for my $b (@$branches) {
179+ my $brcount = $b->{"count"};
180+
181+ if (!defined($brcount) || $unexec) {
182+ $brcount = "-";
183+ }
184+ print($fd "BRDA:$line,0,$branch_num,".
185+ "$brcount\n");
186+
187+ $branch_num++;
188+ }
189+ }
190+
191+ }
192+
193+ print($fd "end_of_record\n");
194+ }
195+}
196+
197+
198 sub get_output_fd($$)
199 {
200 my ($outfile, $file) = @_;
201@@ -2243,6 +2387,8 @@ sub process_intermediate($$$)
202 my $srcdata;
203 my $is_graph = 0;
204 my ($out, $err, $rc);
205+ my $json_basedir;
206+ my $json_format;
207
208 info("Processing %s\n", abs2rel($file, $dir));
209
210@@ -2296,6 +2442,12 @@ sub process_intermediate($$$)
211 unlink($gcov_filename);
212 }
213
214+ for my $gcov_filename (glob("*.gcov.json.gz")) {
215+ read_intermediate_json($gcov_filename, \%data, \$json_basedir);
216+ unlink($gcov_filename);
217+ $json_format = 1;
218+ }
219+
220 if (!%data) {
221 warn("WARNING: GCOV did not produce any data for $file\n");
222 return;
223@@ -2304,6 +2456,8 @@ sub process_intermediate($$$)
224 # Determine base directory
225 if (defined($base_directory)) {
226 $base = $base_directory;
227+ } elsif (defined($json_basedir)) {
228+ $base = $json_basedir;
229 } else {
230 $base = $fdir;
231
232@@ -2331,7 +2485,11 @@ sub process_intermediate($$$)
233
234 # Generate output
235 $fd = get_output_fd($output_filename, $file);
236- intermediate_text_to_info($fd, \%data, $srcdata);
237+ if ($json_format) {
238+ intermediate_json_to_info($fd, \%data, $srcdata);
239+ } else {
240+ intermediate_text_to_info($fd, \%data, $srcdata);
241+ }
242 close($fd);
243
244 chdir($cwd);
245--
2462.17.1
247
diff --git a/meta-oe/recipes-support/lcov/lcov_1.14.bb b/meta-oe/recipes-support/lcov/lcov_1.16.bb
index f18c7b18e..6b9e050f0 100755
--- a/meta-oe/recipes-support/lcov/lcov_1.14.bb
+++ b/meta-oe/recipes-support/lcov/lcov_1.16.bb
@@ -9,8 +9,6 @@ LICENSE = "GPL-2.0-only"
9LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe" 9LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe"
10 10
11RDEPENDS:${PN} += " \ 11RDEPENDS:${PN} += " \
12 libjson-perl \
13 libperlio-gzip-perl \
14 perl \ 12 perl \
15 perl-module-filehandle \ 13 perl-module-filehandle \
16 perl-module-getopt-std \ 14 perl-module-getopt-std \
@@ -48,15 +46,9 @@ RDEPENDS:${PN}:append:class-target = " \
48 gcov \ 46 gcov \
49 gcov-symlinks \ 47 gcov-symlinks \
50" 48"
51 49SRC_URI = "https://github.com/linux-test-project/lcov/releases/download/v${PV}/lcov-${PV}.tar.gz"
52SRC_URI = " \ 50SRC_URI[md5sum] = "bfee0cef50d7b7bd1df03bfadf68dcef"
53 http://downloads.sourceforge.net/ltp/${BP}.tar.gz \ 51SRC_URI[sha256sum] = "987031ad5528c8a746d4b52b380bc1bffe412de1f2b9c2ba5224995668e3240b"
54 file://0001-geninfo-Add-intermediate-text-format-support.patch \
55 file://0002-geninfo-Add-intermediate-JSON-format-support.patch \
56 "
57
58SRC_URI[md5sum] = "0220d01753469f83921f8f41ae5054c1"
59SRC_URI[sha256sum] = "14995699187440e0ae4da57fe3a64adc0a3c5cf14feab971f8db38fb7d8f071a"
60 52
61do_install() { 53do_install() {
62 oe_runmake install PREFIX=${D}${prefix} CFG_DIR=${D}${sysconfdir} LCOV_PERL_PATH="/usr/bin/env perl" 54 oe_runmake install PREFIX=${D}${prefix} CFG_DIR=${D}${sysconfdir} LCOV_PERL_PATH="/usr/bin/env perl"