xref: /openbsd/gnu/usr.bin/perl/make_ext.pl (revision eac174f2)
143003dfeSmillert#!./miniperl
243003dfeSmillertuse strict;
343003dfeSmillertuse warnings;
443003dfeSmillertuse Config;
5b8851fccSafresh1use constant{IS_CROSS => defined $Config::Config{usecrosscompile} ? 1 : 0,
6b8851fccSafresh1             IS_WIN32 => $^O eq 'MSWin32',
7b8851fccSafresh1             IS_VMS   => $^O eq 'VMS',
8b8851fccSafresh1             IS_UNIX  => $^O ne 'MSWin32' && $^O ne 'VMS',
9b8851fccSafresh1};
10b39c5158Smillert
11b39c5158Smillertmy @ext_dirs = qw(cpan dist ext);
12b39c5158Smillertmy $ext_dirs_re = '(?:' . join('|', @ext_dirs) . ')';
13b39c5158Smillert
1443003dfeSmillert# This script acts as a simple interface for building extensions.
1543003dfeSmillert
1643003dfeSmillert# It's actually a cut and shut of the Unix version ext/utils/makeext and the
1743003dfeSmillert# Windows version win32/build_ext.pl hence the two invocation styles.
1843003dfeSmillert
19898184e3Ssthen# On Unix, it primarily used by the perl Makefile one extension at a time:
2043003dfeSmillert#
2143003dfeSmillert# d_dummy $(dynamic_ext): miniperl preplibrary FORCE
2243003dfeSmillert# 	@$(RUN) ./miniperl make_ext.pl --target=dynamic $@ MAKE=$(MAKE) LIBPERL_A=$(LIBPERL)
2343003dfeSmillert#
2443003dfeSmillert# On Windows or VMS,
2543003dfeSmillert# If '--static' is specified, static extensions will be built.
26b39c5158Smillert# If '--dynamic' is specified, dynamic extensions will be built.
27b39c5158Smillert# If '--nonxs' is specified, nonxs extensions will be built.
28898184e3Ssthen# If '--dynaloader' is specified, DynaLoader will be built.
2943003dfeSmillert# If '--all' is specified, all extensions will be built.
3043003dfeSmillert#
3143003dfeSmillert#    make_ext.pl "MAKE=make [-make_opts]" --dir=directory [--target=target] [--static|--dynamic|--all] +ext2 !ext1
3243003dfeSmillert#
3343003dfeSmillert# E.g.
3443003dfeSmillert#
3543003dfeSmillert#     make_ext.pl "MAKE=nmake -nologo" --dir=..\ext
3643003dfeSmillert#
3743003dfeSmillert#     make_ext.pl "MAKE=nmake -nologo" --dir=..\ext --target=clean
3843003dfeSmillert#
3943003dfeSmillert# Will skip building extensions which are marked with an '!' char.
4043003dfeSmillert# Mostly because they still not ported to specified platform.
4143003dfeSmillert#
4243003dfeSmillert# If any extensions are listed with a '+' char then only those
436fb12b70Safresh1# extensions will be built, but only if they aren't countermanded
4443003dfeSmillert# by an '!ext' and are appropriate to the type of building being done.
456fb12b70Safresh1# An extensions follows the format of Foo/Bar, which would be extension Foo::Bar
4643003dfeSmillert
4756d68f1eSafresh1# To fix dependency ordering, on *nix systems, edit Makefile.SH to create a
4856d68f1eSafresh1# rule.  That isn't sufficient for other systems; you also have to do
4956d68f1eSafresh1# something in this file.  See the code at
5056d68f1eSafresh1#       '# XXX hack for dependency # ordering'
5156d68f1eSafresh1# below.
5256d68f1eSafresh1#
5356d68f1eSafresh1# The basic logic is:
5456d68f1eSafresh1#   1) if there's a Makefile.PL in git for the module, use it. and call make
5556d68f1eSafresh1#   2) If not, auto-generate one (normally)
5656d68f1eSafresh1#   3) unless the auto-generation code figures out that the extension is
5756d68f1eSafresh1#      *really* simple, in which case don't.  This will be for pure perl
5856d68f1eSafresh1#      modules, and all that is needed to be done is to copy from the source
5956d68f1eSafresh1#      to the dest directories.
6056d68f1eSafresh1#
6143003dfeSmillert# It may be deleted in a later release of perl so try to
6243003dfeSmillert# avoid using it for other purposes.
6343003dfeSmillert
64b8851fccSafresh1my (%excl, %incl, %opts, @extspec, @pass_through, $verbose);
6543003dfeSmillert
6643003dfeSmillertforeach (@ARGV) {
6743003dfeSmillert    if (/^!(.*)$/) {
6843003dfeSmillert	$excl{$1} = 1;
6943003dfeSmillert    } elsif (/^\+(.*)$/) {
7043003dfeSmillert	$incl{$1} = 1;
71b8851fccSafresh1    } elsif (/^--verbose$/ or /^-v$/) {
72b8851fccSafresh1	$verbose = 1;
7343003dfeSmillert    } elsif (/^--([\w\-]+)$/) {
7443003dfeSmillert	$opts{$1} = 1;
7543003dfeSmillert    } elsif (/^--([\w\-]+)=(.*)$/) {
76b39c5158Smillert	push @{$opts{$1}}, $2;
7743003dfeSmillert    } elsif (/=/) {
7843003dfeSmillert	push @pass_through, $_;
7943003dfeSmillert    } elsif (length) {
8043003dfeSmillert	push @extspec, $_;
8143003dfeSmillert    }
8243003dfeSmillert}
8343003dfeSmillert
8443003dfeSmillertmy $static = $opts{static} || $opts{all};
8543003dfeSmillertmy $dynamic = $opts{dynamic} || $opts{all};
86b39c5158Smillertmy $nonxs = $opts{nonxs} || $opts{all};
87b39c5158Smillertmy $dynaloader = $opts{dynaloader} || $opts{all};
8843003dfeSmillert
8943003dfeSmillert# The Perl Makefile.SH will expand all extensions to
9043003dfeSmillert#	lib/auto/X/X.a  (or lib/auto/X/Y/Y.a if nested)
9143003dfeSmillert# A user wishing to run make_ext might use
9243003dfeSmillert#	X (or X/Y or X::Y if nested)
9343003dfeSmillert
9443003dfeSmillert# canonise into X/Y form (pname)
9543003dfeSmillert
9643003dfeSmillertforeach (@extspec) {
9743003dfeSmillert    if (s{^lib/auto/}{}) {
9843003dfeSmillert	# Remove lib/auto prefix and /*.* suffix
9943003dfeSmillert	s{/[^/]+\.[^/]+$}{};
100b39c5158Smillert    } elsif (s{^$ext_dirs_re/}{}) {
10143003dfeSmillert	# Remove ext/ prefix and /pm_to_blib suffix
10243003dfeSmillert	s{/pm_to_blib$}{};
10343003dfeSmillert	# Targets are given as files on disk, but the extension spec is still
10443003dfeSmillert	# written using /s for each ::
10543003dfeSmillert	tr!-!/!;
10643003dfeSmillert    } elsif (s{::}{\/}g) {
10743003dfeSmillert	# Convert :: to /
10843003dfeSmillert    } else {
10943003dfeSmillert	s/\..*o//;
11043003dfeSmillert    }
11143003dfeSmillert}
11243003dfeSmillert
11343003dfeSmillertmy $makecmd  = shift @pass_through; # Should be something like MAKE=make
11443003dfeSmillertunshift @pass_through, 'PERL_CORE=1';
11543003dfeSmillert
116b39c5158Smillertmy @dirs  = @{$opts{dir} || \@ext_dirs};
117b39c5158Smillertmy $target   = $opts{target}[0];
11843003dfeSmillert$target = 'all' unless defined $target;
11943003dfeSmillert
12043003dfeSmillert# Previously, $make was taken from config.sh.  However, the user might
12143003dfeSmillert# instead be running a possibly incompatible make.  This might happen if
12243003dfeSmillert# the user types "gmake" instead of a plain "make", for example.  The
12343003dfeSmillert# correct current value of MAKE will come through from the main perl
12443003dfeSmillert# makefile as MAKE=/whatever/make in $makecmd.  We'll be cautious in
12543003dfeSmillert# case third party users of this script (are there any?) don't have the
12643003dfeSmillert# MAKE=$(MAKE) argument, which was added after 5.004_03.
12743003dfeSmillertunless(defined $makecmd and $makecmd =~ /^MAKE=(.*)$/) {
12843003dfeSmillert    die "$0:  WARNING:  Please include MAKE=\$(MAKE) in \@ARGV\n";
12943003dfeSmillert}
13043003dfeSmillert
13143003dfeSmillert# This isn't going to cope with anything fancy, such as spaces inside command
13243003dfeSmillert# names, but neither did what it replaced. Once there is a use case that needs
13343003dfeSmillert# it, please supply patches. Until then, I'm sticking to KISS
13443003dfeSmillertmy @make = split ' ', $1 || $Config{make} || $ENV{MAKE};
13543003dfeSmillert
13643003dfeSmillert
13743003dfeSmillertif ($target eq '') {
13843003dfeSmillert    die "make_ext: no make target specified (eg all or clean)\n";
1396fb12b70Safresh1} elsif ($target !~ /^(?:all|clean|distclean|realclean|veryclean)$/) {
1406fb12b70Safresh1    # we are strict about what make_ext is used for because we emulate these
1416fb12b70Safresh1    # targets for simple modules:
14243003dfeSmillert    die "$0: unknown make target '$target'\n";
14343003dfeSmillert}
14443003dfeSmillert
145b39c5158Smillertif (!@extspec and !$static and !$dynamic and !$nonxs and !$dynaloader)  {
14643003dfeSmillert    die "$0: no extension specified\n";
14743003dfeSmillert}
14843003dfeSmillert
14943003dfeSmillertmy $perl;
15043003dfeSmillertmy %extra_passthrough;
15143003dfeSmillert
152b8851fccSafresh1if (IS_WIN32) {
15391f110e0Safresh1    require Cwd;
15491f110e0Safresh1    require FindExt;
15591f110e0Safresh1    my $build = Cwd::getcwd();
15643003dfeSmillert    $perl = $^X;
15743003dfeSmillert    if ($perl =~ m#^\.\.#) {
158898184e3Ssthen	my $here = $build;
159898184e3Ssthen	$here =~ s{/}{\\}g;
16043003dfeSmillert	$perl = "$here\\$perl";
16143003dfeSmillert    }
16243003dfeSmillert    (my $topdir = $perl) =~ s/\\[^\\]+$//;
16343003dfeSmillert    # miniperl needs to find perlglob and pl2bat
16443003dfeSmillert    $ENV{PATH} = "$topdir;$topdir\\win32\\bin;$ENV{PATH}";
16543003dfeSmillert    my $pl2bat = "$topdir\\win32\\bin\\pl2bat";
16643003dfeSmillert    unless (-f "$pl2bat.bat") {
167*eac174f2Safresh1	my @args = ($perl, "-I$topdir\\lib", "-I$topdir\\cpan\\ExtUtils-PL2Bat\\lib", ("$pl2bat.pl") x 2);
168b8851fccSafresh1	print "@args\n" if $verbose;
1696fb12b70Safresh1	system(@args) unless IS_CROSS;
17043003dfeSmillert    }
17143003dfeSmillert
172b8851fccSafresh1    print "In $build" if $verbose;
173b39c5158Smillert    foreach my $dir (@dirs) {
174b39c5158Smillert	chdir($dir) or die "Cannot cd to $dir: $!\n";
17591f110e0Safresh1	(my $ext = Cwd::getcwd()) =~ s{/}{\\}g;
17643003dfeSmillert	FindExt::scan_ext($ext);
17743003dfeSmillert	FindExt::set_static_extensions(split ' ', $Config{static_ext});
178b39c5158Smillert	chdir $build
179b39c5158Smillert	    or die "Couldn't chdir to '$build': $!"; # restore our start directory
180b39c5158Smillert    }
18143003dfeSmillert
18243003dfeSmillert    my @ext;
18343003dfeSmillert    push @ext, FindExt::static_ext() if $static;
184b39c5158Smillert    push @ext, FindExt::dynamic_ext() if $dynamic;
185b39c5158Smillert    push @ext, FindExt::nonxs_ext() if $nonxs;
186b39c5158Smillert    push @ext, 'DynaLoader' if $dynaloader;
18743003dfeSmillert
18843003dfeSmillert    foreach (sort @ext) {
18943003dfeSmillert	if (%incl and !exists $incl{$_}) {
190b39c5158Smillert	    #warn "Skipping extension $_, not in inclusion list\n";
19143003dfeSmillert	    next;
19243003dfeSmillert	}
19343003dfeSmillert	if (exists $excl{$_}) {
194b39c5158Smillert	    warn "Skipping extension $_, not ported to current platform";
19543003dfeSmillert	    next;
19643003dfeSmillert	}
19743003dfeSmillert	push @extspec, $_;
198b8851fccSafresh1	if($_ ne 'DynaLoader' && FindExt::is_static($_)) {
19943003dfeSmillert	    push @{$extra_passthrough{$_}}, 'LINKTYPE=static';
20043003dfeSmillert	}
20143003dfeSmillert    }
202b39c5158Smillert
203b39c5158Smillert    chdir '..'
204b39c5158Smillert	or die "Couldn't chdir to build directory: $!"; # now in the Perl build
20543003dfeSmillert}
206b8851fccSafresh1elsif (IS_VMS) {
20743003dfeSmillert    $perl = $^X;
20843003dfeSmillert    push @extspec, (split ' ', $Config{static_ext}) if $static;
20943003dfeSmillert    push @extspec, (split ' ', $Config{dynamic_ext}) if $dynamic;
210b39c5158Smillert    push @extspec, (split ' ', $Config{nonxs_ext}) if $nonxs;
211b39c5158Smillert    push @extspec, 'DynaLoader' if $dynaloader;
212b39c5158Smillert}
213b39c5158Smillert
21456d68f1eSafresh1{ # XXX hack for dependency ordering
215b39c5158Smillert    # Cwd needs to be built before Encode recurses into subdirectories.
21656d68f1eSafresh1    # Pod::Simple needs to be built before Pod::Functions, but after 'if'
2179f11ffb7Safresh1    # lib needs to be built before IO-Compress
218b39c5158Smillert    # This seems to be the simplest way to ensure this ordering:
21956d68f1eSafresh1    my (@first, @second, @other);
220b39c5158Smillert    foreach (@extspec) {
22156d68f1eSafresh1	if ($_ eq 'Cwd' || $_ eq 'if' || $_ eq 'lib') {
222b39c5158Smillert	    push @first, $_;
22356d68f1eSafresh1        }
22456d68f1eSafresh1	elsif ($_ eq 'Pod/Simple') {
22556d68f1eSafresh1	    push @second, $_;
226b39c5158Smillert	} else {
227b39c5158Smillert	    push @other, $_;
228b39c5158Smillert	}
229b39c5158Smillert    }
23056d68f1eSafresh1    @extspec = (@first, @second, @other);
231b39c5158Smillert}
232b39c5158Smillert
233b39c5158Smillertif ($Config{osname} eq 'catamount' and @extspec) {
234b39c5158Smillert    # Snowball's chance of building extensions.
235b39c5158Smillert    die "This is $Config{osname}, not building $extspec[0], sorry.\n";
23643003dfeSmillert}
237b8851fccSafresh1$ENV{PERL_CORE} = 1;
23843003dfeSmillert
23943003dfeSmillertforeach my $spec (@extspec)  {
24043003dfeSmillert    my $mname = $spec;
24143003dfeSmillert    $mname =~ s!/!::!g;
24243003dfeSmillert    my $ext_pathname;
243b39c5158Smillert
244b39c5158Smillert    # Try new style ext/Data-Dumper/ first
245b39c5158Smillert    my $copy = $spec;
246b39c5158Smillert    $copy =~ tr!/!-!;
2476fb12b70Safresh1
2486fb12b70Safresh1    # List/Util.xs lives in Scalar-List-Utils, Cwd.xs lives in PathTools
2496fb12b70Safresh1    $copy = 'Scalar-List-Utils' if $copy eq 'List-Util';
2506fb12b70Safresh1    $copy = 'PathTools'         if $copy eq 'Cwd';
2516fb12b70Safresh1
252b39c5158Smillert    foreach my $dir (@ext_dirs) {
253b39c5158Smillert	if (-d "$dir/$copy") {
254b39c5158Smillert	    $ext_pathname = "$dir/$copy";
255b39c5158Smillert	    last;
256b39c5158Smillert	}
257b39c5158Smillert    }
258b39c5158Smillert
259b39c5158Smillert    if (!defined $ext_pathname) {
26043003dfeSmillert	if (-d "ext/$spec") {
26143003dfeSmillert	    # Old style ext/Data/Dumper/
26243003dfeSmillert	    $ext_pathname = "ext/$spec";
26343003dfeSmillert	} else {
264b39c5158Smillert	    warn "Can't find extension $spec in any of @ext_dirs";
265b39c5158Smillert	    next;
26643003dfeSmillert	}
26743003dfeSmillert    }
26843003dfeSmillert
269b8851fccSafresh1    print "\tMaking $mname ($target)\n" if $verbose;
27043003dfeSmillert
2716fb12b70Safresh1    build_extension($ext_pathname, $perl, $mname, $target,
27243003dfeSmillert		    [@pass_through, @{$extra_passthrough{$spec} || []}]);
27343003dfeSmillert}
27443003dfeSmillert
27543003dfeSmillertsub build_extension {
2766fb12b70Safresh1    my ($ext_dir, $perl, $mname, $target, $pass_through) = @_;
277b39c5158Smillert
27843003dfeSmillert    unless (chdir "$ext_dir") {
27943003dfeSmillert	warn "Cannot cd to $ext_dir: $!";
28043003dfeSmillert	return;
28143003dfeSmillert    }
282b39c5158Smillert
283b39c5158Smillert    my $up = $ext_dir;
284b39c5158Smillert    $up =~ s![^/]+!..!g;
285b39c5158Smillert
286b39c5158Smillert    $perl ||= "$up/miniperl";
287b39c5158Smillert    my $return_dir = $up;
288b39c5158Smillert    my $lib_dir = "$up/lib";
289b39c5158Smillert
290b8851fccSafresh1    my ($makefile, $makefile_no_minus_f);
291b8851fccSafresh1    if (IS_VMS) {
29243003dfeSmillert	$makefile = 'descrip.mms';
29343003dfeSmillert	if ($target =~ /clean$/
29443003dfeSmillert	    && !-f $makefile
29543003dfeSmillert	    && -f "${makefile}_old") {
29643003dfeSmillert	    $makefile = "${makefile}_old";
29743003dfeSmillert	}
29843003dfeSmillert    } else {
29943003dfeSmillert	$makefile = 'Makefile';
30043003dfeSmillert    }
30143003dfeSmillert
30291f110e0Safresh1    if (-f $makefile) {
303b8851fccSafresh1	$makefile_no_minus_f = 0;
3049f11ffb7Safresh1	open my $mfh, '<', $makefile or die "Cannot open $makefile: $!";
30591f110e0Safresh1	while (<$mfh>) {
30691f110e0Safresh1	    # Plagiarised from CPAN::Distribution
30791f110e0Safresh1	    last if /MakeMaker post_initialize section/;
30891f110e0Safresh1	    next unless /^#\s+VERSION_FROM\s+=>\s+(.+)/;
30991f110e0Safresh1	    my $vmod = eval $1;
31091f110e0Safresh1	    my $oldv;
31191f110e0Safresh1	    while (<$mfh>) {
31291f110e0Safresh1		next unless /^XS_VERSION = (\S+)/;
31391f110e0Safresh1		$oldv = $1;
31491f110e0Safresh1		last;
31591f110e0Safresh1	    }
31691f110e0Safresh1	    last unless defined $oldv;
31791f110e0Safresh1	    require ExtUtils::MM_Unix;
31891f110e0Safresh1	    defined (my $newv = parse_version MM $vmod) or last;
3199f11ffb7Safresh1	    if (version->parse($newv) ne $oldv) {
3206fb12b70Safresh1		close $mfh or die "close $makefile: $!";
3216fb12b70Safresh1		_unlink($makefile);
3226fb12b70Safresh1		{
3236fb12b70Safresh1		    no warnings 'deprecated';
3246fb12b70Safresh1		    goto NO_MAKEFILE;
3256fb12b70Safresh1		}
3266fb12b70Safresh1	    }
3276fb12b70Safresh1	}
3286fb12b70Safresh1
3296fb12b70Safresh1        if (IS_CROSS) {
3306fb12b70Safresh1            # If we're cross-compiling, it's possible that the host's
3316fb12b70Safresh1            # Makefiles are around.
3326fb12b70Safresh1            seek($mfh, 0, 0) or die "Cannot seek $makefile: $!";
3336fb12b70Safresh1
3346fb12b70Safresh1            my $cross_makefile;
3356fb12b70Safresh1            while (<$mfh>) {
3366fb12b70Safresh1                # XXX This might not be throughout enough.
3376fb12b70Safresh1                # For example, it's possible to cause a false-positive
3386fb12b70Safresh1                # if cross compiling on and for the Raspberry Pi,
3396fb12b70Safresh1                # which is insane but plausible.
3406fb12b70Safresh1                # False positives are really not troublesome, though;
3416fb12b70Safresh1                # all they mean is that the module gets rebuilt.
3426fb12b70Safresh1                if (/^CC = \Q$Config{cc}\E/) {
3436fb12b70Safresh1                    $cross_makefile = 1;
3446fb12b70Safresh1                    last;
3456fb12b70Safresh1                }
3466fb12b70Safresh1            }
3476fb12b70Safresh1
3486fb12b70Safresh1            if (!$cross_makefile) {
3496fb12b70Safresh1                print "Deleting non-Cross makefile\n";
3506fb12b70Safresh1                close $mfh or die "close $makefile: $!";
3516fb12b70Safresh1                _unlink($makefile);
35291f110e0Safresh1            }
35391f110e0Safresh1        }
354b8851fccSafresh1    } else {
355b8851fccSafresh1	$makefile_no_minus_f = 1;
35691f110e0Safresh1    }
35791f110e0Safresh1
358b8851fccSafresh1    if ($makefile_no_minus_f || !-f $makefile) {
3596fb12b70Safresh1	NO_MAKEFILE:
36043003dfeSmillert	if (!-f 'Makefile.PL') {
3616fb12b70Safresh1            unless (just_pm_to_blib($target, $ext_dir, $mname, $return_dir)) {
3626fb12b70Safresh1                # No problems returned, so it has faked everything for us. :-)
3636fb12b70Safresh1                chdir $return_dir || die "Cannot cd to $return_dir: $!";
3646fb12b70Safresh1                return;
3656fb12b70Safresh1            }
3666fb12b70Safresh1
367b8851fccSafresh1	    print "\nCreating Makefile.PL in $ext_dir for $mname\n" if $verbose;
368898184e3Ssthen	    my ($fromname, $key, $value);
369b8851fccSafresh1
370898184e3Ssthen	    $key = 'ABSTRACT_FROM';
37143003dfeSmillert	    # We need to cope well with various possible layouts
37243003dfeSmillert	    my @dirs = split /::/, $mname;
37343003dfeSmillert	    my $leaf = pop @dirs;
37443003dfeSmillert	    my $leafname = "$leaf.pm";
37543003dfeSmillert	    my $pathname = join '/', @dirs, $leafname;
37643003dfeSmillert	    my @locations = ($leafname, $pathname, "lib/$pathname");
37743003dfeSmillert	    foreach (@locations) {
37843003dfeSmillert		if (-f $_) {
37943003dfeSmillert		    $fromname = $_;
38043003dfeSmillert		    last;
38143003dfeSmillert		}
38243003dfeSmillert	}
38343003dfeSmillert
38443003dfeSmillert	unless ($fromname) {
385b8851fccSafresh1	    die "For $mname tried @locations in $ext_dir but can't find source";
38643003dfeSmillert	}
387898184e3Ssthen	($value = $fromname) =~ s/\.pm\z/.pod/;
388898184e3Ssthen	$value = $fromname unless -e $value;
389b8851fccSafresh1
390b8851fccSafresh1            if ($mname eq 'Pod::Checker') {
391b8851fccSafresh1                # the abstract in the .pm file is unparseable by MM,
392b8851fccSafresh1                # so special-case it. We can't use the package's own
393b8851fccSafresh1                # Makefile.PL, as it doesn't handle the executable scripts
394b8851fccSafresh1                # right.
395b8851fccSafresh1                $key = 'ABSTRACT';
396b8851fccSafresh1                # this is copied from the CPAN Makefile.PL v 1.171
397b8851fccSafresh1                $value = 'Pod::Checker verifies POD documentation contents for compliance with the POD format specifications';
398898184e3Ssthen            }
399b8851fccSafresh1
40043003dfeSmillert	    open my $fh, '>', 'Makefile.PL'
40143003dfeSmillert		or die "Can't open Makefile.PL for writing: $!";
402898184e3Ssthen	    printf $fh <<'EOM', $0, $mname, $fromname, $key, $value;
40343003dfeSmillert#-*- buffer-read-only: t -*-
40443003dfeSmillert
405898184e3Ssthen# This Makefile.PL was written by %s.
40643003dfeSmillert# It will be deleted automatically by make realclean
40743003dfeSmillert
40843003dfeSmillertuse strict;
40943003dfeSmillertuse ExtUtils::MakeMaker;
41043003dfeSmillert
411898184e3Ssthen# This is what the .PL extracts to. Not the ultimate file that is installed.
412898184e3Ssthen# (ie Win32 runs pl2bat after this)
413898184e3Ssthen
414898184e3Ssthen# Doing this here avoids all sort of quoting issues that would come from
415898184e3Ssthen# attempting to write out perl source with literals to generate the arrays and
416898184e3Ssthen# hash.
417898184e3Ssthenmy @temps = 'Makefile.PL';
418898184e3Ssthenforeach (glob('scripts/pod*.PL')) {
419898184e3Ssthen    # The various pod*.PL extractors change directory. Doing that with relative
420898184e3Ssthen    # paths in @INC breaks. It seems the lesser of two evils to copy (to avoid)
421898184e3Ssthen    # the chdir doing anything, than to attempt to convert lib paths to
422898184e3Ssthen    # absolute, and potentially run into problems with quoting special
423898184e3Ssthen    # characters in the path to our build dir (such as spaces)
424898184e3Ssthen    require File::Copy;
425898184e3Ssthen
426898184e3Ssthen    my $temp = $_;
427898184e3Ssthen    $temp =~ s!scripts/!!;
428898184e3Ssthen    File::Copy::copy($_, $temp) or die "Can't copy $temp to $_: $!";
429898184e3Ssthen    push @temps, $temp;
430898184e3Ssthen}
431898184e3Ssthen
432898184e3Ssthenmy $script_ext = $^O eq 'VMS' ? '.com' : '';
433898184e3Ssthenmy %%pod_scripts;
434898184e3Ssthenforeach (glob('pod*.PL')) {
435898184e3Ssthen    my $script = $_;
436898184e3Ssthen    s/.PL$/$script_ext/i;
437898184e3Ssthen    $pod_scripts{$script} = $_;
438898184e3Ssthen}
439898184e3Ssthenmy @exe_files = values %%pod_scripts;
440898184e3Ssthen
44143003dfeSmillertWriteMakefile(
442898184e3Ssthen    NAME          => '%s',
443898184e3Ssthen    VERSION_FROM  => '%s',
444898184e3Ssthen    %-13s => '%s',
445898184e3Ssthen    realclean     => { FILES => "@temps" },
446898184e3Ssthen    (%%pod_scripts ? (
447898184e3Ssthen        PL_FILES  => \%%pod_scripts,
448898184e3Ssthen        EXE_FILES => \@exe_files,
449898184e3Ssthen        clean     => { FILES => "@exe_files" },
450898184e3Ssthen    ) : ()),
45143003dfeSmillert);
45243003dfeSmillert
45343003dfeSmillert# ex: set ro:
45443003dfeSmillertEOM
45543003dfeSmillert	    close $fh or die "Can't close Makefile.PL: $!";
45691f110e0Safresh1	    # As described in commit 23525070d6c0e51f:
45791f110e0Safresh1	    # Push the atime and mtime of generated Makefile.PLs back 4
45891f110e0Safresh1	    # seconds. In certain circumstances ( on virtual machines ) the
45991f110e0Safresh1	    # generated Makefile.PL can produce a Makefile that is older than
46091f110e0Safresh1	    # the Makefile.PL. Altering the atime and mtime backwards by 4
46191f110e0Safresh1	    # seconds seems to resolve the issue.
462898184e3Ssthen	    eval {
46352736614Safresh1        my $ftime = (stat('Makefile.PL'))[9] - 4;
464898184e3Ssthen        utime $ftime, $ftime, 'Makefile.PL';
465898184e3Ssthen	    };
4666fb12b70Safresh1        } elsif ($mname =~ /\A(?:Carp
4676fb12b70Safresh1                            |ExtUtils::CBuilder
4686fb12b70Safresh1                            |Safe
4696fb12b70Safresh1                            |Search::Dict)\z/x) {
4706fb12b70Safresh1            # An explicit list of dual-life extensions that have a Makefile.PL
4716fb12b70Safresh1            # for CPAN, but we have verified can also be built using the fakery.
4726fb12b70Safresh1            my ($problem) = just_pm_to_blib($target, $ext_dir, $mname, $return_dir);
4736fb12b70Safresh1            # We really need to sanity test that we can fake it.
4746fb12b70Safresh1            # Otherwise "skips" will go undetected, and the build slow down for
4756fb12b70Safresh1            # everyone, defeating the purpose.
4766fb12b70Safresh1            if (defined $problem) {
4776fb12b70Safresh1                if (-d "$return_dir/.git") {
4786fb12b70Safresh1                    # Get the list of files that git isn't ignoring:
4796fb12b70Safresh1                    my @files = `git ls-files --cached --others --exclude-standard 2>/dev/null`;
4806fb12b70Safresh1                    # on error (eg no git) we get nothing, but that's not a
4816fb12b70Safresh1                    # problem. The goal is to see if git thinks that the problem
4826fb12b70Safresh1                    # file is interesting, by getting a positive match with
4836fb12b70Safresh1                    # something git told us about, and if so bail out:
4846fb12b70Safresh1                    foreach (@files) {
4856fb12b70Safresh1                        chomp;
4866fb12b70Safresh1                        # We really need to sanity test that we can fake it.
4876fb12b70Safresh1                        # The intent is that this should only fail because
4886fb12b70Safresh1                        # you've just added a file to the dual-life dist that
4896fb12b70Safresh1                        # we can't handle. In which case you should either
4906fb12b70Safresh1                        # 1) remove the dist from the regex a few lines above.
4916fb12b70Safresh1                        # or
4926fb12b70Safresh1                        # 2) add the file to regex of "safe" filenames earlier
4936fb12b70Safresh1                        #    in this function, that starts with ChangeLog
4946fb12b70Safresh1                        die "FATAL - $0 has $mname in the list of simple extensions, but it now contains file '$problem' which we can't handle"
4956fb12b70Safresh1                            if $problem eq $_;
49691f110e0Safresh1                    }
4976fb12b70Safresh1                    # There's an unexpected file, but it seems to be something
4986fb12b70Safresh1                    # that git will ignore. So fall through to the regular
4996fb12b70Safresh1                    # Makefile.PL handling code below, on the assumption that
5006fb12b70Safresh1                    # we won't get here for a clean build.
5016fb12b70Safresh1                }
5026fb12b70Safresh1                warn "WARNING - $0 is building $mname using EU::MM, as it found file '$problem'";
5036fb12b70Safresh1            } else {
5046fb12b70Safresh1                # It faked everything for us.
5056fb12b70Safresh1                chdir $return_dir || die "Cannot cd to $return_dir: $!";
5066fb12b70Safresh1                return;
5076fb12b70Safresh1            }
5086fb12b70Safresh1	}
5096fb12b70Safresh1
5106fb12b70Safresh1        # We are going to have to use Makefile.PL:
511b8851fccSafresh1	print "\nRunning Makefile.PL in $ext_dir\n" if $verbose;
51243003dfeSmillert
5136fb12b70Safresh1	my @args = ("-I$lib_dir", 'Makefile.PL');
514b8851fccSafresh1	if (IS_VMS) {
51543003dfeSmillert	    my $libd = VMS::Filespec::vmspath($lib_dir);
51643003dfeSmillert	    push @args, "INST_LIB=$libd", "INST_ARCHLIB=$libd";
51743003dfeSmillert	} else {
51843003dfeSmillert	    push @args, 'INSTALLDIRS=perl', 'INSTALLMAN1DIR=none',
51943003dfeSmillert		'INSTALLMAN3DIR=none';
52043003dfeSmillert	}
52143003dfeSmillert	push @args, @$pass_through;
52256d68f1eSafresh1	push @args, 'PERL=' . $perl if $perl; # use miniperl to run the Makefile later
523b8851fccSafresh1	_quote_args(\@args) if IS_VMS;
524b8851fccSafresh1	print join(' ', $perl, @args), "\n" if $verbose;
525b8851fccSafresh1	my $code = do {
526b8851fccSafresh1	   local $ENV{PERL_MM_USE_DEFAULT} = 1;
527b8851fccSafresh1	    system $perl, @args;
528b8851fccSafresh1	};
529b8851fccSafresh1	if($code != 0){
530b8851fccSafresh1	    #make sure next build attempt/run of make_ext.pl doesn't succeed
531b8851fccSafresh1	    _unlink($makefile);
532b8851fccSafresh1	    die "Unsuccessful Makefile.PL($ext_dir): code=$code";
533b8851fccSafresh1	}
53443003dfeSmillert
53543003dfeSmillert	# Right. The reason for this little hack is that we're sitting inside
53643003dfeSmillert	# a program run by ./miniperl, but there are tasks we need to perform
53743003dfeSmillert	# when the 'realclean', 'distclean' or 'veryclean' targets are run.
53843003dfeSmillert	# Unfortunately, they can be run *after* 'clean', which deletes
53943003dfeSmillert	# ./miniperl
54043003dfeSmillert	# So we do our best to leave a set of instructions identical to what
54143003dfeSmillert	# we would do if we are run directly as 'realclean' etc
54243003dfeSmillert	# Whilst we're perfect, unfortunately the targets we call are not, as
54343003dfeSmillert	# some of them rely on a $(PERL) for their own distclean targets.
54443003dfeSmillert	# But this always used to be a problem with the old /bin/sh version of
54543003dfeSmillert	# this.
546b8851fccSafresh1	if (IS_UNIX) {
54743003dfeSmillert	    foreach my $clean_target ('realclean', 'veryclean') {
5486fb12b70Safresh1                fallback_cleanup($return_dir, $clean_target, <<"EOS");
54943003dfeSmillertcd $ext_dir
55043003dfeSmillertif test ! -f Makefile -a -f Makefile.old; then
55143003dfeSmillert    echo "Note: Using Makefile.old"
55243003dfeSmillert    make -f Makefile.old $clean_target MAKE='@make' @pass_through
55343003dfeSmillertelse
55443003dfeSmillert    if test ! -f Makefile ; then
55543003dfeSmillert	echo "Warning: No Makefile!"
55643003dfeSmillert    fi
557b8851fccSafresh1    @make $clean_target MAKE='@make' @pass_through
55843003dfeSmillertfi
55943003dfeSmillertcd $return_dir
56043003dfeSmillertEOS
56143003dfeSmillert	    }
56243003dfeSmillert	}
56343003dfeSmillert    }
56443003dfeSmillert
56543003dfeSmillert    if (not -f $makefile) {
56643003dfeSmillert	print "Warning: No Makefile!\n";
56743003dfeSmillert    }
56843003dfeSmillert
569b8851fccSafresh1    if (IS_VMS) {
57091f110e0Safresh1	_quote_args($pass_through);
57191f110e0Safresh1	@$pass_through = (
57291f110e0Safresh1			  "/DESCRIPTION=$makefile",
57391f110e0Safresh1			  '/MACRO=(' . join(',',@$pass_through) . ')'
57491f110e0Safresh1			 );
57543003dfeSmillert    }
57643003dfeSmillert
57743003dfeSmillert    my @targ = ($target, @$pass_through);
578b8851fccSafresh1    print "Making $target in $ext_dir\n@make @targ\n" if $verbose;
579b8851fccSafresh1    local $ENV{PERL_INSTALL_QUIET} = 1;
5806fb12b70Safresh1    my $code = system(@make, @targ);
581b8851fccSafresh1    if($code >> 8 != 0){ # probably cleaned itself, try again once more time
582b8851fccSafresh1        $code = system(@make, @targ);
583b8851fccSafresh1    }
58443003dfeSmillert    die "Unsuccessful make($ext_dir): code=$code" if $code != 0;
58543003dfeSmillert
58643003dfeSmillert    chdir $return_dir || die "Cannot cd to $return_dir: $!";
58743003dfeSmillert}
58843003dfeSmillert
58943003dfeSmillertsub _quote_args {
59043003dfeSmillert    my $args = shift; # must be array reference
59143003dfeSmillert
59243003dfeSmillert    # Do not quote qualifiers that begin with '/'.
59343003dfeSmillert    map { if (!/^\//) {
59443003dfeSmillert          $_ =~ s/\"/""/g;     # escape C<"> by doubling
59543003dfeSmillert          $_ = q(").$_.q(");
59643003dfeSmillert        }
59743003dfeSmillert    } @{$args}
59843003dfeSmillert    ;
59943003dfeSmillert}
6006fb12b70Safresh1
6016fb12b70Safresh1#guarentee that a file is deleted or die, void _unlink($filename)
6026fb12b70Safresh1#xxx replace with _unlink_or_rename from EU::Install?
6036fb12b70Safresh1sub _unlink {
6046fb12b70Safresh1    1 while unlink $_[0];
6056fb12b70Safresh1    my $err = $!;
6066fb12b70Safresh1    die "Can't unlink $_[0]: $err" if -f $_[0];
6076fb12b70Safresh1}
6086fb12b70Safresh1
6096fb12b70Safresh1# Figure out if this extension is simple enough that it would only use
6106fb12b70Safresh1# ExtUtils::MakeMaker's pm_to_blib target. If we're confident that it would,
6116fb12b70Safresh1# then do all the work ourselves (returning an empty list), else return the
6126fb12b70Safresh1# name of a file that we identified as beyond our ability to handle.
6136fb12b70Safresh1#
6146fb12b70Safresh1# While this is clearly quite a bit more work than just letting
6156fb12b70Safresh1# ExtUtils::MakeMaker do it, and effectively is some code duplication, the time
6166fb12b70Safresh1# savings are impressive.
6176fb12b70Safresh1
6186fb12b70Safresh1sub just_pm_to_blib {
6196fb12b70Safresh1    my ($target, $ext_dir, $mname, $return_dir) = @_;
6206fb12b70Safresh1    my ($has_lib, $has_top, $has_topdir);
6216fb12b70Safresh1    my ($last) = $mname =~ /([^:]+)$/;
6226fb12b70Safresh1    my ($first) = $mname =~ /^([^:]+)/;
6236fb12b70Safresh1
624b8851fccSafresh1    my $pm_to_blib = IS_VMS ? 'pm_to_blib.ts' : 'pm_to_blib';
625b8851fccSafresh1    my $silent = defined $ENV{MAKEFLAGS} && $ENV{MAKEFLAGS} =~ /\b(s|silent|quiet)\b/;
6266fb12b70Safresh1
6276fb12b70Safresh1    foreach my $leaf (<*>) {
6286fb12b70Safresh1        if (-d $leaf) {
6296fb12b70Safresh1            $leaf =~ s/\.DIR\z//i
630b8851fccSafresh1                if IS_VMS;
6316fb12b70Safresh1            next if $leaf =~ /\A(?:\.|\.\.|t|demo)\z/;
6326fb12b70Safresh1            if ($leaf eq 'lib') {
6336fb12b70Safresh1                ++$has_lib;
6346fb12b70Safresh1                next;
6356fb12b70Safresh1            }
6366fb12b70Safresh1            if ($leaf eq $first) {
6376fb12b70Safresh1                ++$has_topdir;
6386fb12b70Safresh1                next;
6396fb12b70Safresh1            }
6406fb12b70Safresh1        }
6416fb12b70Safresh1        return $leaf
6426fb12b70Safresh1            unless -f _;
6436fb12b70Safresh1        $leaf =~ s/\.\z//
644b8851fccSafresh1            if IS_VMS;
6456fb12b70Safresh1        # Makefile.PL is "safe" to ignore because we will only be called for
6466fb12b70Safresh1        # directories that hold a Makefile.PL if they are in the exception list.
6476fb12b70Safresh1        next
6486fb12b70Safresh1            if $leaf =~ /\A(ChangeLog
6496fb12b70Safresh1                            |Changes
6506fb12b70Safresh1                            |LICENSE
6516fb12b70Safresh1                            |Makefile\.PL
6526fb12b70Safresh1                            |MANIFEST
6536fb12b70Safresh1                            |META\.yml
6546fb12b70Safresh1                            |\Q$pm_to_blib\E
6556fb12b70Safresh1                            |README
6566fb12b70Safresh1                            |README\.patching
6576fb12b70Safresh1                            |README\.release
658*eac174f2Safresh1                            |\.gitignore
6596fb12b70Safresh1                            )\z/xi; # /i to deal with case munging systems.
6606fb12b70Safresh1        if ($leaf eq "$last.pm") {
6616fb12b70Safresh1            ++$has_top;
6626fb12b70Safresh1            next;
6636fb12b70Safresh1        }
6646fb12b70Safresh1        return $leaf;
6656fb12b70Safresh1    }
6666fb12b70Safresh1    return 'no lib/'
6676fb12b70Safresh1        unless $has_lib || $has_top;
6686fb12b70Safresh1    die "Inconsistent module $mname has both lib/ and $first/"
6696fb12b70Safresh1        if $has_lib && $has_topdir;
6706fb12b70Safresh1
6719f11ffb7Safresh1    print "Running pm_to_blib for $ext_dir directly\n"
672b8851fccSafresh1      unless $silent;
6736fb12b70Safresh1
6746fb12b70Safresh1    my %pm;
6756fb12b70Safresh1    if ($has_top) {
6766fb12b70Safresh1        my $to = $mname =~ s!::!/!gr;
6776fb12b70Safresh1        $pm{"$last.pm"} = "../../lib/$to.pm";
6786fb12b70Safresh1    }
6796fb12b70Safresh1    if ($has_lib || $has_topdir) {
6806fb12b70Safresh1        # strictly ExtUtils::MakeMaker uses the pm_to_blib target to install
6816fb12b70Safresh1        # .pm, pod and .pl files. We're just going to do it for .pm and .pod
6826fb12b70Safresh1        # files, to avoid problems on case munging file systems. Specifically,
6836fb12b70Safresh1        # _pm.PL which ExtUtils::MakeMaker should run munges to _PM.PL, and
6846fb12b70Safresh1        # looks a lot like a regular foo.pl (ie FOO.PL)
6856fb12b70Safresh1        my @found;
6866fb12b70Safresh1        require File::Find;
6876fb12b70Safresh1        unless (eval {
6886fb12b70Safresh1            File::Find::find({
6896fb12b70Safresh1                              no_chdir => 1,
6906fb12b70Safresh1                              wanted => sub {
6916fb12b70Safresh1                                  return if -d $_;
6926fb12b70Safresh1                                  # Bail out immediately with the problem file:
6936fb12b70Safresh1                                  die \$_
6946fb12b70Safresh1                                      unless -f _;
6956fb12b70Safresh1                                  die \$_
6966fb12b70Safresh1                                      unless /\A[^.]+\.(?:pm|pod)\z/i;
6976fb12b70Safresh1                                  push @found, $_;
6986fb12b70Safresh1                              }
6996fb12b70Safresh1                             }, $has_lib ? 'lib' : $first);
7006fb12b70Safresh1            1;
7016fb12b70Safresh1        }) {
7026fb12b70Safresh1            # Problem files aren't really errors:
7036fb12b70Safresh1            return ${$@}
7046fb12b70Safresh1                if ref $@ eq 'SCALAR';
7056fb12b70Safresh1            # But anything else is:
7066fb12b70Safresh1            die $@;
7076fb12b70Safresh1        }
7086fb12b70Safresh1        if ($has_lib) {
7096fb12b70Safresh1            $pm{$_} = "../../$_"
7106fb12b70Safresh1                foreach @found;
7116fb12b70Safresh1        } else {
7126fb12b70Safresh1            $pm{$_} = "../../lib/$_"
7136fb12b70Safresh1                foreach @found;
7146fb12b70Safresh1        }
7156fb12b70Safresh1    }
7166fb12b70Safresh1    # This is running under miniperl, so no autodie
7176fb12b70Safresh1    if ($target eq 'all') {
7189f11ffb7Safresh1        my $need_update = 1;
7199f11ffb7Safresh1        if (-f $pm_to_blib) {
7209f11ffb7Safresh1            # avoid touching pm_to_blib unless there's something that
7219f11ffb7Safresh1            # needs updating, see #126710
7229f11ffb7Safresh1            $need_update = 0;
7239f11ffb7Safresh1            my $test_at = -M _;
7249f11ffb7Safresh1            while (my $from = each(%pm)) {
7259f11ffb7Safresh1                if (-M $from < $test_at) {
7269f11ffb7Safresh1                    ++$need_update;
7279f11ffb7Safresh1                    last;
7289f11ffb7Safresh1                }
7299f11ffb7Safresh1            }
7309f11ffb7Safresh1            keys %pm; # reset iterator
7319f11ffb7Safresh1        }
7329f11ffb7Safresh1
7339f11ffb7Safresh1        if ($need_update) {
734b8851fccSafresh1            local $ENV{PERL_INSTALL_QUIET} = 1;
7356fb12b70Safresh1            require ExtUtils::Install;
7366fb12b70Safresh1            ExtUtils::Install::pm_to_blib(\%pm, '../../lib/auto');
7376fb12b70Safresh1            open my $fh, '>', $pm_to_blib
7386fb12b70Safresh1                or die "Can't open '$pm_to_blib': $!";
7396fb12b70Safresh1            print $fh "$0 has handled pm_to_blib directly\n";
7406fb12b70Safresh1            close $fh
7416fb12b70Safresh1                or die "Can't close '$pm_to_blib': $!";
742b8851fccSafresh1            if (IS_UNIX) {
7436fb12b70Safresh1                # Fake the fallback cleanup
7446fb12b70Safresh1                my $fallback
7456fb12b70Safresh1                    = join '', map {s!^\.\./\.\./!!; "rm -f $_\n"} sort values %pm;
7466fb12b70Safresh1                foreach my $clean_target ('realclean', 'veryclean') {
7476fb12b70Safresh1                    fallback_cleanup($return_dir, $clean_target, $fallback);
7486fb12b70Safresh1                }
7496fb12b70Safresh1            }
7509f11ffb7Safresh1        }
7516fb12b70Safresh1    } else {
7526fb12b70Safresh1        # A clean target.
7536fb12b70Safresh1        # For now, make the targets behave the same way as ExtUtils::MakeMaker
7546fb12b70Safresh1        # does
7556fb12b70Safresh1        _unlink($pm_to_blib);
7566fb12b70Safresh1        unless ($target eq 'clean') {
7576fb12b70Safresh1            # but cheat a bit, by relying on the top level Makefile clean target
7586fb12b70Safresh1            # to take out our directory lib/auto/...
7596fb12b70Safresh1            # (which it has to deal with, as cpan/foo/bar creates
7606fb12b70Safresh1            # lib/auto/foo/bar, but the EU::MM rule will only
7616fb12b70Safresh1            # rmdir lib/auto/foo/bar, leaving lib/auto/foo
76252736614Safresh1            _unlink($_)
7636fb12b70Safresh1                foreach sort values %pm;
7646fb12b70Safresh1        }
7656fb12b70Safresh1    }
7666fb12b70Safresh1    return;
7676fb12b70Safresh1}
7686fb12b70Safresh1
7696fb12b70Safresh1sub fallback_cleanup {
7706fb12b70Safresh1    my ($dir, $clean_target, $contents) = @_;
7716fb12b70Safresh1    my $file = "$dir/$clean_target.sh";
7726fb12b70Safresh1    open my $fh, '>>', $file or die "open $file: $!";
7736fb12b70Safresh1    # Quite possible that we're being run in parallel here.
7746fb12b70Safresh1    # Can't use Fcntl this early to get the LOCK_EX
7756fb12b70Safresh1    flock $fh, 2 or warn "flock $file: $!";
7766fb12b70Safresh1    print $fh $contents or die "print $file: $!";
7776fb12b70Safresh1    close $fh or die "close $file: $!";
7786fb12b70Safresh1}
779