#!/usr/bin/perl
# Copyright 2001-2014, Paul Johnson (paul@pjcj.net)
# This software is free. It is licensed under the same terms as Perl itself.
# The latest version of this software should be available from my homepage:
# http://www.pjcj.net
use strict;
use warnings;
require 5.012;
use autodie;
use System "sys:dsys: command, error";
my @opt = qw( perl modules
postgres
zlib openssl
apache mod_perl fastcgi
git
coverage all );
my $Usage =
"Usage: $0 /src/dir perl_version /installation [" . join("|", @opt) . "]\n";
my $Src_dir = shift || die $Usage;
my $Perl_src = shift || die $Usage;
my $Installation = shift || die $Usage;
my $Options = "@ARGV";
$Options = "dry" if $Options =~ /\bdry\b/;
$Options = "@opt" if $Options =~ /\ball\b/;
pop @opt for 1 .. 8;
$Options = "@opt" unless $Options;
my $Sw;
my $Perl;
my $Top = `pwd`;
chomp $Top;
my $Build = "$Top/build";
my $Blead = $Perl_src eq "blead";
my $Maint = $Perl_src eq "maint";
sub get_src
{
my ($package, $dir) = @_;
$dir ||= $Src_dir;
my $src = $package;
$src = "$package.tar.gz" unless -f $src;
$src = "$package.tar.bz2" unless -f $src;
$src = "$dir/$package" unless -f $src;
$src = "$dir/$package.tar.gz" unless -f $src;
$src = "$dir/$package.tar.bz2" unless -f $src;
$src = $package unless -f $src;
# die "Can't find $package in $dir ($Src_dir)\n" unless -f $src;
return $src;
}
sub building ($)
{
my ($option) = @_;
return $Options =~ /\b$option\b/i;
}
sub uncompress
{
$_[0] =~ /2$/ ? "bzcat" : "zcat"
}
sub build ($$$)
{
my ($module, $src_dir, $opts) = @_;
chdir $Build or die "Can't chdir $Build: $!";
my $src = get_src($module, $src_dir);
$opts =
{
"unpack" => sub { dsys uncompress($src) . " $src | tar xf -" },
dir => sub { $src =~ m|.*/(.*)\.tar\.| && $1 },
config => sub { dsys "$Perl Makefile.PL" },
make => sub { dsys "make" },
test => sub { sys "make test" }, # some modules fail their tests...
install => sub { dsys "make install" },
%$opts
};
print "build $module\n";
my $dir = $opts->{dir}->();
$opts->{"unpack"}->();
chdir $dir or die "Can't chdir $dir: $!";
$opts->{config}->();
$opts->{make}->();
$opts->{test}->();
$opts->{install}->();
print "built $module\n";
}
sub main ()
{
dsys "rm -rf $Build";
mkdir $Build, 0750;
$ENV{HOME} = $Sw;
my $gmake = "make";
if (building "perl" && (!-e "$Sw/bin/perl" || building "force"))
{
chdir $Build or die "Can't chdir $Build: $!";
dsys "rm -rf $Sw/*";
if ($Blead)
{
my $perl_dir = "/usr/local/pkg/bleadperl";
mkdir $perl_dir;
chdir $perl_dir;
dsys "rsync -avz --delete " .
"rsync://ftp.activestate.com/perl-current/ .";
}
elsif ($Maint)
{
my $perl_dir = "$Installation/tmp/maintperl";
dsys "mkdir -p $perl_dir";
chdir $perl_dir;
if (1)
{
dsys "rsync -avz --delete " .
"rsync://ftp.linux.activestate.com/perl-5.8.x/ .";
}
else
{
my $url = "http://git.develooper.com/?p=perl.git;a=snapshot;" .
"h=maint-5.10;sf=tgz";
my $src = "maint.tar.gz";
dsys "rm -f *gz";
dsys "wget '$url'";
dsys "mv *gz $src";
dsys uncompress($src) . " $src | tar xf -";
$perl_dir .= "/perl";
chdir $perl_dir or die "Can't chdir $perl_dir: $!";
}
}
else
{
dsys uncompress($Perl_src) . " $Perl_src | tar xf -";
my ($perl_dir) = $Perl_src =~ m!.*/(.*)\.tar\.(gz|bz2)$!;
chdir $perl_dir or die "Can't chdir $perl_dir: $!";
}
my @opts =
(
"-Dperladmin='paul\@pjcj.net'",
"-Dprefix=$Sw",
);
push @opts, "-Dusedevel" if $Blead;
push @opts,
(
# -A, not -D
"-Dccflags='-fprofile-arcs -ftest-coverage'",
"-Dldflags='-fprofile-arcs -ftest-coverage'",
"-Doptimize='-g -O0'",
) if building "Xcoverage";
push @opts, "-A ccflags=-fPIC";
dsys "sh ./Configure -des @opts";
dsys "make" . (building "Xcoverage" ? " perl.gcov" : "");
dsys "HARNESS_OPTIONS=j$ENV{TEST_JOBS}:c " .
"make -j$ENV{TEST_JOBS} test_harness install";
# dsys "make install";
my ($version) = glob "${Perl}5.*";
symlink $version, $Perl unless -e $Perl;
$Options =~ s/\bperl\b//;
}
chdir $Top or die "Can't chdir $Top: $!";
my $restart = "perl -le 'print q()' '' | " .
"$Perl $0 $Src_dir $Perl_src $Installation $Options";
print "<$restart [$^X] [$Perl]>\n";
exec $restart if $^X !~ /$Perl/;
if (building "zlib")
{
my $zlib = "zlib-1.2.5";
build $zlib,
$Src_dir,
{
config => sub { dsys "./configure" },
install => sub { dsys "make install prefix=$Sw" },
};
}
if (building "openssl")
{
# my $openssl = "openssl-0.9.8g"; # Crypt::SSLeay fails
my $openssl = "openssl-0.9.7j";
# my $openssl = "openssl-0.9.8j";
build $openssl,
$Src_dir,
{ config => sub { dsys "./config --prefix=$Sw shared" } };
}
$ENV{LD_PRELOAD} = "$Sw/lib/libssl.so" if -e "$Sw/lib/libssl.so";
# my $apache = "apache_1.3.41";
my $apache = "httpd-2.2.11";
if ($apache =~ /apache/)
{
my $mod_perl = "mod_perl-1.30";
build $apache,
$Src_dir,
{
config => sub {},
make => sub {},
test => sub {},
install => sub {},
}
if building "apache";
build $mod_perl,
$Src_dir,
{
config => sub
{
dsys "$Perl Makefile.PL" .
" APACHE_SRC=../perl/src" .
" DO_HTTPD=1 USE_APACI=1 PREP_HTTPD=1 EVERYTHING=1";
},
}
if building "mod_perl";
build $apache,
$Src_dir,
{
"unpack" => sub {},
config => sub
{
dsys "./configure" .
" --prefix=$Sw" .
" --enable-module=so" .
" --enable-module=rewrite" .
" --activate-module=src/modules/perl/libperl.a";
},
}
if building "apache";
}
else
{
my $mod_perl = "mod_perl-2.0.4";
build $apache,
$Src_dir,
{
config => sub
{
dsys "./configure" .
" --prefix=$Sw" .
" --with-z=$Sw" .
" --with-ssl=$Sw" .
" --enable-mods-shared='ssl'" .
" --enable-modules='dav rewrite deflate headers'";
},
}
if building "apache";
build $mod_perl,
$Src_dir,
{
config => sub
{
dsys "$Perl Makefile.PL MP_APXS=$Sw/bin/apxs";
},
}
if building "mod_perl";
}
if (building "fastcgi" && -e "$Sw/bin/httpd")
{
my $fastcgi = "mod_fastcgi-2.4.6";
build $fastcgi,
$Src_dir,
{
config => sub
{
dsys "cp Makefile.AP2 Makefile";
{
local ($^I, @ARGV) = (".bak", "Makefile");
while (<>)
{
s|/usr/local/apache2|$Sw|;
print;
}
}
},
test => sub {},
}
}
if (building "git")
{
my $git = "git-1.6.3.3";
build $git,
$Src_dir,
{
config => sub { dsys "./configure --prefix=$Sw" },
make => sub { dsys "$gmake all" },
test => sub { dsys "$gmake test" },
test => sub { dsys "echo $gmake test" },
install => sub { dsys "$gmake install" },
}
}
if (building "postgres")
{
my $postgres = "postgresql-9.0.4";
build $postgres,
$Src_dir,
{
config => sub
{
dsys "./configure" .
" --prefix=$Sw" .
" --with-pgport=5433" .
" --without-readline" .
" --without-zlib" .
" --with-perl";
},
make => sub { dsys "$gmake" },
test => sub { dsys "$gmake check" },
install => sub { dsys "$gmake install-strip" },
}
unless -e "$Sw/bin/pg_ctl" && !building "force";
}
if (building "modules")
{
my $modules = <<EOM;
# Modules with many dependencies
Task::Kensho
Task::Plack
Task::Catalyst
Task::Dancer
Mojolicious
Task::Moose
Task::Dist::Zilla
Task::CPAN::SmokeBox
Task::Perl::Critic
Task::Toolchain::Test
Task::Template::Benchmark
MojoMojo
Jifty
Bot::BasicBot
# Stuff for Devel::Cover
Devel::Cover
../..
Parallel::Iterator
Test::Pod::Coverage
# My stuff
Gedcom
Shell::Source
# There's going to be repetition down here
# Modules with many dependents
Exporter
Text::Tabs
Test::Harness
Pod::Escapes
Pod::Simple
IO
Getopt::Long
Pod::Parser
ExtUtils::MakeMaker
Test::Simple
ExtUtils::Manifest
constant
Test
Data::Dumper
File::Temp
ExtUtils::Install
Text::ParseWords
ExtUtils::CBuilder
ExtUtils::ParseXS
Module::Build
File::Path
XSLoader
MIME::Base64
Digest
Digest::MD5
Sub::Uplevel
URI
Test::Exception
HTML::Tagset
HTML::Parser
Compress::Raw::Zlib
Compress::Raw::Bzip2
Storable
base
List::MoreUtils
Params::Util
Task::Weaken
Sub::Install
Data::OptList
Sub::Exporter
Test::Tester
Test::NoWarnings
Attribute::Handlers
Class::Accessor
Algorithm::C3
Class::C3
Sub::Name
MRO::Compat
Time::HiRes
Params::Validate
Try::Tiny
Scope::Guard
Package::Stash
version
Tree::DAG_Node
Test::Warn
Devel::GlobalDestruction
Class::MOP
Moose
Class::Data::Inheritable
Test::Deep
Carp::Clan
Module::Pluggable
Variable::Magic
B::Hooks::EndOfScope
Sub::Identify
namespace::clean
Time::Local
DBI
Text::Balanced
Class::Inspector
Test::Pod
Encode
Path::Class
Digest::SHA1
FCGI
CGI
MooseX::Types
XML::NamespaceSupport
XML::SAX
Class::Singleton
Clone
DateTime::TimeZone
DateTime::Locale
YAML
DateTime
namespace::autoclean
IO::String
Algorithm::Diff
File::Slurp
Devel::StackTrace
# Modules which should not fail
IO
List::MoreUtils
Test::Harness
ExtUtils::MakeMaker
File::Path
XML::Parser
Test::Simple
HTML::Tree
Storable
Net::IP
DB_File
XML::LibXML
Time::HiRes
Exporter
Pod::Escapes
ExtUtils::ParseXS
Module::Build
Pod::Parser
Data::Dumper
ExtUtils::Install
IO::Tty
XML::SAX
Class::ErrorHandler
URI
HTML::Template
Compress::Raw::Zlib
Net::DNS
Test::Pod::Coverage
XSLoader
version
URI::Fetch
Pod::Simple
constant
Test
File::Temp
Template::Toolkit
Cache::Cache
Feed::Find
HTML::Tagset
ExtUtils::PkgConfig
Devel::GlobalDestruction
PadWalker
Sub::Name
Encode
Test::Base
Class::DBI::Plugin::Type
Sub::Identify
Sub::Uplevel
Params::Validate
POE
Class::Singleton
Proc::ProcessTable
Compress::Raw::Bzip2
Class::MOP
HTTP::Server::Simple
Sub::Exporter
Fuse
File::HomeDir
Bot::BasicBot
# URI::Find::Simple
base
# GD
WWW::Mechanize
Test::Most
Sys::Syslog
File::Slurp
Tree::DAG_Node
FCGI
Params::Util
Devel::Peek
DateTime::Format::Mail
Spiffy
HTML::TableExtract
DBD::SQLite
Class::Accessor::Chained
DBIx::ContextualFetch
Test::Tester
Variable::Magic
AppConfig
Class::Accessor
Want
XML::Simple
IO::All
Number::Format
Term::ReadKey
DBI
Test::Exception
EOM
my @modules = grep /\S/, grep !/^ +#/, split /\n/, $modules;
s/^ +//, s/ +$// for @modules;
my %m; @modules = grep !$m{$_}++, @modules;
my $cpanm = "$Sw/bin/cpanm";
dsys((-e $cpanm ? $cpanm : "wget -O - http://cpanmin.us | $Perl -") .
" --self-upgrade");
for my $mod (@modules)
{
sys "$cpanm $mod" or
dsys "$cpanm -v --force --mirror http://cpan.cpantesters.org/ $mod";
}
}
if (building "coverage")
{
my $dir = "$Sw/.cpanm/work";
my $mods = "$Sw/modules";
mkdir $mods, 0750 unless -d $mods;
for my $d (grep -d, <$dir/*/*>)
{
print "Linking $d\n";
my ($e) = $d =~ m|/([^/]+)$| or die "Can't find module name";
my $new = "$mods/$e";
unlink $new if -e $new;
symlink $d => $new;
}
my $c;
$c .= "perl5.12.2 $Sw/bin/" if $Blead;
$c .= "cpancover -directory $mods -outputdir $Sw/cpancover ";
$c .= "-outputfile index.html -report ";
$c .= $Blead ? "html" : "html_basic";
# $c .= " -force";
$c .= " -redo_html";
dsys $c;
}
if (building "postgres" || building "dry")
{
my $pg = "$Installation/pgsql";
my $data = "$pg/data";
my $log = "$pg/postgres.log";
my $user = getpwuid($<);
print <<"EOT";
Now run the following commands as root:
rm -rf $pg
mkdir -p $data
# chown -R postgres.postgres $pg
# su - postgres
$Sw/bin/initdb -D $data
$Sw/bin/pg_ctl start -l $log -D $data
sleep 10
$Sw/bin/createuser -P -e -s tsg
$Sw/bin/createdb -e -O tsg tsg
# $Sw/bin/psql tsg
and stop the db with:
$Sw/bin/pg_ctl stop -l $log -D $data
EOT
}
}
$Perl_src = get_src($Perl_src, $Src_dir);
$Sw = "$Installation/sw";
$Perl = "$Sw/bin/perl";
$ENV{PATH} = "$Sw/bin:$ENV{PATH}";
$ENV{LD_LIBRARY_PATH} = "$Sw/lib:$ENV{LD_LIBRARY_PATH}";
$ENV{AUTOMATED_TESTING} = 1;
$ENV{TEST_JOBS} = 7;
print "sw directory is $Sw\n";
print "perl is $Perl\n";
print "PATH is $ENV{PATH}\n";
print "LD_LIBRARY_PATH is $ENV{LD_LIBRARY_PATH}\n";
# $Perl = <${Perl}5*> unless -e $Perl;
# die "Can't find perl under $Sw" unless -e $Perl;
main
__END__
$ perl ./buildperl ~/g/perl/src perl-5.14.1 /usr/local/pkg/tsg perl modules coverage