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