Skip to content

Commit d2f4f03

Browse files
author
florian
committed
Add script. Comes in handy when messing with the build system
to make sure no compiler flags get lost (as they did at some point in the past). git-svn-id: svn://svn.valgrind.org/valgrind/trunk@14797 a5019735-40e9-0310-863c-91ae7b9d1cf9
1 parent 6d982cc commit d2f4f03

File tree

1 file changed

+196
-0
lines changed

1 file changed

+196
-0
lines changed

auxprogs/compare-build-logs

+196
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
#!/usr/bin/env perl
2+
3+
# Lame script to compare two build logs.
4+
#
5+
# The script intercepts directory changes and compiler invocations and
6+
# compares the compiler invocations for equality. Equality is defined
7+
# as "same options in both invocations ignoring order". So we only test
8+
# a necessary condition.
9+
#
10+
# Both builds must be configured with the same --prefix. Otherwise,
11+
# the value of -DVG_LIBDIR= will differ. They also need to use the same
12+
# compiler.
13+
14+
use Getopt::Long;
15+
use strict;
16+
use warnings;
17+
18+
my $prog_name = "compare-build-logs";
19+
20+
my $usage=<<EOF;
21+
USAGE
22+
23+
$prog_name log1 log2
24+
25+
[--gcc] intercept GCC invocations (this is default)
26+
27+
[--clang] intercept clang invocations
28+
29+
[-v] verbose mode
30+
31+
log-file1
32+
33+
log-file2
34+
EOF
35+
36+
my $compiler = "gcc";
37+
my $verbose = 0;
38+
39+
GetOptions( "gcc" => sub { $compiler = "gcc" },
40+
"clang" => sub { $compiler = "clang" },
41+
"v" => sub { $verbose = 1 },
42+
) || die $usage;
43+
44+
my $num_arg = $#ARGV + 1;
45+
46+
if ($num_arg != 2) {
47+
die $usage;
48+
}
49+
50+
my $log1 = $ARGV[0];
51+
my $log2 = $ARGV[1];
52+
53+
# Hashes: relative filename -> compiler invocation
54+
my %cmd1 = read_log_file($log1);
55+
my %cmd2 = read_log_file($log2);
56+
57+
# Compare the log files
58+
59+
foreach my $file (keys %cmd1) {
60+
if (! $cmd2{$file}) {
61+
print "*** $file missing in $log2\n";
62+
} else {
63+
compare_invocations($file, $cmd1{$file }, $cmd2{$file});
64+
}
65+
}
66+
foreach my $file (keys %cmd2) {
67+
if (! $cmd1{$file}) {
68+
print "*** $file missing in $log1\n";
69+
}
70+
}
71+
72+
exit 0;
73+
74+
# Compare two lines |c1| and |c2| which are compiler invocations for |file|.
75+
# Basically, we look at a compiler invocation as a sequence of blank-separated
76+
# options.
77+
sub compare_invocations {
78+
my ($file, $c1, $c2) = @_;
79+
my ($found1, $found2);
80+
# print "COMPARE $file\n";
81+
82+
# Remove stuff that has embedded spaces
83+
84+
# Remove: `test -f 'whatever.c' || echo './'`
85+
$c1 =~ s|(`[^`]*`)||;
86+
$found1 = $1;
87+
$c2 =~ s|(`[^`]*`)||;
88+
$found2 = $1;
89+
if ($found1 && $found2) {
90+
die if ($found1 ne $found2);
91+
}
92+
93+
# Remove: -o whatever
94+
$c1 =~ s|-o[ ][ ]*([^ ][^ ]*)||;
95+
$found1 = $1;
96+
$c2 =~ s|-o[ ][ ]*([^ ][^ ]*)||;
97+
$found2 = $1;
98+
if ($found1 && $found2) {
99+
die if ($found1 ne $found2);
100+
}
101+
102+
# The remaining lines are considered to be blank-separated options and file
103+
# names. They should be identical in both invocations (but in any order).
104+
my %o1 = ();
105+
my %o2 = ();
106+
foreach my $k (split /\s+/,$c1) {
107+
$o1{$k} = 1;
108+
}
109+
foreach my $k (split /\s+/,$c2) {
110+
$o2{$k} = 1;
111+
}
112+
# foreach my $zz (keys %o1) {
113+
# print "$zz\n";
114+
# }
115+
foreach my $k (keys %o1) {
116+
if (! $o2{$k}) {
117+
print "*** '$k' is missing in compilation of '$file' in $log2\n";
118+
}
119+
}
120+
foreach my $k (keys %o2) {
121+
if (! $o1{$k}) {
122+
print "*** '$k' is missing in compilation of '$file' in $log1\n";
123+
}
124+
}
125+
}
126+
127+
# Read a compiler log file.
128+
# Return hash: relative (to build root) file name -> compiler invocation
129+
sub read_log_file
130+
{
131+
my ($log) = @_;
132+
my $dir = "";
133+
my $root = "";
134+
my %cmd = ();
135+
136+
print "...reading $log\n" if ($verbose);
137+
138+
open(LOG, "$log") || die "cannot open $log\n";
139+
while (my $line = <LOG>) {
140+
chomp $line;
141+
if ($line =~ /^make/) {
142+
if ($line =~ /Entering directory/) {
143+
$dir = $line;
144+
$dir =~ s/^.*`//;
145+
$dir =~ s/'.*//;
146+
if ($root eq "") {
147+
$root = $dir;
148+
# Append a slash if not present
149+
$root = "$root/" if (! ($root =~ /\/$/));
150+
print "...build root is $root\n" if ($verbose);
151+
}
152+
# print "DIR = $dir\n";
153+
next;
154+
}
155+
}
156+
if ($line =~ /^\s*[^\s]*$compiler\s/) {
157+
# If line ends in \ read continuation line.
158+
while ($line =~ /\\$/) {
159+
my $next = <LOG>;
160+
chomp($next);
161+
$line =~ s/\\$//;
162+
$line .= $next;
163+
}
164+
165+
my $file = extract_file($line);
166+
$file = "$dir/$file"; # make absolute
167+
$file =~ s/$root//; # remove build root
168+
# print "FILE $file\n";
169+
$cmd{"$file"} = $line;
170+
}
171+
}
172+
close(LOG);
173+
174+
my $num_invocations = int(keys %cmd);
175+
176+
if ($num_invocations == 0) {
177+
print "*** File $log does not contain any compiler invocations\n";
178+
} else {
179+
print "...found $num_invocations invocations\n" if ($verbose);
180+
}
181+
return %cmd;
182+
}
183+
184+
# Extract a file name from the command line. Assume there is a -o filename
185+
# present. If not, issue a warning.
186+
#
187+
sub extract_file {
188+
my($line) = @_;
189+
# Look for -o executable
190+
if ($line =~ /-o[ ][ ]*([^ ][^ ]*)/) {
191+
return $1;
192+
} else {
193+
print "*** Could not extract file name from $line\n";
194+
return "UNKNOWN";
195+
}
196+
}

0 commit comments

Comments
 (0)