Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

MakeAll.Pl

by demerphq (Chancellor)
on May 01, 2004 at 12:58 UTC ( [id://349601]=sourcecode: print w/replies, xml ) Need Help??
Category: Utility Scripts
Author/Contact Info demerphq
Description:

NAME

MakeAll.pl - Build, test and optionally install a module on all versions of perl located in path.


SYNOPSIS

MakeAll.pl [options] [file ...]
Options: --help brief help message --man full documentation --verbose be talkative, repeat or assign a higher value for + more --install do an install in each perl if build is good --no-run don't run test, just scan path --scan short for --verbose --no-run


DESCRIPTION

This program will run the standard

perl Makefile.PL make make test

and optionally

make install

for each distinct perl executable it finds in the path (it uses some tricks to make sure they aren't dupes). On Win32 it will use make or nmake as is necessary based on whether the script itself is run under Activestate perl or Cygwin perl. On non win32 machines it will use make.

AUTHOR AND COPYRIGHT

Copyright Yves Orton 2004. Released under the same terms as Perl itself. Please see the Perl Artistic License distributed with Perl for details.

## MakeAll.pl -- See pod at bottom.
use strict;
use warnings;
use Data::Dumper;
use File::Find;
use File::Spec;
use Getopt::Long;
use Pod::Usage;
use Text::Wrap qw(wrap);
use Cwd;
use vars qw/$VERSION/;
$VERSION='0.1';

sub _join {
    return join("\n",map { wrap "","  ",$_ } @_),"\n";
}

GetOptions(
           'help|?'     => \(my $Help    =0 ),
           'run|r!'     => \(my $Run     =1 ),
           'install|i!' => \(my $Install =0 ),
           'verbose|v:+'=> \(my $Verbose =0 ),
           'debug|d:+'  => \(my $Debug   =0 ),
           'scan|s!'    => \(my $Scan    =0 ),
           'man'        => \(my $Man     =0 )
          )
           or pod2usage(2);
pod2usage(1) if $Help;
pod2usage(-exitstatus => 0, -verbose => 2) if $Man;

warn "Run:$Run : Install:$Install : Verbose:$Verbose : Scan:$Scan\n"
    if $Debug;

if($Scan) {
    $Run=0;
    $Verbose||=1;
}

my $fs='File::Spec';
my @vers;

foreach my $dir (split /;/,$ENV{PATH}) {
    foreach (glob $fs->catdir("$dir","perl*.*")) {
        if(/(perl(?:\d+\.\d+\.\d+)?(\.exe)?)$/i and -e $_){
            my $name=$1;
            my $spec=$_;
            chomp( my ($ver,$arch,@V)=`$spec -V:version -V:archname -V
+`);
            s/\w+='([^'']+)';/$1/g for $ver,$arch;
            my $V=join "\n",@V;
            push @vers,[$name,$spec,$ver,$arch,$V];
        }
    }
}

my %seen;
my %vers;
@vers=reverse grep {
            if (!$seen{$_->[-1]}) {
                $seen{$_->[-1]}=$_->[0];
                printf "--- Found %s at %s version %s on %s ---\n",@$_
                    if $Verbose;
                $vers{$_->[2]}{$_->[3]}++;
                1
            } else {
                printf "--- Skipping duplicate of %s at %s version %s 
+on %s ---\n",
                        $seen{$_->[-1]},@{$_}[1..$#$_-1]
                    if $Verbose>2;
                0
           }
        }  sort {
                $b->[0] cmp $a->[0] ||
                $b->[2] cmp $a->[2] ||
                $b->[3] cmp $a->[3]
           } @vers;



exit(0) unless $Run;

print "--- Work Dir: ".cwd()." ---\n";

my %status;

foreach my $perl (@vers) {
    my ($name,$spec,$ver,$arch,$V)=@$perl;
    my $test_name="Perl$ver ($arch) ".($vers{$perl->[2]}{$perl->[3]}>1
+ ? "[$spec]" : '');
    $status{$test_name}=0;
    print "--- Testing $test_name ---\n";
    unlink 'Makefile';
    print "Makefile.PL\n" if $Verbose;
    my $makefile=`$spec Makefile.PL 2>&1 `;
    unless(-e 'Makefile') {
        warn "Failed to build with $test_name\nMakefile.PL output:\n$m
+akefile\n";
        next;
    } elsif ($Verbose>2) {
        print "$makefile\n";
    }
    #print $makefile,"\n";
    my $maker='make';
    $maker="n$maker" if $arch=~/Win32/i;
    print "$maker\n" if $Verbose;
    my $make_out=`$maker 2>&1 `;
    my $exit=$? >> 8;
    if ($exit) {
        warn "Failed to build with $test_name\n$maker output:\n$make_o
+ut\n";
        next;
    } elsif ($Verbose>2) {
        print "$make_out\n";
    }
    print "$maker test\n" if $Verbose;
    chomp(my @res=`$maker test 2>&1 `);
    if ($exit) {
        warn "Failed test with $test_name\n$maker test output:\n"._joi
+n(@res)."\n";
        next;
    }
    if (join("",@res)=~/No tests defined/i) {
        warn "No tests defined for the module\n";
        next;
    }

    unless ($Verbose>4) {
        # remove some stuff at the front, like possible version
        # copyright crap from the maker.
        shift @res while @res and $res[0]!~/\Q$name\E/;
        shift @res if @res and $res[0]=~/\Q$name\E/;
    }

    #print Dumper(\@res),"\n\n";
    #All tests successful, 38 subtests skipped.
    #Files=16, Tests=279, 12 wallclock secs ( 0.00 cusr +  0.00 csys =
+  0.00 CPU)
    if ($res[-1]=~/Stop|Error|Failed/i) {

        pop @res while @res and $res[-1]!~/$maker/i;
        pop @res;

        if ($Verbose>2) {
            print _join(@res)."\n";
        } else {
            my @out;

            unshift @out,pop @res until $res[-1]=~/^\s*Failed\s+\d+/;
            unshift @out,pop @res;

            print _join(@out);
        }
    } else {
        #all goood
        if ($Verbose>2) {
            print _join(@res);
        } else {
            #all goood
            print "$res[-2]\n$res[-1]\n";
        }
        $status{$test_name}=1;
        if ($Install) {
            # should trap errors here...
            my $install=`$maker install 2>&1 `;
            my $exit=$? >> 8;
            if ($exit) {
                warn "Exitcode $exit.\nFailed install with $test_name\
+n$maker install output:\n$install\n";
                next;
            } elsif ($Verbose>2) {
                print "$install\n";
            }
        }
    }
    print "---End Test---\n\n";
}

__END__

=head1 NAME

MakeAll.pl - Build, test and optionally install a module on all versio
+ns of perl
located in path.

=head1 SYNOPSIS

 MakeAll.pl  [options] [file ...]

 Options:
   --help            brief help message
   --man             full documentation
   --verbose         be talkative, repeat or assign a higher value for
+ more
   --install         do an install in each perl if build is good
   --no-run          don't run test, just scan path
   --scan            short for --verbose --no-run

=head1 DESCRIPTION

B<This program> will run the standard

  perl Makefile.PL
  make
  make test

and optionally

  make install

for each distinct perl executable it finds in the path (it uses some t
+ricks to make sure
they aren't dupes). On Win32 it will use make or nmake as is necessary
+ based on whether
the script itself is run under Activestate perl or Cygwin perl. On non
+ win32 machines
it will use make.

=head1 NOTES

Theres probably issues with this on some platform or another. Patches 
+welcome.

=head1 AUTHOR AND COPYRIGHT

Copyright Yves Orton 2004. Released under the same terms as Perl itsel
+f. Please
see the Perl Artistic License distributed with Perl for details.

=cut
Replies are listed 'Best First'.
Re: MakeAll.Pl (Config.pm)
by tye (Sage) on May 01, 2004 at 16:56 UTC

    Have you run this on Unix? You split $ENV{PATH} on ';', which is only appropriate for Win32. You should use Config, it knows what separator to use on each platform.

    You should also use Config.pm to figure out what 'make' to run. It'd be nice to do this per perl rather than just based on the perl being used to run this script. This makes me think it'd be nice to write ake.pm so the standard install dance could be changed to:

    perl Makefile.PL perl -make -em perl -make -em test perl -make -em install

    and ake.pm could prompt to download and install nmake.exe if appropriate and point users toward FAQs if the module has XS code but they don't have the right C compiler. (:

    Short of that, you could use $make= `$perl -V=make` (sorry, don't have Perl reinstalled here so I can't test that so I probably got it a bit wrong).

    - tye        

      something like:
      $make = `$perl -V:make`; $make =~ s/.*?'//; $make =~ s/'.*//;
      Someone had proposed something like a -V:make= syntax that would just output the value; don't think it ever got applied, though.
Re: MakeAll.Pl
by ysth (Canon) on May 02, 2004 at 10:13 UTC
    use `$perl -V:path_sep` to look up the separator instead of ;, make distclean instead of unlink 'Makefile'
      Err, since you need the path separator before you find a perl, you should just use $Config::Config{path_sep}.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://349601]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (3)
As of 2024-11-03 04:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    chatterbot is...






    Results (13 votes). Check out past polls.