2 ################################################################################
4 # buildperl.pl -- build various versions of perl automatically
6 ################################################################################
8 # Version 3.x, Copyright (C) 2004-2013, Marcus Holland-Moritz.
9 # Version 2.x, Copyright (C) 2001, Paul Marquess.
10 # Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
12 # This program is free software; you can redistribute it and/or
13 # modify it under the same terms as Perl itself.
15 ################################################################################
26 # TODO: - extra arguments to Configure
29 # --test-archives=1 check if archives can be read
30 # --test-archives=2 like 1, but also extract archives
31 # --test-archives=3 like 2, but also apply patches
35 prefix => '/tmp/perl/install/<config>/<perl>',
36 build => '/tmp/perl/build/<config>',
37 source => '/tmp/perl/source',
48 config_args => '-des',
51 config_args => '-des -Dusethreads',
52 masked_versions => [ qr/^5\.00[01234]/ ],
55 config_args => '-des -Duse5005threads',
56 masked_versions => [ qr/^5\.00[012345]|^5\.(9|\d\d)|^5\.8\.9/ ],
59 config_args => '-des -Doptimize=-g',
111 [ \&patch_sysv, old_format => 1 ],
132 qr/^5\.005(?:_0[1-4])?$/,
136 [ \&patch_configure ],
137 [ \&patch_makedepend_lc ],
145 [ \&patch_makedepend_lc ],
152 GetOptions(\%opt, qw(
168 if ($opt{patch} || $opt{oneshot}) {
169 @{$opt{perl}} == 1 or die "Exactly one --perl must be given with --patch or --oneshot\n";
170 my $perl = $opt{perl}[0];
171 patch_source($perl) if !exists $opt{patch} || $opt{patch};
172 if (exists $opt{oneshot}) {
173 eval { require String::ShellQuote };
174 die "--oneshot requires String::ShellQuote to be installed\n" if $@;
175 %current = (config => 'oneshot', version => $perl);
176 $config{oneshot} = { config_args => String::ShellQuote::shell_quote(@ARGV) };
177 build_and_install($perl{$perl});
182 if (exists $opt{config}) {
183 for my $cfg (@{$opt{config}}) {
184 exists $config{$cfg} or die "Unknown configuration: $cfg\n";
188 $opt{config} = [sort keys %config];
192 /^(perl-?(5\..*))\.tar\.(gz|bz2|lzma)$/ or return;
193 $perl{$1} = { version => $2, source => $File::Find::name, compress => $3 };
196 if (exists $opt{perl}) {
197 for my $perl (@{$opt{perl}}) {
199 exists $perl{$p} or $p = "perl$perl";
200 exists $perl{$p} or $p = "perl-$perl";
201 exists $perl{$p} or die "Cannot find perl: $perl\n";
206 @perls = sort keys %perl;
209 if ($opt{'test-archives'}) {
212 -d $test or mkpath($test);
213 chdir $test or die "chdir $test: $!\n";
214 for my $perl (@perls) {
216 my $d = extract_source($perl{$perl});
217 if ($opt{'test-archives'} > 2) {
219 chdir $d or die "chdir $d: $!\n";
220 patch_source($perl{$perl}{version});
221 chdir $cwd2 or die "chdir $cwd2:$!\n"
227 chdir $cwd or die "chdir $cwd: $!\n";
228 print STDERR "cleaning up\n";
233 for my $cfg (@{$opt{config}}) {
234 for my $perl (@perls) {
235 my $config = $config{$cfg};
236 %current = (config => $cfg, perl => $perl, version => $perl{$perl}{version});
238 if (is($config->{masked_versions}, $current{version})) {
239 print STDERR "skipping $perl for configuration $cfg (masked)\n";
243 if (-d expand($opt{prefix}) and !$opt{force}) {
244 print STDERR "skipping $perl for configuration $cfg (already installed)\n";
250 my $build = expand($opt{build});
251 -d $build or mkpath($build);
252 chdir $build or die "chdir $build: $!\n";
254 print STDERR "building $perl with configuration $cfg\n";
255 buildperl($perl, $config);
257 chdir $cwd or die "chdir $cwd: $!\n";
264 $in =~ s/(<(\w+)>)/exists $current{$2} ? $current{$2} : $1/eg;
272 defined $s1 != defined $s2 and return 0;
274 ref $s2 and ($s1, $s2) = ($s2, $s1);
277 if (ref $s1 eq 'ARRAY') {
278 is($_, $s2) and return 1 for @$s1;
289 my($perl, $cfg) = @_;
291 my $d = extract_source($perl{$perl});
292 chdir $d or die "chdir $d: $!\n";
294 patch_source($perl{$perl}{version});
296 build_and_install($perl{$perl});
301 eval { require Archive::Tar };
302 die "Archive processing requires Archive::Tar to be installed\n" if $@;
306 my $what = $opt{'test-archives'} ? 'test' : 'read';
307 print "${what}ing $perl->{source}\n";
311 for my $f (Archive::Tar->list_archive($perl->{source})) {
312 my($t) = $f =~ /^([^\\\/]+)/ or die "ooops, should always match...\n";
313 die "refusing to extract $perl->{source}, as it would not extract to a single directory\n"
314 if defined $target and $target ne $t;
318 if ($opt{'test-archives'} == 0 || $opt{'test-archives'} > 1) {
320 print "removing old build directory $target\n";
324 print "extracting $perl->{source}\n";
326 Archive::Tar->extract_archive($perl->{source})
327 or die "extract failed: " . Archive::Tar->error() . "\n";
329 -d $target or die "oooops, $target not found\n";
340 if (is($p->{perl}, $version)) {
341 for my $s (@{$p->{subs}}) {
342 my($sub, @args) = @$s;
349 sub build_and_install
352 my $prefix = expand($opt{prefix});
354 run_or_die(q{sed -i -e "s:\\*/\\*) finc=\\"-I\\`echo \\$file | sed 's#/\\[^/\\]\\*\\$##\\`\\" ;;:*/*) finc=\\"-I\\`echo \\$file | sed 's#/[^/]\\*\\$##'\\`\\" ;;:" makedepend.SH});
356 print "building perl $perl->{version} ($current{config})\n";
358 run_or_die("./Configure $config{$current{config}}{config_args} -Dusedevel -Uinstallusrbinperl -Dprefix=$prefix");
359 if (-f "x2p/makefile") {
360 run_or_die("sed -i -e '/^.*<builtin>/d' -e '/^.*<built-in>/d' -e '/^.*<command line>/d' -e '/^.*<command-line>/d' makefile x2p/makefile");
362 run_or_die("make all");
363 run("make test") if $opt{test};
365 run_or_die("make install");
368 print "\n*** NOT INSTALLING PERL ***\n\n";
375 print "patching ext/DB_File/DB_File.xs\n";
376 run_or_die("sed -i -e 's/<db.h>/<db$ver\\/db.h>/' ext/DB_File/DB_File.xs");
382 --- doio.c.org 2004-06-07 23:14:45.000000000 +0200
383 +++ doio.c 2003-11-04 08:03:03.000000000 +0100
388 +#if _SEM_SEMUN_UNDEFINED
392 + struct semid_ds *buf;
393 + unsigned short int *array;
394 + struct seminfo *__buf;
399 do_open(gv,name,len,as_raw,rawmode,rawperm,supplied_fp)
408 # check if patching is required
409 return if $^O ne 'linux' or -f '/usr/include/asm/page.h';
411 if ($opt{old_format}) {
413 --- ext/IPC/SysV/SysV.xs.org 1998-07-20 10:20:07.000000000 +0200
414 +++ ext/IPC/SysV/SysV.xs 2007-08-12 10:51:06.000000000 +0200
418 #include <sys/types.h>
420 -#include <asm/page.h>
422 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
429 --- ext/IPC/SysV/SysV.xs.org 2007-08-11 00:12:46.000000000 +0200
430 +++ ext/IPC/SysV/SysV.xs 2007-08-11 00:10:51.000000000 +0200
434 #include <sys/types.h>
436 -# include <asm/page.h>
438 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
440 # include <sys/ipc.h>
450 @@ -3380,6 +3380,18 @@
451 test "X$gfpthkeep" != Xy && gfpth=""
454 +# gcc 3.1 complains about adding -Idirectories that it already knows about,
455 +# so we will take those off from locincpth.
456 +case "$gccversion" in
458 + echo "main(){}">try.c
459 + for incdir in `$cc -v -c try.c 2>&1 | \
460 + sed '1,/^#include <\.\.\.>/d;/^End of search list/,$d;s/^ //'` ; do
461 + locincpth=`echo $locincpth | sed s!$incdir!!`
466 : What should the include directory be ?
472 sub patch_makedepend_lc
477 @@ -58,6 +58,10 @@ case $PERL_CONFIG_SH in
481 +# Avoid localized gcc/cc messages
485 # We need .. when we are in the x2p directory if we are using the
486 # cppstdin wrapper script.
487 # Put .. and . first so that we pick up the present cppstdin, not
494 print "patching $_\n" for $patch =~ /^\+{3}\s+(\S+)/gm;
495 my $diff = 'tmp.diff';
496 write_or_die($diff, $patch);
497 run_or_die("patch -s -p0 <$diff");
498 unlink $diff or die "unlink $diff: $!\n";
503 my($file, $data) = @_;
504 my $fh = new IO::File ">$file" or die "$file: $!\n";
510 # print "[running @_]\n";
511 system "@_" and die "@_: $?\n";
516 # print "[running @_]\n";
517 system "@_" and warn "@_: $?\n";
524 buildperl.pl - build/install perl distributions
528 perl buildperl.pl [options]
530 --help show this help
532 --source=directory directory containing source tarballs
533 [default: /tmp/perl/source]
535 --build=directory directory used for building perls [EXPAND]
536 [default: /tmp/perl/build/<config>]
538 --prefix=directory use this installation prefix [EXPAND]
539 [default: /tmp/perl/install/<config>/<perl>]
541 --config=configuration build this configuration [MULTI]
542 [default: all possible configurations]
544 --perl=version build this version of perl [MULTI]
545 [default: all possible versions]
547 --force rebuild and install already installed versions
549 --test run test suite after building
551 --noinstall don't install after building
553 --patch only patch the perl source in the current directory
555 --oneshot build from the perl source in the current directory
556 (extra arguments are passed to Configure)
558 options tagged with [MULTI] can be given multiple times
560 options tagged with [EXPAND] expand the following items
562 <perl> versioned perl directory (e.g. 'perl-5.6.1')
563 <version> perl version (e.g. '5.6.1')
564 <config> name of the configuration (e.g. 'default')
568 The following examples assume that your Perl source tarballs are
569 in F</tmp/perl/source>. If they are somewhere else, use the C<--source>
570 option to specify a different source directory.
572 To build a default configuration of perl5.004_05 and install it
573 to F</opt/perl5.004_05>, you would say:
575 buildperl.pl --prefix='/opt/<perl>' --perl=5.004_05 --config=default
577 To build debugging configurations of all perls in the source directory
578 and install them to F</opt>, use:
580 buildperl.pl --prefix='/opt/<perl>' --config=debug
582 To build all configurations for perl-5.8.5 and perl-5.8.6, test them
583 and don't install them, run:
585 buildperl.pl --perl=5.8.5 --perl=5.8.6 --test --noinstall
587 To build and install a single version of perl with special configuration
590 buildperl.pl --perl=5.6.0 --prefix=/opt/p560ld --oneshot -- -des -Duselongdouble
594 Copyright (c) 2004-2013, Marcus Holland-Moritz.
596 This program is free software; you can redistribute it and/or
597 modify it under the same terms as Perl itself.
601 See L<Devel::PPPort> and L<HACKERS>.