This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perldelta: s/nul\k/l/g
[perl5.git] / Porting / bisect-runner.pl
CommitLineData
6a8dbfd7
NC
1#!/usr/bin/perl -w
2use strict;
3
390a69a9 4use Getopt::Long qw(:config bundling no_auto_abbrev);
77ae6092 5use Pod::Usage;
2526f4b8 6use Config;
6a8dbfd7 7
2526f4b8
NC
8my @targets
9 = qw(config.sh config.h miniperl lib/Config.pm Fcntl perl test_prep);
6a8dbfd7 10
e4516dd0
NC
11my $cpus;
12if (open my $fh, '<', '/proc/cpuinfo') {
13 while (<$fh>) {
14 ++$cpus if /^processor\s+:\s+\d+$/;
15 }
d64af352
NC
16} elsif (-x '/sbin/sysctl') {
17 $cpus = 1 + $1 if `/sbin/sysctl hw.ncpu` =~ /^hw\.ncpu: (\d+)$/;
da83cd31
NC
18} elsif (-x '/usr/bin/getconf') {
19 $cpus = 1 + $1 if `/usr/bin/getconf _NPROCESSORS_ONLN` =~ /^(\d+)$/;
e4516dd0
NC
20}
21
f4800c99
NC
22my %options =
23 (
e4516dd0 24 jobs => defined $cpus ? $cpus + 1 : 2,
f4800c99
NC
25 'expect-pass' => 1,
26 clean => 1, # mostly for debugging this
27 );
6a8dbfd7 28
fdbac266
NC
29my $linux64 = `uname -sm` eq "Linux x86_64\n" ? '64' : '';
30
31my @paths = map {$_ . $linux64} qw(/usr/local/lib /lib /usr/lib);
390a69a9
NC
32
33my %defines =
34 (
35 usedevel => '',
36 optimize => '-g',
37 cc => 'ccache gcc',
38 ld => 'gcc',
fdbac266 39 ($linux64 ? (libpth => \@paths) : ()),
390a69a9
NC
40 );
41
f4800c99
NC
42unless(GetOptions(\%options,
43 'target=s', 'jobs|j=i', 'expect-pass=i',
44 'expect-fail' => sub { $options{'expect-pass'} = 0; },
45 'clean!', 'one-liner|e=s', 'match=s', 'force-manifest',
77ae6092 46 'test-build', 'check-args', 'A=s@', 'usage|help|?',
390a69a9
NC
47 'D=s@' => sub {
48 my (undef, $val) = @_;
49 if ($val =~ /\A([^=]+)=(.*)/s) {
50 $defines{$1} = length $2 ? $2 : "\0";
51 } else {
52 $defines{$val} = '';
53 }
54 },
55 'U=s@' => sub {
56 $defines{$_[1]} = undef;
57 },
6a8dbfd7 58 )) {
77ae6092 59 pod2usage(exitval => 255, verbose => 1);
6a8dbfd7
NC
60}
61
f4800c99 62my ($target, $j, $match) = @options{qw(target jobs match)};
e295b7be 63
77ae6092
NC
64pod2usage(exitval => 255, verbose => 1) if $options{usage};
65pod2usage(exitval => 255, verbose => 1)
66 unless @ARGV || $match || $options{'test-build'} || defined $options{'one-liner'};
6a8dbfd7 67
f4800c99 68exit 0 if $options{'check-args'};
6a8dbfd7 69
77ae6092
NC
70=head1 NAME
71
72bisect.pl - use git bisect to pinpoint changes
73
74=head1 SYNOPSIS
75
76 # When did this become an error?
77 .../Porting/bisect.pl -e 'my $a := 2;'
71d80638 78 # When did this stop being an error?
77ae6092
NC
79 .../Porting/bisect.pl --expect-fail -e '1 // 2'
80 # When did this stop matching?
81 .../Porting/bisect.pl --match '\b(?:PL_)hash_seed_set\b'
82 # When did this start matching?
83 .../Porting/bisect.pl --expect-fail --match '\buseithreads\b'
84 # When did this test program stop working?
facd1b88 85 .../Porting/bisect.pl -- ./perl -Ilib test_prog.pl
77ae6092
NC
86 # When did this first become valid syntax?
87 .../Porting/bisect.pl --target=miniperl --end=v5.10.0 \
88 --expect-fail -e 'my $a := 2;'
89 # What was the last revision to build with these options?
90 .../Porting/bisect.pl --test-build -Dd_dosuid
91
92=head1 DESCRIPTION
93
facd1b88 94Together F<bisect.pl> and F<bisect-runner.pl> attempt to automate the use
77ae6092
NC
95of C<git bisect> as much as possible. With one command (and no other files)
96it's easy to find out
97
98=over 4
99
100=item *
101
102Which commit caused this example code to break?
103
104=item *
105
106Which commit caused this example code to start working?
107
108=item *
109
110Which commit added the first to match this regex?
111
112=item *
113
114Which commit removed the last to match this regex?
115
116=back
117
118usually without needing to know which versions of perl to use as start and
119end revisions.
120
facd1b88 121By default F<bisect.pl> will process all options, then use the rest of the
77ae6092
NC
122command line as arguments to list C<system> to run a test case. By default,
123the test case should pass (exit with 0) on earlier perls, and fail (exit
facd1b88 124non-zero) on I<blead>. F<bisect.pl> will use F<bisect-runner.pl> to find the
77ae6092 125earliest stable perl version on which the test case passes, check that it
facd1b88 126fails on blead, and then use F<bisect-runner.pl> with C<git bisect run> to
77ae6092
NC
127find the commit which caused the failure.
128
129Because the test case is the complete argument to C<system>, it is easy to
130run something other than the F<perl> built, if necessary. If you need to run
131the perl built, you'll probably need to invoke it as C<./perl -Ilib ...>
132
5842706e
NC
133You need a clean checkout to run a bisect, and you can't use the checkout
134which contains F<Porting/bisect.pl> (because C<git bisect>) will check out
135a revision before F<Porting/bisect-runner.pl> was added, which
136C<git bisect run> needs). If your working checkout is called F<perl>, the
137simplest solution is to make a local clone, and run from that. I<i.e.>:
138
139 cd ..
140 git clone perl perl2
141 cd perl2
142 ../perl/Porting/bisect.pl ...
143
facd1b88 144By default, F<bisect-runner.pl> will automatically disable the build of
cfadff5f
NC
145L<DB_File> for commits earlier than ccb44e3bf3be2c30, as it's not practical
146to patch DB_File 1.70 and earlier to build with current Berkeley DB headers.
147(ccb44e3bf3be2c30 was in September 1999, between 5.005_62 and 5.005_63.)
148If your F<db.h> is old enough you can override this with C<-Unoextensions>.
149
77ae6092
NC
150=head1 OPTIONS
151
152=over 4
153
154=item *
155
156--start I<commit-ish>
157
158Earliest revision to test, as a I<commit-ish> (a tag, commit or anything
facd1b88 159else C<git> understands as a revision). If not specified, F<bisect.pl> will
77ae6092
NC
160search stable perl releases from 5.002 to 5.14.0 until it finds one where
161the test case passes.
162
163=item *
164
165--end I<commit-ish>
166
167Most recent revision to test, as a I<commit-ish>. If not specified, defaults
b4f0ec5f 168to I<blead>.
77ae6092
NC
169
170=item *
171
172--target I<target>
173
174F<Makefile> target (or equivalent) needed, to run the test case. If specified,
175this should be one of
176
177=over 4
178
179=item *
180
181I<config.sh>
182
facd1b88 183Just run F<./Configure>
77ae6092
NC
184
185=item *
186
187I<config.h>
188
189Run the various F<*.SH> files to generate F<Makefile>, F<config.h>, I<etc>.
190
191=item *
192
193I<miniperl>
194
195Build F<miniperl>.
196
197=item *
198
199I<lib/Config.pm>
200
201Use F<miniperl> to build F<lib/Config.pm>
202
203=item *
204
2526f4b8
NC
205I<Fcntl>
206
207Build F<lib/auto/Fcntl/Fnctl.so> (strictly, C<.$Config{so}>). As L<Fcntl>
208is simple XS module present since 5.000, this provides a fast test of
b4f0ec5f 209whether XS modules can be built. Note, XS modules are built by F<miniperl>,
2526f4b8
NC
210hence this target will not build F<perl>.
211
212=item *
213
77ae6092
NC
214I<perl>
215
216Build F<perl>. This also builds pure-Perl modules in F<cpan>, F<dist> and
2526f4b8
NC
217F<ext>. XS modules (such as L<Fcntl>) are not built.
218
219=item *
220
77ae6092
NC
221I<test_prep>
222
223Build everything needed to run the tests. This is the default if we're
224running test code, but is time consuming, as it means building all
b4f0ec5f 225XS modules. For older F<Makefile>s, the previous name of C<test-prep>
77ae6092
NC
226is automatically substituted. For very old F<Makefile>s, C<make test> is
227run, as there is no target provided to just get things ready, and for 5.004
228and earlier the tests run very quickly.
229
230=back
231
232=item *
233
234--one-liner 'code to run'
235
236=item *
237
238-e 'code to run'
239
a1756669 240Example code to run, just like you'd use with C<perl -e>.
77ae6092
NC
241
242This prepends C<./perl -Ilib -e 'code to run'> to the test case given,
facd1b88 243or F<./miniperl> if I<target> is C<miniperl>.
77ae6092
NC
244
245(Usually you'll use C<-e> instead of providing a test case in the
facd1b88 246non-option arguments to F<bisect.pl>)
77ae6092
NC
247
248C<-E> intentionally isn't supported, as it's an error in 5.8.0 and earlier,
249which interferes with detecting errors in the example code itself.
250
251=item *
252
253--expect-fail
254
255The test case should fail for the I<start> revision, and pass for the I<end>
256revision. The bisect run will find the first commit where it passes.
257
258=item *
259
af7c500f 260-Dnoextensions=Encode
77ae6092
NC
261
262=item *
263
264-Uusedevel
265
266=item *
267
268-Accflags=-DNO_MATHOMS
269
270Arguments to pass to F<Configure>. Repeated C<-A> arguments are passed
271through as is. C<-D> and C<-U> are processed in order, and override
af7c500f
NC
272previous settings for the same parameter. F<bisect-runner.pl> emulates
273C<-Dnoextensions> when F<Configure> itself does not provide it, as it's
274often very useful to be able to disable some XS extensions.
77ae6092
NC
275
276=item *
277
b4f0ec5f 278--jobs I<jobs>
77ae6092
NC
279
280=item *
281
b4f0ec5f 282-j I<jobs>
77ae6092 283
da83cd31
NC
284Number of C<make> jobs to run in parallel. If F</proc/cpuinfo> exists and
285can be parsed, or F</sbin/sysctl> exists and reports C<hw.ncpu>, or
286F</usr/bin/getconf> exists and reports C<_NPROCESSORS_ONLN> defaults to 1 +
287I<number of CPUs>. Otherwise defaults to 2.
77ae6092
NC
288
289=item *
290
b4f0ec5f 291--match pattern
77ae6092
NC
292
293Instead of running a test program to determine I<pass> or I<fail>, pass
294if the given regex matches, and hence search for the commit that removes
295the last matching file.
296
297If no I<target> is specified, the match is against all files in the
298repository (which is fast). If a I<target> is specified, that target is
299built, and the match is against only the built files. C<--expect-fail> can
300be used with C<--match> to search for a commit that adds files that match.
301
302=item *
303
304--test-build
305
306Test that the build completes, without running any test case.
307
308By default, if the build for the desired I<target> fails to complete,
309F<bisect-runner.pl> reports a I<skip> back to C<git bisect>, the assumption
310being that one wants to find a commit which changed state "builds && passes"
311to "builds && fails". If instead one is interested in which commit broke the
312build (possibly for particular F<Configure> options), use I<--test-build>
313to treat a build failure as a failure, not a "skip".
314
b4f0ec5f
NC
315Often this option isn't as useful as it first seems, because I<any> build
316failure will be reported to C<git bisect> as a failure, not just the failure
317that you're interested in. Generally, to debug a particular problem, it's
318more useful to use a I<target> that builds properly at the point of interest,
319and then a test case that runs C<make>. For example:
320
321 .../Porting/bisect.pl --start=perl-5.000 --end=perl-5.002 \
322 --expect-fail --force-manifest --target=miniperl make perl
323
facd1b88
NC
324will find the first revision capable of building L<DynaLoader> and then
325F<perl>, without becoming confused by revisions where F<miniperl> won't
b4f0ec5f
NC
326even link.
327
77ae6092
NC
328=item *
329
b4f0ec5f
NC
330--force-manifest
331
77ae6092
NC
332By default, a build will "skip" if any files listed in F<MANIFEST> are not
333present. Usually this is useful, as it avoids false-failures. However, there
334are some long ranges of commits where listed files are missing, which can
335cause a bisect to abort because all that remain are skipped revisions.
336
337In these cases, particularly if the test case uses F<miniperl> and no modules,
338it may be more useful to force the build to continue, even if files
339F<MANIFEST> are missing.
340
341=item *
342
343--expect-pass [0|1]
344
345C<--expect-pass=0> is equivalent to C<--expect-fail>. I<1> is the default.
346
347=item *
348
349--no-clean
350
351Tell F<bisect-runner.pl> not to clean up after the build. This allows one
352to use F<bisect-runner.pl> to build the current particular perl revision for
353interactive testing, or for debugging F<bisect-runner.pl>.
354
355Passing this to F<bisect.pl> will likely cause the bisect to fail badly.
356
357=item *
358
359--check-args
360
361Validate the options and arguments, and exit silently if they are valid.
362
363=item *
364
365--usage
366
367=item *
368
369--help
370
371=item *
372
373-?
374
375Display the usage information and exit.
376
377=back
378
379=cut
380
0afef97d 381die "$0: Can't build $target" if defined $target && !grep {@targets} $target;
6a8dbfd7
NC
382
383$j = "-j$j" if $j =~ /\A\d+\z/;
384
0142f0ce
NC
385# Sadly, however hard we try, I don't think that it will be possible to build
386# modules in ext/ on x86_64 Linux before commit e1666bf5602ae794 on 1999/12/29,
387# which updated to MakeMaker 3.7, which changed from using a hard coded ld
388# in the Makefile to $(LD). On x86_64 Linux the "linker" is gcc.
389
6a8dbfd7
NC
390sub extract_from_file {
391 my ($file, $rx, $default) = @_;
392 open my $fh, '<', $file or die "Can't open $file: $!";
393 while (<$fh>) {
394 my @got = $_ =~ $rx;
395 return wantarray ? @got : $got[0]
396 if @got;
397 }
398 return $default if defined $default;
399 return;
400}
401
c59e8fd6
NC
402sub edit_file {
403 my ($file, $munger) = @_;
404 local $/;
405 open my $fh, '<', $file or die "Can't open $file: $!";
406 my $orig = <$fh>;
407 die "Can't read $file: $!" unless defined $orig && close $fh;
408 my $new = $munger->($orig);
409 return if $new eq $orig;
410 open $fh, '>', $file or die "Can't open $file: $!";
411 print $fh $new or die "Can't print to $file: $!";
412 close $fh or die "Can't close $file: $!";
413}
414
415sub apply_patch {
416 my $patch = shift;
417
418 my ($file) = $patch =~ qr!^diff.*a/(\S+) b/\1!;
419 open my $fh, '|-', 'patch', '-p1' or die "Can't run patch: $!";
420 print $fh $patch;
5fceabf3
NC
421 return if close $fh;
422 print STDERR "Patch is <<'EOPATCH'\n${patch}EOPATCH\n";
423 die "Can't patch $file: $?, $!";
c59e8fd6
NC
424}
425
ab4a15f9 426sub clean {
f4800c99 427 if ($options{clean}) {
ab4a15f9
NC
428 # Needed, because files that are build products in this checked out
429 # version might be in git in the next desired version.
9da8cb0a 430 system 'git clean -dxf </dev/null';
ab4a15f9
NC
431 # Needed, because at some revisions the build alters checked out files.
432 # (eg pod/perlapi.pod). Also undoes any changes to makedepend.SH
9da8cb0a 433 system 'git reset --hard HEAD </dev/null';
ab4a15f9
NC
434 }
435}
436
437sub skip {
438 my $reason = shift;
439 clean();
440 warn "skipping - $reason";
441 exit 125;
442}
443
f1050811
NC
444sub report_and_exit {
445 my ($ret, $pass, $fail, $desc) = @_;
446
447 clean();
448
f4800c99 449 my $got = ($options{'expect-pass'} ? !$ret : $ret) ? 'good' : 'bad';
f1050811
NC
450 if ($ret) {
451 print "$got - $fail $desc\n";
452 } else {
453 print "$got - $pass $desc\n";
454 }
455
456 exit($got eq 'bad');
457}
458
0afef97d
NC
459sub match_and_exit {
460 my $target = shift;
461 my $matches = 0;
462 my $re = qr/$match/;
463 my @files;
464
465 {
466 local $/ = "\0";
467 @files = defined $target ? `git ls-files -o -z`: `git ls-files -z`;
468 chomp @files;
469 }
470
471 foreach my $file (@files) {
472 open my $fh, '<', $file or die "Can't open $file: $!";
473 while (<$fh>) {
474 if ($_ =~ $re) {
475 ++$matches;
476 if (tr/\t\r\n -~\200-\377//c) {
477 print "Binary file $file matches\n";
478 } else {
479 $_ .= "\n" unless /\n\z/;
480 print "$file: $_";
481 }
482 }
483 }
484 close $fh or die "Can't close $file: $!";
485 }
486 report_and_exit(!$matches,
487 $matches == 1 ? '1 match for' : "$matches matches for",
488 'no matches for', $match);
489}
490
6a8dbfd7 491# Not going to assume that system perl is yet new enough to have autodie
9da8cb0a 492system 'git clean -dxf </dev/null' and die;
6a8dbfd7 493
0afef97d
NC
494if (!defined $target) {
495 match_and_exit() if $match;
496 $target = 'test_prep';
bc96a05a
NC
497}
498
4b081584
NC
499skip('no Configure - is this the //depot/perlext/Compiler branch?')
500 unless -f 'Configure';
501
dbcdc176
NC
502# This changes to PERL_VERSION in 4d8076ea25903dcb in 1999
503my $major
504 = extract_from_file('patchlevel.h',
505 qr/^#define\s+(?:PERL_VERSION|PATCHLEVEL)\s+(\d+)\s/,
506 0);
507
0142f0ce
NC
508if ($major < 1) {
509 if (extract_from_file('Configure',
510 qr/^ \*=\*\) echo "\$1" >> \$optdef;;$/)) {
511 # This is " Spaces now allowed in -D command line options.",
512 # part of commit ecfc54246c2a6f42
513 apply_patch(<<'EOPATCH');
514diff --git a/Configure b/Configure
515index 3d3b38d..78ffe16 100755
516--- a/Configure
517+++ b/Configure
518@@ -652,7 +777,8 @@ while test $# -gt 0; do
519 echo "$me: use '-U symbol=', not '-D symbol='." >&2
520 echo "$me: ignoring -D $1" >&2
521 ;;
522- *=*) echo "$1" >> $optdef;;
523+ *=*) echo "$1" | \
524+ sed -e "s/'/'\"'\"'/g" -e "s/=\(.*\)/='\1'/" >> $optdef;;
525 *) echo "$1='define'" >> $optdef;;
526 esac
527 shift
528EOPATCH
529 }
530 if (extract_from_file('Configure', qr/^if \$contains 'd_namlen' \$xinc\b/)) {
531 # Configure's original simple "grep" for d_namlen falls foul of the
532 # approach taken by the glibc headers:
533 # #ifdef _DIRENT_HAVE_D_NAMLEN
534 # # define _D_EXACT_NAMLEN(d) ((d)->d_namlen)
535 #
536 # where _DIRENT_HAVE_D_NAMLEN is not defined on Linux.
537 # This is also part of commit ecfc54246c2a6f42
538 apply_patch(<<'EOPATCH');
539diff --git a/Configure b/Configure
540index 3d3b38d..78ffe16 100755
541--- a/Configure
542+++ b/Configure
543@@ -3935,7 +4045,8 @@ $rm -f try.c
544
545 : see if the directory entry stores field length
546 echo " "
547-if $contains 'd_namlen' $xinc >/dev/null 2>&1; then
548+$cppstdin $cppflags $cppminus < "$xinc" > try.c
549+if $contains 'd_namlen' try.c >/dev/null 2>&1; then
550 echo "Good, your directory entry keeps length information in d_namlen." >&4
551 val="$define"
552 else
553EOPATCH
554 }
555}
d90ae42b 556
af7c500f
NC
557if ($major < 8 && !extract_from_file('Configure',
558 qr/^\t\tif test ! -t 0; then$/)) {
7c22f158
NC
559 # Before dfe9444ca7881e71, Configure would refuse to run if stdin was not a
560 # tty. With that commit, the tty requirement was dropped for -de and -dE
af7c500f 561 # Commit aaeb8e512e8e9e14 dropped the tty requirement for -S
7c22f158
NC
562 # For those older versions, it's probably easiest if we simply remove the
563 # sanity test.
af7c500f
NC
564 edit_file('Configure', sub {
565 my $code = shift;
566 $code =~ s/test ! -t 0/test Perl = rules/;
567 return $code;
568 });
7c22f158
NC
569}
570
d90ae42b 571if ($major < 10 && extract_from_file('Configure', qr/^set malloc\.h i_malloc$/)) {
5541f5e3
NC
572 # This is commit 01d07975f7ef0e7d, trimmed, with $compile inlined as
573 # prior to bd9b35c97ad661cc Configure had the malloc.h test before the
574 # definition of $compile.
d90ae42b
NC
575 apply_patch(<<'EOPATCH');
576diff --git a/Configure b/Configure
577index 3d2e8b9..6ce7766 100755
578--- a/Configure
579+++ b/Configure
580@@ -6743,5 +6743,22 @@ set d_dosuid
581
582 : see if this is a malloc.h system
583-set malloc.h i_malloc
584-eval $inhdr
585+: we want a real compile instead of Inhdr because some systems have a
586+: malloc.h that just gives a compile error saying to use stdlib.h instead
587+echo " "
588+$cat >try.c <<EOCP
589+#include <stdlib.h>
590+#include <malloc.h>
591+int main () { return 0; }
592+EOCP
593+set try
5541f5e3 594+if $cc $optimize $ccflags $ldflags -o try $* try.c $libs > /dev/null 2>&1; then
d90ae42b
NC
595+ echo "<malloc.h> found." >&4
596+ val="$define"
597+else
598+ echo "<malloc.h> NOT found." >&4
599+ val="$undef"
600+fi
601+$rm -f try.c try
602+set i_malloc
603+eval $setvar
604
605EOPATCH
606}
a1756669 607
6ff3edb1
NC
608if ($major < 10 && -d 'ext/Unicode/Normalize/'
609 && !extract_from_file('Configure', qr/^extra_dep=''$/)) {
610 # The Makefile.PL for Unicode::Normalize needs
611 # lib/unicore/CombiningClass.pl. Even without a parallel build, we need
612 # a dependency to ensure that it builds. This is a variant of commit
613 # 9f3ef600c170f61e
614 apply_patch(<<'EOPATCH');
615diff --git a/Makefile.SH b/Makefile.SH
616index f61d0db..6097954 100644
617--- a/Makefile.SH
618+++ b/Makefile.SH
619@@ -155,10 +155,20 @@ esac
620
621 : Prepare dependency lists for Makefile.
622 dynamic_list=' '
623+extra_dep=''
624 for f in $dynamic_ext; do
625 : the dependency named here will never exist
626 base=`echo "$f" | sed 's/.*\///'`
627- dynamic_list="$dynamic_list lib/auto/$f/$base.$dlext"
628+ this_target="lib/auto/$f/$base.$dlext"
629+ dynamic_list="$dynamic_list $this_target"
630+
631+ : Parallel makes reveal that we have some interdependencies
632+ case $f in
633+ Math/BigInt/FastCalc) extra_dep="$extra_dep
634+$this_target: lib/auto/List/Util/Util.$dlext" ;;
635+ Unicode/Normalize) extra_dep="$extra_dep
636+$this_target: lib/unicore/CombiningClass.pl" ;;
637+ esac
638 done
639
640 static_list=' '
641@@ -987,2 +997,9 @@ n_dummy $(nonxs_ext): miniperl$(EXE_EXT) preplibrary $(DYNALOADER) FORCE
642 @$(LDLIBPTH) sh ext/util/make_ext nonxs $@ MAKE=$(MAKE) LIBPERL_A=$(LIBPERL)
643+!NO!SUBS!
644+
645+$spitshell >>Makefile <<EOF
646+$extra_dep
647+EOF
648+
649+$spitshell >>Makefile <<'!NO!SUBS!'
650
651EOPATCH
652}
653
6a8dbfd7
NC
654# There was a bug in makedepend.SH which was fixed in version 96a8704c.
655# Symptom was './makedepend: 1: Syntax error: Unterminated quoted string'
656# Remove this if you're actually bisecting a problem related to makedepend.SH
9da8cb0a 657system 'git show blead:makedepend.SH > makedepend.SH </dev/null' and die;
6a8dbfd7 658
d64af352
NC
659if ($^O eq 'freebsd') {
660 # There are rather too many version-specific FreeBSD hints fixes to patch
661 # individually. Also, more than once the FreeBSD hints file has been
662 # written in what turned out to be a rather non-future-proof style,
663 # with case statements treating the most recent version as the exception,
664 # instead of treating previous versions' behaviour explicitly and changing
665 # the default to cater for the current behaviour. (As strangely, future
666 # versions inherit the current behaviour.)
9da8cb0a
NC
667 system 'git show blead:hints/freebsd.sh > hints/freebsd.sh </dev/null'
668 and die;
641e2ba6
NC
669
670 if ($major < 2) {
671 # 5.002 Configure and later have code to
672 #
673 # : Try to guess additional flags to pick up local libraries.
674 #
675 # which will automatically add --L/usr/local/lib because libpth
676 # contains /usr/local/lib
677 #
678 # Without it, if Configure finds libraries in /usr/local/lib (eg
679 # libgdbm.so) and adds them to the compiler commandline (as -lgdbm),
680 # then the link will fail. We can't fix this up in config.sh because
681 # the link will *also* fail in the test compiles that Configure does
682 # (eg $inlibc) which makes Configure get all sorts of things
683 # wrong. :-( So bodge it here.
684 #
685 # Possibly other platforms will need something similar. (if they
686 # have "wanted" libraries in /usr/local/lib, but the compiler
687 # doesn't default to putting that directory in its link path)
688 apply_patch(<<'EOPATCH');
689--- perl2/hints/freebsd.sh.orig 2011-10-05 16:44:55.000000000 +0200
690+++ perl2/hints/freebsd.sh 2011-10-05 16:45:52.000000000 +0200
691@@ -125,7 +125,7 @@
692 else
693 libpth="/usr/lib /usr/local/lib"
694 glibpth="/usr/lib /usr/local/lib"
695- ldflags="-Wl,-E "
696+ ldflags="-Wl,-E -L/usr/local/lib "
697 lddlflags="-shared "
698 fi
699 cccdlflags='-DPIC -fPIC'
700@@ -133,7 +133,7 @@
701 *)
702 libpth="/usr/lib /usr/local/lib"
703 glibpth="/usr/lib /usr/local/lib"
704- ldflags="-Wl,-E "
705+ ldflags="-Wl,-E -L/usr/local/lib "
706 lddlflags="-shared "
707 cccdlflags='-DPIC -fPIC'
708 ;;
641e2ba6
NC
709EOPATCH
710 }
d64af352
NC
711}
712
cfadff5f
NC
713if ($major < 10) {
714 if (!extract_from_file('ext/DB_File/DB_File.xs',
715 qr!^#else /\* Berkeley DB Version > 2 \*/$!)) {
716 # This DB_File.xs is really too old to patch up.
717 # Skip DB_File, unless we're invoked with an explicit -Unoextensions
718 if (!exists $defines{noextensions}) {
719 $defines{noextensions} = 'DB_File';
720 } elsif (defined $defines{noextensions}) {
721 $defines{noextensions} .= ' DB_File';
722 }
723 } elsif (!extract_from_file('ext/DB_File/DB_File.xs',
724 qr/^#ifdef AT_LEAST_DB_4_1$/)) {
725 # This line is changed by commit 3245f0580c13b3ab
726 my $line = extract_from_file('ext/DB_File/DB_File.xs',
727 qr/^( status = \(?RETVAL->dbp->open\)?\(RETVAL->dbp, name, NULL, RETVAL->type, $)/);
728 apply_patch(<<"EOPATCH");
729diff --git a/ext/DB_File/DB_File.xs b/ext/DB_File/DB_File.xs
730index 489ba96..fba8ded 100644
731--- a/ext/DB_File/DB_File.xs
732+++ b/ext/DB_File/DB_File.xs
733\@\@ -183,4 +187,8 \@\@
734 #endif
735
736+#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
737+# define AT_LEAST_DB_4_1
738+#endif
739+
740 /* map version 2 features & constants onto their version 1 equivalent */
741
742\@\@ -1334,7 +1419,12 \@\@ SV * sv ;
743 #endif
744
745+#ifdef AT_LEAST_DB_4_1
746+ status = (RETVAL->dbp->open)(RETVAL->dbp, NULL, name, NULL, RETVAL->type,
747+ Flags, mode) ;
748+#else
749 $line
750 Flags, mode) ;
751+#endif
752 /* printf("open returned %d %s\\n", status, db_strerror(status)) ; */
753
754EOPATCH
755 }
756}
757
6a8dbfd7
NC
758# if Encode is not needed for the test, you can speed up the bisect by
759# excluding it from the runs with -Dnoextensions=Encode
760# ccache is an easy win. Remove it if it causes problems.
6a8dbfd7
NC
761# Commit 1cfa4ec74d4933da adds ignore_versioned_solibs to Configure, and sets it
762# to true in hints/linux.sh
763# On dromedary, from that point on, Configure (by default) fails to find any
764# libraries, because it scans /usr/local/lib /lib /usr/lib, which only contain
765# versioned libraries. Without -lm, the build fails.
766# Telling /usr/local/lib64 /lib64 /usr/lib64 works from that commit onwards,
767# until commit faae14e6e968e1c0 adds it to the hints.
768# However, prior to 1cfa4ec74d4933da telling Configure the truth doesn't work,
769# because it will spot versioned libraries, pass them to the compiler, and then
770# bail out pretty early on. Configure won't let us override libswanted, but it
771# will let us override the entire libs list.
772
773unless (extract_from_file('Configure', 'ignore_versioned_solibs')) {
774 # Before 1cfa4ec74d4933da, so force the libs list.
775
776 my @libs;
777 # This is the current libswanted list from Configure, less the libs removed
778 # by current hints/linux.sh
779 foreach my $lib (qw(sfio socket inet nsl nm ndbm gdbm dbm db malloc dl dld
780 ld sun m crypt sec util c cposix posix ucb BSD)) {
781 foreach my $dir (@paths) {
782 next unless -f "$dir/lib$lib.so";
783 push @libs, "-l$lib";
784 last;
785 }
786 }
390a69a9 787 $defines{libs} = \@libs unless exists $defines{libs};
6a8dbfd7
NC
788}
789
4b081584
NC
790# This seems to be necessary to avoid makedepend becoming confused, and hanging
791# on stdin. Seems that the code after make shlist || ...here... is never run.
390a69a9
NC
792$defines{trnl} = q{'\n'}
793 if $major < 4 && !exists $defines{trnl};
4b081584 794
390a69a9
NC
795$defines{usenm} = undef
796 if $major < 2 && !exists $defines{usenm};
0142f0ce 797
67382a3b
NC
798my (@missing, @created_dirs);
799
f4800c99 800if ($options{'force-manifest'}) {
67382a3b
NC
801 open my $fh, '<', 'MANIFEST'
802 or die "Could not open MANIFEST: $!";
803 while (<$fh>) {
804 next unless /^(\S+)/;
805 push @missing, $1
806 unless -f $1;
807 }
808 close $fh or die "Can't close MANIFEST: $!";
809
810 foreach my $pathname (@missing) {
811 my @parts = split '/', $pathname;
812 my $leaf = pop @parts;
813 my $path = '.';
814 while (@parts) {
815 $path .= '/' . shift @parts;
816 next if -d $path;
817 mkdir $path, 0700 or die "Can't create $path: $!";
818 unshift @created_dirs, $path;
819 }
820 open $fh, '>', $pathname or die "Can't open $pathname: $!";
821 close $fh or die "Can't close $pathname: $!";
822 chmod 0, $pathname or die "Can't chmod 0 $pathname: $!";
823 }
824}
825
af7c500f 826my @ARGS = '-dEs';
390a69a9
NC
827foreach my $key (sort keys %defines) {
828 my $val = $defines{$key};
829 if (ref $val) {
830 push @ARGS, "-D$key=@$val";
831 } elsif (!defined $val) {
832 push @ARGS, "-U$key";
833 } elsif (!length $val) {
834 push @ARGS, "-D$key";
835 } else {
836 $val = "" if $val eq "\0";
837 push @ARGS, "-D$key=$val";
838 }
839}
840push @ARGS, map {"-A$_"} @{$options{A}};
841
6a8dbfd7
NC
842# </dev/null because it seems that some earlier versions of Configure can
843# call commands in a way that now has them reading from stdin (and hanging)
844my $pid = fork;
845die "Can't fork: $!" unless defined $pid;
846if (!$pid) {
7c22f158
NC
847 open STDIN, '<', '/dev/null';
848 # If a file in MANIFEST is missing, Configure asks if you want to
849 # continue (the default being 'n'). With stdin closed or /dev/null,
850 # it exits immediately and the check for config.sh below will skip.
6a8dbfd7
NC
851 exec './Configure', @ARGS;
852 die "Failed to start Configure: $!";
853}
854waitpid $pid, 0
855 or die "wait for Configure, pid $pid failed: $!";
856
af7c500f
NC
857# Emulate noextensions if Configure doesn't support it.
858if (-f 'config.sh') {
859 if ($major < 10 && $defines{noextensions}) {
860 edit_file('config.sh', sub {
861 my @lines = split /\n/, shift;
862 my @ext = split /\s+/, $defines{noextensions};
863 foreach (@lines) {
864 next unless /^extensions=/ || /^dynamic_ext/;
865 foreach my $ext (@ext) {
866 s/\b$ext( )?\b/$1/;
867 }
868 }
869 return join "\n", @lines;
870 });
871 }
872 system './Configure -S </dev/null' and die;
873}
874
0afef97d
NC
875if ($target =~ /config\.s?h/) {
876 match_and_exit($target) if $match && -f $target;
dd4e46d7
NC
877 report_and_exit(!-f $target, 'could build', 'could not build', $target);
878} elsif (!-f 'config.sh') {
879 # Skip if something went wrong with Configure
880
881 skip('could not build config.sh');
882}
6a8dbfd7 883
67382a3b
NC
884# This is probably way too paranoid:
885if (@missing) {
886 my @errors;
eb4906f4 887 require Fcntl;
67382a3b
NC
888 foreach my $file (@missing) {
889 my (undef, undef, $mode, undef, undef, undef, undef, $size)
890 = stat $file;
891 if (!defined $mode) {
892 push @errors, "Added file $file has been deleted by Configure";
893 next;
894 }
eb4906f4 895 if (Fcntl::S_IMODE($mode) != 0) {
67382a3b
NC
896 push @errors,
897 sprintf 'Added file %s had mode changed by Configure to %03o',
898 $file, $mode;
899 }
900 if ($size != 0) {
901 push @errors,
902 "Added file $file had sized changed by Configure to $size";
903 }
904 unlink $file or die "Can't unlink $file: $!";
905 }
906 foreach my $dir (@created_dirs) {
907 rmdir $dir or die "Can't rmdir $dir: $!";
908 }
6c0925a0
NC
909 skip("@errors")
910 if @errors;
67382a3b
NC
911}
912
6a8dbfd7
NC
913# Correct makefile for newer GNU gcc
914# Only really needed if you comment out the use of blead's makedepend.SH
915{
916 local $^I = "";
917 local @ARGV = qw(makefile x2p/makefile);
918 while (<>) {
919 print unless /<(?:built-in|command|stdin)/;
920 }
921}
6a8dbfd7 922
0142f0ce
NC
923if ($major == 2 && extract_from_file('perl.c', qr/^ fclose\(e_fp\);$/)) {
924 # need to patch perl.c to avoid calling fclose() twice on e_fp when using -e
925 # This diff is part of commit ab821d7fdc14a438. The second close was
926 # introduced with perl-5.002, commit a5f75d667838e8e7
927 # Might want a6c477ed8d4864e6 too, for the corresponding change to pp_ctl.c
928 # (likely without this, eval will have "fun")
929 apply_patch(<<'EOPATCH');
930diff --git a/perl.c b/perl.c
931index 03c4d48..3c814a2 100644
932--- a/perl.c
933+++ b/perl.c
934@@ -252,6 +252,7 @@ setuid perl scripts securely.\n");
935 #ifndef VMS /* VMS doesn't have environ array */
936 origenviron = environ;
937 #endif
938+ e_tmpname = Nullch;
939
940 if (do_undump) {
941
942@@ -405,6 +406,7 @@ setuid perl scripts securely.\n");
943 if (e_fp) {
944 if (Fflush(e_fp) || ferror(e_fp) || fclose(e_fp))
945 croak("Can't write to temp file for -e: %s", Strerror(errno));
946+ e_fp = Nullfp;
947 argc++,argv--;
948 scriptname = e_tmpname;
949 }
950@@ -470,10 +472,10 @@ setuid perl scripts securely.\n");
951 curcop->cop_line = 0;
952 curstash = defstash;
953 preprocess = FALSE;
954- if (e_fp) {
955- fclose(e_fp);
956- e_fp = Nullfp;
957+ if (e_tmpname) {
958 (void)UNLINK(e_tmpname);
959+ Safefree(e_tmpname);
960+ e_tmpname = Nullch;
961 }
962
963 /* now that script is parsed, we can modify record separator */
964@@ -1369,7 +1371,7 @@ SV *sv;
965 scriptname = xfound;
966 }
967
968- origfilename = savepv(e_fp ? "-e" : scriptname);
969+ origfilename = savepv(e_tmpname ? "-e" : scriptname);
970 curcop->cop_filegv = gv_fetchfile(origfilename);
971 if (strEQ(origfilename,"-"))
972 scriptname = "";
973
974EOPATCH
975}
976
c59e8fd6
NC
977if ($major < 10 and -f 'ext/IPC/SysV/SysV.xs') {
978 edit_file('ext/IPC/SysV/SysV.xs', sub {
979 my $xs = shift;
980 my $fixed = <<'EOFIX';
981
982#include <sys/types.h>
983#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
984#ifndef HAS_SEM
985# include <sys/ipc.h>
986#endif
987# ifdef HAS_MSG
988# include <sys/msg.h>
989# endif
990# ifdef HAS_SHM
991# if defined(PERL_SCO) || defined(PERL_ISC)
992# include <sys/sysmacros.h> /* SHMLBA */
993# endif
994# include <sys/shm.h>
995# ifndef HAS_SHMAT_PROTOTYPE
996 extern Shmat_t shmat (int, char *, int);
997# endif
998# if defined(HAS_SYSCONF) && defined(_SC_PAGESIZE)
999# undef SHMLBA /* not static: determined at boot time */
1000# define SHMLBA sysconf(_SC_PAGESIZE)
1001# elif defined(HAS_GETPAGESIZE)
1002# undef SHMLBA /* not static: determined at boot time */
1003# define SHMLBA getpagesize()
1004# endif
1005# endif
1006#endif
1007EOFIX
1008 $xs =~ s!
1009#include <sys/types\.h>
1010.*
1011(#ifdef newCONSTSUB|/\* Required)!$fixed$1!ms;
1012 return $xs;
1013 });
1014}
1015
9a999a97 1016# Parallel build for miniperl is safe
9da8cb0a 1017system "make $j miniperl </dev/null";
9a999a97 1018
2526f4b8
NC
1019my $expected = $target =~ /^test/ ? 't/perl'
1020 : $target eq 'Fcntl' ? "lib/auto/Fcntl/Fcntl.$Config{so}"
1021 : $target;
1022my $real_target = $target eq 'Fcntl' ? $expected : $target;
1023
9a999a97
NC
1024if ($target ne 'miniperl') {
1025 # Nearly all parallel build issues fixed by 5.10.0. Untrustworthy before that.
372ba1f9 1026 $j = '' if $major < 10;
9a999a97 1027
2526f4b8 1028 if ($real_target eq 'test_prep') {
9a999a97
NC
1029 if ($major < 8) {
1030 # test-prep was added in 5.004_01, 3e3baf6d63945cb6.
1031 # renamed to test_prep in 2001 in 5fe84fd29acaf55c.
1032 # earlier than that, just make test. It will be fast enough.
2526f4b8
NC
1033 $real_target = extract_from_file('Makefile.SH',
1034 qr/^(test[-_]prep):/,
1035 'test');
9a999a97 1036 }
6a8dbfd7 1037 }
6a8dbfd7 1038
9da8cb0a 1039 system "make $j $real_target </dev/null";
9a999a97 1040}
6a8dbfd7 1041
67382a3b
NC
1042my $missing_target = $expected =~ /perl$/ ? !-x $expected : !-r $expected;
1043
f4800c99 1044if ($options{'test-build'}) {
2526f4b8
NC
1045 report_and_exit($missing_target, 'could build', 'could not build',
1046 $real_target);
67382a3b 1047} elsif ($missing_target) {
2526f4b8 1048 skip("could not build $real_target");
67382a3b 1049}
6a8dbfd7 1050
2526f4b8 1051match_and_exit($real_target) if $match;
0afef97d
NC
1052
1053if (defined $options{'one-liner'}) {
2526f4b8 1054 my $exe = $target =~ /^(?:perl$|test)/ ? 'perl' : 'miniperl';
0afef97d
NC
1055 unshift @ARGV, "./$exe", '-Ilib', '-e', $options{'one-liner'};
1056}
1057
6a8dbfd7
NC
1058# This is what we came here to run:
1059my $ret = system @ARGV;
1060
f1050811 1061report_and_exit($ret, 'zero exit from', 'non-zero exit from', "@ARGV");
9a999a97
NC
1062
1063# Local variables:
1064# cperl-indent-level: 4
1065# indent-tabs-mode: nil
1066# End:
1067#
1068# ex: set ts=8 sts=4 sw=4 et: