die "'CIPRES_PERL_HOME' undefined" if not $ENV{'CIPRES_PERL_HOME'};
my @argv = @ARGV;
use ExtUtils::MakeMaker;
use Config;
use strict;
use warnings;
use Getopt::Long;

# build targets, default 'base' target installs prerequisites
# to run cipres services. These are invoked as --base --cpan etc.
my $TARGETS = { 
    'base'      => 1,
    'cpan'      => 0, # updates cpan, for newer installation options
    'bioperl'   => 0, # installs bioperl, big install
    'testsuite' => 0, # to be able to run build tests
    'wx'        => 0, # for gui stuff
};

# parse command line arguments
GetOptions(
    'base'      => sub { $TARGETS->{'base'}++      },
    'cpan'      => sub { $TARGETS->{'cpan'}++      }, 
    'bioperl'   => sub { $TARGETS->{'bioperl'}++   },   
    'testsuite' => sub { $TARGETS->{'testsuite'}++ },
    'wx'        => sub { $TARGETS->{'wx'}++        },
);


our $programs = {
    'perl'  => {
        'status'  => 'required',
        'default' => &_find_prog( 'perl' ),
        'reason'  => "We need a multi-threaded perl version 5.8.*. \nOn Windows, use ActivePerl or Indigoperl. \nOn OSX, you can use the default in /usr/bin/perl \nif you have the developer tools installed",
    },
    'bzip2' => {
        'status'  => 'optional',
        'default' => &_find_prog( 'bzip2' ),    
        'reason'  => "We may need this to unpack prerequisites. \nGzip/unzip and tar are probably enough, though.",
    },
    'curl'  => {
        'status'  => 'optional', 
        'default' => &_find_prog( 'curl' ), 
        'reason'  => "We may need this to download prerequisites. \nFtp is probably enough, though.",                      
    },
    'wget'  => {
        'status'  => 'optional',    
        'default' => &_find_prog( 'wget' ),  
        'reason'  => "We may need this to download prerequisites. \nFtp is probably enough, though.",               
    },
    'gpg'   => {
        'status'  => 'optional',  
        'default' => &_find_prog( 'gpg' ), 
        'reason'  => "We may want this to check signatures on prerequisites. \nThis is one for the paranoid.",          
    },
    'shell' => {
        'status'  => 'optional',  
        'default' => &_find_prog( $^O eq 'MSWin32' ? 'cmd' : 'bash' ), 
        'reason'  => "We may want to open a subshell at some point. \nProbably not, though.",        
    },
    'gzip'  => {
        'status'  => 'required', 
        'default' => &_find_prog( 'gzip' ),   
        'reason'  => "We need this to unpack prerequisites.",          
    },
    'tar'   => {
        'status'  => 'required', 
        'default' => &_find_prog( 'tar' ), 
        'reason'  => "We need this to unpack prerequisites.",                        
    },
    'unzip' => {
        'status'  => 'required', 
        'default' => &_find_prog( 'unzip' ),  
        'reason'  => "We need this to unpack prerequisites.",                       
    },
    'make'  => {
        'status'  => 'required', 
        'default' => &_find_prog( $^O eq 'MSWin32' ? 'nmake' : 'make' ),  
        'reason'  => "We need this to build prerequisites.",
    },
    'more'  => {
        'status'  => 'required', 
        'default' => &_find_prog( 'more' ),    
        'reason'  => "We need this to page through screens of confusing stuff.",                    
    },
    'ftp'   => {
        'status'  => 'required',
        'default' => &_find_prog( 'ftp' ),
        'reason'  => "We may need this to download prerequisites.",                           
    },
    'ncftp' => {
        'status'  => 'optional',     
        'default' => &_find_prog( 'ncftp' ), 
        'reason'  => "We may need this to download prerequisites.",                 
    },
    'cc'    => {
        'status'  => 'optional',     
        'default' => &_find_prog( $^O eq 'MSWin32' ? 'cl' : 'gcc' ),  
        'reason'  => "We may need this to build prerequisites.",                
    },
};

our $paths = {
    'CIPRES_PERL_HOME' => {
        'status'  => 'required',
        'default' => "$ENV{CIPRES_PERL_HOME}",
        'reason'  => 'This should be an environment variable. We need this to install into.',
    },
    'cpan build dir' => {
        'status'  => 'required',
        'default' => "$ENV{CIPRES_PERL_HOME}/src/CPAN/LOCAL",
        'reason'  => 'We need this as a build directory for prerequisites.'
    },
    'cpan local mirror' => {
        'status'  => 'optional',
        'default' => "$ENV{CIPRES_PERL_HOME}/src/CPAN/MIRROR",
        'reason'  => "We may want this to 'download' prerequisites from a local cpan mirror.\nThis is intended for offline installs.",
    },
    '.cpan config dir' => {
        'status'  => 'required',
        'default' => "$ENV{'HOME'}/.cpan",
        'reason'  => 'We need this to override CPAN.pm configuration.',
    },
};

our $outfiles = {
    'perlvars.properties' => {
        'status'  => 'required',
        'default' => "$ENV{CIPRES_PERL_HOME}/etc/perlvars.properties",
        'reason'  => 'Java needs this to invoke perl services with the right environment.',
    },
    'perlvars.bashrc' => {
        'status'  => 'optional',
        'default' => "$ENV{CIPRES_PERL_HOME}/etc/perlvars.bashrc",
        'reason'  => 'We may want this to "source" the right environment settings in a bash shell.',        
    },
    'perlvars.bat' => {
        'status'   => 'optional',
        'default'  => "$ENV{CIPRES_PERL_HOME}/etc/perlvars.bat",
        'reason'   => 'We may want this to "call" the right environment settings in a windows terminal.',        
    },
};

our $buildtargets = {
    'base'       => {
        'status' => 'required',
        'build'  => 1,
        'reason' => 'We need this to run services.',
    },
    'wx'         => {
        'status' => 'optional',
        'build'  => 0,
        'reason' => 'We need this to run GUI programs, like regman.',    
    },
    'testsuite'  => {
        'status' => 'optional',
        'build'  => 0,
        'reason' => 'We need this if we want to run the make test target.',      
    },
    'bioperl'    => {
        'status' => 'optional',
        'build'  => 0,
        'reason' => 'At present, we do not need this, but it\'s good to have.',     
    },
    'cpan'       => {
        'status' => 'optional',
        'build'  => 0,
        'reason' => 'This target updates the cpan installation environment, which is useful, but unnecessary.',      
    },
};

sub _prompt ($$$$$) {
    my ( $msg, $needed, $status, $default, $reason ) = @_;
    printf $msg, $needed;
    print "\n\nThis is $status. \n$reason\nTo accept the default, press enter.\n\n[$default] > ";
    my $response = <>;
    chomp( $response );
    return $response ? $response : $needed;
}

sub _prompt_bool {
    my ( $msg, $needed, $status, $default, $reason ) = @_;
    printf $msg, $needed;
    printf "\n\nThis is $status. \n$reason\nRight now, this is %s. \nTo %s instead, press %s.\n\n[%s] > ", $default ? 'accepted' : 'declined', $default ? 'decline' : 'accept', $default ? 'N' : 'Y', $default ? 'Y' : 'N';
    my $response = <>;
    chomp( $response );
    return $response =~ qr/Y/i ? 1 : 0;
}

sub _find_prog ($) {
    my $prog = shift;
    for my $path ( split $Config{'path_sep'}, $ENV{'PATH'} ) {
        if ( -X "$path/$prog$Config{exe_ext}" ) {
            return &_fix_slashes( "$path/$prog$Config{exe_ext}" );
        }
    }
    return $prog;
}
print "\n\n================ TARGETS ==================\n\n";
for my $target ( keys %$buildtargets ) {
    my $t = $buildtargets->{$target};
    my $msg = "\nDo you want to build the '%s' target?";
    $t->{'build'} = &_prompt_bool( $msg, $target, $t->{'status'}, $t->{'build'}, $t->{'reason'} );
}
print "\n\n============= BUILD BINARIES ==============\n\n";
for my $prog ( keys %$programs ) {
    my $bin = $programs->{$prog};
    my $msg = "\nWhere is your '%s' program?";
    $bin->{'path'} = &_prompt( $msg, $prog, $bin->{'status'}, $bin->{'default'}, $bin->{'reason'} );
}
print "\n\n============== BUILD PATHS ================\n\n";
for my $dir ( keys %$paths ) {
    my $path = $paths->{$dir};
    my $msg = "\nWhere do I find your '%s' folder?";
    $paths->{'path'} = &_prompt( $msg, $dir, $path->{'status'}, $path->{'default'}, $path->{'reason'} );
}
print "\n\n============== OUTPUT FILES ===============\n\n";
for my $outfile ( keys %$outfiles ) {
    my $path = $outfiles->{$outfile};
    my $msg = "\nWhere can I write the '%s' output file?";
    $paths->{'path'} = &_prompt( $msg, $outfile, $path->{'status'}, $path->{'default'}, $path->{'reason'} );
}

# CIPRES_PERL_HOME is the installation root for
# all cipres perl dependencies (and core libraries).
# Typically, this points to $CIPRES_DIST/lib/perl
my $HOME = &_fix_slashes( $ENV{'CIPRES_PERL_HOME'} );

# 'Cipres/Config.pm' is a package that functions like 
# ExtUtils::FakeConfig in that it overrides %Config for
# custom installation paths. If it's not in %INC at this
# point, the assumption is that cipres hasn't been set up yet.
if ( not exists $INC{'Cipres/Config.pm'} ) {
    &writeCIPRESConfig( $HOME );
    &writeCIPRESbashrc( $HOME );
    &writeCPANConfig( 'MyConfig.pm' );
    my $source_command = $^O eq 'MSWin32' 
                         ? "call $HOME/etc/perlvars.bat" 
                         : "source $HOME/etc/perlvars.bashrc";
    print 
"
        This script was invoked with the wrong environment. 
        I wrote a new configuration file with the right 
        settings. Import these with the following command:
        
        $source_command
        
        ...and rerun this script.

";
    exit 0;
}

local $/ = undef;
my $__ENDDB__ = <DATA>; # this <DATA> handle refers to the __DATA__ section at the bottom of this script.
my $prereqs = eval $__ENDDB__;
die "Prerequisites data base corrupted: $@" if $@;

# this is the main loop that iterates over the entries in the __DATA__ section,
# tries to load them, if not present tries to install from ppd or cpan
for my $prereq ( @$prereqs ) {
    next unless $TARGETS->{ $prereq->{'target'} };
    my $mod = $prereq->{'mod'};
    my $version = $prereq->{'version'};
    my $PPDInstall = &makePPDInstallFunc();
    if ( $version ) {
        eval "use $mod $version";
    }
    else {
        eval "require $mod";    
    }
    if ( $@ ) {
        print "Going to install $mod...(because: $@)\n";
        undef($@);
        eval {
            if ( $prereq->{'ppd'} and $PPDInstall and $^O eq 'MSWin32' ) {        
                $PPDInstall->( $prereq->{'ppd'} );
            }
            else {
                &CPANInstall( $prereq );
            }
        };
        if ( $@ ) {
            print "$mod NOK: $@\n";
            undef($@);
        }
        else {
            print "$mod OK: installed succesfully\n";        
        }
    }
    else {
        print "$mod OK: already installed\n";
    }
}

# final report printout
my ( %success, %failure );
for my $prereq ( @$prereqs ) {
    next unless $TARGETS->{ $prereq->{'target'} };
    my $mod = $prereq->{'mod'};
    eval "require $mod";
    if ( $@ ) {
        $failure{$mod}++;
        undef($@);
    }
    else {
        $success{$mod}++;
    }
}
print "\n================================\n";
printf
    "SUCCESS (%s):\n\n%s\n\nFAILURE (%s):\n\n%s",
    scalar( keys( %success ) ),
    join( "\n", keys( %success ) ),
    scalar( keys( %failure ) ),
    join( "\n", keys( %failure ) ),
;
print "\n================================\n";

# attempt to locate binary package managers. PPM
# is for activestate perl, IPM for indigoperl
# (the two are binary compatible)
sub makePPDInstallFunc {
    my $InstallFunc;
    for ( qw(PPM IPM_InstallPkg) ) {
        my $class = "$_";
        eval "require $class";
        if ( not $@ ) {
            $InstallFunc = \&PPM::InstallPackage if $class =~ qr/PPM/;
            $InstallFunc = \&IPM_InstallPkg::InstallPkg if $class =~ qr/IPM/;
            last;
        }
        else {
            undef($@);
        }
    }
    return $InstallFunc ? $InstallFunc : undef;
}

sub CPANInstall {
    my $prereq = shift;
    require CPAN;
    # it looks like CPAN system wide config data is reloaded
    # under some conditions (overwriting MyConfig data in the
    # process). The hack below is to reload custom config.
    use lib "$ENV{'HOME'}/.cpan";
    delete $INC{'Cipres/Config.pm'};
    delete $INC{'CPAN/MyConfig.pm'};
    require 'Cipres/Config.pm';
    require 'CPAN/MyConfig.pm';
        
    my $mbuildpl_arg      = $CPAN::Config->{'mbuildpl_arg'};
    my $makepl_arg        = $CPAN::Config->{'makepl_arg'};
    my $prefer_installer  = $CPAN::Config->{'prefer_installer'};
    $CPAN::Config->{'prefer_installer'} = $prereq->{'builder'};
    if ( $CPAN::Config->{'prefer_installer'} eq 'MB' ) {
        $CPAN::Config->{'mbuildpl_arg'} .= $prereq->{'flags'} if $prereq->{'flags'};
    }
    else {
        $CPAN::Config->{'makepl_arg'} .= $prereq->{'flags'} if $prereq->{'flags'};            
    }    

    if ( $prereq->{'force'} ) {
        CPAN::Distribution::force( 'install', $prereq->{'cpan'} );
    }
    else {
        CPAN::Shell->install( $prereq->{'cpan'} );
    }
    $CPAN::Config->{'mbuildpl_arg'}     = $mbuildpl_arg;
    $CPAN::Config->{'makepl_arg'}       = $makepl_arg;
    $CPAN::Config->{'prefer_installer'} = $prefer_installer;    
}



