#! /usr/bin/env perl # -*- Mode: perl; -*- # # Set Defaults $debug = 0; $debugDir = 0; $gDebugOther = 0; $summaryOutput = 0; $terseOutput = 1; $rootSrcDir = ""; # Define the known commands, along with known make noise (results of # echo) # We include /bin/rm and /bin/mv because some Makefile authors prefer # to get the full path for these routines @commands = ( "cc", "pgcc", "gcc", "icc", "acc", "rm", "mv", "cp", "ar", "ranlib", "perl", "for", "/bin/rm", "/bin/mv", "/bin/cp", "/bin/chmod", "rm", "mv", "cp", "chmod", "if", "make", "gnumake", "[A-Za-z0-9_\/\.-]*\/mpicc", "[A-Za-z0-9_\/\.-]*\/mpifort", "[A-Za-z0-9_\/\.-]*\/mpicxx", "cleaning", "sleep", "date", "g77", "f77", "f90", "f95", "pgCC", "pgf77", "pgf90", "CC", "g95", "g\\+\\+", "c\\+\\+", "acc\\+\\+", "xlc", "xlf", "xlC", "xlf90", "gfortran", "ifort", "ifc", "test", "true", "false", "/[A-Za-z0-9_\/\.-]*createshlib", "/bin/sh\\s+[A-Za-z0-9_\/\.-]*libtool\\s+\(--tag=\\w+\)*\\s+--mode=\\w+", "/bin/bash\\s+[A-Za-z0-9_\/\.-]*libtool\\s+--mode=\\w+", "/bin/sh\\s+[A-Za-z0-9_\/\.-]*libtool\\s+--finish", "/bin/bash\\s+[A-Za-z0-9_\/\.-]*libtool\\s+--finish", "libtool:\\s+compile:", "libtool:\\s+link:", "libtool:\\s+install:", "libtool:\\s+finish:", "[A-Za-z0-9_\/-]*\/icc", "[A-Za-z0-9_\/-]*\/install-sh", "/usr/bin/ar", "mkdir", "/bin/mkdir", "/.*bin/mkdir", "/usr/ucb/ld", "mpicc", "mpicxx", "compiling ROMIO in", "Make completed", "echo", "cat", "CC", "CCLD", "AR", "RANLIB", "LIBTOOL", "MV", "MOD", "GEN", "F77", "FC", "CXXLD", "CXX", "FCLD", "CP", # "terse" make versions "\\(?cd", "\\(\\s*cd", "creating\s+lib.*", "cd\\s+\&\&\\s+make", "sed -e", "PATH=\"\\\$PATH.*\\sldconfig\\s", "building profiling interface in directory", "/usr/bin/install", "/.*bin/install", ".*confdb/install-sh", "Copying Upshot", "Cleaning directory", "[*][*][*][*] Making .*\.\.\.\.", "Making .* in .*", "Making upshot", "\\s*\$", "ld: warning: directory not found for option '-L\\S*src/mpl'", "ld: warning: directory not found for option '-L\\S*src/openpa/src'", ); # OtherNoise is an array of patterns that describe blocks of # text that we'd like to skip. The initial use it to handle # libtool install output. # The PG entries are work-arounds for bugs in the PG header files that have # small incompatibilities with the system header file /usr/include/unistd.h # @OtherNoise = ( 'Libraries have been installed in:more information, such as the ld\(1\) and ld.so\(8\) manual pages.20', '^\s*-+\s*$1', '^In directory:1', '^creating\s1', # '^PGC-W-0114-More than one type.*/usr/include/unistd.h: 189^PGC-W-0143-Useless typedef.*/usr/include/unistd.h: 1892', # '^PGC-W-0114-More than one type.*/usr/include/unistd.h: 243^PGC-W-0143-Useless typedef.*/usr/include/unistd.h: 2432', '^PGC.*: compilation completed with warnings1', # This next is a general version to handle all of these mistakes '^PGC-W-0114-More than one type specified.*/usr/include^PGC-W-0143-Useless typedef declaration \(no declarators present\).*/usr/include2', 'copying python', 'LOOP WAS VECTORIZED', 'Using variables ', ); # In the past, we also needed # WARNING 84.*not used for resolving any symbol # Info: File not optimized $trimCompileLine = 1; # Create the variables that keep track of state # dirstack keeps the directory name that gnumake and similar make # implementations echo as a directory is entered or exited (this can generate # a great deal of output noise that can obscure important data. However, when # a problem *does* occur, this directory information is valuable. # dirprinted is a parallel array that indicates whether the corresponding # directory entry has been printed. @dirstack = (); @dirprinted = (); # Process arguments to select options foreach $_ (@ARGV) { if (/^--?debug/) { $debug = 1; } elsif (/^--?showdir/) { $debugDir = 1; } elsif (/^--?summary/) { $summaryOutput = 1; } elsif (/^--?notrimcompileline/) { $trimCompileLine = 0; } elsif (/^-/) { print STDERR "Unrecognized argument $_\n"; print STDERR "clmake [ -debug ] [ -showdir ] [ -summary ]\n"; exit(1); } else { last; } shift @ARGV; } # Read lines. Categorize lines as commands and output. This # script suppresses commands that generate no extra output. # The approach is to read a line and then read the next line. # While the line is a command and the next line is not, output the # line. # # We use eof() (see man perlfun) so that we can accept filenames on the # commandline. # $cmdline = ""; T: while ($line = <>) { if (eof()) { next; } $line =~ s/\r//; # remove returns from line (de DOSify) # Read the next line, including handling any continuation lines while ($line =~ /\\$/) { print "Read continuation line (cmd) ... \n" if $debug; $line .= <>; } # Check for noise foreach my $pat (@OtherNoise) { # maxlines is the maximum number of lines to match my ($beginpat,$endpat,$maxlines) = split( '', $pat ); print "Trying to match $beginpat\n" if $gDebugOther; if ($line =~ /$beginpat/) { $maxlines --; print "Found match to $beginpat\n" if $gDebugOther; # Found the beginning. Look for the end (if one requested) if ($endpat =~ /\S/) { print "Trying to match endpat $endpat\n" if $gDebugOther; while ($line = <>) { if (eof()) { last; } print "Trying to match to $line" if $gDebugOther; if ($line =~ /$endpat/) { last; } if ($maxlines-- <= 0) { print STDOUT "Failed to match $endpat; last line was $line"; last; } } } next T; } } # Is the line a command (including a directory change?) # Check first for a directory change if ($line =~ /^\s*make.* Entering directory \`([^\']*)\'/) { my $dirname = $1; $dirstack[$#dirstack+1] = $dirname; $dirprinted[$#dirprinted+1] = 0; print ">>entering $dirname\n" if $debugDir; $cmdline = ""; next; } elsif ($line =~ /^\s*make.* Leaving directory \`([^\']*)\'/) { # We should check that the directory names match my $dirname = $1; print ">>leaving $dirname\n" if $debugDir; if ($dirname ne $dirstack[$#dirstack]) { print STDERR "Warning: leaving directory $dirname but expected to leave directory " . $dirstack[$#dirstack] . "\n"; } $#dirstack--; $#dirprinted--; $cmdline = ""; next; } else { $is_command = 0; foreach $cmdname (@commands) { if ($line =~ /^\s*$cmdname\W/) { $is_command = 1; $cmdline = $line; last; } } if ($is_command) { if ($summaryOutput) { # FIXME: Summarize the command if ($terseOutput) { if ($rootSrcDir eq "") { if ($line =~ /\s(\/\S+\/src\/)/) { $rootSrcDir = $1; print "rootSrcDir = $rootSrcDir\n"; } } else { $line =~ s/$rootSrcDir//g; } # Compiler options to remove $line =~ s/-I\S+\s+//g; $line =~ s/-W\S+\s+//g; $line =~ s/-D\S+\s+//g; } print $line; } next; } } # If we got to this point, the line was not a recognized command or # ignorable output. Output the line, including the command if this # is the first time. We can then forget the command if ($#dirstack >= 0 && $dirprinted[$#dirstack] == 0) { print "In directory: ". $dirstack[$#dirstack] . "\n"; $dirprinted[$#dirstack] = 1; } if ($cmdline ne "") { if ($trimCompileLine) { # Simplify the command line before printing $cmdline =~ s/-I\S*\s+//g; $cmdline =~ s/-ansi//g; $cmdline =~ s/-W\S*\s+//g; $cmdline =~ s/-DHAVE_CONFIG_H//g; $cmdline =~ s/-DGCC_WALL//g; } # We could print a newline here to separate commands print $cmdline; $cmdline = ""; } print $line; } # # ToDo: # Handle lines containing just ----, e.g., patterns of the form # -*