5 # Reduces the amount of output from make.
6 # Recognises commands from glibc and linux kernel builds.
8 # Copyright 2002 Philip Craig (philipc@snapgear.com)
9 # Based on Rob Landley's blueberry.py
12 ### Start of configurable options...
14 # Print the full file paths instead of the "Entering $dir" messages
17 # Print errors highlighted
19 # Using ^H to make errors bold (less understands this)
21 # Use a color ("1;38" is light grey) (less needs the -R option for this)
22 $errorcolour = "1;38";
24 # Display "Installing ... " messages
26 # Display "Archiving to ... " messages
29 # Exec make instead of reading stdin
31 # Run make based on whether stdin is a tty
32 # This lets you use qmake as a replacement for make if stdin is a tty,
33 # or otherwise pipe the output of make into qmake.
39 $nexttarget = '(unknown)';
40 @target = ('(default)');
41 chomp($topdir = `pwd`);
52 $file = "$dir[$#dir]/$file";
54 if ($file =~ /^\Q$topdir\E\/(.*)$/) {
59 if ($file =~ /^\Q$topdir\E\/(.*)$/) {
60 if ($1 =~ /^\Q$dir[$#dir]\E\/(.*)$/) {
81 if (defined($splitline)) {
88 defined($_) || return $_;
94 defined($nextline) || last;
96 $_ = join(' ', split(/\s+/, $_.' '.$nextline));
101 # We're not smart enough to split loop constructs yet though
102 if (!(/^\s*for\s+/ || /^\s*do\s+/ || /^\s*if\s+/)
103 && /^([^\[\]\(\)\{\}\`\;]+);\s+(.+)$/) {
132 if (!$fullpath && (!defined($lastdir) || $lastdir ne $dir[$#dir])) {
133 $lastdir = $dir[$#dir];
134 if ($target[$#target] !~ /dep/) {
138 put_message("Entering $lastdir\n");
146 if (defined($line)) {
152 #print "Unknown: $raw";
166 sub put_action_file {
167 my($action, $file) = @_;
170 if (defined($action) && defined($file)) {
171 $line = "$action " . nice_file($file);
176 sub show_lasthidden {
177 if (defined($lasthidden)) {
178 put_message($lasthidden);
184 my($error1, $error2) = @_;
188 if ($highlighterror) {
191 foreach $i (split(//, $error1)) {
197 $raw = "\033[" . $errorcolour . "m"
198 . $error1 . "\033[0m" . $error2;
202 $raw = $error1 . $error2;
217 open(MAKE, '-|', "make " . join(' ', @ARGV) . " 2>&1")
218 || die 'Could not execute make';
231 LINE: while (defined($_ = get_line($fh))) {
233 next LINE if /^\d+\s+/;
237 next LINE if /^[ar]\s+-\s+/;
243 next LINE if /^\s*-?\d+\.\d+%/;
244 next LINE if /^Directory/;
247 if ($makewait ne "") {
249 next LINE if ($#word <= 0 || $word[0] ne $makewait);
253 # Remove '[ ... ] || ' from start
254 if (/^\[[^\[\]]*\]\s*\|\|\s*(.*)$/) {
259 # Remove ENVVAR="..." from start
260 if (/^\w+=\"[^\"]*\"\s+(.*)$/) {
265 # Remove 'cd dir && " from start
266 if (/^cd\s+\S+\s+\&\&\s+(.*)$/) {
267 # TODO: should remember dir for displaying filenames
272 # Remove '(echo ...) | ' from start (glibc stuff)
273 if (/^\(echo.*\)\s+\|\s+(gcc.*)$/) {
278 # Remove 'ld-linux.so.2' from start (glibc stuff)
279 if (/^\S*\/ld-linux.so.2\s+(--library-path\s+\S+)?\s+(.*)$/) {
284 # Remove + from the start (from bash set +x)
289 # Handle 'In file included from xxx.c:dd:' errors
290 if (/^In file included from /) {
297 if (/^[mM]aking all in /
298 || /^You may get an error following this line./) {
310 if (/ -> .*busybox/) {
315 #parallel job output during configure check
316 if (/^checking .*\.\.\. (make.*[^.])$/) {
317 print("Found checking continuation\n");
323 ($#word >= 0) || next LINE;
326 /^(.*[-\/])?ar$/ && do {
329 put_action_file('Creating empty', $word[2]);
336 put_action_file('Archiving to', $word[2]);
344 (/^(.*[-\/])?as$/ || /^(.*\/)?as86$/) && do {
346 put_action_file('Assembling', $word[$#word]);
352 (/^(.*[-\/])?(k?g)?cc$/ || /^(.*[-\/])?g\+\+$/) && do {
355 for $i (@word[1 .. $#word]) {
357 $action = 'Preprocessing';
359 elsif ($i eq '-c' || $i eq '-S') {
360 $action = 'Compiling';
363 $action = 'Generating dependencies for';
366 if ($action eq 'Linking') {
367 for ($i=1; $i<$#word; $i++) {
368 if ($word[$i] eq '-o') {
375 WORD: for $i (@word[1 .. $#word]) {
376 if ($i =~ /\.[sS]$/) {
377 if ($action eq 'Compiling') {
378 $action = 'Assembling';
383 elsif ($i =~ /\.c(pp)?$/ || $i =~ /\.ld$/) {
388 for ($i=1; $i<$#word; $i++) {
389 if ($word[$i] eq '-o') {
390 $action .= ' from stdin to';
398 if (defined($file)) {
399 put_action_file($action, $file);
413 if ($#word >=3 && $word[$#word-1] eq '>'
414 && $word[$#word] =~ /\/stamp\.o[sS]?T$/) {
419 if ($#word >=3 && $word[$#word-1] eq '>'
420 && $word[$#word] =~ /\.lo$/) {
430 for ($i=1; $i<$#word; $i++) {
431 if ($word[$i] eq '-f') {
434 if ($word[$i] eq '-d') {
438 if (defined($from) && defined($to)) {
439 put_line("Generating romfs $to from $from");
448 (/^(.*\/)?install$/ || /^romfs-inst.sh$/) && do {
454 if ($word[$#word] =~ /(.*)\.new$/) {
455 put_action_file('Installing', $1);
458 put_action_file('Installing', $word[$#word]);
465 (/^(.*[-\/])?ld$/ || /^(.*\/)?ld86$/) && do {
466 for ($i=1; $i<$#word; $i++) {
467 if ($word[$i] eq '-o') {
468 put_action_file('Linking', $word[$i+1]);
475 /^(.*\/)?ln$/ && do {
476 if ($#word >= 2 && $word[1] =~ /^-.*s/) {
485 put_action_file('Preprocessing', $word[$#word]);
492 if ($#word >= 3 && $word[1] eq '-C') {
493 $nexttarget = join(' ', @word[3 .. $#word]);
495 elsif ($#word >= 1) {
496 $nexttarget = join(' ', @word[1 .. $#word]);
499 $nexttarget = '(default)';
501 # TODO: nexttarget needs more cleaning to be printable,
502 # but it's good enough to determine 'make dep' targets...
507 /^make(\[[0-9]+\])?:$/ && do {
509 if ($word[2] eq 'directory') {
510 if ($word[1] eq 'Entering') {
512 if ($dir =~ /^\`(.*)\'$/) {
515 if ($dir =~ /^\Q$topdir\E\/(.*)$/) {
519 push @target, $nexttarget;
520 $nexttarget = '(unknown)';
522 elsif ($word[1] eq 'Leaving') {
529 elsif ($word[1] eq 'Nothing') {
533 elsif ($word[$#word] eq 'date.') {
537 elsif ($word[2] eq 'jobserver'|| $word[$#word-1] eq 'jobserver') {
541 elsif ($word[2] eq 'Waiting') {
542 $makewait = $word[0];
547 put_error($word[0], substr($allwords, length($word[0])));
551 /^\.\/mkbuiltins$/ && do {
557 /^(.*\/)?mkcramfs$/ && do {
563 put_line("Finding dependencies in $dir[$#dir]");
567 (/\/mkinstalldirs$/ || /^mkdir$/) && do {
575 if ($word[$#word-1] eq $word[$#word].'T') {
580 if ($word[$#word-1] eq $word[$#word].'.new') {
588 /^(.*[-\/])?nm$/ && do {
590 put_action_file('Extracting symbols to', $word[$#word]);
596 /^(.*[-\/])?objcopy$/ && do {
598 put_action_file('Objcopy to', $word[$#word]);
604 /^(.*[-\/])?ranlib$/ && do {
609 /^(.*\/)?rm$/ && do {
615 # mysql dependency checking
620 /^(.*[-\/])?strip$/ && do {
627 if ($#word >=1 && $word[$#word] =~ /\/stamp.o[sS]?$/) {
636 if ($word[1] eq 'GCC_EXEC_PREFIX') {
645 put_action_file('Compiling timezone', $word[$#word]);
662 put_error($allwords, '');
667 put_error($word[0], substr($allwords, length($word[0])));