All pastes #374742 Raw Edit

Stuff

public text v1 · immutable
#374742 ·published 2007-02-27 20:15 UTC
rendered paste body
#!/usr/bin/perl -w
=pod

This program is Copyright © 2007 Thiago Macieira <thiago@kde.org>
=head1 License
   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; see the file COPYING.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.

=head1 Description
   pmake is a make-colourising and progress reporting tool.
   It's not very intelligent at all...

   It simply runs make with the -n (--dry-run) option to count the lines
   and then displays a percentage based on how much of that make has run
   already.

   That means it very often gets the percentages very, very wrong. You can
   get 120% or more, easily, in some builds. In other cases, make -n reports
   an error that make would not report. In that case, pmake will not work.

   pmake can be used with colorgcc if you apply to it a patch to make
   it send its output to stdout. If you fail to do that, pmake will report
   all compilation errors and warnings as "Executing:" commands.

=item patch to apply to colorgcc:
--- /usr/bin/colorgcc-4.1.2~    2007-01-15 14:02:08.000000000 +0100
+++ /usr/bin/colorgcc-4.1.2     2007-01-21 17:43:03.000000000 +0100
@@ -232,6 +232,7 @@
 $compiler_pid = open3('<&STDIN', \*GCCOUT, \*GCCOUT, $compiler, @ARGV);

 # Colorize the output from the compiler.
+select STDERR;
 while(<GCCOUT>)
 {
    if (m/^(.*?):([0-9]+):(.*)$/) # filename:lineno:message
=cut
use strict;

my $MAKE = $ENV{"MAKE"} || "/usr/bin/make";
my ($RED, $GREEN, $YELLOW, $NORMAL, $BOLD) = ("") x 5;
my $TOTAL;
my $NR = 0;

# Count the number of lines in the output
open(FROM_CHILD, "-|", $MAKE, "-n", @ARGV);
while (<FROM_CHILD>)
{
    next if (/^make/);          # Don't count make's own lines
    $NR++;
}
close(FROM_CHILD);
exit $? >> 8 if $?;
$TOTAL = $NR;

if (! -t STDOUT || $ENV{"TERM"} eq "dumb") {
    # Dumb terminal or output is not a terminal
    # Don't try to colourise, so we don't need to open a terminal
    # Just use a pipe

    pipe(FROM_CHILD, TO_PARENT) or die "Cannot execute make: $!";
    my $pid = fork;
    die "Cannot execute make: $!" if not defined($pid);
    unless ($pid) {
        # Child
        close(FROM_CHILD);
        open(STDOUT, ">&TO_PARENT");
        close(TO_PARENT);
        exec $MAKE, @ARGV;
    }
    close(TO_PARENT);
} else {
    # Colour-capable terminal (we hope)
    # Colourise
    # We open a new terminal so that colorgcc colourises too
    $RED = "\e[31m";
    $GREEN = "\e[32m";
    $YELLOW = "\e[1;33m";
    $NORMAL = "\e[0m";
    $BOLD = "\e[1m";

    use IO::Pty;
    my $pty = new IO::Pty;
    my $pid = fork;
    die "Cannot execute make: $!" if not defined($pid);
    unless ($pid) {
        # Child
        my $slave = $pty->slave();
        $slave->set_raw();

        # Dup the terminal to stdout
        open(STDOUT, ">&" . $slave->fileno());
        close($slave);
        close($pty);

        exec $MAKE, @ARGV;
    }
    open(FROM_CHILD, "<&=" . $pty->fileno());

    $pty->close_slave();
    close($pty);
}

# Process make's output
$NR = 0;
while (<FROM_CHILD>) {
    next if (/^make/);          # Don't display make's own lines
    chomp;
    my $original = $_;

    # Display the progress percentage
    printf "[%3d%%] ", $NR++ * 100 / $TOTAL
        if $TOTAL;

    # Find out which program was run
    s,^ *[^ ]*/,,;
    if (/^(cc|gcc|c\+\+|g\+\+|g?as|moc|uic3?)/) {
        # A compiler was run
        my $target = "";
        my $prog = $1;
        s/^[^ ]* //;

        if ($prog eq "moc" or $prog eq "uic" or $prog eq "uic3") {
            print "${YELLOW}Running $prog on ";
        } elsif ($prog eq "as" or $prog eq "gas") {
            print "${GREEN}Assembling ";
        } elsif (/(^| )-c( |$)/) {
            print "${GREEN}Compiling ";
        } else {
            print "${RED}Linking ";
            print "library " if (/(^| )-shared( |$)/);
            print "executable " unless (/(^| )-shared( |$)/);
            /(^| )-o +([^ ]+)( |$)/ and $target = $2;
        }
        if ($target eq "") {
            s/(^| )*-(o|x|include) +[^ ]+ */ /g;
            /(^| )([^- ][^ ]*)( |$)/;
            $target = $2;
        }
        print $BOLD, $target;
    } elsif (/^ar c[^ ]* ([^ ]*) /) {
        print "${RED}Creating static library $1";
    } else {
        print "${BOLD}Executing: $NORMAL$original";
    }
    print "$NORMAL\n";
}
close(FROM_CHILD);
wait();
exit $? >> 8;