This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Don’t put malformed UTF8 in $AUTOLOAD
[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?
85 .../Porting/bisect.pl --target=perl -- ./perl -Ilib test_prog.pl
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
94Together C<bisect.pl> and C<bisect-runner.pl> attempt to automate the use
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
121By default C<bisect.pl> will process all options, then use the rest of the
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
124non-zero) on I<blead>. C<bisect.pl> will use C<bisect-runner.pl> to find the
125earliest stable perl version on which the test case passes, check that it
126fails on blead, and then use C<bisect-runner.pl> with C<git bisect run> to
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
77ae6092
NC
144=head1 OPTIONS
145
146=over 4
147
148=item *
149
150--start I<commit-ish>
151
152Earliest revision to test, as a I<commit-ish> (a tag, commit or anything
71d80638 153else C<git> understands as a revision). If not specified, C<bisect.pl> will
77ae6092
NC
154search stable perl releases from 5.002 to 5.14.0 until it finds one where
155the test case passes.
156
157=item *
158
159--end I<commit-ish>
160
161Most recent revision to test, as a I<commit-ish>. If not specified, defaults
b4f0ec5f 162to I<blead>.
77ae6092
NC
163
164=item *
165
166--target I<target>
167
168F<Makefile> target (or equivalent) needed, to run the test case. If specified,
169this should be one of
170
171=over 4
172
173=item *
174
175I<config.sh>
176
177Just run C<Configure>
178
179=item *
180
181I<config.h>
182
183Run the various F<*.SH> files to generate F<Makefile>, F<config.h>, I<etc>.
184
185=item *
186
187I<miniperl>
188
189Build F<miniperl>.
190
191=item *
192
193I<lib/Config.pm>
194
195Use F<miniperl> to build F<lib/Config.pm>
196
197=item *
198
2526f4b8
NC
199I<Fcntl>
200
201Build F<lib/auto/Fcntl/Fnctl.so> (strictly, C<.$Config{so}>). As L<Fcntl>
202is simple XS module present since 5.000, this provides a fast test of
b4f0ec5f 203whether XS modules can be built. Note, XS modules are built by F<miniperl>,
2526f4b8
NC
204hence this target will not build F<perl>.
205
206=item *
207
77ae6092
NC
208I<perl>
209
210Build F<perl>. This also builds pure-Perl modules in F<cpan>, F<dist> and
2526f4b8
NC
211F<ext>. XS modules (such as L<Fcntl>) are not built.
212
213=item *
214
77ae6092
NC
215I<test_prep>
216
217Build everything needed to run the tests. This is the default if we're
218running test code, but is time consuming, as it means building all
b4f0ec5f 219XS modules. For older F<Makefile>s, the previous name of C<test-prep>
77ae6092
NC
220is automatically substituted. For very old F<Makefile>s, C<make test> is
221run, as there is no target provided to just get things ready, and for 5.004
222and earlier the tests run very quickly.
223
224=back
225
226=item *
227
228--one-liner 'code to run'
229
230=item *
231
232-e 'code to run'
233
a1756669 234Example code to run, just like you'd use with C<perl -e>.
77ae6092
NC
235
236This prepends C<./perl -Ilib -e 'code to run'> to the test case given,
b4f0ec5f 237or C<./miniperl> if I<target> is C<miniperl>.
77ae6092
NC
238
239(Usually you'll use C<-e> instead of providing a test case in the
240non-option arguments to C<bisect.pl>)
241
242C<-E> intentionally isn't supported, as it's an error in 5.8.0 and earlier,
243which interferes with detecting errors in the example code itself.
244
245=item *
246
247--expect-fail
248
249The test case should fail for the I<start> revision, and pass for the I<end>
250revision. The bisect run will find the first commit where it passes.
251
252=item *
253
254-Dusethreads
255
256=item *
257
258-Uusedevel
259
260=item *
261
262-Accflags=-DNO_MATHOMS
263
264Arguments to pass to F<Configure>. Repeated C<-A> arguments are passed
265through as is. C<-D> and C<-U> are processed in order, and override
266previous settings for the same parameter.
267
268=item *
269
b4f0ec5f 270--jobs I<jobs>
77ae6092
NC
271
272=item *
273
b4f0ec5f 274-j I<jobs>
77ae6092 275
da83cd31
NC
276Number of C<make> jobs to run in parallel. If F</proc/cpuinfo> exists and
277can be parsed, or F</sbin/sysctl> exists and reports C<hw.ncpu>, or
278F</usr/bin/getconf> exists and reports C<_NPROCESSORS_ONLN> defaults to 1 +
279I<number of CPUs>. Otherwise defaults to 2.
77ae6092
NC
280
281=item *
282
b4f0ec5f 283--match pattern
77ae6092
NC
284
285Instead of running a test program to determine I<pass> or I<fail>, pass
286if the given regex matches, and hence search for the commit that removes
287the last matching file.
288
289If no I<target> is specified, the match is against all files in the
290repository (which is fast). If a I<target> is specified, that target is
291built, and the match is against only the built files. C<--expect-fail> can
292be used with C<--match> to search for a commit that adds files that match.
293
294=item *
295
296--test-build
297
298Test that the build completes, without running any test case.
299
300By default, if the build for the desired I<target> fails to complete,
301F<bisect-runner.pl> reports a I<skip> back to C<git bisect>, the assumption
302being that one wants to find a commit which changed state "builds && passes"
303to "builds && fails". If instead one is interested in which commit broke the
304build (possibly for particular F<Configure> options), use I<--test-build>
305to treat a build failure as a failure, not a "skip".
306
b4f0ec5f
NC
307Often this option isn't as useful as it first seems, because I<any> build
308failure will be reported to C<git bisect> as a failure, not just the failure
309that you're interested in. Generally, to debug a particular problem, it's
310more useful to use a I<target> that builds properly at the point of interest,
311and then a test case that runs C<make>. For example:
312
313 .../Porting/bisect.pl --start=perl-5.000 --end=perl-5.002 \
314 --expect-fail --force-manifest --target=miniperl make perl
315
316will find the first revision capable of building C<DynaLoader> and then
317C<perl>, without becoming confused by revisions where C<miniperl> won't
318even link.
319
77ae6092
NC
320=item *
321
b4f0ec5f
NC
322--force-manifest
323
77ae6092
NC
324By default, a build will "skip" if any files listed in F<MANIFEST> are not
325present. Usually this is useful, as it avoids false-failures. However, there
326are some long ranges of commits where listed files are missing, which can
327cause a bisect to abort because all that remain are skipped revisions.
328
329In these cases, particularly if the test case uses F<miniperl> and no modules,
330it may be more useful to force the build to continue, even if files
331F<MANIFEST> are missing.
332
333=item *
334
335--expect-pass [0|1]
336
337C<--expect-pass=0> is equivalent to C<--expect-fail>. I<1> is the default.
338
339=item *
340
341--no-clean
342
343Tell F<bisect-runner.pl> not to clean up after the build. This allows one
344to use F<bisect-runner.pl> to build the current particular perl revision for
345interactive testing, or for debugging F<bisect-runner.pl>.
346
347Passing this to F<bisect.pl> will likely cause the bisect to fail badly.
348
349=item *
350
351--check-args
352
353Validate the options and arguments, and exit silently if they are valid.
354
355=item *
356
357--usage
358
359=item *
360
361--help
362
363=item *
364
365-?
366
367Display the usage information and exit.
368
369=back
370
371=cut
372
0afef97d 373die "$0: Can't build $target" if defined $target && !grep {@targets} $target;
6a8dbfd7
NC
374
375$j = "-j$j" if $j =~ /\A\d+\z/;
376
0142f0ce
NC
377# Sadly, however hard we try, I don't think that it will be possible to build
378# modules in ext/ on x86_64 Linux before commit e1666bf5602ae794 on 1999/12/29,
379# which updated to MakeMaker 3.7, which changed from using a hard coded ld
380# in the Makefile to $(LD). On x86_64 Linux the "linker" is gcc.
381
6a8dbfd7
NC
382sub extract_from_file {
383 my ($file, $rx, $default) = @_;
384 open my $fh, '<', $file or die "Can't open $file: $!";
385 while (<$fh>) {
386 my @got = $_ =~ $rx;
387 return wantarray ? @got : $got[0]
388 if @got;
389 }
390 return $default if defined $default;
391 return;
392}
393
c59e8fd6
NC
394sub edit_file {
395 my ($file, $munger) = @_;
396 local $/;
397 open my $fh, '<', $file or die "Can't open $file: $!";
398 my $orig = <$fh>;
399 die "Can't read $file: $!" unless defined $orig && close $fh;
400 my $new = $munger->($orig);
401 return if $new eq $orig;
402 open $fh, '>', $file or die "Can't open $file: $!";
403 print $fh $new or die "Can't print to $file: $!";
404 close $fh or die "Can't close $file: $!";
405}
406
407sub apply_patch {
408 my $patch = shift;
409
410 my ($file) = $patch =~ qr!^diff.*a/(\S+) b/\1!;
411 open my $fh, '|-', 'patch', '-p1' or die "Can't run patch: $!";
412 print $fh $patch;
5fceabf3
NC
413 return if close $fh;
414 print STDERR "Patch is <<'EOPATCH'\n${patch}EOPATCH\n";
415 die "Can't patch $file: $?, $!";
c59e8fd6
NC
416}
417
ab4a15f9 418sub clean {
f4800c99 419 if ($options{clean}) {
ab4a15f9
NC
420 # Needed, because files that are build products in this checked out
421 # version might be in git in the next desired version.
9da8cb0a 422 system 'git clean -dxf </dev/null';
ab4a15f9
NC
423 # Needed, because at some revisions the build alters checked out files.
424 # (eg pod/perlapi.pod). Also undoes any changes to makedepend.SH
9da8cb0a 425 system 'git reset --hard HEAD </dev/null';
ab4a15f9
NC
426 }
427}
428
429sub skip {
430 my $reason = shift;
431 clean();
432 warn "skipping - $reason";
433 exit 125;
434}
435
f1050811
NC
436sub report_and_exit {
437 my ($ret, $pass, $fail, $desc) = @_;
438
439 clean();
440
f4800c99 441 my $got = ($options{'expect-pass'} ? !$ret : $ret) ? 'good' : 'bad';
f1050811
NC
442 if ($ret) {
443 print "$got - $fail $desc\n";
444 } else {
445 print "$got - $pass $desc\n";
446 }
447
448 exit($got eq 'bad');
449}
450
0afef97d
NC
451sub match_and_exit {
452 my $target = shift;
453 my $matches = 0;
454 my $re = qr/$match/;
455 my @files;
456
457 {
458 local $/ = "\0";
459 @files = defined $target ? `git ls-files -o -z`: `git ls-files -z`;
460 chomp @files;
461 }
462
463 foreach my $file (@files) {
464 open my $fh, '<', $file or die "Can't open $file: $!";
465 while (<$fh>) {
466 if ($_ =~ $re) {
467 ++$matches;
468 if (tr/\t\r\n -~\200-\377//c) {
469 print "Binary file $file matches\n";
470 } else {
471 $_ .= "\n" unless /\n\z/;
472 print "$file: $_";
473 }
474 }
475 }
476 close $fh or die "Can't close $file: $!";
477 }
478 report_and_exit(!$matches,
479 $matches == 1 ? '1 match for' : "$matches matches for",
480 'no matches for', $match);
481}
482
6a8dbfd7 483# Not going to assume that system perl is yet new enough to have autodie
9da8cb0a 484system 'git clean -dxf </dev/null' and die;
6a8dbfd7 485
0afef97d
NC
486if (!defined $target) {
487 match_and_exit() if $match;
488 $target = 'test_prep';
bc96a05a
NC
489}
490
4b081584
NC
491skip('no Configure - is this the //depot/perlext/Compiler branch?')
492 unless -f 'Configure';
493
dbcdc176
NC
494# This changes to PERL_VERSION in 4d8076ea25903dcb in 1999
495my $major
496 = extract_from_file('patchlevel.h',
497 qr/^#define\s+(?:PERL_VERSION|PATCHLEVEL)\s+(\d+)\s/,
498 0);
499
0142f0ce
NC
500if ($major < 1) {
501 if (extract_from_file('Configure',
502 qr/^ \*=\*\) echo "\$1" >> \$optdef;;$/)) {
503 # This is " Spaces now allowed in -D command line options.",
504 # part of commit ecfc54246c2a6f42
505 apply_patch(<<'EOPATCH');
506diff --git a/Configure b/Configure
507index 3d3b38d..78ffe16 100755
508--- a/Configure
509+++ b/Configure
510@@ -652,7 +777,8 @@ while test $# -gt 0; do
511 echo "$me: use '-U symbol=', not '-D symbol='." >&2
512 echo "$me: ignoring -D $1" >&2
513 ;;
514- *=*) echo "$1" >> $optdef;;
515+ *=*) echo "$1" | \
516+ sed -e "s/'/'\"'\"'/g" -e "s/=\(.*\)/='\1'/" >> $optdef;;
517 *) echo "$1='define'" >> $optdef;;
518 esac
519 shift
520EOPATCH
521 }
522 if (extract_from_file('Configure', qr/^if \$contains 'd_namlen' \$xinc\b/)) {
523 # Configure's original simple "grep" for d_namlen falls foul of the
524 # approach taken by the glibc headers:
525 # #ifdef _DIRENT_HAVE_D_NAMLEN
526 # # define _D_EXACT_NAMLEN(d) ((d)->d_namlen)
527 #
528 # where _DIRENT_HAVE_D_NAMLEN is not defined on Linux.
529 # This is also part of commit ecfc54246c2a6f42
530 apply_patch(<<'EOPATCH');
531diff --git a/Configure b/Configure
532index 3d3b38d..78ffe16 100755
533--- a/Configure
534+++ b/Configure
535@@ -3935,7 +4045,8 @@ $rm -f try.c
536
537 : see if the directory entry stores field length
538 echo " "
539-if $contains 'd_namlen' $xinc >/dev/null 2>&1; then
540+$cppstdin $cppflags $cppminus < "$xinc" > try.c
541+if $contains 'd_namlen' try.c >/dev/null 2>&1; then
542 echo "Good, your directory entry keeps length information in d_namlen." >&4
543 val="$define"
544 else
545EOPATCH
546 }
547}
d90ae42b 548
7c22f158
NC
549if ($major < 5 && extract_from_file('Configure',
550 qr/^if test ! -t 0; then$/)) {
551 # Before dfe9444ca7881e71, Configure would refuse to run if stdin was not a
552 # tty. With that commit, the tty requirement was dropped for -de and -dE
553 # For those older versions, it's probably easiest if we simply remove the
554 # sanity test.
555 apply_patch(<<'EOPATCH');
556diff --git a/Configure b/Configure
557index 0071a7c..8a61caa 100755
558--- a/Configure
559+++ b/Configure
560@@ -93,7 +93,2 @@ esac
561
562-: Sanity checks
563-if test ! -t 0; then
564- echo "Say 'sh $me', not 'sh <$me'"
565- exit 1
566-fi
567
568EOPATCH
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
6a8dbfd7
NC
713# if Encode is not needed for the test, you can speed up the bisect by
714# excluding it from the runs with -Dnoextensions=Encode
715# ccache is an easy win. Remove it if it causes problems.
6a8dbfd7
NC
716# Commit 1cfa4ec74d4933da adds ignore_versioned_solibs to Configure, and sets it
717# to true in hints/linux.sh
718# On dromedary, from that point on, Configure (by default) fails to find any
719# libraries, because it scans /usr/local/lib /lib /usr/lib, which only contain
720# versioned libraries. Without -lm, the build fails.
721# Telling /usr/local/lib64 /lib64 /usr/lib64 works from that commit onwards,
722# until commit faae14e6e968e1c0 adds it to the hints.
723# However, prior to 1cfa4ec74d4933da telling Configure the truth doesn't work,
724# because it will spot versioned libraries, pass them to the compiler, and then
725# bail out pretty early on. Configure won't let us override libswanted, but it
726# will let us override the entire libs list.
727
728unless (extract_from_file('Configure', 'ignore_versioned_solibs')) {
729 # Before 1cfa4ec74d4933da, so force the libs list.
730
731 my @libs;
732 # This is the current libswanted list from Configure, less the libs removed
733 # by current hints/linux.sh
734 foreach my $lib (qw(sfio socket inet nsl nm ndbm gdbm dbm db malloc dl dld
735 ld sun m crypt sec util c cposix posix ucb BSD)) {
736 foreach my $dir (@paths) {
737 next unless -f "$dir/lib$lib.so";
738 push @libs, "-l$lib";
739 last;
740 }
741 }
390a69a9 742 $defines{libs} = \@libs unless exists $defines{libs};
6a8dbfd7
NC
743}
744
4b081584
NC
745# This seems to be necessary to avoid makedepend becoming confused, and hanging
746# on stdin. Seems that the code after make shlist || ...here... is never run.
390a69a9
NC
747$defines{trnl} = q{'\n'}
748 if $major < 4 && !exists $defines{trnl};
4b081584 749
390a69a9
NC
750$defines{usenm} = undef
751 if $major < 2 && !exists $defines{usenm};
0142f0ce 752
67382a3b
NC
753my (@missing, @created_dirs);
754
f4800c99 755if ($options{'force-manifest'}) {
67382a3b
NC
756 open my $fh, '<', 'MANIFEST'
757 or die "Could not open MANIFEST: $!";
758 while (<$fh>) {
759 next unless /^(\S+)/;
760 push @missing, $1
761 unless -f $1;
762 }
763 close $fh or die "Can't close MANIFEST: $!";
764
765 foreach my $pathname (@missing) {
766 my @parts = split '/', $pathname;
767 my $leaf = pop @parts;
768 my $path = '.';
769 while (@parts) {
770 $path .= '/' . shift @parts;
771 next if -d $path;
772 mkdir $path, 0700 or die "Can't create $path: $!";
773 unshift @created_dirs, $path;
774 }
775 open $fh, '>', $pathname or die "Can't open $pathname: $!";
776 close $fh or die "Can't close $pathname: $!";
777 chmod 0, $pathname or die "Can't chmod 0 $pathname: $!";
778 }
779}
780
dd4e46d7 781my @ARGS = $target eq 'config.sh' ? '-dEs' : '-des';
390a69a9
NC
782foreach my $key (sort keys %defines) {
783 my $val = $defines{$key};
784 if (ref $val) {
785 push @ARGS, "-D$key=@$val";
786 } elsif (!defined $val) {
787 push @ARGS, "-U$key";
788 } elsif (!length $val) {
789 push @ARGS, "-D$key";
790 } else {
791 $val = "" if $val eq "\0";
792 push @ARGS, "-D$key=$val";
793 }
794}
795push @ARGS, map {"-A$_"} @{$options{A}};
796
6a8dbfd7
NC
797# </dev/null because it seems that some earlier versions of Configure can
798# call commands in a way that now has them reading from stdin (and hanging)
799my $pid = fork;
800die "Can't fork: $!" unless defined $pid;
801if (!$pid) {
7c22f158
NC
802 open STDIN, '<', '/dev/null';
803 # If a file in MANIFEST is missing, Configure asks if you want to
804 # continue (the default being 'n'). With stdin closed or /dev/null,
805 # it exits immediately and the check for config.sh below will skip.
6a8dbfd7
NC
806 exec './Configure', @ARGS;
807 die "Failed to start Configure: $!";
808}
809waitpid $pid, 0
810 or die "wait for Configure, pid $pid failed: $!";
811
0afef97d
NC
812if ($target =~ /config\.s?h/) {
813 match_and_exit($target) if $match && -f $target;
dd4e46d7
NC
814 report_and_exit(!-f $target, 'could build', 'could not build', $target);
815} elsif (!-f 'config.sh') {
816 # Skip if something went wrong with Configure
817
818 skip('could not build config.sh');
819}
6a8dbfd7 820
67382a3b
NC
821# This is probably way too paranoid:
822if (@missing) {
823 my @errors;
eb4906f4 824 require Fcntl;
67382a3b
NC
825 foreach my $file (@missing) {
826 my (undef, undef, $mode, undef, undef, undef, undef, $size)
827 = stat $file;
828 if (!defined $mode) {
829 push @errors, "Added file $file has been deleted by Configure";
830 next;
831 }
eb4906f4 832 if (Fcntl::S_IMODE($mode) != 0) {
67382a3b
NC
833 push @errors,
834 sprintf 'Added file %s had mode changed by Configure to %03o',
835 $file, $mode;
836 }
837 if ($size != 0) {
838 push @errors,
839 "Added file $file had sized changed by Configure to $size";
840 }
841 unlink $file or die "Can't unlink $file: $!";
842 }
843 foreach my $dir (@created_dirs) {
844 rmdir $dir or die "Can't rmdir $dir: $!";
845 }
6c0925a0
NC
846 skip("@errors")
847 if @errors;
67382a3b
NC
848}
849
6a8dbfd7
NC
850# Correct makefile for newer GNU gcc
851# Only really needed if you comment out the use of blead's makedepend.SH
852{
853 local $^I = "";
854 local @ARGV = qw(makefile x2p/makefile);
855 while (<>) {
856 print unless /<(?:built-in|command|stdin)/;
857 }
858}
6a8dbfd7 859
0142f0ce
NC
860if ($major == 2 && extract_from_file('perl.c', qr/^ fclose\(e_fp\);$/)) {
861 # need to patch perl.c to avoid calling fclose() twice on e_fp when using -e
862 # This diff is part of commit ab821d7fdc14a438. The second close was
863 # introduced with perl-5.002, commit a5f75d667838e8e7
864 # Might want a6c477ed8d4864e6 too, for the corresponding change to pp_ctl.c
865 # (likely without this, eval will have "fun")
866 apply_patch(<<'EOPATCH');
867diff --git a/perl.c b/perl.c
868index 03c4d48..3c814a2 100644
869--- a/perl.c
870+++ b/perl.c
871@@ -252,6 +252,7 @@ setuid perl scripts securely.\n");
872 #ifndef VMS /* VMS doesn't have environ array */
873 origenviron = environ;
874 #endif
875+ e_tmpname = Nullch;
876
877 if (do_undump) {
878
879@@ -405,6 +406,7 @@ setuid perl scripts securely.\n");
880 if (e_fp) {
881 if (Fflush(e_fp) || ferror(e_fp) || fclose(e_fp))
882 croak("Can't write to temp file for -e: %s", Strerror(errno));
883+ e_fp = Nullfp;
884 argc++,argv--;
885 scriptname = e_tmpname;
886 }
887@@ -470,10 +472,10 @@ setuid perl scripts securely.\n");
888 curcop->cop_line = 0;
889 curstash = defstash;
890 preprocess = FALSE;
891- if (e_fp) {
892- fclose(e_fp);
893- e_fp = Nullfp;
894+ if (e_tmpname) {
895 (void)UNLINK(e_tmpname);
896+ Safefree(e_tmpname);
897+ e_tmpname = Nullch;
898 }
899
900 /* now that script is parsed, we can modify record separator */
901@@ -1369,7 +1371,7 @@ SV *sv;
902 scriptname = xfound;
903 }
904
905- origfilename = savepv(e_fp ? "-e" : scriptname);
906+ origfilename = savepv(e_tmpname ? "-e" : scriptname);
907 curcop->cop_filegv = gv_fetchfile(origfilename);
908 if (strEQ(origfilename,"-"))
909 scriptname = "";
910
911EOPATCH
912}
913
5fceabf3
NC
914if ($major < 10
915 && extract_from_file('ext/DB_File/DB_File.xs',
916 qr!^#else /\* Berkeley DB Version > 2 \*/$!)
917 && !extract_from_file('ext/DB_File/DB_File.xs',
918 qr/^#ifdef AT_LEAST_DB_4_1$/)) {
919 # This line is changed by commit 3245f0580c13b3ab
920 my $line = extract_from_file('ext/DB_File/DB_File.xs',
921 qr/^( status = \(?RETVAL->dbp->open\)?\(RETVAL->dbp, name, NULL, RETVAL->type, $)/);
922 apply_patch(<<"EOPATCH");
923diff --git a/ext/DB_File/DB_File.xs b/ext/DB_File/DB_File.xs
924index 489ba96..fba8ded 100644
925--- a/ext/DB_File/DB_File.xs
926+++ b/ext/DB_File/DB_File.xs
927\@\@ -183,4 +187,8 \@\@
928 #endif
929
930+#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
931+# define AT_LEAST_DB_4_1
932+#endif
933+
934 /* map version 2 features & constants onto their version 1 equivalent */
935
936\@\@ -1334,7 +1419,12 \@\@ SV * sv ;
937 #endif
938
939+#ifdef AT_LEAST_DB_4_1
940+ status = (RETVAL->dbp->open)(RETVAL->dbp, NULL, name, NULL, RETVAL->type,
941+ Flags, mode) ;
942+#else
943 $line
944 Flags, mode) ;
945+#endif
946 /* printf("open returned %d %s\\n", status, db_strerror(status)) ; */
947
948EOPATCH
949}
950
c59e8fd6
NC
951if ($major < 10 and -f 'ext/IPC/SysV/SysV.xs') {
952 edit_file('ext/IPC/SysV/SysV.xs', sub {
953 my $xs = shift;
954 my $fixed = <<'EOFIX';
955
956#include <sys/types.h>
957#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
958#ifndef HAS_SEM
959# include <sys/ipc.h>
960#endif
961# ifdef HAS_MSG
962# include <sys/msg.h>
963# endif
964# ifdef HAS_SHM
965# if defined(PERL_SCO) || defined(PERL_ISC)
966# include <sys/sysmacros.h> /* SHMLBA */
967# endif
968# include <sys/shm.h>
969# ifndef HAS_SHMAT_PROTOTYPE
970 extern Shmat_t shmat (int, char *, int);
971# endif
972# if defined(HAS_SYSCONF) && defined(_SC_PAGESIZE)
973# undef SHMLBA /* not static: determined at boot time */
974# define SHMLBA sysconf(_SC_PAGESIZE)
975# elif defined(HAS_GETPAGESIZE)
976# undef SHMLBA /* not static: determined at boot time */
977# define SHMLBA getpagesize()
978# endif
979# endif
980#endif
981EOFIX
982 $xs =~ s!
983#include <sys/types\.h>
984.*
985(#ifdef newCONSTSUB|/\* Required)!$fixed$1!ms;
986 return $xs;
987 });
988}
989
9a999a97 990# Parallel build for miniperl is safe
9da8cb0a 991system "make $j miniperl </dev/null";
9a999a97 992
2526f4b8
NC
993my $expected = $target =~ /^test/ ? 't/perl'
994 : $target eq 'Fcntl' ? "lib/auto/Fcntl/Fcntl.$Config{so}"
995 : $target;
996my $real_target = $target eq 'Fcntl' ? $expected : $target;
997
9a999a97
NC
998if ($target ne 'miniperl') {
999 # Nearly all parallel build issues fixed by 5.10.0. Untrustworthy before that.
372ba1f9 1000 $j = '' if $major < 10;
9a999a97 1001
2526f4b8 1002 if ($real_target eq 'test_prep') {
9a999a97
NC
1003 if ($major < 8) {
1004 # test-prep was added in 5.004_01, 3e3baf6d63945cb6.
1005 # renamed to test_prep in 2001 in 5fe84fd29acaf55c.
1006 # earlier than that, just make test. It will be fast enough.
2526f4b8
NC
1007 $real_target = extract_from_file('Makefile.SH',
1008 qr/^(test[-_]prep):/,
1009 'test');
9a999a97 1010 }
6a8dbfd7 1011 }
6a8dbfd7 1012
9da8cb0a 1013 system "make $j $real_target </dev/null";
9a999a97 1014}
6a8dbfd7 1015
67382a3b
NC
1016my $missing_target = $expected =~ /perl$/ ? !-x $expected : !-r $expected;
1017
f4800c99 1018if ($options{'test-build'}) {
2526f4b8
NC
1019 report_and_exit($missing_target, 'could build', 'could not build',
1020 $real_target);
67382a3b 1021} elsif ($missing_target) {
2526f4b8 1022 skip("could not build $real_target");
67382a3b 1023}
6a8dbfd7 1024
2526f4b8 1025match_and_exit($real_target) if $match;
0afef97d
NC
1026
1027if (defined $options{'one-liner'}) {
2526f4b8 1028 my $exe = $target =~ /^(?:perl$|test)/ ? 'perl' : 'miniperl';
0afef97d
NC
1029 unshift @ARGV, "./$exe", '-Ilib', '-e', $options{'one-liner'};
1030}
1031
6a8dbfd7
NC
1032# This is what we came here to run:
1033my $ret = system @ARGV;
1034
f1050811 1035report_and_exit($ret, 'zero exit from', 'non-zero exit from', "@ARGV");
9a999a97
NC
1036
1037# Local variables:
1038# cperl-indent-level: 4
1039# indent-tabs-mode: nil
1040# End:
1041#
1042# ex: set ts=8 sts=4 sw=4 et: