#!/usr/perl5/5.8.4/bin/perl -T
#
# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
#
# This script builds and installs perl into the same location as when shipped
# with ON.
# This script should be run from within a perl source directory,
# and needs to be setuid-root.
#
use strict;
use warnings;
use POSIX qw(uname setuid);
use Cwd qw(abs_path);
use File::Find;
# Global config variables.
our ($PerlPfx, $PerlArch, $PerlRel, $SolRel, $SolVer, $SolArch);
# Globals for File::Find callbacks below.
our ($Start, $Fh);
#
# File::Find callback for finding files touched after Start
# and saving them in Fh. Uses globals $Start and $Fh.
#
sub touched
{
my ($p, $f) = ($File::Find::dir, $_);
# Ignore directories and object files.
return if (-d $f || $f =~ m{\.(?:a|o|so)$});
$p =~ s{^\./?}{};
my $pf = $p eq '' ? $f : "$p/$f";
# atime, mtime, ctime.
my ($a, $m, $c) = (lstat($f))[8, 9, 10];
$a = $m if ($m > $a);
$a = $c if ($c > $a);
print $Fh ("$pf\n") if ($a >= $Start);
}
#
# File::Find callback for finding all .packlist files and saving their
# contents in $Fh. Uses global $Fh.
#
sub cat_packlists
{
my ($p, $f) = ($File::Find::dir, $_);
# Ignore everything except .packlist files.
return unless ($f eq '.packlist');
$p =~ s{^\./?}{};
my $pf = $p eq '' ? $f : "$p/$f";
# Open .packlist, save into $Fh.
my $fh;
open($fh, '<', $f) || die("Can't open $pf: $!\n");
while (defined(my $line = <$fh>)) {
# Files only.
next unless ($line =~ s/\s+type=file.*$//);
$line =~ s{$PerlPfx/$PerlRel/}{};
print $Fh ($line)
}
close($fh);
}
#
# Main.
#
my $config_only = @ARGV && $ARGV[0] eq '-c' ? 1 : 0;
my $fh;
# This is all rather dangerous...
my ($ruid, $euid, $rgid, $egid) = ($<, $>, $(, $));
$ENV{PATH} =~ s{:/usr/dist[^:]*}{}g;
($ENV{PATH}) = $ENV{PATH} =~ /^(.*)$/;
delete($ENV{ENV});
if (! $config_only) {
$) = $rgid;
$> = $ruid;
}
# Basic environment check.
die("Not a perl build directory\n")
unless (-f 'Configure' && -f 'MANIFEST' && -f 'perl.c');
die("Needs to be run as root or setuid root\n")
unless ($config_only || $euid == 0);
# Prefix for perl installation.
$PerlPfx = '/usr/perl5';
# Perl architecture.
$PerlArch=qx{arch};
($PerlArch) = $PerlArch =~ /^(.*)\n$/;
$PerlArch="${PerlArch}-solaris-64int";
# Perl release.
my ($r, $v, $s);
open($fh, '<', 'patchlevel.h') || die("Can't open patchlevel.h: $!\n");
while (defined(my $line = <$fh>)) {
($line =~ /\bPERL_REVISION\s+(\d+)/) && ($r = $1);
($line =~ /\bPERL_VERSION\s+(\d+)/) && ($v = $1);
($line =~ /\bPERL_SUBVERSION\s+(\d+)/) && ($s = $1);
last if (defined($r) && defined($v) && defined($s));
}
$PerlRel = "$r.$v.$s";
undef($r);
undef($v);
undef($s);
# Solaris config.
$SolRel = (uname())[2]; # Solaris Release.
$SolVer = '2.' . substr($SolRel, 2); # Solaris Version.
$SolArch = qx{uname -p}; # Solaris architecture.
chomp($SolArch);
# Compiler and flags.
my $compiler1 = qx{exec ksh -e whence cc};
chomp($compiler1);
$compiler1 =~ s{/bin/cc}{};
my $compiler2 = abs_path($compiler1);
$compiler1 = ' *' . $compiler1 . '[^ ]* *';
$compiler2 = ' *' . $compiler2 . '[^ ]* *';
my $optimize='-xO3 -xspace -xildoff';
my ($ccextraflags, $myuname);
if ($SolArch eq 'sparc') {
$ccextraflags='-xarch=v8';
$myuname="sunos localhost $SolRel sun4u sparc SUNW,Ultra-2";
} else {
$ccextraflags='';
$myuname="sunos localhost $SolRel i86pc i386 i86pc";
}
$ccextraflags .= " -D_TS_ERRNO";
$ccextraflags =~ s/\s\s+/ /g;
$ccextraflags =~ s/^\s+//;
$ccextraflags =~ s/\s+$//;
# Dmake parallelism.
my $DmakeJobs = 4;
# Clean up, delete any old configuration files.
system('make realclean') if (-f 'Makefile');
unlink('config.sh') if (-f 'config.sh');
unlink('Policy.sh') if (-f 'Policy.sh');
# Create the config.over file to override some common settings.
open($fh, '>', 'config.over') || die("Can't open config.over: $!\n");
print $fh <<"EOF";
ccflags=`echo \$ccflags | sed -e 's! *-I/usr/local/include *! !'`
ccflags="\$ccflags $ccextraflags"
ccversion='Sun WorkShop'
cf_by='perl-bugs'
cf_email='perl-bugs\@sun.com'
cf_time=''
cppflags=''
inc_version_list=''
inc_version_list_init='0'
installusrbinperl='undef'
lddlflags='-G'
ldflags=''
libpth='/lib /usr/lib'
libsdirs=`echo \$libsdirs | sed -e 's!$compiler1! !' -e 's!$compiler2! !'`
libsfound=`echo \$libsfound | sed -e 's!$compiler1! !' -e 's!$compiler2! !'`
libspath='/lib /usr/lib'
locincpth="/usr/sfw/include /opt/sfw/include \$locincpth"
loclibpth=`echo \$loclibpth | sed -e 's!$compiler1! !' -e 's!$compiler2! !'`
loclibpth="/usr/sfw/lib /opt/sfw/lib \$loclibpth"
make_set_make='#'
mydomain='.sun.com'
myhostname='localhost'
myuname='$myuname'
osvers='$SolVer'
pager='/usr/bin/more'
perl5='/bin/perl'
perladmin='perl-bugs\@sun.com'
EOF
close($fh);
#
# Run Configure with the correct flags to give the required config files,
# then remove the record of the Configure command-line and extra whitespace.
# Finally, expand config.sh into the generated files used during the build.
# Note: due to the fact that '-D' options confuse Configure, ccflags are
# handled in config.over, above.
#
system <<"EOF";
./Configure -dsOE \\
-Duseshrplib -Uusemymalloc -Duse64bitint -Doptimize="$optimize" \\
-Dcc=cc \\
-Dprefix=$PerlPfx/$PerlRel \\
-Dprivlib=$PerlPfx/$PerlRel/lib \\
-Darchlib=$PerlPfx/$PerlRel/lib/$PerlArch \\
-Dsiteprefix=$PerlPfx/$PerlRel \\
-Dsitelib=$PerlPfx/site_perl/$PerlRel \\
-Dsitearch=$PerlPfx/site_perl/$PerlRel/$PerlArch \\
-Dvendorprefix=$PerlPfx/$PerlRel \\
-Dvendorlib=$PerlPfx/vendor_perl/$PerlRel \\
-Dvendorarch=$PerlPfx/vendor_perl/$PerlRel/$PerlArch \\
-Dman1dir=$PerlPfx/$PerlRel/man/man1 \\
-Dman3dir=$PerlPfx/$PerlRel/man/man3 \\
| 2>&1 tee configure.log
sed -e "s/^config_args=.*/config_args=''/" \\
-e "s/^config_argc=.*/config_argc=0/" \\
-e "/^config_arg[1-9][0-9]*=/d" \\
-e "s/ threads threads\\/shared//" \\
-e "s/' */'/g" \\
-e "s/ *'/'/g" \\
config.sh > config.new
mv config.new config.sh
EOF
# Get the start time of the build.
$Start = time();
# Expand the configure-generated files.
system <<"EOF" || die("Build failed\n");
./Configure -S | 2>&1 tee -a configure.log
EOF
# Stop here if just configuring.
exit(0) if ($config_only);
# Make and test perl.
system <<"EOF" || die("Build failed\n");
dmake -j $DmakeJobs | 2>&1 tee make.log
/usr/bin/make test | 2>&1 tee test.log
EOF
# Find all files touched by the build & save in build.touched
open($Fh, '>', 'build.touched') || die("Can't open build.touched: $!\n");
find({ wanted => \&touched, untaint => 1 }, '.');
close($Fh);
# Install perl (needs to be root!)
$( = $) = $egid; $< = $> = $euid;
system <<"EOF";
/bin/rm -rf $PerlPfx/$PerlRel
/usr/bin/make install
EOF
$) = $rgid; $> = $ruid;
#
# Find all the .packlist files, cat them together
# and save them in install.packlist
#
open($Fh, '>', 'install.packlist') || die("Can't open install.packlist: $!\n");
print $Fh ("PREFIX: $PerlPfx/$PerlRel\n");
find({ wanted => \&cat_packlists, untaint => 1 }, "$PerlPfx/$PerlRel");
close($Fh);
exit(0);