sub writeCPANConfig {
    my $outfile = shift;
    mkdir "$ENV{'HOME'}/.cpan";
    mkdir "$ENV{'HOME'}/.cpan/CPAN";
    my $configfile = "$ENV{'HOME'}/.cpan/CPAN/$outfile";
    my $make = $^O eq 'MSWin32' ? 'nmake' : 'make';
    my $bin = {
        'gzip'  => '',
        'tar'   => '',
        'unzip' => '',
        $make   => '',
        'more'  => '',
        'ftp'   => '',
        'ncftp' => '',
    };
    EXE: for my $exe ( keys %$bin ) {
        for my $path ( split $Config::Config{path_sep}, $ENV{'PATH'} ) {
            if ( -X "$path/$exe$Config::Config{exe_ext}" ) {
                $bin->{$exe} = "$path/$exe$Config::Config{exe_ext}";
                next EXE;
            }
        }
    }
    if ( -e $configfile ) {
        rename $configfile, "$configfile.bak";
    }
    my $time = localtime;
    open my $fh, '>', $configfile or die $!;
    print $fh 
"
        # This file was automatically generated by $0 with args '@argv'
        # on $time. Do not edit by hand! All changes will 
        # be lost next time $0 is run.
        # The purpose of this file is to provide CPAN.pm with a 
        # configuration that:
        #	* is not interactive (no scary choices)
        #	* uses a local (tiny) CPAN mirror at:
        #	  file://$HOME/src/CPAN/MIRROR
        #	* sets up prefixes for non-root installs
        
        \$CPAN::Config = {
        'gzip'                         => '$bin->{'gzip'}',
        'tar'                          => '$bin->{'tar'}',
        'unzip'                        => '$bin->{'unzip'}',
        'make'                         => '$bin->{$make}',
        'pager'                        => '$bin->{'more'}',
        'ftp'                          => '$bin->{'ftp'}',
        'ncftp'                        => '$bin->{'ncftp'}',
        'build_cache'                  => 0,
        'build_dir'                    => '$HOME/src/CPAN/LOCAL/build',
        'cache_metadata'               => 0,
        'cpan_home'                    => '$HOME/src/CPAN/LOCAL/',
        'dontload_hash'                => {  },
        'ftp_proxy'                    => '',
        'http_proxy'                   => '',
        'inactivity_timeout'           => 30,
        'index_expire'                 => 1,
        'inhibit_startup_message'      => 1,
        'keep_source_where'            => '$HOME/src/CPAN/LOCAL',
        'make_arg'                     => '',
        'make_install_arg'             => '',
        'makepl_arg'                   => ' PREFIX=$HOME SITEPREFIX=$HOME VENDORPREFIX=$HOME ',
        'mbuildpl_arg'                 => ' --prefix $HOME ',        
        'mbuild_arg'                   => '',
        'mbuild_install_arg'           => '',
        'mbuild_install_build_command' => '',        
        'no_proxy'                     => '',
        'prerequisites_policy'         => 'follow',
        'scan_cache'                   => 'never',
        
        # using firewall friendly local repository
        'urllist'                      => [ 'file://$HOME/src/CPAN/MIRROR' ],
        };
1;
";
    close $fh;
}

# all slashes become forward slashes, multiple // are turned into /
sub _fix_slashes {
    my $path = shift;
    $path =~ tr/\\/\//;
    $path =~ s/\/+/\//g;
    return $path;
}

sub makePERL5LIB {
    my $home = shift;
    my $ciprefix  = &_fix_slashes( $home );
    my $sysprefix = &_fix_slashes( $Config::Config{'prefix'} ); # e.g. '/usr'

    # base
    my $PERL5LIB = "$home/lib";

    # replicate system subtrees, change prefix
    for my $subtree ( qw(sitelibexp archlibexp vendorlibexp privlibexp) ) {
        my $fixed_subtree = &_fix_slashes( $Config::Config{$subtree} );
        $fixed_subtree =~ s/^\Q$sysprefix\E//;
        $PERL5LIB .= $Config{'path_sep'} . $ciprefix . $fixed_subtree;
    }

    return $PERL5LIB;
}

sub writeCIPRESproperties {

}

sub writeCIPRESbashrc {
    my $home = shift;
    &writeCIPRESdirs( $home );    
    my $INCLUDES = "$home/etc";  
    my $PERL5LIB = &makePERL5LIB( $home );  
    if ( $^O eq 'MSWin32' ) {
        open my $fh, '>', "$home/etc/perlvars.bat" or die $!;
        print $fh 
"
        :: to import these variables, execute
        :: call $home/etc/perlvars.bat
        set CIPRES_PERL_HOME=$home
        set PATH=$home/bin;\%PATH\%
        set PERL5LIB=$PERL5LIB;\%PERL5LIB\%
        set PERL5OPT=-I$INCLUDES -MCipres::Config \%PERL5OPT\%
";
        close $fh; 
    }
    else {
        open my $fh, '>', "$home/etc/perlvars.bashrc" or die $!;
        print $fh 
"
        # to import these variables, execute
        # source $home/etc/perlvars.bashrc
        CIPRES_PERL_HOME=$home; export CIPRES_PERL_HOME
        PATH=$home/bin:\$PATH; export PATH
        PERL5LIB=$PERL5LIB:\$PERL5LIB; export PERL5LIB
        PERL5OPT=-I$INCLUDES\\ -MCipres::Config\\ \$PERL5OPT; export PERL5OPT
";
        close $fh;
    }
}

