Skip to content

Commit 8800a12

Browse files
committed
Add '--context-script ..' callback.
Enable user to keep track of environment and other settings - to aid in infrastructure debugging and tracking. See man genhtml(1) for details (but note the callback is implemented by lcov, geninfo, genhtml). Collected data is written into '--profile' JSON output file, under key 'context'. Signed-off-by: Henry Cox <[email protected]>
1 parent 87d01f3 commit 8800a12

File tree

10 files changed

+319
-3
lines changed

10 files changed

+319
-3
lines changed

README

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,8 @@ New features and capabilities fall into 7 major categories:
387387
v) select a subset of coverage data to display - e.g., to
388388
use in a code review which wants to concentrate on only
389389
the changes caused by a particular commit or range of commits.
390+
vi) keep track of environment and otehr settings - to aid
391+
infrastructure debugging in more complicated use cases.
390392

391393
The callback may be any desired script or executable - but there
392394
may be performance advantages if it is written as a Perl module.
@@ -399,7 +401,7 @@ New features and capabilities fall into 7 major categories:
399401

400402
Related options:
401403
--annotate-script, --criteria-script, --version-script
402-
--resolve-script --select-script
404+
--resolve-script, --select-script, --context-script
403405

404406
f) Performance
405407

bin/lcov

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,7 @@ sub lcov_geninfo(@)
934934
['--demangle-cpp', \@lcovutil::cpp_demangle],
935935
['--include', \@lcovutil::include_file_patterns],
936936
['--exclude', \@lcovutil::exclude_file_patterns],
937+
['--context-script', \@lcovutil::contextCallback],
937938
['--criteria-script',
938939
\@CoverageCriteria::coverageCriteriaScript
939940
],

lib/lcovutil.pm

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,10 @@ our @build_directory;
211211

212212
our @configured_callbacks;
213213

214+
# optional callback to keep track of whatever user decides is important
215+
our @contextCallback;
216+
our $contextCallback;
217+
214218
# filename substitutions
215219
our @file_subst_patterns;
216220
# resolve callback
@@ -1096,6 +1100,7 @@ my %rc_common = (
10961100
'substitute' => \@rc_subst_patterns,
10971101
'omit_lines' => \@rc_omit_patterns,
10981102
'erase_functions' => \@rc_erase_patterns,
1103+
'context_script' => \@rc_contextCallback,
10991104
"version_script" => \@rc_version_script,
11001105
'resolve_script' => \@rc_resolveCallback,
11011106
'criteria_callback_data' =>
@@ -1184,6 +1189,7 @@ our %argCommon = ("tempdir=s" => \$tempdirname,
11841189
'build-directory=s' => \@lcovutil::build_directory,
11851190

11861191
'resolve-script=s' => \@lcovutil::resolveCallback,
1192+
'context-script=s' => \@lcovutil::contextCallback,
11871193
"filter=s" => \@opt_filter,
11881194
"demangle-cpp:s" => \@lcovutil::cpp_demangle,
11891195
"ignore-errors=s" => \@opt_ignore_errors,
@@ -1428,7 +1434,8 @@ sub parseOptions
14281434
\@rc_source_directories
14291435
],
14301436
[\@lcovutil::build_directory, \@rc_build_dir],
1431-
[\@lcovutil::resolveCallback, \@rc_resolveCallback]
1437+
[\@lcovutil::resolveCallback, \@rc_resolveCallback],
1438+
[\@lcovutil::contextCallback, \@rc_contextCallback],
14321439
) {
14331440
@{$rc->[0]} = @{$rc->[1]} unless (@{$rc->[0]});
14341441
}
@@ -1459,6 +1466,7 @@ sub parseOptions
14591466
[\$CoverageCriteria::criteriaCallback,
14601467
\@CoverageCriteria::coverageCriteriaScript
14611468
],
1469+
[\$contextCallback, \@lcovutil::contextCallback],
14621470
) {
14631471
lcovutil::configure_callback($cb->[0], @{$cb->[1]})
14641472
if (@{$cb->[1]});
@@ -1481,6 +1489,9 @@ sub parseOptions
14811489
unless grep(/^$x$/, @$valid);
14821490
}
14831491
}
1492+
# context only gets grabbed/stored with '--profile'
1493+
$lcovutil::profile = ''
1494+
if ($contextCallback && !defined($lcovutil::profile));
14841495

