Revert "Upgrade to Devel::PPPort 3.19_02" - we're frozen. This will be great when...
[p5sagit/p5-mst-13.2.git] / cpan / Devel-PPPort / devel / buildperl.pl
CommitLineData
adfe19db 1#!/usr/bin/perl -w
2################################################################################
3#
4# buildperl.pl -- build various versions of perl automatically
5#
6################################################################################
7#
3f0c6e0c 8# $Revision: 15 $
adfe19db 9# $Author: mhx $
3f0c6e0c 10# $Date: 2009/01/18 14:10:50 +0100 $
adfe19db 11#
12################################################################################
13#
3f0c6e0c 14# Version 3.x, Copyright (C) 2004-2009, Marcus Holland-Moritz.
adfe19db 15# Version 2.x, Copyright (C) 2001, Paul Marquess.
16# Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
17#
18# This program is free software; you can redistribute it and/or
19# modify it under the same terms as Perl itself.
20#
21################################################################################
22
23use strict;
24use Getopt::Long;
25use Pod::Usage;
26use File::Find;
27use File::Path;
28use Data::Dumper;
29use IO::File;
30use Cwd;
31
0d0f8426 32# TODO: - extra arguments to Configure
33
679ad62d 34#
35# --test-archives=1 check if archives can be read
36# --test-archives=2 like 1, but also extract archives
37# --test-archives=3 like 2, but also apply patches
38#
39
adfe19db 40my %opt = (
1d175cda 41 prefix => '/tmp/perl/install/<config>/<perl>',
42 build => '/tmp/perl/build/<config>',
43 source => '/tmp/perl/source',
44 force => 0,
45 test => 0,
46 install => 1,
47 oneshot => 0,
48 configure => 0,
cac25305 49 'test-archives' => 0,
adfe19db 50);
51
52my %config = (
4a582685 53 default => {
adfe19db 54 config_args => '-des',
55 },
4a582685 56 thread => {
adfe19db 57 config_args => '-des -Dusethreads',
0d0f8426 58 masked_versions => [ qr/^5\.00[01234]/ ],
adfe19db 59 },
4a582685 60 thread5005 => {
adfe19db 61 config_args => '-des -Duse5005threads',
0d0f8426 62 masked_versions => [ qr/^5\.00[012345]|^5.(9|\d\d)/ ],
adfe19db 63 },
4a582685 64 debug => {
adfe19db 65 config_args => '-des -Doptimize=-g',
66 },
67);
68
69my @patch = (
70 {
71 perl => [
0d0f8426 72 qr/^5\.00[01234]/,
adfe19db 73 qw/
0d0f8426 74 5.005
75 5.005_01
76 5.005_02
77 5.005_03
adfe19db 78 /,
79 ],
80 subs => [
81 [ \&patch_db, 1 ],
82 ],
83 },
84 {
85 perl => [
86 qw/
0d0f8426 87 5.6.0
88 5.6.1
89 5.7.0
90 5.7.1
91 5.7.2
92 5.7.3
93 5.8.0
adfe19db 94 /,
95 ],
96 subs => [
97 [ \&patch_db, 3 ],
98 ],
99 },
100 {
101 perl => [
679ad62d 102 qr/^5\.004_0[1234]$/,
adfe19db 103 ],
104 subs => [
105 [ \&patch_doio ],
106 ],
107 },
679ad62d 108 {
109 perl => [
110 qw/
111 5.005
112 5.005_01
113 5.005_02
114 /,
115 ],
116 subs => [
117 [ \&patch_sysv, old_format => 1 ],
118 ],
119 },
120 {
121 perl => [
122 qw/
123 5.005_03
124 5.005_04
125 /,
126 qr/^5\.6\.[0-2]$/,
127 qr/^5\.7\.[0-3]$/,
128 qr/^5\.8\.[0-8]$/,
129 qr/^5\.9\.[0-5]$/
130 ],
131 subs => [
132 [ \&patch_sysv ],
133 ],
134 },
adfe19db 135);
136
137my(%perl, @perls);
138
139GetOptions(\%opt, qw(
140 config=s@
141 prefix=s
0d0f8426 142 build=s
adfe19db 143 source=s
144 perl=s@
145 force
0d0f8426 146 test
147 install!
679ad62d 148 test-archives=i
1d175cda 149 patch!
150 oneshot
adfe19db 151)) or pod2usage(2);
152
1d175cda 153my %current;
154
155if ($opt{patch} || $opt{oneshot}) {
156 @{$opt{perl}} == 1 or die "Exactly one --perl must be given with --patch or --oneshot\n";
157 my $perl = $opt{perl}[0];
158 patch_source($perl) if !exists $opt{patch} || $opt{patch};
159 if (exists $opt{oneshot}) {
160 eval { require String::ShellQuote };
161 die "--oneshot requires String::ShellQuote to be installed\n" if $@;
162 %current = (config => 'oneshot', version => $perl);
163 $config{oneshot} = { config_args => String::ShellQuote::shell_quote(@ARGV) };
164 build_and_install($perl{$perl});
165 }
166 exit 0;
167}
168
adfe19db 169if (exists $opt{config}) {
170 for my $cfg (@{$opt{config}}) {
171 exists $config{$cfg} or die "Unknown configuration: $cfg\n";
172 }
173}
174else {
175 $opt{config} = [sort keys %config];
176}
177
178find(sub {
3f0c6e0c 179 /^(perl-?(5\..*))\.tar\.(gz|bz2)$/ or return;
0d0f8426 180 $perl{$1} = { version => $2, source => $File::Find::name, compress => $3 };
adfe19db 181}, $opt{source});
182
183if (exists $opt{perl}) {
184 for my $perl (@{$opt{perl}}) {
185 my $p = $perl;
186 exists $perl{$p} or $p = "perl$perl";
187 exists $perl{$p} or $p = "perl-$perl";
188 exists $perl{$p} or die "Cannot find perl: $perl\n";
189 push @perls, $p;
190 }
191}
192else {
193 @perls = sort keys %perl;
194}
195
cac25305 196if ($opt{'test-archives'}) {
197 my $test = 'test';
198 my $cwd = cwd;
199 -d $test or mkpath($test);
200 chdir $test or die "chdir $test: $!\n";
201 for my $perl (@perls) {
202 eval {
203 my $d = extract_source($perl{$perl});
679ad62d 204 if ($opt{'test-archives'} > 2) {
205 my $cwd2 = cwd;
206 chdir $d or die "chdir $d: $!\n";
207 patch_source($perl{$perl}{version});
208 chdir $cwd2 or die "chdir $cwd2:$!\n"
209 }
cac25305 210 rmtree($d) if -e $d;
211 };
212 warn $@ if $@;
213 }
214 chdir $cwd or die "chdir $cwd: $!\n";
215 print STDERR "cleaning up\n";
216 rmtree($test);
217 exit 0;
218}
219
adfe19db 220for my $cfg (@{$opt{config}}) {
221 for my $perl (@perls) {
222 my $config = $config{$cfg};
0d0f8426 223 %current = (config => $cfg, perl => $perl, version => $perl{$perl}{version});
adfe19db 224
0d0f8426 225 if (is($config->{masked_versions}, $current{version})) {
adfe19db 226 print STDERR "skipping $perl for configuration $cfg (masked)\n";
227 next;
228 }
229
230 if (-d expand($opt{prefix}) and !$opt{force}) {
231 print STDERR "skipping $perl for configuration $cfg (already installed)\n";
232 next;
233 }
234
235 my $cwd = cwd;
236
237 my $build = expand($opt{build});
238 -d $build or mkpath($build);
239 chdir $build or die "chdir $build: $!\n";
240
241 print STDERR "building $perl with configuration $cfg\n";
242 buildperl($perl, $config);
243
244 chdir $cwd or die "chdir $cwd: $!\n";
245 }
246}
247
248sub expand
249{
250 my $in = shift;
251 $in =~ s/(<(\w+)>)/exists $current{$2} ? $current{$2} : $1/eg;
252 return $in;
253}
254
255sub is
256{
257 my($s1, $s2) = @_;
4a582685 258
adfe19db 259 defined $s1 != defined $s2 and return 0;
260
261 ref $s2 and ($s1, $s2) = ($s2, $s1);
262
263 if (ref $s1) {
264 if (ref $s1 eq 'ARRAY') {
265 is($_, $s2) and return 1 for @$s1;
266 return 0;
267 }
268 return $s2 =~ $s1;
269 }
270
271 return $s1 eq $s2;
272}
273
274sub buildperl
275{
276 my($perl, $cfg) = @_;
277
278 my $d = extract_source($perl{$perl});
279 chdir $d or die "chdir $d: $!\n";
280
0d0f8426 281 patch_source($perl{$perl}{version});
adfe19db 282
283 build_and_install($perl{$perl});
284}
285
286sub extract_source
287{
1d175cda 288 eval { require Archive::Tar };
289 die "Archive processing requires Archive::Tar to be installed\n" if $@;
290
adfe19db 291 my $perl = shift;
adfe19db 292
cac25305 293 my $what = $opt{'test-archives'} ? 'test' : 'read';
294 print "${what}ing $perl->{source}\n";
adfe19db 295
0d0f8426 296 my $target;
adfe19db 297
0d0f8426 298 for my $f (Archive::Tar->list_archive($perl->{source})) {
299 my($t) = $f =~ /^([^\\\/]+)/ or die "ooops, should always match...\n";
300 die "refusing to extract $perl->{source}, as it would not extract to a single directory\n"
301 if defined $target and $target ne $t;
302 $target = $t;
303 }
adfe19db 304
cac25305 305 if ($opt{'test-archives'} == 0 || $opt{'test-archives'} > 1) {
306 if (-d $target) {
307 print "removing old build directory $target\n";
308 rmtree($target);
309 }
adfe19db 310
cac25305 311 print "extracting $perl->{source}\n";
0d0f8426 312
cac25305 313 Archive::Tar->extract_archive($perl->{source})
314 or die "extract failed: " . Archive::Tar->error() . "\n";
0d0f8426 315
cac25305 316 -d $target or die "oooops, $target not found\n";
317 }
adfe19db 318
319 return $target;
320}
321
322sub patch_source
323{
0d0f8426 324 my $version = shift;
adfe19db 325
326 for my $p (@patch) {
0d0f8426 327 if (is($p->{perl}, $version)) {
adfe19db 328 for my $s (@{$p->{subs}}) {
329 my($sub, @args) = @$s;
330 $sub->(@args);
331 }
332 }
333 }
334}
335
336sub build_and_install
337{
338 my $perl = shift;
339 my $prefix = expand($opt{prefix});
340
341 print "building perl $perl->{version} ($current{config})\n";
342
343 run_or_die("./Configure $config{$current{config}}{config_args} -Dusedevel -Uinstallusrbinperl -Dprefix=$prefix");
3f0c6e0c 344 run_or_die("sed -i -e '/^.*<built-in>/d' -e '/^.*<command line>/d' makefile x2p/makefile");
adfe19db 345 run_or_die("make all");
0d0f8426 346 run("make test") if $opt{test};
347 if ($opt{install}) {
348 run_or_die("make install");
349 }
350 else {
351 print "\n*** NOT INSTALLING PERL ***\n\n";
352 }
adfe19db 353}
354
355sub patch_db
356{
357 my $ver = shift;
679ad62d 358 print "patching ext/DB_File/DB_File.xs\n";
adfe19db 359 run_or_die("sed -i -e 's/<db.h>/<db$ver\\/db.h>/' ext/DB_File/DB_File.xs");
360}
361
362sub patch_doio
363{
679ad62d 364 patch(<<'END');
adfe19db 365--- doio.c.org 2004-06-07 23:14:45.000000000 +0200
366+++ doio.c 2003-11-04 08:03:03.000000000 +0100
367@@ -75,6 +75,16 @@
368 # endif
369 #endif
4a582685 370
adfe19db 371+#if _SEM_SEMUN_UNDEFINED
372+union semun
373+{
374+ int val;
375+ struct semid_ds *buf;
376+ unsigned short int *array;
377+ struct seminfo *__buf;
378+};
379+#endif
380+
381 bool
382 do_open(gv,name,len,as_raw,rawmode,rawperm,supplied_fp)
383 GV *gv;
384END
385}
386
679ad62d 387sub patch_sysv
388{
389 my %opt = @_;
390
391 # check if patching is required
392 return if $^O ne 'linux' or -f '/usr/include/asm/page.h';
393
394 if ($opt{old_format}) {
395 patch(<<'END');
396--- ext/IPC/SysV/SysV.xs.org 1998-07-20 10:20:07.000000000 +0200
397+++ ext/IPC/SysV/SysV.xs 2007-08-12 10:51:06.000000000 +0200
398@@ -3,9 +3,6 @@
399 #include "XSUB.h"
400
401 #include <sys/types.h>
402-#ifdef __linux__
403-#include <asm/page.h>
404-#endif
405 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
406 #include <sys/ipc.h>
407 #ifdef HAS_MSG
408END
409 }
410 else {
411 patch(<<'END');
412--- ext/IPC/SysV/SysV.xs.org 2007-08-11 00:12:46.000000000 +0200
413+++ ext/IPC/SysV/SysV.xs 2007-08-11 00:10:51.000000000 +0200
414@@ -3,9 +3,6 @@
415 #include "XSUB.h"
416
417 #include <sys/types.h>
418-#ifdef __linux__
419-# include <asm/page.h>
420-#endif
421 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
422 #ifndef HAS_SEM
423 # include <sys/ipc.h>
424END
425 }
426}
427
adfe19db 428sub patch
429{
679ad62d 430 my($patch) = @_;
431 print "patching $_\n" for $patch =~ /^\+{3}\s+(\S+)/gm;
432 my $diff = 'tmp.diff';
adfe19db 433 write_or_die($diff, $patch);
434 run_or_die("patch -s -p0 <$diff");
435 unlink $diff or die "unlink $diff: $!\n";
436}
437
438sub write_or_die
439{
440 my($file, $data) = @_;
441 my $fh = new IO::File ">$file" or die "$file: $!\n";
442 $fh->print($data);
443}
444
445sub run_or_die
446{
447 # print "[running @_]\n";
448 system "@_" and die "@_: $?\n";
449}
450
451sub run
452{
453 # print "[running @_]\n";
454 system "@_" and warn "@_: $?\n";
455}
0d0f8426 456
457__END__
458
459=head1 NAME
460
461buildperl.pl - build/install perl distributions
462
463=head1 SYNOPSIS
464
465 perl buildperl.pl [options]
466
467 --help show this help
468
469 --source=directory directory containing source tarballs
470 [default: /tmp/perl/source]
471
472 --build=directory directory used for building perls [EXPAND]
473 [default: /tmp/perl/build/<config>]
474
475 --prefix=directory use this installation prefix [EXPAND]
476 [default: /tmp/perl/install/<config>/<perl>]
477
478 --config=configuration build this configuration [MULTI]
479 [default: all possible configurations]
480
481 --perl=version build this version of perl [MULTI]
482 [default: all possible versions]
483
484 --force rebuild and install already installed versions
485
486 --test run test suite after building
487
488 --noinstall don't install after building
489
1d175cda 490 --patch only patch the perl source in the current directory
491
492 --oneshot build from the perl source in the current directory
493 (extra arguments are passed to Configure)
494
0d0f8426 495 options tagged with [MULTI] can be given multiple times
496
497 options tagged with [EXPAND] expand the following items
498
499 <perl> versioned perl directory (e.g. 'perl-5.6.1')
500 <version> perl version (e.g. '5.6.1')
501 <config> name of the configuration (e.g. 'default')
502
503=head1 EXAMPLES
504
505The following examples assume that your Perl source tarballs are
506in F</tmp/perl/source>. If they are somewhere else, use the C<--source>
507option to specify a different source directory.
508
509To build a default configuration of perl5.004_05 and install it
510to F</opt/perl5.004_05>, you would say:
511
512 buildperl.pl --prefix='/opt/<perl>' --perl=5.004_05 --config=default
513
514To build debugging configurations of all perls in the source directory
515and install them to F</opt>, use:
516
517 buildperl.pl --prefix='/opt/<perl>' --config=debug
518
519To build all configurations for perl-5.8.5 and perl-5.8.6, test them
520and don't install them, run:
521
522 buildperl.pl --perl=5.8.5 --perl=5.8.6 --test --noinstall
523
1d175cda 524To build and install a single version of perl with special configuration
525options, use:
526
527 buildperl.pl --perl=5.6.0 --prefix=/opt/p560ld --oneshot -- -des -Duselongdouble
528
0d0f8426 529=head1 COPYRIGHT
530
3f0c6e0c 531Copyright (c) 2004-2009, Marcus Holland-Moritz.
0d0f8426 532
533This program is free software; you can redistribute it and/or
534modify it under the same terms as Perl itself.
535
536=head1 SEE ALSO
537
ba120f6f 538See L<Devel::PPPort> and L<HACKERS>.
0d0f8426 539