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