14851496
if (!$lcov_capture) {
14861497
if ($lcovutil::compute_file_version &&
@@ -2894,6 +2905,29 @@ sub pipe
28942905
return PipeHelper->new($reason, @$self, @_);
28952906
}
28962907

2908+
sub context
2909+
{
2910+
my $self = shift;
2911+
lcovutil::info(1, 'context ' . join(' ', @$self) . "\n");
2912+
my $iter = $self->pipe('context');
2913+
return unless defined($iter);
2914+
my %context;
2915+
while (my $line = $iter->next()) {
2916+
chomp($line);
2917+
$line =~ s/\r//g; # remove CR from line-end
2918+
# first word on line is the key..
2919+
my ($key, $value) = split(/ +/, $line, 2);
2920+
if (exists($context{key})) {
2921+
$context{key} .= "\n" . $value;
2922+
} else {
2923+
$context{key} = $value;
2924+
}
2925+
}
2926+
my $status = $iter->close(1); # check error return
2927+
2928+
return \%context;
2929+
}
2930+
28972931
sub extract_version
28982932
{
28992933
my ($self, $filename) = @_;

man/genhtml.1

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ genhtml \- Generate HTML view from LCOV coverage data files
118118
.RB [ \-\-annotate\-script
119119
.IR script ]
120120
.br
121+
.RB [ \-\-context\-script
122+
.IR script ]
123+
.br
121124
.RB [ \-\-criteria\-script
122125
.IR script ]
123126
.br
@@ -400,6 +403,8 @@ following options:
400403
.RS
401404
.B \-\-annotate\-script
402405
.br
406+
.B \-\-context\-script
407+
.br
403408
.B \-\-criteria\-script
404409
.br
405410
.B \-\-resolve\-script
@@ -503,6 +508,39 @@ and
503508
.I $LCOV_HOME/share/lcov/support-scripts/p4annotate.pm.
504509
.RE
505510

511+
.IP context\-script
512+
.I $hash = $callback_obj->context();
513+
.br
514+
.br
515+
516+
where
517+
.I $hash
518+
is a reference to a hask of key/value pairs which are meaningful to you.
519+
This data is stored in the
520+
.I profile
521+
database. See the 'profile' section in man
522+
.B lcovrc(5)
523+
for more information.
524+
525+
If your callback is not a perl module - for example, is a shellscript - then it should return a string such that the first word on each line is the key and the remainder is the associated data. If a key is repeated, then the corresponding data strings are concatentated, separated by newline.
526+
527+
If you want to record only system information, then a shell callback is likely sufficient. If you want to record any tool-specific/internal information, then you will need to implement a perl module so that your callback will be able to access the information.
528+
Note that the constructor of your
529+
.I context-script
530+
callback (or of any callback) can perform any additional actions which
531+
are required - for example, to write additional files, to query or set
532+
tool-specific information,
533+
.I etc.
534+
For example, the example implementation, below, has an option to append
535+
comments to the generated .info file.
536+
537+
538+
See the example implementation
539+
.I $LCOV_HOME/share/lcov/support-scripts/context.pm.
540+
.RE
541+
542+
543+
506544
.IP criteria\-script
507545
.I ($status, $array) = $callback_obj->check_criteria($obj_name, $type, $json);
508546
.br

man/geninfo.1

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ geninfo \- Generate tracefiles from GCOV coverage data files
105105
.br
106106
.RB [ \-\-forget\-test\-names ]
107107
.br
108+
.RB [ \-\-context\-script
109+
.IR script_file ]
110+
.br
108111
.RB [ \-\-criteria\-script
109112
.IR script_file ]
110113
.br
@@ -1089,6 +1092,21 @@ handling), use this option to specify the respective filename. By default,
10891092
one tracefile will be created for each processed .gcda file.
10901093
.RE
10911094

1095+
.RE
1096+
.B \-\-context\-script
1097+
.I script
1098+
.br
1099+
.RS
1100+
1101+
Use
1102+
.I script
1103+
to collect additional tool execution context information - to aid in
1104+
infrastructure debugging and/or tracking.
1105+
1106+
See the genhtml man page for more details on the context script.
1107+
1108+
.br
1109+
10921110
.RE
10931111
.B \-\-criteria\-script
10941112
.I script

man/lcov.1

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ Capture coverage data tracefile (from compiler-generated data):
6868
.RB [ \-\-compat
6969
.IR mode =on|off|auto]
7070
.br
71+
.RB [ \-\-context\-script
72+
.IR script_file ]
73+
.br
7174
.RB [ \-\-criteria\-script
7275
.IR script_file ]
7376
.br
@@ -1071,6 +1074,21 @@ When specified,
10711074
will emit the list of functions and associated tracefiles rather than combined tracefile data.
10721075
.br
10731076

1077+
.RE
1078+
.B \-\-context\-script
1079+
.I script
1080+
.br
1081+
.RS
1082+
1083+
Use
1084+
.I script
1085+
to collect additional tool execution context information - to aid in
1086+
infrastructure debugging and/or tracking.
1087+
1088+
See the genhtml man page for more details on the context script.
1089+
1090+
.br
1091+
10741092
.RE
10751093
.B \-\-criteria\-script
10761094
.I script

man/lcovrc.5

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2451,6 +2451,21 @@ source line number.
24512451
.PP
24522452

24532453

2454+
.BR context_script " ="
2455+
.IR path_to_executable_or_module | parameter
2456+
.IP
2457+
This option is equivalent to the
2458+
.I \-\-context\-script
2459+
option of genhtml/lcov/geninfo
2460+
2461+
This option can be used multiple times in the lcovrc file to specify both a criteria script and additional options which are passed to the script.
2462+
2463+
See the genhtml man page for details.
2464+
2465+
.PP
2466+
2467+
2468+
24542469
.BR criteria_script " ="
24552470
.IR path_to_executable_or_module | parameter
24562471
.IP

scripts/context.pm

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#!/usr/bin/env perl
2+
3+
# Copyright (c) MediaTek USA Inc., 2024
4+
#
5+
# This program is free software; you can redistribute it and/or modify
6+
# it under the terms of the GNU General Public License as published by
7+
# the Free Software Foundation; either version 2 of the License, or (at
8+
# your option) any later version.
9+
#
10+
# This program is distributed in the hope that it will be useful, but
11+
# WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
# General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU General Public License
16+
# along with this program; if not, see
17+
# <http://www.gnu.org/licenses/>.
18+
#
19+
# context
20+
#
21+
# This script is used as a lcov/geninfo/genhtml "--context-script context" callback.
22+
# It is called at the end of tool execution to collect and store data which
23+
# might be useful for infrastructure debugging and/or tracking.
24+
#
25+
# The result is a hash of key/value pairs - see man genhtml(1) for more
26+
# details.
27+
#
28+
# You may want to collect and entirely different set of data.
29+
# You can also add operations to the constructor to do something earlier in
30+
# processing - e.g., to write data to some other files(s), etc.
31+
32+
package context;
33+
34+
use strict;
35+
use Getopt::Long qw(GetOptionsFromArray);
36+
use lcovutil;
37+
38+
our @ISA = qw(Exporter);
39+
our @EXPORT_OK = qw(new);
40+
41+
sub new
42+
{
43+
my $class = shift;
44+
my $script = shift;
45+
my $standalone = $script eq $0;
46+
my @options = @_;
47+
my $comment;
48+
49+
if (!GetOptionsFromArray(\@_, ('comment' => \$comment)) ||
50+
(!$standalone && @_)) {
51+
print(STDERR "Error: unexpected option:\n " .
52+
join(' ', @options) . "\nusage: [--comment]\n");
53+
exit(1) if $standalone;
54+
return undef;
55+
}
56+
my $self = [$script];
57+
58+
$self = bless $self, $class;
59+
if ($comment) {
60+
# 'genhtml' and certain 'lcov' modes do not write a '.info' file
61+
# so the comments won't go anywhere
62+
my $data = $self->context();
63+
foreach my $key (sort keys %$data) {
64+
push(@lcovutil::comments, $key . ': ' . $data->{$key});
65+
}
66+
}
67+
68+
return $self;
69+
}
70+
71+
sub context
72+
{
73+
my $self = shift;
74+
75+
my %data;
76+
$data{user} = `whoami`;
77+
$data{perl_version} = $^V->{original};
78+
$data{perl} = `which perl`;
79+
$data{PERL5LIB} = $ENV{PERL5LIB}
80+
if exists($ENV{PERL5LIB});
81+
82+
foreach my $k (keys %data) {
83+
chomp($data{$k});
84+
}
85+
86+
return \%data;
87+
}
88+
89+
1;

0 commit comments

Comments
 (0)