#!/usr/perl5/5.8.4/bin/perl -T # # Copyright 2004 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" # # 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 /usr/ccs/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 /usr/ccs/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/ccs/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/ccs/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);