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