#!/usr/bin/perl -w # NAME: showerrors.pl # AIM: Read a cmake bldlog and show errors (and warnings) with the projects name # 07/08/2013 - extend to show LINK errors also # 05/08/2013 geoff mclane http://geoffair.net/mperl use strict; use warnings; use File::Basename; # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] ) use Cwd; my $os = $^O; my $perl_dir = '/home/geoff/bin'; my $PATH_SEP = '/'; my $temp_dir = '/tmp'; if ($os =~ /win/i) { $perl_dir = 'C:\GTools\perl'; $temp_dir = $perl_dir; $PATH_SEP = "\\"; } unshift(@INC, $perl_dir); require 'lib_utils.pl' or die "Unable to load 'lib_utils.pl' Check paths in \@INC...\n"; # log file stuff our ($LF); my $pgmname = $0; if ($pgmname =~ /(\\|\/)/) { my @tmpsp = split(/(\\|\/)/,$pgmname); $pgmname = $tmpsp[-1]; } my $outfile = $temp_dir.$PATH_SEP."temp.$pgmname.txt"; open_log($outfile); # user variables my $VERS = "0.0.2 2013-08-07"; #my $VERS = "0.0.1 2013-08-03"; my $load_log = 0; my $in_file = ''; my $verbosity = 0; my $out_file = ''; my $max_errors = 50; my $shown_errors = 0; # ### DEBUG ### my $debug_on = 0; my $def_file = 'C:\FG\18\gettext-0.18.1.1\build\bldlog-1.txt'; ### program variables my @warnings = (); my $cwd = cwd(); sub VERB1() { return $verbosity >= 1; } sub VERB2() { return $verbosity >= 2; } sub VERB5() { return $verbosity >= 5; } sub VERB9() { return $verbosity >= 9; } sub show_warnings($) { my ($val) = @_; if (@warnings) { prt( "\nGot ".scalar @warnings." WARNINGS...\n" ); foreach my $itm (@warnings) { prt("$itm\n"); } prt("\n"); } else { prt( "\nNo warnings issued.\n\n" ) if (VERB9()); } } sub pgm_exit($$) { my ($val,$msg) = @_; if (length($msg)) { $msg .= "\n" if (!($msg =~ /\n$/)); prt($msg); } show_warnings($val); close_log($outfile,$load_log); exit($val); } sub prtw($) { my ($tx) = shift; $tx =~ s/\n$//; prt("$tx\n"); push(@warnings,$tx); } sub process_in_file($) { my ($inf) = @_; if (! open INF, "<$inf") { pgm_exit(1,"ERROR: Unable to open file [$inf]\n"); } my @lines = ; close INF; my $lncnt = scalar @lines; prt("Processing $lncnt lines, from [$inf]...\n"); my ($line,$inc,$lnn,$proj,$conf,$tline,$len,$num,$cnt,$smsg,$ecnt,$wcnt,$twcnt,$tecnt,$lecnt); my ($pcnt,@arr,$func,$key,$j,$gotf1,$gotf2,$func2,$tmp,$ind,$msg); my ($i,$mt); $lnn = 0; $proj = ''; $conf = ''; my %errors_nums = (); my %warn_nums = (); my %link_nums = (); my %link_func = (); my @warn_lines = (); my @msg_lines = (); my $mt_start = 1; my $mt_warn = 2; my $mt_errc = 3; my $mt_errl = 4; my $mt_fatal = 5; $ecnt = 0; $wcnt = 0; $twcnt = 0; $tecnt = 0; $pcnt = 0; $lecnt = 0; my %wnums = (); foreach $line (@lines) { chomp $line; $lnn++; $tline = trim_all($line); $len = length($tline); next if ($len == 0); # ------ Build started: Project: libxml, Configuration: Debug Win32 ------ if ($line =~ /^------ Build started: Project: (.+), Configuration: (.+) ------/) { $proj = $1; $conf = $2; $cnt = scalar @warn_lines; if ($cnt) { if (length($smsg)) { prt("$smsg\n"); push(@msg_lines, [$mt_start,$smsg]); } @arr = keys %wnums; $msg = "Got $cnt warnings... ".join(" ",@arr); prt("$msg\n"); push(@msg_lines, [$mt_start,$msg]); } $smsg = "$lnn: Starting [$proj], config [$conf]"; prt("$smsg\n") if (VERB9()); $ecnt = 0; $wcnt = 0; %wnums = (); @warn_lines = (); $pcnt++; } # ..\gettext-tools\gnulib-lib\tempname.c(270): error C2065: 'O_ACCMODE' : undeclared identifier elsif ($line =~ /: error C(\d+):/) { $num = $1; if (length($smsg)) { push(@msg_lines, [$mt_start,$smsg]); prt("$smsg\n"); } $msg = "$lnn: $num [$tline]"; if ($max_errors > 0) { prt("$msg\n") if ($shown_errors < $max_errors); } else { prt("$msg\n"); } push(@msg_lines, [$mt_errc,$msg]); $shown_errors++; $errors_nums{$num} = 1; $ecnt++; $tecnt++; $smsg = ''; } # ..\gettext-tools\gnulib-lib\gettimeofday.c(24): fatal error C1083: Cannot open include file: 'sys/time.h': No such file or directory elsif ($line =~ /: fatal error C(\d+):/) { $num = $1; prt("$smsg\n") if (length($smsg)); $msg = "$lnn: $num [$tline]"; if ($max_errors > 0) { prt("$msg\n") if ($shown_errors < $max_errors); } else { prt("$msg\n"); } push(@msg_lines, [$mt_fatal,$msg]); $shown_errors++; $errors_nums{$num} = 1; $ecnt++; $tecnt++; $smsg = ''; } # ..\gettext-tools\gnulib-lib\fd-safer.c(39): warning C4047: '<=' : 'int' differs in levels of indirection from 'FILE *' elsif ($line =~ /: warning C(\d+):/) { $num = $1; $msg = "$lnn: $num [$tline]"; push(@msg_lines, [$mt_warn,$msg]); if (!defined $warn_nums{$num}) { push(@warn_lines,[$lnn,$tline]); $warn_nums{$num} = 1; $wnums{$num} = 1; } $twcnt++; } # MSVCRTD.lib(MSVCR100D.dll) : error LNK2005: _setlocale already defined in setlocale.obj # libgnuintld.lib(dcigettext.obj) : error LNK2019: unresolved external symbol __nl_locale_name_default referenced in function _guess_category_value elsif ($line =~ /: error LNK(\d+):\s+(\S+)\s+/ ) { $num = $1; $func = $2; $gotf1 = 0; $gotf2 = 0; if ($func eq 'unresolved') { @arr = space_split($line); $cnt = scalar @arr; for ($j = 0; $j < $cnt; $j++) { $tmp = $arr[$j]; if ($gotf1) { if (($tmp eq 'function')&&(($j + 1) < $cnt)) { $j++; $func2 = $arr[$j]; $gotf2 = 1; last; } } else { if (($tmp eq 'symbol')&&(($j + 1) < $cnt)) { $j++; $func = $arr[$j]; $gotf1 = 1; } } } } $tmp = $line; if ( ($num == 2019) && $gotf1 && $gotf2 ) { $ind = index($line,' : error LNK'); if ($ind > 3) { $tmp = substr($line,0,$ind); $tmp .= " func: $func2"; } } $msg = "$lnn:$num:$func:$tmp"; push(@msg_lines,[$mt_errl,$msg]); if (!defined $link_func{$num.$func}) { $link_func{$num.$func} = "$lnn: $func $tmp"; } if (!defined $link_nums{$num}) { $link_nums{$num} = "$lnn: $tmp"; } $lecnt++; } elsif ($line =~ /: error LNK(\d+):/ ) { $num = $1; $msg = "$lnn:$num:$line"; push(@msg_lines,[$mt_errl,$msg]); if (!defined $link_nums{$num}) { $link_nums{$num} = "$lnn: $line"; } $lecnt++; } } $cnt = scalar @warn_lines; if ($cnt) { if (length($smsg)) { prt("$smsg\n"); push(@msg_lines, [$mt_start,$smsg]); } @arr = keys %wnums; $msg = "Got $cnt warnings... ".join(" ",@arr); prt("$msg\n"); push(@msg_lines, [$mt_start,$msg]); } prt("Had $pcnt project, total errors comp $tecnt, link $lecnt, warnings $twcnt\n"); @arr = keys(%errors_nums); prt("Err # ".join(" ",@arr)); @arr = keys(%warn_nums); prt(" Warn # ".join(" ",@arr)); @arr = keys(%link_nums); prt(" Link # ".join(" ",@arr)); prt("\n"); @arr = keys(%link_func); $cnt = scalar @arr; if ($cnt) { prt("Link errors: $cnt\n"); foreach $key (@arr) { $line = $link_func{$key}; prt("$line\n"); } } # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # 115: 1083 [C:\FG\18\beye\src\plugins/bin/mmio.h(5): fatal error C1083: Cannot open include file: 'plugin.h': No such file or directory] # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 # 190: 1903 [C:\FG\18\beye\src\plugins/bin/lx_le.h(215): fatal error C1903: unable to recover from previous error(s); stopping compilation] $cnt = scalar @msg_lines; my $fcnt = 0; my ($acnt,$file); my %inc_files = (); my @fatal_errors = (); for ($i = 0; $i < $cnt; $i++) { $mt = $msg_lines[$i][0]; if ($mt == $mt_fatal) { $msg = $msg_lines[$i][1]; @arr = space_split($msg); $acnt = scalar @arr; if ($acnt > 10) { next if ($arr[6] eq 'unable'); $lnn = $arr[0]; $file = $arr[2]; $tmp = $arr[10]; if (!defined $inc_files{$tmp}) { $inc_files{$tmp} = 1; $msg = "$lnn: in $file, unable to open [$tmp]\n"; push(@fatal_errors,$msg); } } else { push(@fatal_errors,"$msg\n"); } } } $fcnt = scalar @fatal_errors; if ($fcnt) { prt("Have $fcnt fatal errors...\n"); prt(join("",@fatal_errors)); } } ######################################### ### MAIN ### parse_args(@ARGV); process_in_file($in_file); pgm_exit(0,""); ######################################## sub need_arg { my ($arg,@av) = @_; pgm_exit(1,"ERROR: [$arg] must have a following argument!\n") if (!@av); } sub parse_args { my (@av) = @_; my ($arg,$sarg); while (@av) { $arg = $av[0]; if ($arg =~ /^-/) { $sarg = substr($arg,1); $sarg = substr($sarg,1) while ($sarg =~ /^-/); if (($sarg =~ /^h/i)||($sarg eq '?')) { give_help(); pgm_exit(0,"Help exit(0)"); } elsif ($sarg =~ /^v/) { if ($sarg =~ /^v.*(\d+)$/) { $verbosity = $1; } else { while ($sarg =~ /^v/) { $verbosity++; $sarg = substr($sarg,1); } } prt("Verbosity = $verbosity\n") if (VERB1()); } elsif ($sarg =~ /^l/) { if ($sarg =~ /^ll/) { $load_log = 2; } else { $load_log = 1; } prt("Set to load log at end. ($load_log)\n") if (VERB1()); } elsif ($sarg =~ /^o/) { need_arg(@av); shift @av; $sarg = $av[0]; $out_file = $sarg; prt("Set out file to [$out_file].\n") if (VERB1()); } else { pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n"); } } else { $in_file = $arg; prt("Set input to [$in_file]\n") if (VERB1()); } shift @av; } if ($debug_on) { prtw("WARNING: DEBUG is ON!\n"); if ((length($in_file) == 0) && $debug_on) { $in_file = $def_file; prt("Set DEFAULT input to [$in_file]\n"); } } if (length($in_file) == 0) { pgm_exit(1,"ERROR: No input files found in command!\n"); } if (! -f $in_file) { pgm_exit(1,"ERROR: Unable to find in file [$in_file]! Check name, location...\n"); } } sub give_help { prt("$pgmname: version $VERS\n"); prt("Usage: $pgmname [options] in-file\n"); prt("Options:\n"); prt(" --help (-h or -?) = This help, and exit 0.\n"); prt(" --verb[n] (-v) = Bump [or set] verbosity. def=$verbosity\n"); prt(" --load (-l) = Load LOG at end. ($outfile)\n"); prt(" --out (-o) = Write output to this file.\n"); } # eof - template.pl