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