#!/usr/bin/awk -f # # filter stdout/stderr of make to output from tree leves where # the make failed # # output looks like this if a command executed by a target fails: # make[3]: Entering directory `/scratch/markd/kent/src/hg/lib/tests' # .. # make[3]: *** [spDbTest] Error 255 # make[3]: Leaving directory `/scratch/markd/kent/src/hg/lib/tests' # # If make generates an error, the results looks like this if it's in the # top top level make: # # make[1]: Entering directory `/cluster/store3/markd/kent/src/lib' # ../inc/common.mk:2: *** missing separator. Stop. # make[1]: Leaving directory `/cluster/store3/markd/kent/src/lib' # make: *** [clean] Error 2 # # and like this in lower-levels # make[2]: Entering directory `/cluster/store3/markd/kent/src/lib' # ../inc/common.mk:2: *** missing separator. Stop. # make[2]: Leaving directory `/cluster/store3/markd/kent/src/lib' # make[1]: *** [clean] Error 2 # make[1]: Leaving directory `/cluster/store3/markd/kent/src' # # this makes the state machine somewhat complex # # parse make[n] to get level function getLevel(line) { if (match(line, "^make:") != 0) { return "0"; # top level } if (match(line, "^make\\[([0-9]+)\\]:", a) == 0) { print "Error: can't parse:",line >"/dev/stderr"; exit(1); } return a[1]; } # print buffered lines, if there is any output buffered. Reset buffer # state function prLines(level) { if ((levelOutCnt[level] > 0) && (levelStarts[level] <= nLines)) { if (errCount == 0) { print sep >"/dev/stderr"; } for (i = levelStarts[level]; i <= nLines; i++) { print lines[i] >"/dev/stderr"; } print sep >"/dev/stderr"; nLines = 0; levelOutCnt[level] = 0; levelStarts[level] = -1; errCount++; } } BEGIN { nLines = 0; # count of lines buffered in lines array level = 0; # current make level curLevel = 0; # currrent level being parsed prevWasLeave = 0; # previous line was leaving a directory errCount = 0; # count of errors reported # arrays # lines - array of all lines in file # levelStarts - contains line index where level started # levelOutCnt - count of none make: lines at this level sep = "-----------------------------------------------------"; } { lines[++nLines] = $0; } /^make\[[0-9]+\]: Entering directory/ { curLevel = getLevel($0); levelStarts[curLevel] = nLines; levelOutCnt[curLevel] = 0; } /^make.*: \*\*\*/ { prLines((prevWasLeave ? curLevel+1 : curLevel)); } { prevWasLeave = 0; # reset now that print check is done. } /^make\[[0-9]+\]: Leaving directory/ { curLevel = getLevel($0)-1; prevWasLeave = 1; } !/^make\[[0-9]+\]:/ { levelOutCnt[curLevel]++; }