From: Florian Krohm Date: Wed, 3 Dec 2014 22:48:29 +0000 (+0000) Subject: Add script. Comes in handy when messing with the build system X-Git-Tag: svn/VALGRIND_3_11_0~789 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d7811e3de704dc12d225fdb255ce66b2373b10de;p=thirdparty%2Fvalgrind.git 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 --- diff --git a/auxprogs/compare-build-logs b/auxprogs/compare-build-logs new file mode 100755 index 0000000000..704552b00d --- /dev/null +++ b/auxprogs/compare-build-logs @@ -0,0 +1,196 @@ +#!/usr/bin/env perl + +# Lame script to compare two build logs. +# +# The script intercepts directory changes and compiler invocations and +# compares the compiler invocations for equality. Equality is defined +# as "same options in both invocations ignoring order". So we only test +# a necessary condition. +# +# Both builds must be configured with the same --prefix. Otherwise, +# the value of -DVG_LIBDIR= will differ. They also need to use the same +# compiler. + +use Getopt::Long; +use strict; +use warnings; + +my $prog_name = "compare-build-logs"; + +my $usage=< sub { $compiler = "gcc" }, + "clang" => sub { $compiler = "clang" }, + "v" => sub { $verbose = 1 }, + ) || die $usage; + +my $num_arg = $#ARGV + 1; + +if ($num_arg != 2) { + die $usage; +} + +my $log1 = $ARGV[0]; +my $log2 = $ARGV[1]; + +# Hashes: relative filename -> compiler invocation +my %cmd1 = read_log_file($log1); +my %cmd2 = read_log_file($log2); + +# Compare the log files + +foreach my $file (keys %cmd1) { + if (! $cmd2{$file}) { + print "*** $file missing in $log2\n"; + } else { + compare_invocations($file, $cmd1{$file }, $cmd2{$file}); + } +} +foreach my $file (keys %cmd2) { + if (! $cmd1{$file}) { + print "*** $file missing in $log1\n"; + } +} + +exit 0; + +# Compare two lines |c1| and |c2| which are compiler invocations for |file|. +# Basically, we look at a compiler invocation as a sequence of blank-separated +# options. +sub compare_invocations { + my ($file, $c1, $c2) = @_; + my ($found1, $found2); +# print "COMPARE $file\n"; + +# Remove stuff that has embedded spaces + +# Remove: `test -f 'whatever.c' || echo './'` + $c1 =~ s|(`[^`]*`)||; + $found1 = $1; + $c2 =~ s|(`[^`]*`)||; + $found2 = $1; + if ($found1 && $found2) { + die if ($found1 ne $found2); + } + +# Remove: -o whatever + $c1 =~ s|-o[ ][ ]*([^ ][^ ]*)||; + $found1 = $1; + $c2 =~ s|-o[ ][ ]*([^ ][^ ]*)||; + $found2 = $1; + if ($found1 && $found2) { + die if ($found1 ne $found2); + } + +# The remaining lines are considered to be blank-separated options and file +# names. They should be identical in both invocations (but in any order). + my %o1 = (); + my %o2 = (); + foreach my $k (split /\s+/,$c1) { + $o1{$k} = 1; + } + foreach my $k (split /\s+/,$c2) { + $o2{$k} = 1; + } +# foreach my $zz (keys %o1) { +# print "$zz\n"; +# } + foreach my $k (keys %o1) { + if (! $o2{$k}) { + print "*** '$k' is missing in compilation of '$file' in $log2\n"; + } + } + foreach my $k (keys %o2) { + if (! $o1{$k}) { + print "*** '$k' is missing in compilation of '$file' in $log1\n"; + } + } +} + +# Read a compiler log file. +# Return hash: relative (to build root) file name -> compiler invocation +sub read_log_file +{ + my ($log) = @_; + my $dir = ""; + my $root = ""; + my %cmd = (); + + print "...reading $log\n" if ($verbose); + + open(LOG, "$log") || die "cannot open $log\n"; + while (my $line = ) { + chomp $line; + if ($line =~ /^make/) { + if ($line =~ /Entering directory/) { + $dir = $line; + $dir =~ s/^.*`//; + $dir =~ s/'.*//; + if ($root eq "") { + $root = $dir; + # Append a slash if not present + $root = "$root/" if (! ($root =~ /\/$/)); + print "...build root is $root\n" if ($verbose); + } +# print "DIR = $dir\n"; + next; + } + } + if ($line =~ /^\s*[^\s]*$compiler\s/) { + # If line ends in \ read continuation line. + while ($line =~ /\\$/) { + my $next = ; + chomp($next); + $line =~ s/\\$//; + $line .= $next; + } + + my $file = extract_file($line); + $file = "$dir/$file"; # make absolute + $file =~ s/$root//; # remove build root +# print "FILE $file\n"; + $cmd{"$file"} = $line; + } + } + close(LOG); + + my $num_invocations = int(keys %cmd); + + if ($num_invocations == 0) { + print "*** File $log does not contain any compiler invocations\n"; + } else { + print "...found $num_invocations invocations\n" if ($verbose); + } + return %cmd; +} + +# Extract a file name from the command line. Assume there is a -o filename +# present. If not, issue a warning. +# +sub extract_file { + my($line) = @_; +# Look for -o executable + if ($line =~ /-o[ ][ ]*([^ ][^ ]*)/) { + return $1; + } else { + print "*** Could not extract file name from $line\n"; + return "UNKNOWN"; + } +}