This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
bisect-runner.pl should patch unreliable C symbol detection code.
[perl5.git] / Porting / bisect-runner.pl
1 #!/usr/bin/perl -w
2 use strict;
3
4 use Getopt::Long qw(:config bundling no_auto_abbrev);
5 use Pod::Usage;
6 use Config;
7
8 my @targets
9     = qw(config.sh config.h miniperl lib/Config.pm Fcntl perl test_prep);
10
11 my $cpus;
12 if (open my $fh, '<', '/proc/cpuinfo') {
13     while (<$fh>) {
14         ++$cpus if /^processor\s+:\s+\d+$/;
15     }
16 } elsif (-x '/sbin/sysctl') {
17     $cpus = 1 + $1 if `/sbin/sysctl hw.ncpu` =~ /^hw\.ncpu: (\d+)$/;
18 } elsif (-x '/usr/bin/getconf') {
19     $cpus = 1 + $1 if `/usr/bin/getconf _NPROCESSORS_ONLN` =~ /^(\d+)$/;
20 }
21
22 my %options =
23     (
24      jobs => defined $cpus ? $cpus + 1 : 2,
25      'expect-pass' => 1,
26      clean => 1, # mostly for debugging this
27     );
28
29 my $linux64 = `uname -sm` eq "Linux x86_64\n" ? '64' : '';
30
31 my @paths;
32
33 if ($^O eq 'linux') {
34     # This is the search logic for a multi-arch library layout
35     # added to linux.sh in commits 40f026236b9959b7 and dcffd848632af2c7.
36     my $gcc = -x '/usr/bin/gcc' ? '/usr/bin/gcc' : 'gcc';
37
38     foreach (`$gcc -print-search-dirs`) {
39         next unless /^libraries: =(.*)/;
40         foreach (split ':', $1) {
41             next if m/gcc/;
42             next unless -d $_;
43             s!/$!!;
44             push @paths, $_;
45         }
46     }
47 }
48
49 push @paths, map {$_ . $linux64} qw(/usr/local/lib /lib /usr/lib);
50
51 my %defines =
52     (
53      usedevel => '',
54      optimize => '-g',
55      cc => 'ccache cc',
56      ld => 'cc',
57      ($linux64 ? (libpth => \@paths) : ()),
58     );
59
60 unless(GetOptions(\%options,
61                   'target=s', 'jobs|j=i', 'expect-pass=i',
62                   'expect-fail' => sub { $options{'expect-pass'} = 0; },
63                   'clean!', 'one-liner|e=s', 'match=s', 'force-manifest',
64                   'test-build', 'check-args', 'A=s@', 'usage|help|?',
65                   'D=s@' => sub {
66                       my (undef, $val) = @_;
67                       if ($val =~ /\A([^=]+)=(.*)/s) {
68                           $defines{$1} = length $2 ? $2 : "\0";
69                       } else {
70                           $defines{$val} = '';
71                       }
72                   },
73                   'U=s@' => sub {
74                       $defines{$_[1]} = undef;
75                   },
76                  )) {
77     pod2usage(exitval => 255, verbose => 1);
78 }
79
80 my ($target, $j, $match) = @options{qw(target jobs match)};
81
82 pod2usage(exitval => 255, verbose => 1) if $options{usage};
83 pod2usage(exitval => 255, verbose => 1)
84     unless @ARGV || $match || $options{'test-build'} || defined $options{'one-liner'};
85
86 exit 0 if $options{'check-args'};
87
88 =head1 NAME
89
90 bisect.pl - use git bisect to pinpoint changes
91
92 =head1 SYNOPSIS
93
94     # When did this become an error?
95     .../Porting/bisect.pl -e 'my $a := 2;'
96     # When did this stop being an error?
97     .../Porting/bisect.pl --expect-fail -e '1 // 2'
98     # When did this stop matching?
99     .../Porting/bisect.pl --match '\b(?:PL_)hash_seed_set\b'
100     # When did this start matching?
101     .../Porting/bisect.pl --expect-fail --match '\buseithreads\b'
102     # When did this test program stop working?
103     .../Porting/bisect.pl -- ./perl -Ilib ../test_prog.pl
104     # When did this first become valid syntax?
105     .../Porting/bisect.pl --target=miniperl --end=v5.10.0 \
106          --expect-fail -e 'my $a := 2;'
107     # What was the last revision to build with these options?
108     .../Porting/bisect.pl --test-build -Dd_dosuid
109
110 =head1 DESCRIPTION
111
112 Together F<bisect.pl> and F<bisect-runner.pl> attempt to automate the use
113 of C<git bisect> as much as possible. With one command (and no other files)
114 it's easy to find out
115
116 =over 4
117
118 =item *
119
120 Which commit caused this example code to break?
121
122 =item *
123
124 Which commit caused this example code to start working?
125
126 =item *
127
128 Which commit added the first to match this regex?
129
130 =item *
131
132 Which commit removed the last to match this regex?
133
134 =back
135
136 usually without needing to know which versions of perl to use as start and
137 end revisions.
138
139 By default F<bisect.pl> will process all options, then use the rest of the
140 command line as arguments to list C<system> to run a test case. By default,
141 the test case should pass (exit with 0) on earlier perls, and fail (exit
142 non-zero) on I<blead>. F<bisect.pl> will use F<bisect-runner.pl> to find the
143 earliest stable perl version on which the test case passes, check that it
144 fails on blead, and then use F<bisect-runner.pl> with C<git bisect run> to
145 find the commit which caused the failure.
146
147 Because the test case is the complete argument to C<system>, it is easy to
148 run something other than the F<perl> built, if necessary. If you need to run
149 the perl built, you'll probably need to invoke it as C<./perl -Ilib ...>
150
151 You need a clean checkout to run a bisect, and you can't use the checkout
152 which contains F<Porting/bisect.pl> (because C<git bisect>) will check out
153 a revision before F<Porting/bisect-runner.pl> was added, which
154 C<git bisect run> needs). If your working checkout is called F<perl>, the
155 simplest solution is to make a local clone, and run from that. I<i.e.>:
156
157     cd ..
158     git clone perl perl2
159     cd perl2
160     ../perl/Porting/bisect.pl ...
161
162 By default, F<bisect-runner.pl> will automatically disable the build of
163 L<DB_File> for commits earlier than ccb44e3bf3be2c30, as it's not practical
164 to patch DB_File 1.70 and earlier to build with current Berkeley DB headers.
165 (ccb44e3bf3be2c30 was in September 1999, between 5.005_62 and 5.005_63.)
166 If your F<db.h> is old enough you can override this with C<-Unoextensions>.
167
168 =head1 OPTIONS
169
170 =over 4
171
172 =item *
173
174 --start I<commit-ish>
175
176 Earliest revision to test, as a I<commit-ish> (a tag, commit or anything
177 else C<git> understands as a revision). If not specified, F<bisect.pl> will
178 search stable perl releases from 5.002 to 5.14.0 until it finds one where
179 the test case passes.
180
181 =item *
182
183 --end I<commit-ish>
184
185 Most recent revision to test, as a I<commit-ish>. If not specified, defaults
186 to I<blead>.
187
188 =item *
189
190 --target I<target>
191
192 F<Makefile> target (or equivalent) needed, to run the test case. If specified,
193 this should be one of
194
195 =over 4
196
197 =item *
198
199 I<config.sh>
200
201 Just run F<./Configure>
202
203 =item *
204
205 I<config.h>
206
207 Run the various F<*.SH> files to generate F<Makefile>, F<config.h>, I<etc>.
208
209 =item *
210
211 I<miniperl>
212
213 Build F<miniperl>.
214
215 =item *
216
217 I<lib/Config.pm>
218
219 Use F<miniperl> to build F<lib/Config.pm>
220
221 =item *
222
223 I<Fcntl>
224
225 Build F<lib/auto/Fcntl/Fnctl.so> (strictly, C<.$Config{so}>). As L<Fcntl>
226 is simple XS module present since 5.000, this provides a fast test of
227 whether XS modules can be built. Note, XS modules are built by F<miniperl>,
228 hence this target will not build F<perl>.
229
230 =item *
231
232 I<perl>
233
234 Build F<perl>. This also builds pure-Perl modules in F<cpan>, F<dist> and
235 F<ext>. XS modules (such as L<Fcntl>) are not built.
236
237 =item *
238
239 I<test_prep>
240
241 Build everything needed to run the tests. This is the default if we're
242 running test code, but is time consuming, as it means building all
243 XS modules. For older F<Makefile>s, the previous name of C<test-prep>
244 is automatically substituted. For very old F<Makefile>s, C<make test> is
245 run, as there is no target provided to just get things ready, and for 5.004
246 and earlier the tests run very quickly.
247
248 =back
249
250 =item *
251
252 --one-liner 'code to run'
253
254 =item *
255
256 -e 'code to run'
257
258 Example code to run, just like you'd use with C<perl -e>.
259
260 This prepends C<./perl -Ilib -e 'code to run'> to the test case given,
261 or F<./miniperl> if I<target> is C<miniperl>.
262
263 (Usually you'll use C<-e> instead of providing a test case in the
264 non-option arguments to F<bisect.pl>)
265
266 C<-E> intentionally isn't supported, as it's an error in 5.8.0 and earlier,
267 which interferes with detecting errors in the example code itself.
268
269 =item *
270
271 --expect-fail
272
273 The test case should fail for the I<start> revision, and pass for the I<end>
274 revision. The bisect run will find the first commit where it passes.
275
276 =item *
277
278 -Dnoextensions=Encode
279
280 =item *
281
282 -Uusedevel
283
284 =item *
285
286 -Accflags=-DNO_MATHOMS
287
288 Arguments to pass to F<Configure>. Repeated C<-A> arguments are passed
289 through as is. C<-D> and C<-U> are processed in order, and override
290 previous settings for the same parameter. F<bisect-runner.pl> emulates
291 C<-Dnoextensions> when F<Configure> itself does not provide it, as it's
292 often very useful to be able to disable some XS extensions.
293
294 =item *
295
296 --jobs I<jobs>
297
298 =item *
299
300 -j I<jobs>
301
302 Number of C<make> jobs to run in parallel. If F</proc/cpuinfo> exists and
303 can be parsed, or F</sbin/sysctl> exists and reports C<hw.ncpu>, or
304 F</usr/bin/getconf> exists and reports C<_NPROCESSORS_ONLN> defaults to 1 +
305 I<number of CPUs>. Otherwise defaults to 2.
306
307 =item *
308
309 --match pattern
310
311 Instead of running a test program to determine I<pass> or I<fail>, pass
312 if the given regex matches, and hence search for the commit that removes
313 the last matching file.
314
315 If no I<target> is specified, the match is against all files in the
316 repository (which is fast). If a I<target> is specified, that target is
317 built, and the match is against only the built files. C<--expect-fail> can
318 be used with C<--match> to search for a commit that adds files that match.
319
320 =item *
321
322 --test-build
323
324 Test that the build completes, without running any test case.
325
326 By default, if the build for the desired I<target> fails to complete,
327 F<bisect-runner.pl> reports a I<skip> back to C<git bisect>, the assumption
328 being that one wants to find a commit which changed state "builds && passes"
329 to "builds && fails". If instead one is interested in which commit broke the
330 build (possibly for particular F<Configure> options), use I<--test-build>
331 to treat a build failure as a failure, not a "skip".
332
333 Often this option isn't as useful as it first seems, because I<any> build
334 failure will be reported to C<git bisect> as a failure, not just the failure
335 that you're interested in. Generally, to debug a particular problem, it's
336 more useful to use a I<target> that builds properly at the point of interest,
337 and then a test case that runs C<make>. For example:
338
339     .../Porting/bisect.pl --start=perl-5.000 --end=perl-5.002 \
340         --expect-fail --force-manifest --target=miniperl make perl
341
342 will find the first revision capable of building L<DynaLoader> and then
343 F<perl>, without becoming confused by revisions where F<miniperl> won't
344 even link.
345
346 =item *
347
348 --force-manifest
349
350 By default, a build will "skip" if any files listed in F<MANIFEST> are not
351 present. Usually this is useful, as it avoids false-failures. However, there
352 are some long ranges of commits where listed files are missing, which can
353 cause a bisect to abort because all that remain are skipped revisions.
354
355 In these cases, particularly if the test case uses F<miniperl> and no modules,
356 it may be more useful to force the build to continue, even if files
357 F<MANIFEST> are missing.
358
359 =item *
360
361 --expect-pass [0|1]
362
363 C<--expect-pass=0> is equivalent to C<--expect-fail>. I<1> is the default.
364
365 =item *
366
367 --no-clean
368
369 Tell F<bisect-runner.pl> not to clean up after the build. This allows one
370 to use F<bisect-runner.pl> to build the current particular perl revision for
371 interactive testing, or for debugging F<bisect-runner.pl>.
372
373 Passing this to F<bisect.pl> will likely cause the bisect to fail badly.
374
375 =item *
376
377 --check-args
378
379 Validate the options and arguments, and exit silently if they are valid.
380
381 =item *
382
383 --usage
384
385 =item *
386
387 --help
388
389 =item *
390
391 -?
392
393 Display the usage information and exit.
394
395 =back
396
397 =cut
398
399 die "$0: Can't build $target" if defined $target && !grep {@targets} $target;
400
401 $j = "-j$j" if $j =~ /\A\d+\z/;
402
403 # Sadly, however hard we try, I don't think that it will be possible to build
404 # modules in ext/ on x86_64 Linux before commit e1666bf5602ae794 on 1999/12/29,
405 # which updated to MakeMaker 3.7, which changed from using a hard coded ld
406 # in the Makefile to $(LD). On x86_64 Linux the "linker" is gcc.
407
408 sub extract_from_file {
409     my ($file, $rx, $default) = @_;
410     open my $fh, '<', $file or die "Can't open $file: $!";
411     while (<$fh>) {
412         my @got = $_ =~ $rx;
413         return wantarray ? @got : $got[0]
414             if @got;
415     }
416     return $default if defined $default;
417     return;
418 }
419
420 sub edit_file {
421     my ($file, $munger) = @_;
422     local $/;
423     open my $fh, '<', $file or die "Can't open $file: $!";
424     my $orig = <$fh>;
425     die "Can't read $file: $!" unless defined $orig && close $fh;
426     my $new = $munger->($orig);
427     return if $new eq $orig;
428     open $fh, '>', $file or die "Can't open $file: $!";
429     print $fh $new or die "Can't print to $file: $!";
430     close $fh or die "Can't close $file: $!";
431 }
432
433 sub apply_patch {
434     my $patch = shift;
435
436     my ($file) = $patch =~ qr!^diff.*a/(\S+) b/\1!;
437     open my $fh, '|-', 'patch', '-p1' or die "Can't run patch: $!";
438     print $fh $patch;
439     return if close $fh;
440     print STDERR "Patch is <<'EOPATCH'\n${patch}EOPATCH\n";
441     die "Can't patch $file: $?, $!";
442 }
443
444 sub clean {
445     if ($options{clean}) {
446         # Needed, because files that are build products in this checked out
447         # version might be in git in the next desired version.
448         system 'git clean -dxf </dev/null';
449         # Needed, because at some revisions the build alters checked out files.
450         # (eg pod/perlapi.pod). Also undoes any changes to makedepend.SH
451         system 'git reset --hard HEAD </dev/null';
452     }
453 }
454
455 sub skip {
456     my $reason = shift;
457     clean();
458     warn "skipping - $reason";
459     exit 125;
460 }
461
462 sub report_and_exit {
463     my ($ret, $pass, $fail, $desc) = @_;
464
465     clean();
466
467     my $got = ($options{'expect-pass'} ? !$ret : $ret) ? 'good' : 'bad';
468     if ($ret) {
469         print "$got - $fail $desc\n";
470     } else {
471         print "$got - $pass $desc\n";
472     }
473
474     exit($got eq 'bad');
475 }
476
477 sub match_and_exit {
478     my $target = shift;
479     my $matches = 0;
480     my $re = qr/$match/;
481     my @files;
482
483     {
484         local $/ = "\0";
485         @files = defined $target ? `git ls-files -o -z`: `git ls-files -z`;
486         chomp @files;
487     }
488
489     foreach my $file (@files) {
490         open my $fh, '<', $file or die "Can't open $file: $!";
491         while (<$fh>) {
492             if ($_ =~ $re) {
493                 ++$matches;
494                 if (tr/\t\r\n -~\200-\377//c) {
495                     print "Binary file $file matches\n";
496                 } else {
497                     $_ .= "\n" unless /\n\z/;
498                     print "$file: $_";
499                 }
500             }
501         }
502         close $fh or die "Can't close $file: $!";
503     }
504     report_and_exit(!$matches,
505                     $matches == 1 ? '1 match for' : "$matches matches for",
506                     'no matches for', $match);
507 }
508
509 # Not going to assume that system perl is yet new enough to have autodie
510 system 'git clean -dxf </dev/null' and die;
511
512 if (!defined $target) {
513     match_and_exit() if $match;
514     $target = 'test_prep';
515 }
516
517 skip('no Configure - is this the //depot/perlext/Compiler branch?')
518     unless -f 'Configure';
519
520 # This changes to PERL_VERSION in 4d8076ea25903dcb in 1999
521 my $major
522     = extract_from_file('patchlevel.h',
523                         qr/^#define\s+(?:PERL_VERSION|PATCHLEVEL)\s+(\d+)\s/,
524                         0);
525
526 if ($major < 1) {
527     if (extract_from_file('Configure',
528                           qr/^          \*=\*\) echo "\$1" >> \$optdef;;$/)) {
529         # This is "        Spaces now allowed in -D command line options.",
530         # part of commit ecfc54246c2a6f42
531         apply_patch(<<'EOPATCH');
532 diff --git a/Configure b/Configure
533 index 3d3b38d..78ffe16 100755
534 --- a/Configure
535 +++ b/Configure
536 @@ -652,7 +777,8 @@ while test $# -gt 0; do
537                         echo "$me: use '-U symbol=', not '-D symbol='." >&2
538                         echo "$me: ignoring -D $1" >&2
539                         ;;
540 -               *=*) echo "$1" >> $optdef;;
541 +               *=*) echo "$1" | \
542 +                               sed -e "s/'/'\"'\"'/g" -e "s/=\(.*\)/='\1'/" >> $optdef;;
543                 *) echo "$1='define'" >> $optdef;;
544                 esac
545                 shift
546 EOPATCH
547     }
548     if (extract_from_file('Configure', qr/^if \$contains 'd_namlen' \$xinc\b/)) {
549         # Configure's original simple "grep" for d_namlen falls foul of the
550         # approach taken by the glibc headers:
551         # #ifdef _DIRENT_HAVE_D_NAMLEN
552         # # define _D_EXACT_NAMLEN(d) ((d)->d_namlen)
553         #
554         # where _DIRENT_HAVE_D_NAMLEN is not defined on Linux.
555         # This is also part of commit ecfc54246c2a6f42
556         apply_patch(<<'EOPATCH');
557 diff --git a/Configure b/Configure
558 index 3d3b38d..78ffe16 100755
559 --- a/Configure
560 +++ b/Configure
561 @@ -3935,7 +4045,8 @@ $rm -f try.c
562  
563  : see if the directory entry stores field length
564  echo " "
565 -if $contains 'd_namlen' $xinc >/dev/null 2>&1; then
566 +$cppstdin $cppflags $cppminus < "$xinc" > try.c
567 +if $contains 'd_namlen' try.c >/dev/null 2>&1; then
568         echo "Good, your directory entry keeps length information in d_namlen." >&4
569         val="$define"
570  else
571 EOPATCH
572     }
573 }
574
575 if ($major < 8 && !extract_from_file('Configure',
576                                     qr/^\t\tif test ! -t 0; then$/)) {
577     # Before dfe9444ca7881e71, Configure would refuse to run if stdin was not a
578     # tty. With that commit, the tty requirement was dropped for -de and -dE
579     # Commit aaeb8e512e8e9e14 dropped the tty requirement for -S
580     # For those older versions, it's probably easiest if we simply remove the
581     # sanity test.
582     edit_file('Configure', sub {
583                   my $code = shift;
584                   $code =~ s/test ! -t 0/test Perl = rules/;
585                   return $code;
586               });
587 }
588
589 if ($major == 8 || $major == 9) {
590     # Fix symbol detection to that of commit 373dfab3839ca168 if it's any
591     # intermediate version 5129fff43c4fe08c or later, as the intermediate
592     # versions don't work correctly on (at least) Sparc Linux.
593     # 5129fff43c4fe08c adds the first mention of mistrustnm.
594     # 373dfab3839ca168 removes the last mention of lc=""
595     edit_file('Configure', sub {
596                   my $code = shift;
597                   return $code
598                       if $code !~ /\btc="";/; # 373dfab3839ca168 or later
599                   return $code
600                       if $code !~ /\bmistrustnm\b/; # before 5129fff43c4fe08c
601                   my $fixed = <<'EOC';
602
603 : is a C symbol defined?
604 csym='tlook=$1;
605 case "$3" in
606 -v) tf=libc.tmp; tdc="";;
607 -a) tf=libc.tmp; tdc="[]";;
608 *) tlook="^$1\$"; tf=libc.list; tdc="()";;
609 esac;
610 tx=yes;
611 case "$reuseval-$4" in
612 true-) ;;
613 true-*) tx=no; eval "tval=\$$4"; case "$tval" in "") tx=yes;; esac;;
614 esac;
615 case "$tx" in
616 yes)
617         tval=false;
618         if $test "$runnm" = true; then
619                 if $contains $tlook $tf >/dev/null 2>&1; then
620                         tval=true;
621                 elif $test "$mistrustnm" = compile -o "$mistrustnm" = run; then
622                         echo "void *(*(p()))$tdc { extern void *$1$tdc; return &$1; } int main() { if(p()) return(0); else return(1); }"> try.c;
623                         $cc -o try $optimize $ccflags $ldflags try.c >/dev/null 2>&1 $libs && tval=true;
624                         $test "$mistrustnm" = run -a -x try && { $run ./try$_exe >/dev/null 2>&1 || tval=false; };
625                         $rm -f try$_exe try.c core core.* try.core;
626                 fi;
627         else
628                 echo "void *(*(p()))$tdc { extern void *$1$tdc; return &$1; } int main() { if(p()) return(0); else return(1); }"> try.c;
629                 $cc -o try $optimize $ccflags $ldflags try.c $libs >/dev/null 2>&1 && tval=true;
630                 $rm -f try$_exe try.c;
631         fi;
632         ;;
633 *)
634         case "$tval" in
635         $define) tval=true;;
636         *) tval=false;;
637         esac;
638         ;;
639 esac;
640 eval "$2=$tval"'
641
642 EOC
643                   $code =~ s/\n: is a C symbol defined\?\n.*?\neval "\$2=\$tval"'\n\n/$fixed/sm
644                       or die "substitution failed";
645                   return $code;
646               });
647 }
648
649 if ($major < 10 && extract_from_file('Configure', qr/^set malloc\.h i_malloc$/)) {
650     # This is commit 01d07975f7ef0e7d, trimmed, with $compile inlined as
651     # prior to bd9b35c97ad661cc Configure had the malloc.h test before the
652     # definition of $compile.
653     apply_patch(<<'EOPATCH');
654 diff --git a/Configure b/Configure
655 index 3d2e8b9..6ce7766 100755
656 --- a/Configure
657 +++ b/Configure
658 @@ -6743,5 +6743,22 @@ set d_dosuid
659  
660  : see if this is a malloc.h system
661 -set malloc.h i_malloc
662 -eval $inhdr
663 +: we want a real compile instead of Inhdr because some systems have a
664 +: malloc.h that just gives a compile error saying to use stdlib.h instead
665 +echo " "
666 +$cat >try.c <<EOCP
667 +#include <stdlib.h>
668 +#include <malloc.h>
669 +int main () { return 0; }
670 +EOCP
671 +set try
672 +if $cc $optimize $ccflags $ldflags -o try $* try.c $libs > /dev/null 2>&1; then
673 +    echo "<malloc.h> found." >&4
674 +    val="$define"
675 +else
676 +    echo "<malloc.h> NOT found." >&4
677 +    val="$undef"
678 +fi
679 +$rm -f try.c try
680 +set i_malloc
681 +eval $setvar
682  
683 EOPATCH
684 }
685
686 # Cwd.xs added in commit 0d2079faa739aaa9. Cwd.pm moved to ext/ 8 years later
687 # in commit 403f501d5b37ebf0
688 if ($major > 0 && <*/Cwd/Cwd.xs>) {
689     if ($major < 10 && !extract_from_file('Makefile.SH', qr/^extra_dep=''$/)) {
690         # The Makefile.PL for Unicode::Normalize needs
691         # lib/unicore/CombiningClass.pl. Even without a parallel build, we need
692         # a dependency to ensure that it builds. This is a variant of commit
693         # 9f3ef600c170f61e. Putting this for earlier versions gives us a spot
694         # on which to hang the edits below
695         apply_patch(<<'EOPATCH');
696 diff --git a/Makefile.SH b/Makefile.SH
697 index f61d0db..6097954 100644
698 --- a/Makefile.SH
699 +++ b/Makefile.SH
700 @@ -155,10 +155,20 @@ esac
701  
702  : Prepare dependency lists for Makefile.
703  dynamic_list=' '
704 +extra_dep=''
705  for f in $dynamic_ext; do
706      : the dependency named here will never exist
707        base=`echo "$f" | sed 's/.*\///'`
708 -    dynamic_list="$dynamic_list lib/auto/$f/$base.$dlext"
709 +    this_target="lib/auto/$f/$base.$dlext"
710 +    dynamic_list="$dynamic_list $this_target"
711 +
712 +    : Parallel makes reveal that we have some interdependencies
713 +    case $f in
714 +       Math/BigInt/FastCalc) extra_dep="$extra_dep
715 +$this_target: lib/auto/List/Util/Util.$dlext" ;;
716 +       Unicode/Normalize) extra_dep="$extra_dep
717 +$this_target: lib/unicore/CombiningClass.pl" ;;
718 +    esac
719  done
720  
721  static_list=' '
722 @@ -987,2 +997,9 @@ n_dummy $(nonxs_ext):       miniperl$(EXE_EXT) preplibrary $(DYNALOADER) FORCE
723         @$(LDLIBPTH) sh ext/util/make_ext nonxs $@ MAKE=$(MAKE) LIBPERL_A=$(LIBPERL)
724 +!NO!SUBS!
725 +
726 +$spitshell >>Makefile <<EOF
727 +$extra_dep
728 +EOF
729 +
730 +$spitshell >>Makefile <<'!NO!SUBS!'
731  
732 EOPATCH
733     }
734     if ($major < 14) {
735         # Commits dc0655f797469c47 and d11a62fe01f2ecb2
736         edit_file('Makefile.SH', sub {
737                       my $code = shift;
738                       foreach my $ext (qw(Encode SDBM_File)) {
739                           next if $code =~ /\b$ext\) extra_dep=/s;
740                           $code =~ s!(\) extra_dep="\$extra_dep
741 \$this_target: .*?" ;;)
742 (    esac
743 )!$1
744         $ext) extra_dep="\$extra_dep
745 \$this_target: lib/auto/Cwd/Cwd.\$dlext" ;;
746 $2!;
747                       }
748                       return $code;
749                   });
750     }
751 }
752 if ($major == 7) {
753     # Remove commits 9fec149bb652b6e9 and 5bab1179608f81d8, which add/amend
754     # rules to automatically run regen scripts that rebuild C headers. These
755     # cause problems because a git checkout doesn't preserve relative file
756     # modification times, hence the regen scripts may fire. This will obscure
757     # whether the repository had the correct generated headers checked in.
758     # Also, the dependency rules for running the scripts were not correct,
759     # which could cause spurious re-builds on re-running make, and can cause
760     # complete build failures for a parallel make.
761     if (extract_from_file('Makefile.SH',
762                           qr/Writing it this way gives make a big hint to always run opcode\.pl before/)) {
763         system 'git show 70c6e6715e8fec53 | patch -p1'
764             and die;
765     } elsif (extract_from_file('Makefile.SH',
766                                qr/^opcode\.h opnames\.h pp_proto\.h pp\.sym: opcode\.pl$/)) {
767         system 'git show 9fec149bb652b6e9 | patch -p1 -R'
768             and die;
769     }
770 }
771
772 # There was a bug in makedepend.SH which was fixed in version 96a8704c.
773 # Symptom was './makedepend: 1: Syntax error: Unterminated quoted string'
774 # Remove this if you're actually bisecting a problem related to makedepend.SH
775 system 'git show blead:makedepend.SH > makedepend.SH </dev/null' and die;
776
777 if ($^O eq 'freebsd') {
778     # There are rather too many version-specific FreeBSD hints fixes to patch
779     # individually. Also, more than once the FreeBSD hints file has been
780     # written in what turned out to be a rather non-future-proof style,
781     # with case statements treating the most recent version as the exception,
782     # instead of treating previous versions' behaviour explicitly and changing
783     # the default to cater for the current behaviour. (As strangely, future
784     # versions inherit the current behaviour.)
785     system 'git show blead:hints/freebsd.sh > hints/freebsd.sh </dev/null'
786       and die;
787
788     if ($major < 2) {
789         # 5.002 Configure and later have code to
790         #
791         # : Try to guess additional flags to pick up local libraries.
792         #
793         # which will automatically add --L/usr/local/lib because libpth
794         # contains /usr/local/lib
795         #
796         # Without it, if Configure finds libraries in /usr/local/lib (eg
797         # libgdbm.so) and adds them to the compiler commandline (as -lgdbm),
798         # then the link will fail. We can't fix this up in config.sh because
799         # the link will *also* fail in the test compiles that Configure does
800         # (eg $inlibc) which makes Configure get all sorts of things
801         # wrong. :-( So bodge it here.
802         #
803         # Possibly other platforms will need something similar. (if they
804         # have "wanted" libraries in /usr/local/lib, but the compiler
805         # doesn't default to putting that directory in its link path)
806         apply_patch(<<'EOPATCH');
807 --- perl2/hints/freebsd.sh.orig 2011-10-05 16:44:55.000000000 +0200
808 +++ perl2/hints/freebsd.sh      2011-10-05 16:45:52.000000000 +0200
809 @@ -125,7 +125,7 @@
810          else
811              libpth="/usr/lib /usr/local/lib"
812              glibpth="/usr/lib /usr/local/lib"
813 -            ldflags="-Wl,-E "
814 +            ldflags="-Wl,-E -L/usr/local/lib "
815              lddlflags="-shared "
816          fi
817          cccdlflags='-DPIC -fPIC'
818 @@ -133,7 +133,7 @@
819  *)
820         libpth="/usr/lib /usr/local/lib"
821         glibpth="/usr/lib /usr/local/lib"
822 -       ldflags="-Wl,-E "
823 +       ldflags="-Wl,-E -L/usr/local/lib "
824          lddlflags="-shared "
825          cccdlflags='-DPIC -fPIC'
826         ;;
827 EOPATCH
828     }
829 } elsif ($^O eq 'darwin') {
830     if ($major < 8) {
831         my $faking_it;
832         # We can't build on darwin without some of the data in the hints file.
833         foreach ('ext/DynaLoader/dl_dyld.xs', 'hints/darwin.sh') {
834             next if -f $_;
835             ++$faking_it;
836             # Probably less surprising to use the earliest version of
837             # hints/darwin.sh and then edit in place just below, than use
838             # blead's version, as that would create a discontinuity at
839             # f556e5b971932902 - before it, hints bugs would be "fixed", after
840             # it they'd resurface. This way, we should give the illusion of
841             # monotonic bug fixing.
842             system "git show f556e5b971932902:$_ >$_"
843                 and die "while attempting to extract $_";
844         }
845         if ($faking_it) {
846             apply_patch(<<'EOPATCH');
847 diff -u a/ext/DynaLoader/dl_dyld.xs~ a/ext/DynaLoader/dl_dyld.xs
848 --- a/ext/DynaLoader/dl_dyld.xs~        2011-10-11 21:41:27.000000000 +0100
849 +++ b/ext/DynaLoader/dl_dyld.xs 2011-10-11 21:42:20.000000000 +0100
850 @@ -41,6 +41,35 @@
851  #include "perl.h"
852  #include "XSUB.h"
853  
854 +#ifndef pTHX
855 +#  define pTHX         void
856 +#  define pTHX_
857 +#endif
858 +#ifndef aTHX
859 +#  define aTHX
860 +#  define aTHX_
861 +#endif
862 +#ifndef dTHX
863 +#  define dTHXa(a)     extern int Perl___notused(void)
864 +#  define dTHX         extern int Perl___notused(void)
865 +#endif
866 +
867 +#ifndef Perl_form_nocontext
868 +#  define Perl_form_nocontext form
869 +#endif
870 +
871 +#ifndef Perl_warn_nocontext
872 +#  define Perl_warn_nocontext warn
873 +#endif
874 +
875 +#ifndef PTR2IV
876 +#  define PTR2IV(p)    (IV)(p)
877 +#endif
878 +
879 +#ifndef get_av
880 +#  define get_av perl_get_av
881 +#endif
882 +
883  #define DL_LOADONCEONLY
884  
885  #include "dlutils.c"   /* SaveError() etc      */
886 @@ -185,7 +191,7 @@
887      CODE:
888      DLDEBUG(1,PerlIO_printf(Perl_debug_log, "dl_load_file(%s,%x):\n", filename,flags));
889      if (flags & 0x01)
890 -       Perl_warn(aTHX_ "Can't make loaded symbols global on this platform while loading %s",filename);
891 +       Perl_warn_nocontext("Can't make loaded symbols global on this platform while loading %s",filename);
892      RETVAL = dlopen(filename, mode) ;
893      DLDEBUG(2,PerlIO_printf(Perl_debug_log, " libref=%x\n", RETVAL));
894      ST(0) = sv_newmortal() ;
895 EOPATCH
896             if ($major < 4 && !extract_from_file('util.c', qr/^form/m)) {
897                 apply_patch(<<'EOPATCH');
898 diff -u a/ext/DynaLoader/dl_dyld.xs~ a/ext/DynaLoader/dl_dyld.xs
899 --- a/ext/DynaLoader/dl_dyld.xs~        2011-10-11 21:56:25.000000000 +0100
900 +++ b/ext/DynaLoader/dl_dyld.xs 2011-10-11 22:00:00.000000000 +0100
901 @@ -60,6 +60,18 @@
902  #  define get_av perl_get_av
903  #endif
904  
905 +static char *
906 +form(char *pat, ...)
907 +{
908 +    char *retval;
909 +    va_list args;
910 +    va_start(args, pat);
911 +    vasprintf(&retval, pat, &args);
912 +    va_end(args);
913 +    SAVEFREEPV(retval);
914 +    return retval;
915 +}
916 +
917  #define DL_LOADONCEONLY
918  
919  #include "dlutils.c"   /* SaveError() etc      */
920 EOPATCH
921             }
922         }
923
924         edit_file('hints/darwin.sh', sub {
925                       my $code = shift;
926                       # Part of commit 8f4f83badb7d1ba9, which mostly undoes
927                       # commit 0511a818910f476c.
928                       $code =~ s/^cppflags='-traditional-cpp';$/cppflags="\${cppflags} -no-cpp-precomp"/m;
929                       # commit 14c11978e9b52e08/803bb6cc74d36a3f
930                       # Without this, code in libperl.bundle links against op.o
931                       # in preference to opmini.o on the linker command line,
932                       # and hence miniperl tries to use File::Glob instead of
933                       # csh
934                       $code =~ s/^(lddlflags=)/ldflags="\${ldflags} -flat_namespace"\n$1/m;
935                       # f556e5b971932902 also patches Makefile.SH with some
936                       # special case code to deal with useshrplib for darwin.
937                       # Given that post 5.8.0 the darwin hints default was
938                       # changed to false, and it would be very complex to splice
939                       # in that code in various versions of Makefile.SH back
940                       # to 5.002, lets just turn it off.
941                       $code =~ s/^useshrplib='true'/useshrplib='false'/m
942                           if $faking_it;
943                       return $code;
944                   });
945     }
946 } elsif ($^O eq 'netbsd') {
947     if ($major < 6) {
948         # These are part of commit 099685bc64c7dbce
949         edit_file('hints/netbsd.sh', sub {
950                       my $code = shift;
951                       my $fixed = <<'EOC';
952 case "$osvers" in
953 0.9|0.8*)
954         usedl="$undef"
955         ;;
956 *)
957         if [ -f /usr/libexec/ld.elf_so ]; then
958                 d_dlopen=$define
959                 d_dlerror=$define
960                 ccdlflags="-Wl,-E -Wl,-R${PREFIX}/lib $ccdlflags"
961                 cccdlflags="-DPIC -fPIC $cccdlflags"
962                 lddlflags="--whole-archive -shared $lddlflags"
963         elif [ "`uname -m`" = "pmax" ]; then
964 # NetBSD 1.3 and 1.3.1 on pmax shipped an `old' ld.so, which will not work.
965                 d_dlopen=$undef
966         elif [ -f /usr/libexec/ld.so ]; then
967                 d_dlopen=$define
968                 d_dlerror=$define
969                 ccdlflags="-Wl,-R${PREFIX}/lib $ccdlflags"
970 # we use -fPIC here because -fpic is *NOT* enough for some of the
971 # extensions like Tk on some netbsd platforms (the sparc is one)
972                 cccdlflags="-DPIC -fPIC $cccdlflags"
973                 lddlflags="-Bforcearchive -Bshareable $lddlflags"
974         else
975                 d_dlopen=$undef
976         fi
977         ;;
978 esac
979 EOC
980                       $code =~ s/^case "\$osvers" in\n0\.9\|0\.8.*?^esac\n/$fixed/ms;
981                       return $code;
982                   });
983         if (!extract_from_file('unixish.h',
984                                qr/defined\(NSIG\).*defined\(__NetBSD__\)/)) {
985             apply_patch(<<'EOPATCH')
986 diff --git a/unixish.h b/unixish.h
987 index 2a6cbcd..eab2de1 100644
988 --- a/unixish.h
989 +++ b/unixish.h
990 @@ -89,7 +89,7 @@
991   */
992  /* #define ALTERNATE_SHEBANG "#!" / **/
993  
994 -#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
995 +#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX) || defined(__NetBSD__)
996  # include <signal.h>
997  #endif
998  
999 EOPATCH
1000         }
1001     }
1002 } elsif ($^O eq 'openbsd') {
1003     if (!-f 'hints/openbsd.sh') {
1004         system 'git show 43051805d53a3e4c:hints/openbsd.sh > hints/openbsd.sh'
1005           and die;
1006     }
1007
1008     if ($major < 8) {
1009         my $which = extract_from_file('hints/openbsd.sh',
1010                                       qr/# from (2\.8|3\.1) onwards/,
1011                                       '');
1012         if ($which eq '') {
1013             my $was = extract_from_file('hints/openbsd.sh',
1014                                         qr/(lddlflags="(?:-Bforcearchive )?-Bshareable)/);
1015             # This is commit 154d43cbcf57271c and parts of 5c75dbfa77b0949c
1016             # and 29b5585702e5e025
1017             apply_patch(sprintf <<'EOPATCH', $was);
1018 diff --git a/hints/openbsd.sh b/hints/openbsd.sh
1019 index a7d8bf2..5b79709 100644
1020 --- a/hints/openbsd.sh
1021 +++ b/hints/openbsd.sh
1022 @@ -37,7 +37,25 @@ OpenBSD.alpha|OpenBSD.mips|OpenBSD.powerpc|OpenBSD.vax)
1023         # we use -fPIC here because -fpic is *NOT* enough for some of the
1024         # extensions like Tk on some OpenBSD platforms (ie: sparc)
1025         cccdlflags="-DPIC -fPIC $cccdlflags"
1026 -       %s $lddlflags"
1027 +       case "$osvers" in
1028 +       [01].*|2.[0-7]|2.[0-7].*)
1029 +               lddlflags="-Bshareable $lddlflags"
1030 +               ;;
1031 +       2.[8-9]|3.0)
1032 +               ld=${cc:-cc}
1033 +               lddlflags="-shared -fPIC $lddlflags"
1034 +               ;;
1035 +       *) # from 3.1 onwards
1036 +               ld=${cc:-cc}
1037 +               lddlflags="-shared -fPIC $lddlflags"
1038 +               libswanted=`echo $libswanted | sed 's/ dl / /'`
1039 +               ;;
1040 +       esac
1041 +
1042 +       # We need to force ld to export symbols on ELF platforms.
1043 +       # Without this, dlopen() is crippled.
1044 +       ELF=`${cc:-cc} -dM -E - </dev/null | grep __ELF__`
1045 +       test -n "$ELF" && ldflags="-Wl,-E $ldflags"
1046         ;;
1047  esac
1048  
1049 EOPATCH
1050         } elsif ($which eq '2.8') {
1051             # This is parts of 5c75dbfa77b0949c and 29b5585702e5e025, and
1052             # possibly eb9cd59d45ad2908
1053             my $was = extract_from_file('hints/openbsd.sh',
1054                                         qr/lddlflags="(-shared(?: -fPIC)?) \$lddlflags"/);
1055
1056             apply_patch(sprintf <<'EOPATCH', $was);
1057 --- a/hints/openbsd.sh  2011-10-21 17:25:20.000000000 +0200
1058 +++ b/hints/openbsd.sh  2011-10-21 16:58:43.000000000 +0200
1059 @@ -44,11 +44,21 @@
1060         [01].*|2.[0-7]|2.[0-7].*)
1061                 lddlflags="-Bshareable $lddlflags"
1062                 ;;
1063 -       *) # from 2.8 onwards
1064 +       2.[8-9]|3.0)
1065                 ld=${cc:-cc}
1066 -               lddlflags="%s $lddlflags"
1067 +               lddlflags="-shared -fPIC $lddlflags"
1068 +               ;;
1069 +       *) # from 3.1 onwards
1070 +               ld=${cc:-cc}
1071 +               lddlflags="-shared -fPIC $lddlflags"
1072 +               libswanted=`echo $libswanted | sed 's/ dl / /'`
1073                 ;;
1074         esac
1075 +
1076 +       # We need to force ld to export symbols on ELF platforms.
1077 +       # Without this, dlopen() is crippled.
1078 +       ELF=`${cc:-cc} -dM -E - </dev/null | grep __ELF__`
1079 +       test -n "$ELF" && ldflags="-Wl,-E $ldflags"
1080         ;;
1081  esac
1082  
1083 EOPATCH
1084         } elsif ($which eq '3.1'
1085                 && !extract_from_file('hints/openbsd.sh',
1086                                      qr/We need to force ld to export symbols on ELF platforms/)) {
1087             # This is part of 29b5585702e5e025
1088             apply_patch(<<'EOPATCH');
1089 diff --git a/hints/openbsd.sh b/hints/openbsd.sh
1090 index c6b6bc9..4839d04 100644
1091 --- a/hints/openbsd.sh
1092 +++ b/hints/openbsd.sh
1093 @@ -54,6 +54,11 @@ alpha-2.[0-8]|mips-*|vax-*|powerpc-2.[0-7]|m88k-*)
1094                 libswanted=`echo $libswanted | sed 's/ dl / /'`
1095                 ;;
1096         esac
1097 +
1098 +       # We need to force ld to export symbols on ELF platforms.
1099 +       # Without this, dlopen() is crippled.
1100 +       ELF=`${cc:-cc} -dM -E - </dev/null | grep __ELF__`
1101 +       test -n "$ELF" && ldflags="-Wl,-E $ldflags"
1102         ;;
1103  esac
1104  
1105 EOPATCH
1106         }
1107     }
1108     if ($major < 4) {
1109         my $bad;
1110         # Need changes from commit a6e633defa583ad5.
1111         # Commits c07a80fdfe3926b5 and f82b3d4130164d5f changed the same part
1112         # of perl.h
1113
1114         if (extract_from_file('perl.h',
1115                               qr/^#ifdef HAS_GETPGRP2$/)) {
1116             $bad = <<'EOBAD';
1117 ***************
1118 *** 57,71 ****
1119   #define TAINT_PROPER(s)       if (tainting) taint_proper(no_security, s)
1120   #define TAINT_ENV()   if (tainting) taint_env()
1121   
1122 ! #ifdef HAS_GETPGRP2
1123 ! #   ifndef HAS_GETPGRP
1124 ! #     define HAS_GETPGRP
1125 ! #   endif
1126 ! #endif
1127
1128 ! #ifdef HAS_SETPGRP2
1129 ! #   ifndef HAS_SETPGRP
1130 ! #     define HAS_SETPGRP
1131 ! #   endif
1132   #endif
1133   
1134 EOBAD
1135         } elsif (extract_from_file('perl.h',
1136                                    qr/Gack, you have one but not both of getpgrp2/)) {
1137             $bad = <<'EOBAD';
1138 ***************
1139 *** 56,76 ****
1140   #define TAINT_PROPER(s)       if (tainting) taint_proper(no_security, s)
1141   #define TAINT_ENV()   if (tainting) taint_env()
1142   
1143 ! #if defined(HAS_GETPGRP2) && defined(HAS_SETPGRP2)
1144 ! #   define getpgrp getpgrp2
1145 ! #   define setpgrp setpgrp2
1146 ! #   ifndef HAS_GETPGRP
1147 ! #     define HAS_GETPGRP
1148 ! #   endif
1149 ! #   ifndef HAS_SETPGRP
1150 ! #     define HAS_SETPGRP
1151 ! #   endif
1152 ! #   ifndef USE_BSDPGRP
1153 ! #     define USE_BSDPGRP
1154 ! #   endif
1155 ! #else
1156 ! #   if defined(HAS_GETPGRP2) || defined(HAS_SETPGRP2)
1157 !       #include "Gack, you have one but not both of getpgrp2() and setpgrp2()."
1158 ! #   endif
1159   #endif
1160   
1161 EOBAD
1162         } elsif (extract_from_file('perl.h',
1163                                    qr/^#ifdef USE_BSDPGRP$/)) {
1164             $bad = <<'EOBAD'
1165 ***************
1166 *** 91,116 ****
1167   #define TAINT_PROPER(s)       if (tainting) taint_proper(no_security, s)
1168   #define TAINT_ENV()   if (tainting) taint_env()
1169   
1170 ! #ifdef USE_BSDPGRP
1171 ! #   ifdef HAS_GETPGRP
1172 ! #       define BSD_GETPGRP(pid) getpgrp((pid))
1173 ! #   endif
1174 ! #   ifdef HAS_SETPGRP
1175 ! #       define BSD_SETPGRP(pid, pgrp) setpgrp((pid), (pgrp))
1176 ! #   endif
1177 ! #else
1178 ! #   ifdef HAS_GETPGRP2
1179 ! #       define BSD_GETPGRP(pid) getpgrp2((pid))
1180 ! #       ifndef HAS_GETPGRP
1181 ! #         define HAS_GETPGRP
1182 ! #     endif
1183 ! #   endif
1184 ! #   ifdef HAS_SETPGRP2
1185 ! #       define BSD_SETPGRP(pid, pgrp) setpgrp2((pid), (pgrp))
1186 ! #       ifndef HAS_SETPGRP
1187 ! #         define HAS_SETPGRP
1188 ! #     endif
1189 ! #   endif
1190   #endif
1191   
1192   #ifndef _TYPES_               /* If types.h defines this it's easy. */
1193 EOBAD
1194         }
1195         if ($bad) {
1196             apply_patch(<<"EOPATCH");
1197 *** a/perl.h    2011-10-21 09:46:12.000000000 +0200
1198 --- b/perl.h    2011-10-21 09:46:12.000000000 +0200
1199 $bad--- 91,144 ----
1200   #define TAINT_PROPER(s)       if (tainting) taint_proper(no_security, s)
1201   #define TAINT_ENV()   if (tainting) taint_env()
1202   
1203 ! /* XXX All process group stuff is handled in pp_sys.c.  Should these 
1204 !    defines move there?  If so, I could simplify this a lot. --AD  9/96.
1205 ! */
1206 ! /* Process group stuff changed from traditional BSD to POSIX.
1207 !    perlfunc.pod documents the traditional BSD-style syntax, so we'll
1208 !    try to preserve that, if possible.
1209 ! */
1210 ! #ifdef HAS_SETPGID
1211 ! #  define BSD_SETPGRP(pid, pgrp)      setpgid((pid), (pgrp))
1212 ! #else
1213 ! #  if defined(HAS_SETPGRP) && defined(USE_BSD_SETPGRP)
1214 ! #    define BSD_SETPGRP(pid, pgrp)    setpgrp((pid), (pgrp))
1215 ! #  else
1216 ! #    ifdef HAS_SETPGRP2  /* DG/UX */
1217 ! #      define BSD_SETPGRP(pid, pgrp)  setpgrp2((pid), (pgrp))
1218 ! #    endif
1219 ! #  endif
1220 ! #endif
1221 ! #if defined(BSD_SETPGRP) && !defined(HAS_SETPGRP)
1222 ! #  define HAS_SETPGRP  /* Well, effectively it does . . . */
1223 ! #endif
1224
1225 ! /* getpgid isn't POSIX, but at least Solaris and Linux have it, and it makes
1226 !     our life easier :-) so we'll try it.
1227 ! */
1228 ! #ifdef HAS_GETPGID
1229 ! #  define BSD_GETPGRP(pid)            getpgid((pid))
1230 ! #else
1231 ! #  if defined(HAS_GETPGRP) && defined(USE_BSD_GETPGRP)
1232 ! #    define BSD_GETPGRP(pid)          getpgrp((pid))
1233 ! #  else
1234 ! #    ifdef HAS_GETPGRP2  /* DG/UX */
1235 ! #      define BSD_GETPGRP(pid)                getpgrp2((pid))
1236 ! #    endif
1237 ! #  endif
1238 ! #endif
1239 ! #if defined(BSD_GETPGRP) && !defined(HAS_GETPGRP)
1240 ! #  define HAS_GETPGRP  /* Well, effectively it does . . . */
1241 ! #endif
1242
1243 ! /* These are not exact synonyms, since setpgrp() and getpgrp() may 
1244 !    have different behaviors, but perl.h used to define USE_BSDPGRP
1245 !    (prior to 5.003_05) so some extension might depend on it.
1246 ! */
1247 ! #if defined(USE_BSD_SETPGRP) || defined(USE_BSD_GETPGRP)
1248 ! #  ifndef USE_BSDPGRP
1249 ! #    define USE_BSDPGRP
1250 ! #  endif
1251   #endif
1252   
1253   #ifndef _TYPES_               /* If types.h defines this it's easy. */
1254 EOPATCH
1255         }
1256     }
1257     if ($major < 3 && !extract_from_file('pp_sys.c', qr/BSD_GETPGRP/)) {
1258         # Part of commit c3293030fd1b7489
1259         apply_patch(<<'EOPATCH');
1260 diff --git a/pp_sys.c b/pp_sys.c
1261 index 4608a2a..f0c9d1d 100644
1262 --- a/pp_sys.c
1263 +++ b/pp_sys.c
1264 @@ -2903,8 +2903,8 @@ PP(pp_getpgrp)
1265         pid = 0;
1266      else
1267         pid = SvIVx(POPs);
1268 -#ifdef USE_BSDPGRP
1269 -    value = (I32)getpgrp(pid);
1270 +#ifdef BSD_GETPGRP
1271 +    value = (I32)BSD_GETPGRP(pid);
1272  #else
1273      if (pid != 0)
1274         DIE("POSIX getpgrp can't take an argument");
1275 @@ -2933,8 +2933,8 @@ PP(pp_setpgrp)
1276      }
1277  
1278      TAINT_PROPER("setpgrp");
1279 -#ifdef USE_BSDPGRP
1280 -    SETi( setpgrp(pid, pgrp) >= 0 );
1281 +#ifdef BSD_SETPGRP
1282 +    SETi( BSD_SETPGRP(pid, pgrp) >= 0 );
1283  #else
1284      if ((pgrp != 0) || (pid != 0)) {
1285         DIE("POSIX setpgrp can't take an argument");
1286 EOPATCH
1287     }
1288 }
1289
1290 if ($major < 10) {
1291     if (!extract_from_file('ext/DB_File/DB_File.xs',
1292                            qr!^#else /\* Berkeley DB Version > 2 \*/$!)) {
1293         # This DB_File.xs is really too old to patch up.
1294         # Skip DB_File, unless we're invoked with an explicit -Unoextensions
1295         if (!exists $defines{noextensions}) {
1296             $defines{noextensions} = 'DB_File';
1297         } elsif (defined $defines{noextensions}) {
1298             $defines{noextensions} .= ' DB_File';
1299         }
1300     } elsif (!extract_from_file('ext/DB_File/DB_File.xs',
1301                                 qr/^#ifdef AT_LEAST_DB_4_1$/)) {
1302         # This line is changed by commit 3245f0580c13b3ab
1303         my $line = extract_from_file('ext/DB_File/DB_File.xs',
1304                                      qr/^(        status = \(?RETVAL->dbp->open\)?\(RETVAL->dbp, name, NULL, RETVAL->type, $)/);
1305         apply_patch(<<"EOPATCH");
1306 diff --git a/ext/DB_File/DB_File.xs b/ext/DB_File/DB_File.xs
1307 index 489ba96..fba8ded 100644
1308 --- a/ext/DB_File/DB_File.xs
1309 +++ b/ext/DB_File/DB_File.xs
1310 \@\@ -183,4 +187,8 \@\@
1311  #endif
1312  
1313 +#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
1314 +#    define AT_LEAST_DB_4_1
1315 +#endif
1316 +
1317  /* map version 2 features & constants onto their version 1 equivalent */
1318  
1319 \@\@ -1334,7 +1419,12 \@\@ SV *   sv ;
1320  #endif
1321  
1322 +#ifdef AT_LEAST_DB_4_1
1323 +        status = (RETVAL->dbp->open)(RETVAL->dbp, NULL, name, NULL, RETVAL->type, 
1324 +                               Flags, mode) ; 
1325 +#else
1326  $line
1327                                 Flags, mode) ; 
1328 +#endif
1329         /* printf("open returned %d %s\\n", status, db_strerror(status)) ; */
1330  
1331 EOPATCH
1332     }
1333 }
1334
1335 # if Encode is not needed for the test, you can speed up the bisect by
1336 # excluding it from the runs with -Dnoextensions=Encode
1337 # ccache is an easy win. Remove it if it causes problems.
1338 # Commit 1cfa4ec74d4933da adds ignore_versioned_solibs to Configure, and sets it
1339 # to true in hints/linux.sh
1340 # On dromedary, from that point on, Configure (by default) fails to find any
1341 # libraries, because it scans /usr/local/lib /lib /usr/lib, which only contain
1342 # versioned libraries. Without -lm, the build fails.
1343 # Telling /usr/local/lib64 /lib64 /usr/lib64 works from that commit onwards,
1344 # until commit faae14e6e968e1c0 adds it to the hints.
1345 # However, prior to 1cfa4ec74d4933da telling Configure the truth doesn't work,
1346 # because it will spot versioned libraries, pass them to the compiler, and then
1347 # bail out pretty early on. Configure won't let us override libswanted, but it
1348 # will let us override the entire libs list.
1349
1350 unless (extract_from_file('Configure', 'ignore_versioned_solibs')) {
1351     # Before 1cfa4ec74d4933da, so force the libs list.
1352
1353     my @libs;
1354     # This is the current libswanted list from Configure, less the libs removed
1355     # by current hints/linux.sh
1356     foreach my $lib (qw(sfio socket inet nsl nm ndbm gdbm dbm db malloc dl dld
1357                         ld sun m crypt sec util c cposix posix ucb BSD)) {
1358         foreach my $dir (@paths) {
1359             next unless -f "$dir/lib$lib.so";
1360             push @libs, "-l$lib";
1361             last;
1362         }
1363     }
1364     $defines{libs} = \@libs unless exists $defines{libs};
1365 }
1366
1367 $defines{usenm} = undef
1368     if $major < 2 && !exists $defines{usenm};
1369
1370 my (@missing, @created_dirs);
1371
1372 if ($options{'force-manifest'}) {
1373     open my $fh, '<', 'MANIFEST'
1374         or die "Could not open MANIFEST: $!";
1375     while (<$fh>) {
1376         next unless /^(\S+)/;
1377         # -d is special case needed (at least) between 27332437a2ed1941 and
1378         # bf3d9ec563d25054^ inclusive, as manifest contains ext/Thread/Thread
1379         push @missing, $1
1380             unless -f $1 || -d $1;
1381     }
1382     close $fh or die "Can't close MANIFEST: $!";
1383
1384     foreach my $pathname (@missing) {
1385         my @parts = split '/', $pathname;
1386         my $leaf = pop @parts;
1387         my $path = '.';
1388         while (@parts) {
1389             $path .= '/' . shift @parts;
1390             next if -d $path;
1391             mkdir $path, 0700 or die "Can't create $path: $!";
1392             unshift @created_dirs, $path;
1393         }
1394         open $fh, '>', $pathname or die "Can't open $pathname: $!";
1395         close $fh or die "Can't close $pathname: $!";
1396         chmod 0, $pathname or die "Can't chmod 0 $pathname: $!";
1397     }
1398 }
1399
1400 my @ARGS = '-dEs';
1401 foreach my $key (sort keys %defines) {
1402     my $val = $defines{$key};
1403     if (ref $val) {
1404         push @ARGS, "-D$key=@$val";
1405     } elsif (!defined $val) {
1406         push @ARGS, "-U$key";
1407     } elsif (!length $val) {
1408         push @ARGS, "-D$key";
1409     } else {
1410         $val = "" if $val eq "\0";
1411         push @ARGS, "-D$key=$val";
1412     }
1413 }
1414 push @ARGS, map {"-A$_"} @{$options{A}};
1415
1416 # </dev/null because it seems that some earlier versions of Configure can
1417 # call commands in a way that now has them reading from stdin (and hanging)
1418 my $pid = fork;
1419 die "Can't fork: $!" unless defined $pid;
1420 if (!$pid) {
1421     open STDIN, '<', '/dev/null';
1422     # If a file in MANIFEST is missing, Configure asks if you want to
1423     # continue (the default being 'n'). With stdin closed or /dev/null,
1424     # it exits immediately and the check for config.sh below will skip.
1425     exec './Configure', @ARGS;
1426     die "Failed to start Configure: $!";
1427 }
1428 waitpid $pid, 0
1429     or die "wait for Configure, pid $pid failed: $!";
1430
1431 # Emulate noextensions if Configure doesn't support it.
1432 if (-f 'config.sh') {
1433     if ($major < 10 && $defines{noextensions}) {
1434         edit_file('config.sh', sub {
1435                       my @lines = split /\n/, shift;
1436                       my @ext = split /\s+/, $defines{noextensions};
1437                       foreach (@lines) {
1438                           next unless /^extensions=/ || /^dynamic_ext/;
1439                           foreach my $ext (@ext) {
1440                               s/\b$ext( )?\b/$1/;
1441                           }
1442                       }
1443                       return join "\n", @lines;
1444                   });
1445     }
1446     if ($major < 4 && !extract_from_file('config.sh', qr/^trnl=/)) {
1447         # This seems to be necessary to avoid makedepend becoming confused,
1448         # and hanging on stdin. Seems that the code after
1449         # make shlist || ...here... is never run.
1450         edit_file('makedepend.SH', sub {
1451                       my $code = shift;
1452                       $code =~ s/^trnl='\$trnl'$/trnl='\\n'/m;
1453                       return $code;
1454                   });
1455     }
1456
1457     system './Configure -S </dev/null' and die;
1458 }
1459
1460 if ($target =~ /config\.s?h/) {
1461     match_and_exit($target) if $match && -f $target;
1462     report_and_exit(!-f $target, 'could build', 'could not build', $target)
1463         if $options{'test-build'};
1464
1465     my $ret = system @ARGV;
1466     report_and_exit($ret, 'zero exit from', 'non-zero exit from', "@ARGV");
1467 } elsif (!-f 'config.sh') {
1468     # Skip if something went wrong with Configure
1469
1470     skip('could not build config.sh');
1471 }
1472
1473 # This is probably way too paranoid:
1474 if (@missing) {
1475     my @errors;
1476     require Fcntl;
1477     foreach my $file (@missing) {
1478         my (undef, undef, $mode, undef, undef, undef, undef, $size)
1479             = stat $file;
1480         if (!defined $mode) {
1481             push @errors, "Added file $file has been deleted by Configure";
1482             next;
1483         }
1484         if (Fcntl::S_IMODE($mode) != 0) {
1485             push @errors,
1486                 sprintf 'Added file %s had mode changed by Configure to %03o',
1487                     $file, $mode;
1488         }
1489         if ($size != 0) {
1490             push @errors,
1491                 "Added file $file had sized changed by Configure to $size";
1492         }
1493         unlink $file or die "Can't unlink $file: $!";
1494     }
1495     foreach my $dir (@created_dirs) {
1496         rmdir $dir or die "Can't rmdir $dir: $!";
1497     }
1498     skip("@errors")
1499         if @errors;
1500 }
1501
1502 # Correct makefile for newer GNU gcc
1503 # Only really needed if you comment out the use of blead's makedepend.SH
1504 {
1505     local $^I = "";
1506     local @ARGV = qw(makefile x2p/makefile);
1507     while (<>) {
1508         print unless /<(?:built-in|command|stdin)/;
1509     }
1510 }
1511
1512 if ($major == 2 && extract_from_file('perl.c', qr/^     fclose\(e_fp\);$/)) {
1513     # need to patch perl.c to avoid calling fclose() twice on e_fp when using -e
1514     # This diff is part of commit ab821d7fdc14a438. The second close was
1515     # introduced with perl-5.002, commit a5f75d667838e8e7
1516     # Might want a6c477ed8d4864e6 too, for the corresponding change to pp_ctl.c
1517     # (likely without this, eval will have "fun")
1518     apply_patch(<<'EOPATCH');
1519 diff --git a/perl.c b/perl.c
1520 index 03c4d48..3c814a2 100644
1521 --- a/perl.c
1522 +++ b/perl.c
1523 @@ -252,6 +252,7 @@ setuid perl scripts securely.\n");
1524  #ifndef VMS  /* VMS doesn't have environ array */
1525      origenviron = environ;
1526  #endif
1527 +    e_tmpname = Nullch;
1528  
1529      if (do_undump) {
1530  
1531 @@ -405,6 +406,7 @@ setuid perl scripts securely.\n");
1532      if (e_fp) {
1533         if (Fflush(e_fp) || ferror(e_fp) || fclose(e_fp))
1534             croak("Can't write to temp file for -e: %s", Strerror(errno));
1535 +       e_fp = Nullfp;
1536         argc++,argv--;
1537         scriptname = e_tmpname;
1538      }
1539 @@ -470,10 +472,10 @@ setuid perl scripts securely.\n");
1540      curcop->cop_line = 0;
1541      curstash = defstash;
1542      preprocess = FALSE;
1543 -    if (e_fp) {
1544 -       fclose(e_fp);
1545 -       e_fp = Nullfp;
1546 +    if (e_tmpname) {
1547         (void)UNLINK(e_tmpname);
1548 +       Safefree(e_tmpname);
1549 +       e_tmpname = Nullch;
1550      }
1551  
1552      /* now that script is parsed, we can modify record separator */
1553 @@ -1369,7 +1371,7 @@ SV *sv;
1554         scriptname = xfound;
1555      }
1556  
1557 -    origfilename = savepv(e_fp ? "-e" : scriptname);
1558 +    origfilename = savepv(e_tmpname ? "-e" : scriptname);
1559      curcop->cop_filegv = gv_fetchfile(origfilename);
1560      if (strEQ(origfilename,"-"))
1561         scriptname = "";
1562
1563 EOPATCH
1564 }
1565
1566 if ($major < 8 && $^O eq 'openbsd'
1567     && !extract_from_file('perl.h', qr/include <unistd\.h>/)) {
1568     # This is part of commit 3f270f98f9305540, applied at a slightly different
1569     # location in perl.h, where the context is stable back to 5.000
1570     apply_patch(<<'EOPATCH');
1571 diff --git a/perl.h b/perl.h
1572 index 9418b52..b8b1a7c 100644
1573 --- a/perl.h
1574 +++ b/perl.h
1575 @@ -496,6 +496,10 @@ register struct op *Perl_op asm(stringify(OP_IN_REGISTER));
1576  #   include <sys/param.h>
1577  #endif
1578  
1579 +/* If this causes problems, set i_unistd=undef in the hint file.  */
1580 +#ifdef I_UNISTD
1581 +#   include <unistd.h>
1582 +#endif
1583  
1584  /* Use all the "standard" definitions? */
1585  #if defined(STANDARD_C) && defined(I_STDLIB)
1586 EOPATCH
1587 }
1588
1589 if ($major == 4 && extract_from_file('scope.c', qr/\(SV\*\)SSPOPINT/)) {
1590     # [PATCH] 5.004_04 +MAINT_TRIAL_1 broken when sizeof(int) != sizeof(void)
1591     # Fixes a bug introduced in 161b7d1635bc830b
1592     system 'git show 9002cb76ec83ef7f | patch -p1'
1593         and die;
1594 }
1595
1596 if ($major == 4 && extract_from_file('av.c', qr/AvARRAY\(av\) = 0;/)) {
1597     # Fixes a bug introduced in 1393e20655efb4bc
1598     system 'git show e1c148c28bf3335b av.c | patch -p1'
1599         and die;
1600 }
1601
1602 if ($major == 4 && $^O eq 'linux') {
1603     # Whilst this is fixed properly in f0784f6a4c3e45e1 which provides the
1604     # Configure probe, it's easier to back out the problematic changes made in
1605     # these previous commits:
1606     if (extract_from_file('doio.c',
1607                           qr!^/\* XXX REALLY need metaconfig test \*/$!)) {
1608         system 'git show -R 4682965a1447ea44 doio.c | patch -p1'
1609             and die;
1610     }
1611     if (my $token = extract_from_file('doio.c',
1612                                       qr!^#if (defined\(__sun(?:__)?\)) && defined\(__svr4__\) /\* XXX Need metaconfig test \*/$!)) {
1613         my $patch = `git show -R 9b599b2a63d2324d doio.c`;
1614         $patch =~ s/defined\(__sun__\)/$token/g;
1615         apply_patch($patch);
1616     }
1617     if (extract_from_file('doio.c',
1618                           qr!^/\* linux \(and Solaris2\?\) uses :$!)) {
1619         system 'git show -R 8490252049bf42d3 doio.c | patch -p1'
1620             and die;
1621     }
1622     if (extract_from_file('doio.c',
1623                           qr/^      unsemds.buf = &semds;$/)) {
1624         system 'git show -R 8e591e46b4c6543e | patch -p1'
1625             and die;
1626     }
1627     if (extract_from_file('doio.c',
1628                           qr!^#ifdef __linux__  /\* XXX Need metaconfig test \*/$!)) {
1629         # Part of commit 3e3baf6d63945cb6
1630         apply_patch(<<'EOPATCH');
1631 diff --git b/doio.c a/doio.c
1632 index 62b7de9..0d57425 100644
1633 --- b/doio.c
1634 +++ a/doio.c
1635 @@ -1333,9 +1331,6 @@ SV **sp;
1636      char *a;
1637      I32 id, n, cmd, infosize, getinfo;
1638      I32 ret = -1;
1639 -#ifdef __linux__       /* XXX Need metaconfig test */
1640 -    union semun unsemds;
1641 -#endif
1642  
1643      id = SvIVx(*++mark);
1644      n = (optype == OP_SEMCTL) ? SvIVx(*++mark) : 0;
1645 @@ -1364,29 +1359,11 @@ SV **sp;
1646             infosize = sizeof(struct semid_ds);
1647         else if (cmd == GETALL || cmd == SETALL)
1648         {
1649 -#ifdef __linux__       /* XXX Need metaconfig test */
1650 -/* linux uses :
1651 -   int semctl (int semid, int semnun, int cmd, union semun arg)
1652 -
1653 -       union semun {
1654 -            int val;
1655 -            struct semid_ds *buf;
1656 -            ushort *array;
1657 -       };
1658 -*/
1659 -            union semun semds;
1660 -           if (semctl(id, 0, IPC_STAT, semds) == -1)
1661 -#else
1662             struct semid_ds semds;
1663             if (semctl(id, 0, IPC_STAT, &semds) == -1)
1664 -#endif
1665                 return -1;
1666             getinfo = (cmd == GETALL);
1667 -#ifdef __linux__       /* XXX Need metaconfig test */
1668 -           infosize = semds.buf->sem_nsems * sizeof(short);
1669 -#else
1670             infosize = semds.sem_nsems * sizeof(short);
1671 -#endif
1672                 /* "short" is technically wrong but much more portable
1673                    than guessing about u_?short(_t)? */
1674         }
1675 @@ -1429,12 +1406,7 @@ SV **sp;
1676  #endif
1677  #ifdef HAS_SEM
1678      case OP_SEMCTL:
1679 -#ifdef __linux__       /* XXX Need metaconfig test */
1680 -        unsemds.buf = (struct semid_ds *)a;
1681 -       ret = semctl(id, n, cmd, unsemds);
1682 -#else
1683         ret = semctl(id, n, cmd, (struct semid_ds *)a);
1684 -#endif
1685         break;
1686  #endif
1687  #ifdef HAS_SHM
1688 EOPATCH
1689     }
1690     # Incorrect prototype added as part of 8ac853655d9b7447, fixed as part of
1691     # commit dc45a647708b6c54, with at least one intermediate modification.
1692     # Correct prototype for gethostbyaddr has socklen_t second. Linux has
1693     # uint32_t first for getnetbyaddr.
1694     # Easiest just to remove, instead of attempting more complex patching.
1695     # Something similar may be needed on other platforms.
1696     edit_file('pp_sys.c', sub {
1697                   my $code = shift;
1698                   $code =~ s/^    struct hostent \*(?:PerlSock_)?gethostbyaddr\([^)]+\);$//m;
1699                   $code =~ s/^    struct netent \*getnetbyaddr\([^)]+\);$//m;
1700                   return $code;
1701               });
1702 }
1703
1704 if ($major < 10 and -f 'ext/IPC/SysV/SysV.xs') {
1705     edit_file('ext/IPC/SysV/SysV.xs', sub {
1706                   my $xs = shift;
1707                   my $fixed = <<'EOFIX';
1708
1709 #include <sys/types.h>
1710 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
1711 #ifndef HAS_SEM
1712 #   include <sys/ipc.h>
1713 #endif
1714 #   ifdef HAS_MSG
1715 #       include <sys/msg.h>
1716 #   endif
1717 #   ifdef HAS_SHM
1718 #       if defined(PERL_SCO) || defined(PERL_ISC)
1719 #           include <sys/sysmacros.h>   /* SHMLBA */
1720 #       endif
1721 #      include <sys/shm.h>
1722 #      ifndef HAS_SHMAT_PROTOTYPE
1723            extern Shmat_t shmat (int, char *, int);
1724 #      endif
1725 #      if defined(HAS_SYSCONF) && defined(_SC_PAGESIZE)
1726 #          undef  SHMLBA /* not static: determined at boot time */
1727 #          define SHMLBA sysconf(_SC_PAGESIZE)
1728 #      elif defined(HAS_GETPAGESIZE)
1729 #          undef  SHMLBA /* not static: determined at boot time */
1730 #          define SHMLBA getpagesize()
1731 #      endif
1732 #   endif
1733 #endif
1734 EOFIX
1735                   $xs =~ s!
1736 #include <sys/types\.h>
1737 .*
1738 (#ifdef newCONSTSUB|/\* Required)!$fixed$1!ms;
1739                   return $xs;
1740               });
1741 }
1742
1743 if (-f 'ext/POSIX/Makefile.PL'
1744     && extract_from_file('ext/POSIX/Makefile.PL',
1745                          qr/Explicitly avoid including/)) {
1746     # commit 6695a346c41138df, which effectively reverts 170888cff5e2ffb7
1747
1748     # PERL5LIB is populated by make_ext.pl with paths to the modules we need
1749     # to run, don't override this with "../../lib" since that may not have
1750     # been populated yet in a parallel build.
1751     apply_patch(<<'EOPATCH');
1752 diff --git a/ext/POSIX/Makefile.PL b/ext/POSIX/Makefile.PL
1753 index 392b6fb..9e6d091 100644
1754 --- a/ext/POSIX/Makefile.PL
1755 +++ b/ext/POSIX/Makefile.PL
1756 @@ -1,7 +1,3 @@
1757 -# Explicitly avoid including '.' in @INC; autoloader gets confused since it
1758 -# can find POSIX.pm, but can't find autosplit.ix.
1759 -BEGIN { @INC = '../../lib';}
1760 -#
1761  use ExtUtils::MakeMaker;
1762  use ExtUtils::Constant 0.11 'WriteConstants';
1763  use Config;
1764 EOPATCH
1765 }
1766
1767 # Parallel build for miniperl is safe
1768 system "make $j miniperl </dev/null";
1769
1770 my $expected = $target =~ /^test/ ? 't/perl'
1771     : $target eq 'Fcntl' ? "lib/auto/Fcntl/Fcntl.$Config{so}"
1772     : $target;
1773 my $real_target = $target eq 'Fcntl' ? $expected : $target;
1774
1775 if ($target ne 'miniperl') {
1776     # Nearly all parallel build issues fixed by 5.10.0. Untrustworthy before that.
1777     $j = '' if $major < 10;
1778
1779     if ($real_target eq 'test_prep') {
1780         if ($major < 8) {
1781             # test-prep was added in 5.004_01, 3e3baf6d63945cb6.
1782             # renamed to test_prep in 2001 in 5fe84fd29acaf55c.
1783             # earlier than that, just make test. It will be fast enough.
1784             $real_target = extract_from_file('Makefile.SH',
1785                                              qr/^(test[-_]prep):/,
1786                                              'test');
1787         }
1788     }
1789
1790     system "make $j $real_target </dev/null";
1791 }
1792
1793 my $missing_target = $expected =~ /perl$/ ? !-x $expected : !-r $expected;
1794
1795 if ($options{'test-build'}) {
1796     report_and_exit($missing_target, 'could build', 'could not build',
1797                     $real_target);
1798 } elsif ($missing_target) {
1799     skip("could not build $real_target");
1800 }
1801
1802 match_and_exit($real_target) if $match;
1803
1804 if (defined $options{'one-liner'}) {
1805     my $exe = $target =~ /^(?:perl$|test)/ ? 'perl' : 'miniperl';
1806     unshift @ARGV, "./$exe", '-Ilib', '-e', $options{'one-liner'};
1807 }
1808
1809 # This is what we came here to run:
1810
1811 if (exists $Config{ldlibpthname}) {
1812     require Cwd;
1813     my $varname = $Config{ldlibpthname};
1814     my $cwd = Cwd::getcwd();
1815     if (defined $ENV{$varname}) {
1816         $ENV{$varname} = $cwd . $Config{path_sep} . $ENV{$varname};
1817     } else {
1818         $ENV{$varname} = $cwd;
1819     }
1820 }
1821
1822 my $ret = system @ARGV;
1823
1824 report_and_exit($ret, 'zero exit from', 'non-zero exit from', "@ARGV");
1825
1826 # Local variables:
1827 # cperl-indent-level: 4
1828 # indent-tabs-mode: nil
1829 # End:
1830 #
1831 # ex: set ts=8 sts=4 sw=4 et: