#!/usr/bin/perl -w
our
%Opt
;
our
$Id
=
q$Id: buildaperl 294 2008-02-22 10:42:30Z k $
;
my
$DEFAULT_CONFIG
=
"-Dinstallusrbinperl=n -Uversiononly -Doptimize=-g "
.
"-des -Duse64bitint -Dusedevel"
;
GetOptions(
\
%Opt
,
"apcdir=s"
,
"branch=s"
,
"config=s"
,
"h!"
,
"noconfigure!"
,
"noinstall!"
,
"notest!"
,
"prefix=s"
,
"remo!"
,
"start=s"
,
"target=s"
,
"verbose!"
,
"version!"
,
"writedotpatch!"
,
) or
die
Usage();
if
(
$Opt
{h}) {
print
Usage();
exit
;
}
if
(
$Opt
{version}) {
print
$Id
,
"\n"
;
exit
;
}
@ARGV
== 1 or
die
Usage();
sub
Usage {
qq{"Usage: $0 [options] version
[--config=...] # Configure options except --prefix; default:
$DEFAULT_CONFIG
[--apcdir=...] # where to find APC; defaults to "APC"
[--branch=...] # where to install: perl, maint-5.6, etc.
[--h] # this help message
[--noconfigure!] # Run without ./Configure
[--notest] # Run without make test
[--noinstall] # Run without ./installperl
[--prefix=...] # prefix of the inst directory; default ./installed-perls
[--remo] # remove source dir at the end
[--start] # start argument to patchaperlup
[--target=...] # e.g. miniperl
[--verbose] # noise
[--writedotpatch!] # write the .patch file for PERL_PATCHLEVEL
Version may be '\@', '5.7.0\@', '5.7.0\@7100', '\@7100', etc.
}
;
}
our
@SYSTEMTIMES
;
sub
mysystem ($);
$Opt
{branch} ||=
"perl"
;
$Opt
{apcdir} ||=
"APC"
;
my
$pwd
= cwd;
$Opt
{prefix} ||=
"$pwd/installed-perls"
;
$Opt
{config} ||=
$DEFAULT_CONFIG
;
my
(
$arg
) =
shift
;
unless
(
$arg
&&
$arg
=~ /\@/) {
die
"$0: argument must contain an \@"
;
}
my
(
$baseperl
,
$patchlevel
) =
$arg
=~ /^([^\@]*)@(\d*)$/;
die
"baseperl not defined"
unless
defined
$baseperl
;
die
"patchlevel not defined"
unless
defined
$patchlevel
;
die
"patchlevel not > 0"
if
length
$patchlevel
&& !
$patchlevel
> 0;
my
$apc
= Perl::Repository::APC->new(
$Opt
{apcdir});
my
$diffdir
;
my
$bap
= Perl::Repository::APC::BAP->new(
$apc
);
(
$baseperl
,
my
$nextperl
,
my
$firstpatch
,
$patchlevel
,
my
$dir
)=
$bap
->translate(
$Opt
{branch},
$baseperl
,
$patchlevel
);
warn
"Info: Target $baseperl\@$patchlevel, firstpatch $firstpatch, nextperl $nextperl, "
.
"branch $Opt{branch}\n"
;
if
(
$dir
=~ /-diffs$/) {
$diffdir
=
"$Opt{apcdir}/$dir"
;
}
else
{
$diffdir
=
"$Opt{apcdir}/$dir/diffs"
;
}
my
$upto_arg
=
" --upto='$patchlevel'"
;
my
(
$branch_letter
) =
substr
(
$Opt
{branch},0,1);
my
$target_dir
=
"perl-$branch_letter-$baseperl\@$patchlevel"
;
die
"Directory $target_dir exists but would be needed for building. Giving up "
if
-e
$target_dir
;
my
(
$src
,
$bdir
,
$start_arg
);
my
$ptempdir
= tempdir(
"psrc-XXXX"
,
DIR
=>
"."
,
CLEANUP
=> 1);
if
(
$baseperl
eq
"0"
) {
$src
=
""
;
$bdir
= File::Spec->catdir(
$ptempdir
,
"emptydir"
);
mkdir
$bdir
or
die
"Could not create $bdir: $!"
;
$start_arg
=
" --start='0'"
;
}
else
{
my
$tarball
=
$apc
->tarball(
$baseperl
) or
die
"Could not determine tarball for $baseperl"
;
if
(File::Spec->file_name_is_absolute(
$tarball
)
||
-e
$tarball
) {
$src
=
$tarball
;
}
else
{
$src
=
"$Opt{apcdir}/$baseperl/$tarball"
;
}
die
"src[$src] not found"
unless
-f
$src
;
open
my
$TAR
,
"tar -tzf $src |"
or
die
;
my
$exbdir
= <
$TAR
>;
chomp
$exbdir
;
$exbdir
=~ s|^\./||;
$exbdir
=~ s|/.*$||;
close
$TAR
;
$bdir
= File::Spec->catdir(
$ptempdir
,
$exbdir
);
my
$apcsrc
= File::Spec->abs2rel(
$src
);
my
$cwd
= Cwd::cwd();
chdir
$ptempdir
or
die
"Could not chdir to '$ptempdir': $!"
;
my
$relsrc
= File::Spec->catdir(
$cwd
,
$apcsrc
);
mysystem
"tar -xzf $relsrc"
;
chdir
$cwd
or
die
"Could not chdir to '$cwd': $!"
;
$start_arg
=
$Opt
{start} ?
" --start='$Opt{start}'"
:
" --start='$firstpatch'"
;
}
my
$verbose_switch
=
$Opt
{verbose} ?
"--verbose "
:
""
;
my
$branch_arg
=
" --branch='$Opt{branch}'"
;
my
$writedotpatch_switch
=
$Opt
{writedotpatch} ?
" --writedotpatch"
:
""
;
$0 =
"buildaperl:$branch_arg$upto_arg$start_arg"
;
mysystem
"patchaperlup $verbose_switch$branch_arg$writedotpatch_switch"
.
" --perldir='$bdir' --diffdir='$diffdir'$upto_arg$start_arg"
;
rename
$bdir
,
$target_dir
or
die
"Could not rename to $target_dir"
;
rmdir
$ptempdir
or
die
"Could not remove temporary directory '$ptempdir': $!"
;
system
"chmod -R u+w $target_dir"
;
chdir
$target_dir
or
die
"Could not chdir to $target_dir"
;
if
(
$Opt
{branch} eq
"perl"
&&
-e
"patchlevel.h"
&&
$patchlevel
>= 18749
) {
0==
system
($^X,
"-x"
,
"patchlevel.h"
,
"patchaperlup:$branch_arg$upto_arg$start_arg"
,
) or
die
;
}
unless
(
$Opt
{noconfigure}) {
my
$absprefix
= File::Spec->file_name_is_absolute(
$Opt
{prefix}) ?
$Opt
{prefix} : File::Spec->catfile(
$pwd
,
$Opt
{prefix});
mkpath
"$absprefix/$Opt{branch}"
;
my
$tempdir
= tempdir(
"pXXXXXX"
,
DIR
=>
"$absprefix/$Opt{branch}"
);
chmod
0755,
$tempdir
or
die
"Could not chmod to mode 0755 on directory '$tempdir': $!"
;
if
(
open
my
$fh
,
"MANIFEST"
) {
my
@manifest
= <
$fh
>;
if
(
grep
{ /^wince\/perl\.ico\s/ }
@manifest
and not -f
"wince/perl.ico"
) {
close
$fh
;
chmod
0644,
"MANIFEST"
or
die
"Could not chmod 0644 MANIFEST: $!"
;
open
$fh
,
">"
,
"MANIFEST"
or
die
"Could not open >MANIFEST: $!"
;
print
$fh
grep
{ ! /^wince\/perl\.ico\s/ }
@manifest
;
close
$fh
;
}
}
mysystem
"sh Configure -Dprefix=$tempdir/perl-$baseperl\@$patchlevel $Opt{config}"
;
my
$target
=
""
;
if
(
$Opt
{target}) {
$target
=
" $Opt{target}"
;
}
my
$makeout
=
""
;
open
my
(
$make
),
"make$target 2>&1 |"
or
die
;
while
(<
$make
>) {
print
;
$makeout
.=
$_
;
}
unless
(
close
$make
) {
my
$ret
= $?;
if
(
$makeout
=~ /(?:
no
rule to make target|don't know how to make).
*built
-in/i) {
print
"\aWARNING: Running
'make'
failed. It produced the infamous
<built-in> error that old perls have
with
new gccs. I'll work
around
this
in the makefiles now and retry. If you
do
not like that, hit ^C and FIXME.
Sleeping 5 seconds...\n";
sleep
5;
{
local
@ARGV
=
qw( makefile x2p/makefile)
;
local
$^I =
"~"
;
while
(<>) {
print
unless
/<(built-in|command line)>/;
}
}
mysystem
"make$target"
;
}
else
{
die
"make failed with ret[$ret]"
;
}
}
mysystem
"make test"
unless
$Opt
{notest};
mysystem
"LD_LIBRARY_PATH=. ./perl installperl"
unless
$Opt
{noinstall};
}
if
(
$Opt
{remo}){
chdir
$pwd
;
my
$rmtree
=
$target_dir
;
warn
"Removing $rmtree\n"
;
rmtree
$rmtree
;
}
sub
mysystem ($) {
my
$system
=
shift
;
warn
"Running $system\n"
;
my
$start
=
time
;
$ENV
{LANG} =
"C"
;
my
$ret
=
system
(
$system
);
unless
(
$ret
==0) {
my
$cwd
= cwd;
Carp::confess(
"system[$system] failed with ret[$ret] in cwd[$cwd]"
);
}
push
@SYSTEMTIMES
,
$system
,
time
-
$start
;
for
(
my
$i
= 0;
$i
<
@SYSTEMTIMES
;
$i
+=2){
printf
"%3d secs for[%s]\n"
,
@SYSTEMTIMES
[
$i
+1,
$i
];
}
}