[Evolution-hackers] Make wrapper



I wrote a small make wrapper that might be useful when doing large
builds (say, of evolution). It makes the build output be more brief, and
colorizes it, drawing attention towards warnings. It doesn't parse
everything correctly (e.g. linking executables), but it's good enough
for my purposes, at least.

I do

alias make='hpj-make'
alias old-make='/usr/bin/make'

in my .bashrc, so I can type make like normal, and fall back to an
unwrapped make in case the script culls some output I want.

In case anyone's interested, it's attached.

I also took a screenshot of an EDS build:

http://hp.cl.no/dist/hpj-make.png

...I hope we can clean that up eventually :)

--
Hans Petter
#!/usr/bin/perl

$DEBUG = 0;

$dump_unmatched = 0;

$topdir      = $ENV {'PWD'};
$status      = { };
$last_status = { };
$exit_status = 0;

sub clear_status
{
    my $pad = "";

    for (my $i = 0; $i < $status {'last_len'}; $i++)
    {
        $pad .= " ";
    }
    print "\r" . $pad . "\r";
}

sub print_status
{
    if (length ($status {'dir'}) == 0) { $status {'dir'} = "."; }

    # Do nothing if display didn't change.
    if ($last_status {'dir'}       eq $status {'dir'}  &&
        $last_status {'file'}      eq $status {'file'} &&
        $last_status {'operation'} eq $status {'operation'} &&
        $status {'force_print'} == 0)
    {
        return;
    }

    my $this_len = 8 +
                   length ($status {'dir'});

    print "\r\e[1;36m" . sprintf ("%7.7s", $status {'operation'}) .
          "\e[0;36m " . $status {'dir'};

    if (length ($status {'file'}) && $this_len < 76)
    {
        print "\e[1;36m | \e[0;36m";
        $this_len += 3;

        if ($this_len + length ($status {'file'}) > 79)
        {
            printf ("%-" . (79 - $this_len) . "." . (79 - $this_len) . "s",
                    $status {'file'});
            $this_len = 79;
        }
        else
        {
            print $status {'file'};
            $this_len += length ($status {'file'});
        }
    }

    print "\e[0;37m";

    if ($this_len < $status {'last_len'})
    {
        my $pad = "";
        for (my $i = 0; $i < $status {'last_len'} - $this_len; $i++)
        {
            $pad .= " ";
        }
        print $pad;
    }

    $status {'force_print'} = 0;
    $status {'last_len'} = $this_len;

    # Update status cache.
    $last_status {'dir'}       = $status {'dir'};
    $last_status {'file'}      = $status {'file'};
    $last_status {'operation'} = $status {'operation'};

    if ($DEBUG == 1) { print "\n"; }
}

sub print_warning
{
    if ($status {'reported'} != 1)
    {
        print "\n";
        $status {'reported'} = 1;
    }
    else
    {
        clear_status;
    }

    print "\e[1;33mwarning\e[0;33m " .
          sprintf ("%-71.71s", @_ [0]) . "\n";

    $status {'force_print'} = 1;
}

sub print_error
{
    if ($status {'reported'} != 1)
    {
        print_status;
        print "\n";
        $status {'reported'} = 1;
    }
    else
    {
        clear_status;
    }

    print "\e[1;31m  error\e[0;31m " .
          sprintf ("%-71.71s", @_ [0]) . "\n";

    $status {'force_print'} = 1;
}

sub reaper
{
    my $child;
    while (($child = waitpid (-1, WNOHANG)) > 0)
    {
        $exit_status = $?;
    }
}

$SIG{CHLD} = \&reaper;

select (STDOUT);
$| = 1;
open (MAKE_FD, "make " . $ARGV [0] . " 2>&1 |");
$status {'operation'} = "make";
print_status;

while (<MAKE_FD>)
{
    my $line = $_;

    chop ($line);

    if ($line =~ /make\[[0-9]+\]: Entering directory `([^']+)'/) # '`
    {
	$status {'operation'} = "make";
	$status {'dir'}       = substr ($1, length ($topdir) + 1);
        $status {'file'}      = "";
        $status {'reported'}  = 0;
    }
    elsif ($line =~ /^gcc .* -c ([^ ]+)/)
    {
        $status {'operation'} = "compile";
        $status {'file'}      = $1;
        $status {'reported'}  = 0;
    }
    elsif ($line =~ /^if gcc/)
    {
        $status {'operation'} = "compile";
        $status {'file'}      = "";
        $status {'reported'}  = 0;
    }
    elsif ($line =~ /^[ \t]*-c -o .* \`test -f '([^']+)/)
    {
        $status {'operation'} = "compile";
        $status {'file'}      = $1;
        $status {'reported'}  = 0;
    }
    elsif ($line =~ /^gcc .* -o (.libs\/)?(lt-)?([^ ]+)/ ||
           $line =~ / (--mode=link) .* (-o) ([^ ]+)/)
    {
        $status {'operation'} = "link";
        $status {'file'}      = $3;
        $status {'reported'}  = 0;
    }
    elsif ($line =~ /[^ ]*install .* ([^ ]+) ([^ ]+)/ ||
           $line =~ /installing ([^ ]+)/)
    {
	$1 =~ /([^\/ ]+)$/;
        my $file = $1;

        $status {'operation'} = "install";
        $status {'reported'}  = 0;

        if (!($file =~ /\$/))
        {
            $status {'file'} = $file;
        }
        else
        {
            $status {'file'} = "";
        }
    }
    elsif ($line =~ /^[ \t]+rm (-[a-zA-Z]+) ([^|&;()]+)/)
    {
        $status {'operation'} = "clean";
        $status {'reported'}  = 0;
        $status {'file'}      = $2;
    }
    elsif ($line =~ /^[a-zA-Z0-9_.-]+:[0-9 ]/ &&
           ($status {'operation'} eq "link" ||
            $status {'operation'} eq "compile"))
    {
        if ($line =~ /:([0-9]+):[0-9]+: warning: \#warning (.+)/ ||
            $line =~ /:([0-9]+):[0-9]+: warning: (.+)/           ||
            $line =~ /:([0-9]+): warning: (.+)/)
        {
            print_warning ("$1: $2");
        }
        elsif ($line =~ /:([0-9]+):[0-9]+: (.+)/ ||
               $line =~ /:([0-9]+): (.+)/)
        {
            print_error ("$1: $2");
        }
    }
    elsif ($line =~ /^make.*No rule to make target `([^']+)', needed by `([^']+)'/)
    {
        print_error ("no rule for '" . $1 . "' (" . $2 . ")");
    }
    elsif ($line =~ /([^ ]+): Permission denied$/)
    {
        $status {'file'} = $1;
        print_error ("permission denied");
    }
    elsif ($dump_unmatched)
    {
	print "\e[1;31m" . $line . "\e[0;37m\n";
    }
    else
    {
        next;
    }

    print_status;
}

close (MAKE_FD);

clear_status;
wait;

if ($exit_status == 0)
{
    print "\e[1;32msuccess \e[0;32m \e[0m\n";
}
else
{
    print "\e[1;31mfailure \e[0;31m \e[0m\n"; 
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]