sub writeCIPRESConfig {
    my $home = shift;
    &writeCIPRESdirs( $home ); 
    open my $fh, '>', "$home/etc/Cipres/Config.pm" or die $!;
    my $time = localtime;
    print $fh 
"
        package Cipres::Config;
        # do not edit this file, it was autogenerated by
        # $0 on $time with commands '@argv'.
        # use this file to configure perl installs as non-root,
        # with the PERL5OPT=-MCipres::Config environment variable
        # and this file in \@INC.
        require Config;
        my \$MyConfig = tied \%Config::Config;
        \$MyConfig->{'Author'}    = 'Rutger Vos';
        \$MyConfig->{'cf_by'}     = 'CIPRES';
        \$MyConfig->{'cf_email'}  = 'rvosa\@sfu.ca';
        \$MyConfig->{'cf_time'}   = '$time';
        \$MyConfig->{'startperl'} = '$Config::Config{startperl}';
        \$MyConfig->{'perlpath'}  = '$Config::Config{perlpath}';
1;
";
    close $fh;
}

sub writeCIPRESdirs {
    my $home = shift;
    if ( not -d $home ) {
        mkdir $home or die "Can't make cipres home dir '$home': $!";
    }
    for ( qw(etc etc/Cipres bin doc lib src src/CPAN scr/CPAN/MIRROR src/CPAN/LOCAL) ) {
        if ( not -d "$home/$_" ) {
            mkdir "$home/$_" or die "Can't make cipres dir '$home/$_': $!";
        }
    }
}

__DATA__

[
    {
        'mod'     => 'Bundle::CPAN',
        'cpan'    => 'ANDK/Bundle-CPAN-1.852.tar.gz',
        'target'  => 'cpan',
        'builder' => 'EUMM',        
    },
    {
        'mod'     => 'CPAN',
        'cpan'    => 'ANDK/CPAN-1.87.tar.gz',
        'target'  => 'cpan',
        'builder' => 'EUMM',        
    },
    { 
        'mod'     => 'Bio::Tree::TreeI',
        'cpan'    => 'BIRNEY/bioperl-1.4.tar.gz',
        'ppd'     => 'http://bioperl.org/DIST/Bioperl-1.4.ppd',
        'force'   => 1,  
        'target'  => 'bioperl', 
        'builder' => 'EUMM',         
    },
    { 
        'mod'     => 'Exception::Class',
        'cpan'    => 'DROLSKY/Exception-Class-1.23.tar.gz',
        'ppd'     => 'http://ppm.activestate.com/PPMPackages/5.8-windows/Exception-Class.ppd',
        'target'  => 'base',
        'builder' => 'EUMM',
    },
    { 
        'mod'     => 'Exception::Class::TCF',
        'cpan'    => 'RVOSA/Exception-Class-TCF-0.03.tar.gz',
        'target'  => 'base',
        'builder' => 'EUMM',        
    },
    { 
        'mod'     => 'Math::Random',
        'cpan'    => 'GROMMEL/Math-Random-0.68.tar.gz',
        'ppd'     => 'http://ppm.activestate.com/PPMPackages/5.8-windows/Math-Random.ppd',
        'target'  => 'base',
        'builder' => 'EUMM',
    },
    { 
        'mod'     => 'Math::BigInt',
        'cpan'    => 'TELS/math/Math-BigInt-1.77.tar.gz',
        'ppd'     => 'http://ppm.activestate.com/PPMPackages/5.8-windows/Math-BigInt.ppd', 
        'target'  => 'base',
        'builder' => 'EUMM',           
    },
    { 
        'mod'     => 'Scalar::Util',
        'cpan'    => 'GBARR/Scalar-List-Utils-1.14.tar.gz',
        'ppd'     => 'http://ppm.activestate.com/PPMPackages/5.8-windows/List-Utils.ppd',  
        'target'  => 'base', 
        'builder' => 'EUMM',
        'version' => '1.14',         
    },
    { 
        'mod'     => 'Module::Build',
        'cpan'    => 'KWILLIAMS/Module-Build-0.2805.tar.gz',
        'ppd'     => 'http://ppm.activestate.com/PPMPackages/5.8-windows/Module-Build.ppd',  
        'target'  => 'base', 
        'builder' => 'EUMM',                 
    },
    { 
        'mod'     => 'SVG',
        'cpan'    => 'RONAN/SVG-2.33.tar.gz',
        'target'  => 'base',
        'builder' => 'EUMM',                
    },
    { 
        'mod'     => 'Class::Inspector',
        'cpan'    => 'ADAMK/Class-Inspector-1.14.tar.gz',
        'ppd'     => 'http://ppm.activestate.com/PPMPackages/5.8-windows/Class-Inspector.ppd',
        'target'  => 'base',
        'builder' => 'EUMM',         
    },
    { 
        'mod'     => 'Log::Dispatch',
        'cpan'    => 'DROLSKY/Log-Dispatch-2.12.tar.gz',
        'ppd'     => 'http://ppm.activestate.com/PPMPackages/5.8-windows/Log-Dispatch.ppd',  
        'target'  => 'base',  
        'builder' => 'EUMM',         
    },        
    { 
        'mod'     => 'Log::Log4perl',
        'cpan'    => 'MSCHILLI/Log-Log4perl-1.06.tar.gz',
        'ppd'     => 'http://theoryx5.uwinnipeg.ca/ppms/Log-Log4perl.ppd',  
        'target'  => 'base',  
        'builder' => 'EUMM',         
    },
    { 
        'mod'     => 'Test::Pod',
        'cpan'    => 'PETDANCE/Test-Pod-1.26.tar.gz',
        'ppd'     => 'http://www.bribes.org/perl/ppm/Test-Pod.ppd',  
        'target'  => 'testsuite',
        'builder' => 'EUMM',          
    },
    { 
        'mod'     => 'Test::Pod::Coverage',
        'cpan'    => 'PETDANCE/Test-Pod-Coverage-1.08.tar.gz',
        'ppd'     => 'http://www.bribes.org/perl/ppm/Test-Pod-Coverage.ppd',
        'target'  => 'testsuite', 
        'builder' => 'EUMM',                
    },
    { 
        'mod'     => 'Test::Distribution',
        'cpan'    => 'SRSHAH/Test-Distribution-1.26.tar.gz', 
        'target'  => 'testsuite',  
        'builder' => 'MB',                          
    },
    {
        'mod'     => 'Alien::wxWidgets',
        'cpan'    => 'MBARBON/Alien-wxWidgets-0.21.tar.gz',
        'builder' => 'MB',
        'flags'   => '--build_wx --source=tar.gz',  
        'ppd'     => 'http://prdownloads.sourceforge.net/wxperl/Wx-0.26-wxmsw2.6.2-win32-u-5.8.6.zip',  
        'target'  => 'wx',        
    },    
    { 
        'mod'     => 'Wx',
        'cpan'    => 'MBARBON/Wx-0.57.tar.gz', 
        'target'  => 'wx',
        'builder' => 'EUMM',            
    },
    { 
        'mod'     => 'Wx::Perl::VirtualTreeCtrl',
        'cpan'    => 'BBC/Wx-Perl-VirtualTreeCtrl-1.015.tar.gz',    
        'target'  => 'wx',
        'builder' => 'EUMM',        
    },    
]
