ExtUtils::MakeMaker 6.03 -> 6.06_05ish
authorMichael G. Schwern <schwern@pobox.com>
Mon, 31 Mar 2003 02:42:58 +0000 (18:42 -0800)
committerJarkko Hietaniemi <jhi@iki.fi>
Mon, 31 Mar 2003 09:54:52 +0000 (09:54 +0000)
Message-ID: <20030331104257.GB15327@windhund.schwern.org>

p4raw-id: //depot/perl@19099

51 files changed:
MANIFEST
lib/ExtUtils/Changes
lib/ExtUtils/Command.pm
lib/ExtUtils/Command/MM.pm
lib/ExtUtils/Install.pm
lib/ExtUtils/Liblist.pm
lib/ExtUtils/Liblist/Kid.pm
lib/ExtUtils/MANIFEST.SKIP
lib/ExtUtils/MM_Any.pm
lib/ExtUtils/MM_BeOS.pm
lib/ExtUtils/MM_Cygwin.pm
lib/ExtUtils/MM_DOS.pm
lib/ExtUtils/MM_MacOS.pm
lib/ExtUtils/MM_NW5.pm
lib/ExtUtils/MM_OS2.pm
lib/ExtUtils/MM_UWIN.pm
lib/ExtUtils/MM_Unix.pm
lib/ExtUtils/MM_VMS.pm
lib/ExtUtils/MM_Win32.pm
lib/ExtUtils/MM_Win95.pm
lib/ExtUtils/MakeMaker.pm
lib/ExtUtils/MakeMaker/FAQ.pod [new file with mode: 0644]
lib/ExtUtils/MakeMaker/Tutorial.pod [new file with mode: 0644]
lib/ExtUtils/MakeMaker/vmsish.pm [new file with mode: 0644]
lib/ExtUtils/Manifest.pm
lib/ExtUtils/NOTES [new file with mode: 0644]
lib/ExtUtils/PATCHING [new file with mode: 0644]
lib/ExtUtils/README [new file with mode: 0644]
lib/ExtUtils/TODO [new file with mode: 0644]
lib/ExtUtils/t/00compile.t [new file with mode: 0644]
lib/ExtUtils/t/00setup_dummy.t
lib/ExtUtils/t/Command.t
lib/ExtUtils/t/INST.t
lib/ExtUtils/t/INST_PREFIX.t
lib/ExtUtils/t/Install.t [new file with mode: 0644]
lib/ExtUtils/t/Liblist.t [new file with mode: 0644]
lib/ExtUtils/t/MM_BeOS.t
lib/ExtUtils/t/MM_Cygwin.t
lib/ExtUtils/t/MM_NW5.t
lib/ExtUtils/t/MM_OS2.t
lib/ExtUtils/t/MM_Unix.t
lib/ExtUtils/t/MM_VMS.t
lib/ExtUtils/t/MM_Win32.t
lib/ExtUtils/t/Manifest.t
lib/ExtUtils/t/basic.t
lib/ExtUtils/t/hints.t
lib/ExtUtils/t/oneliner.t [new file with mode: 0644]
lib/ExtUtils/t/prefixify.t
lib/ExtUtils/t/prompt.t [new file with mode: 0644]
lib/ExtUtils/t/split_command.t [new file with mode: 0644]
t/lib/TieIn.pm [new file with mode: 0644]

index 5205f16..91b9a41 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1074,6 +1074,9 @@ lib/ExtUtils/instmodsh            Give information about installed extensions
 lib/ExtUtils/Liblist.pm                Locates libraries
 lib/ExtUtils/Liblist/Kid.pm    Does the real work of the above
 lib/ExtUtils/MakeMaker.pm      Write Makefiles for extensions
+lib/ExtUtils/MakeMaker/FAQ.pod  MakeMaker FAQ
+lib/ExtUtils/MakeMaker/Tutorial.pod     Writing a module with MakeMaker
+lib/ExtUtils/MakeMaker/vmsish.pm        Platform agnostic vmsish.pm
 lib/ExtUtils/Manifest.pm       Utilities to write MANIFEST files
 lib/ExtUtils/MANIFEST.SKIP     The default MANIFEST.SKIP
 lib/ExtUtils/Mkbootstrap.pm    Writes a bootstrap file (see MakeMaker)
@@ -1092,7 +1095,11 @@ lib/ExtUtils/MM_VMS.pm           MakeMaker methods for VMS
 lib/ExtUtils/MM_Win32.pm       MakeMaker methods for Win32
 lib/ExtUtils/MM_Win95.pm       MakeMaker methods for Win95
 lib/ExtUtils/MY.pm             MakeMaker user override class
+lib/ExtUtils/NOTES              Notes about MakeMaker internals
+lib/ExtUtils/PATCHING           Suggestions for patching MakeMaker
+lib/ExtUtils/README             MakeMaker README
 lib/ExtUtils/Packlist.pm       Manipulates .packlist files
+lib/ExtUtils/t/00compile.t      See if MakeMaker modules compile
 lib/ExtUtils/t/00setup_dummy.t Setup MakeMaker test module
 lib/ExtUtils/t/backwards.t     Check MakeMaker's backwards compatibility
 lib/ExtUtils/t/basic.t         See if MakeMaker can build a module
@@ -1101,8 +1108,10 @@ lib/ExtUtils/t/Constant.t        See if ExtUtils::Constant works
 lib/ExtUtils/t/Embed.t         See if ExtUtils::Embed and embedding works
 lib/ExtUtils/t/hints.t         See if hint files are honored.
 lib/ExtUtils/t/INST.t          Check MakeMaker INST_* macros
+lib/ExtUtils/t/Install.t        See if ExtUtils::Install works
 lib/ExtUtils/t/Installed.t     See if ExtUtils::Installed works
 lib/ExtUtils/t/INST_PREFIX.t   See if MakeMaker can apply PREFIXs
+lib/ExtUtils/t/Liblist.t        See if ExtUtils::Liblist works
 lib/ExtUtils/t/Manifest.t      See if ExtUtils::Manifest works
 lib/ExtUtils/t/Mkbootstrap.t   See if ExtUtils::Mkbootstrap works
 lib/ExtUtils/t/MM_BeOS.t       See if ExtUtils::MM_BeOS works
@@ -1112,14 +1121,18 @@ lib/ExtUtils/t/MM_OS2.t         See if ExtUtils::MM_OS2 works
 lib/ExtUtils/t/MM_Unix.t       See if ExtUtils::MM_UNIX works
 lib/ExtUtils/t/MM_VMS.t                See if ExtUtils::MM_VMS works
 lib/ExtUtils/t/MM_Win32.t      See if ExtUtils::MM_Win32 works
+lib/ExtUtils/t/oneliner.t       See if MM can generate perl one-liners
 lib/ExtUtils/t/Packlist.t      See if Packlist works
 lib/ExtUtils/t/prefixify.t     See if MakeMaker can apply a PREFIX
 lib/ExtUtils/t/problems.t      How MakeMaker reacts to build problems
+lib/ExtUtils/t/prompt.t         See if E::MM::prompt() works
+lib/ExtUtils/t/split_command.t  See if MM's xargs-like function works
 lib/ExtUtils/t/testlib.t       See if ExtUtils::testlib works
 lib/ExtUtils/t/VERSION_FROM.t  See if MakeMaker's VERSION_FROM works
 lib/ExtUtils/t/writemakefile_args.t    See if WriteMakefile works
 lib/ExtUtils/t/zz_cleanup_dummy.t      Cleanup MakeMaker test module
 lib/ExtUtils/testlib.pm                Fixes up @INC to use just-built extension
+lib/ExtUtils/TODO               Things TODO in MakeMaker
 lib/ExtUtils/typemap           Extension interface types
 lib/ExtUtils/xsubpp            External subroutine preprocessor
 lib/fastcwd.pl                 a faster but more dangerous getcwd
@@ -2502,6 +2515,7 @@ t/lib/Test/Simple/sample_tests/require.plx                for exit.t
 t/lib/Test/Simple/sample_tests/success.plx             for exit.t
 t/lib/Test/Simple/sample_tests/too_few.plx             for exit.t
 t/lib/Test/Simple/sample_tests/two_fail.plx            for exit.t
+t/lib/TieIn.pm                  Testing library for dummy input handles
 t/lib/TieOut.pm                        Testing library to capture prints
 t/lib/warnings/1global         Tests of global warnings for warnings.t
 t/lib/warnings/2use            Tests for "use warnings" for warnings.t
index 39bd0c8..879f55d 100644 (file)
@@ -1,3 +1,263 @@
+6.06_05
+    - Syncing into bleadperl.  Minor nits revealed...
+    - AutoSplit open filehandle bug was fixed in bleadperl.  Averted a
+      warning because of this.
+    - hint files were only being loaded if . happened to be in @INC.
+      A bug/feature of File::Spec was stripping off the current dir from
+      the front of hintfile paths causing Perl to look for them in @INC.
+      Worked around.
+    - Now checking $! for errors if a hint file returns undef
+    - compile test was testing all of perl!  Scaling back to just ExtUtils/
+
+6.06_04 Sun Mar 30 20:34:39 PST 2003
+    - Now looking for ExtUtils::xsubpp through @INC rather than just
+      the perl core directories.  This helps ExtUtils::ParseXS.
+    - Systems which don't put their libraries under their $Config{prefix}
+      (OS X, Debian) weren't putting their libraries in the spot declared
+      in Config.  It was going under $Config{prefix}.
+    - Prerequisites check now deals better with X.Y_Z style alpha versions
+    - ExtUtils::Liblist->ext() was using $Config{perllibs} which is a 5.6.1
+      thing.  Falling back to $Config{libs} if perllibs isn't there.
+    - ExtUtils::Command::MM now reads from @ARGV if called with no
+      args.  Makes the one liner a bit simpler.
+    * Restored ExtUtils::Liblist::ext() for backwards compatibility.
+      Missing since 5.6.1.
+    - Switching to relative dirs for self-building to shorten
+      command line lengths.
+    - Fixing minor test warning on VMS when compiling ExtUtils::Manifest
+    - Skipping STDIN read prompt() tests on 5.5.3.  Can't test due to
+      eof() not honor tied handles.
+    - Config.pm on 5.5.3 doesn't have any concept of vendor*.  This was
+      causing warnings when generating the Makefile.
+
+6.06_03 Sat Mar 29 19:44:53 PST 2003
+    - Added AUTHOR and ABSTRACT_FROM info for ppd generation.
+    - Added echo() method to portably echo text to a file.
+    - Worked around 5.8.0 eval 'require Foo::Bar' bug causing MakeMaker
+      to think modules weren't installed.
+    - Modernized VMS doc_*_install targets
+    - Changed some $(PERL) -e "print ..." code to use $(ECHO).
+    - Replaced uses of Delete/NoLog/NoConfirm with $(RM_F) in MM_VMS
+    - Fixed some duplicate macros making MMS happy.
+    - Fixed $ExtUtils::MM_VMS::Revision.  It was just the $VERSION before.
+    - Fixed ExtUtils::Command::MM::perllocal_install(), uninstall(),
+      warn_if_old_packlist().
+    * Pulling File::Spec::VMS::fixpath() and eliminate_macros() into MM_VMS
+      as the new cannonical location.  They never should have been in F::S
+      in the first place.
+    * ExtUtils::Command::eqtime() would truncate the file being equalized!
+      Holdover from exclusive .exists usage.
+    - Cleaned up hard coded 'echo' and '@' to $(ECHO) and $(NOECHO)
+    - $(SAY) is now $(ECHO) on VMS
+    - Moved rogue initializations from tools_other() to init_others()
+    - Normalized MM_VMS's tools_other() to mostly use its superclass.
+    - split_command() was off-by-one when calculating max command line
+      lengths causing it to run over on VMS
+    - made split_command() a bit smarter, taking into account some macro
+      expansion
+    - Fixed initialization of OBJECT, DISTNAME and LDFROM on VMS
+    - Fixed *_install target uses of File::Spec.
+    - Added ExtUtils::MakeMaker::vmsish wrapper around vmsish so MM_VMS
+      can be compiled on non-VMS machines.  For testing.
+    * Added ExtUtils::MakeMaker::Tutorial about writing modules with
+      MakeMaker.
+    - Removed "always use h2xs" dogma.
+    - Added compile & POD test
+    * 'make distdir' now generates META.yml module meta-data file.
+      Proof of concept.  Have to syncronize with Module::Build.
+    * Added maniadd() to ExtUtils::Manifest to add entries to the MANIFEST
+    * ExtUtils::Command::chmod was not interpreting file permissions as
+      octal.  Also, docs & tests slightly wrong (thanks Stas Bekman).
+    - ExtUtils::Install was hard coding blib/lib and blib/arch, unportable
+      [perl #21526]
+
+6.06_02 Mon Dec 23 20:39:57 PST 2002
+    * Lots of Win32 fixes busted between 6.05 and 6.06_01.  
+    * split_command() tests still not happy on Win32.  Problems with
+      shell vs Makefile escaping makes testing difficult.
+    * VMS still broken.  Need to convert File::Spec method calls back to
+      object method calls so the weird FS::VMS->eliminate_macros() and 
+      fixpath() work again.
+
+6.06_01 Thu Dec 19 00:14:49 PST 2002
+    - Andreas found that when building the core it is desirable for
+      MakeMaker to use a relative path to perl.
+    - File::Spec->catfile() has a bug where the resulting file may not be
+      canonicalized.  This was causing problems when generating manpaths.
+      MakeMaker now uses its own fixed override for catfile().
+    - Fixed the POD recognition regex to properly catch /=head\d/ tags.
+    * Added a PATCHING guideline document.
+    - Updated the class hierarchy in NOTES.
+    - Installed.t now cleans up after itself better.
+    - Steve Purkis rewrote the manifypods system to use Pod::Man
+      rather than pod2man.  Its now portable and manifypods() moved from 
+      MM_Unix to MM_Any.  As a result, lots of icky and redudant code went
+      away.  This also removes the POD2MAN macro, but noone should be
+      using that.  
+    - "make manifypods" now works on Win32
+    - "make manifypods" is now be faster
+    - Made MM_Unix->find_perl more portable.  Eliminated MM_Win32->find_perl
+      override.  MM_VMS->find_perl remains.
+    * find_perl() can now handle filenames with spaces in them (RT448)
+    * find_perl() on Win32 no longer produces spurious "File Creation error"
+      messages (perlbug ID 20020709.001)
+    - Removed unfinished and unused maybe_command_in_dirs()
+    - Removed dead SelfLoader cruft from MM_Unix.
+    - Fixed PPD generation when the ppd contains quotes (RT1473)
+    - Fixed PPD generation on VMS
+    - Moved Win9x specific subdir_x() code from MM_Unix to MM_Win95
+    * Craig Berry fixed hint files on VMS
+    - Added the perl_onliner() method to generate portable, safe one-liners
+    - Changing hardcoded $self->{MAKEFILE} to $(FIRST_MAKEFILE).
+    * Rafael Garcia-Suarez made MakeMaker ignore Subversion control files
+      by default.
+    - Added MAKEFILE_OLD macro.
+    * No longer generating man pages by default on VMS.
+    - Improved DISTNAME docs
+    * Documented DISTVNAME and VERSION_SYM
+    * Documented dist()
+    - Seperated dist_core() into dist, tardist, uutardist, tarfile,
+      zipdist, zipfile and shdist_target methods.  Allows elimination
+      of redundant code in MM_VMS.
+    - Replaced WARN_IF_OLD_PACKLIST, DOC_INSTALL and UNINSTALL
+      one-liners with ExtUtils::Command::MM functions
+    - Replaced VMS hand-rolled perl code for TOUCH, CHMOD, RM_F and RM_RF
+      with ExtUtils::Command functions.  Added TEST_F.
+    - Adding clean_subdirs target and clean_subdirs_target() method to
+      generate same.  This allows easier overriding of an unportable part
+      of the clean target.
+    - Defined DEV_NULL for MacOS
+    - Removed ROOTEXT from MM_MacOS, apparently unused
+    - Added $(DIRFILESEP) macro and init_DIRFILESEP to avoid
+      hardcoding / or \.  Reduces code duplication in the MM_* modules.
+    - Added init_platform() and platform_constants() for OS specific
+      macros.  Moved OS specific macros from constants() overrides there.
+    - Added init_VERSION() to setup various *VERSION* macros.
+    - Added default wraplist() to make porting easier.
+    - Added makemakerdflt_target() to guarantee 'all' is the default
+      target.
+    - Added special_targets() to handle things like .PHONY and make sure
+      they come first.
+    - Added init_linker() to initialize linker relatied macros.
+    - MM_MacOS constants() disolves
+        Moved MACPERL_SRC, MACPERL_LIB, MACPERL_INC from init_main() to 
+          init_platform().
+        Moved DEFINE and INC tweaking from constants() to init_main()
+        Moved DEFINE_VERSION & XS_DEFINE_VERSION from constants() to
+          init_VERSION().
+        Eliminated MODULES.  Unused and its the same as TO_INST_PM
+        Moved .INCLUDE from constants() to special_targets()
+
+    - MM_NW5 constants() & init_others() disolves
+        Moved LIBPTH, BASE_IMPORT, NLM_VERSION, MPKTOOL, TOOLPATH from 
+          init_others() to init_platform()
+        Moved INCLUDE and PATH definitions from constants() to 
+          init_platform()
+        Moved BOOT_SYMBOL, NLM_SHORT_NAME, PATH and INCLUDE from
+          constants() to init_platform()
+
+    - MM_Unix constants() goes on a diet
+        Moved all macro definitions to init_* methods.
+        Added MM_REVISION for completeness
+        Using wraplist() instead of manual joining
+        Moved .NO_CONFIG_REC, .SUFFIXES and .PHONY to special_targets()
+        Moved makemakerdflt: to makemakerdeflt_target()
+        Moved INST_{STATIC,DYNAMIC,BOOT} to init_INST()
+        Moved EXPORT_LIST, PERL_ARCHIVE & PERL_ARCHIVE_AFTER to init_linker().
+        Moved PERL_MALLOC_DEF to init_platform()
+
+    - MM_VMS constants() goes on a diet
+        Moved DEFINE from constants() to init_main()
+        Moved OBJECT & LDFROM from constants() to init_others()
+        Moved MM_VMS_REVISION and PERL_VMS to init_platform
+        Added MM_VMS_VERSION
+        Moved DEFINE_VERSION, XS_DEFINE_VERSION and MAKEMAKER changes to
+            init_VERSION
+        Moved .SUFFIXES changes to special_targets() override.
+        Eliminated $self->{PM_TO_BLIB}.  Its redundant with $self->{PM}.
+        constants() now consists only of fixpath() calls.
+
+    - MM_Win32 constants() goes away
+        Moved .USESHELL to special_targets() override.
+        Everything else was redundant.
+
+    - Added $(VERSION_FROM) to $(MAKEFILE) dependencies.  Helpful for
+      XS builds where the version number is very sensitive.
+    - export_list(), perl_archive() and perl_archive_after() consolodated
+      into init_linker().
+    - Added MM_NW5_VERSION, MM_Unix_VERSION, MM_Win32_VERSION, 
+      MM_VMS_VERSION.
+    - Eliminated duplicate code in constants() overrides
+    - Added all_target() for easier customization of what's run by default
+    - Eliminated duplicate top_targets() overrides
+    - Made tool_autosplit() method portable.  Moved to MM_Any.  Eliminated
+      overrides.
+    - Adding realclean_subdirs target and realclean_subdirs_target()
+      method to generate same.  This allows easier overriding of an 
+      unportable part of the realclean target.    
+    - Added oneliner() to create portable perl one-liners.
+    - Craig Berry found some typos in ExtUtils::Liblist::Kid's VMS part
+    * ExtUtils::Install did not work on MacPerl due to a hardcoded '.'
+    * prompt() will now read from STDIN.
+    - Craig Berry made sure extliblist() is always called even if LIBS
+      is explicitly set to empty.
+    * Added DESTDIR to make repacking easier.
+    * $(*PREFIX) are returned to the INSTALL* variables.
+    * Split $(PREFIX) into $(PERLPREFIX) and $(PREFIX).  The former
+      holds the location of the core libraries.  The latter is the
+      optional override prefix supplied by the user.
+    * PREFIX overrides all other *PREFIXes when set in the Makefile.PL.
+      This restores "make install PREFIX=foo".
+    - Added quote_literal() to handle some shell quoting.
+    - ExtUtils::MM_VMS now compilable on non-VMS platforms.
+    - J. D. Laub made MakeMaker honor $Config{installstyle}
+    - Renaming on OS/2 requires the target file to be removed.  
+      Partially fixed by Ilya, should be applied universally later.
+    - Default MANIFEST.SKIP not catching files in subdirs.  Fixed by Ilya.
+    - Ilya fixed ExtUtils::Liblist->ext when called outside MakeMaker.
+    - realclean was duplicating work already done by clean
+    - Adding an explicit LICENSE
+    - Cleaning up ExtUtils::Install docs.
+    - ExtUtils::Install::uninstall() now has default verbose and
+      dont_execute arguments.
+    - Added some basic ExtUtils::Install tests
+    - Fixed ExtUtils::Install::install() for relative dirs
+    - Added split_command() and max_exec_len() to deal with long
+      commands.
+    - Seperated escape_newlines() from quote_literal().  This may
+      be pointless.
+    - pm_to_blib() now generated with split_command().  3x speedup.
+    - added init_dist() to initialize distribution constants
+    - ExtUtils::Install::pm_to_blib() working around open filehandle
+      bug in AutoSplit for systems with mandatory file locking.
+
+6.05 Tue Aug 27 16:09:51 PDT 2002
+    - Output format of the hint file verbose diagnostic is now in
+      a format native to the OS, so it broke a test on non-Unixen.
+
+6.04 Mon Aug 26 18:31:11 PDT 2002 
+    - Little fix for pre-5.8 Cygwin test to get the shared library names 
+      right.
+    * disttest on Win9X broken because of forgotten tabs
+    * WriteMakefile argument verification should now be accurate
+    - Documented the LD flag.
+    * Documented prompt()
+    * vendor install was not adding to packlist or updating perllocal.
+    - Supporting $Config{vendorarchexp} and $Config{vendorlibexp}.
+    - Fixed conflict on VMS between logical names and directories 
+      (bleadperl 17488)
+    - Fixed space-vs-tab bug on Netware (bleadperl 17579)
+    - Mysterious NetWare fix from Ananth (bleadperl 17376)
+    - Support OPTIMIZE in MacOS (bleadperl 17347)
+    - Support hints in MacOS (mutation of bleadperl 17347)
+    * Default man installation directories were using $(MAN*EXT) to
+      generate the directory name.  This turned out to be wrong more
+      often than right, so we'll use man1 and man3 hard-coded.
+    - Debian folks fixed the doc_install targets so the Appending
+      diagnostic gives the correct directory for perllocal.pod
+    * Added ExtUtils::MakeMaker::FAQ
+    - Quieted some warnings on MacOS (bleadperl 17669)
+
 6.03 Wed Jun 19 17:06:14 EDT 2002
     - Documented that we're clamping down on cargo-cult MakeMaker
       programming.
 
 5.50_01 Mon Mar  4 23:44:48 EST 2002
     [[ API Changes ]]
-      htmlifypods and all HTML targets have been removed.  It didn't
+    - htmlifypods and all HTML targets have been removed.  It didn't
       work properly.  A target for HTMLifying of docs will be
       added sometime in the future (read: send a patch).
     - Deprecated ROOTEXT variable removed (its been deprecated for
index 829de16..b06430d 100644 (file)
@@ -21,16 +21,16 @@ ExtUtils::Command - utilities to replace common UNIX commands in Makefiles etc.
 
 =head1 SYNOPSIS
 
-  perl -MExtUtils::Command -e cat files... > destination
-  perl -MExtUtils::Command -e mv source... destination
-  perl -MExtUtils::Command -e cp source... destination
-  perl -MExtUtils::Command -e touch files...
-  perl -MExtUtils::Command -e rm_f file...
-  perl -MExtUtils::Command -e rm_rf directories...
-  perl -MExtUtils::Command -e mkpath directories...
-  perl -MExtUtils::Command -e eqtime source destination
-  perl -MExtUtils::Command -e chmod mode files...
-  perl -MExtUtils::Command -e test_f file
+  perl -MExtUtils::Command       -e cat files... > destination
+  perl -MExtUtils::Command       -e mv source... destination
+  perl -MExtUtils::Command       -e cp source... destination
+  perl -MExtUtils::Command       -e touch files...
+  perl -MExtUtils::Command       -e rm_f files...
+  perl -MExtUtils::Command       -e rm_rf directories...
+  perl -MExtUtils::Command       -e mkpath directories...
+  perl -MExtUtils::Command       -e eqtime source destination
+  perl -MExtUtils::Command       -e test_f file
+  perl -MExtUtils::Command=chmod -e chmod mode files...
 
 =head1 DESCRIPTION
 
@@ -57,6 +57,7 @@ sub expand_wildcards
  @ARGV = map(/[$wild_regex]/o ? glob($_) : $_,@ARGV);
 }
 
+
 =item cat 
 
 Concatenates all files mentioned on command line to STDOUT.
@@ -78,8 +79,7 @@ Sets modified time of dst to that of src
 sub eqtime
 {
  my ($src,$dst) = @ARGV;
- open(F,">>$dst");
- close(F);
+ local @ARGV = ($dst);  touch();  # in case $dst doesn't exist
  utime((stat($src))[8,9],$dst);
 }
 
@@ -120,17 +120,14 @@ Makes files exist, with current timestamp
 
 =cut 
 
-sub touch
-{
- my $t    = time;
- expand_wildcards();
- while (@ARGV)
-  {
-   my $file = shift(@ARGV);
-   open(FILE,">>$file") || die "Cannot write $file:$!";
-   close(FILE);
-   utime($t,$t,$file);
-  }
+sub touch {
+    my $t    = time;
+    expand_wildcards();
+    foreach my $file (@ARGV) {
+        open(FILE,">>$file") || die "Cannot write $file:$!";
+        close(FILE);
+        utime($t,$t,$file);
+    }
 }
 
 =item mv source... destination
@@ -140,16 +137,13 @@ Multiple sources are allowed if destination is an existing directory.
 
 =cut 
 
-sub mv
-{
- my $dst = pop(@ARGV);
- expand_wildcards();
- croak("Too many arguments") if (@ARGV > 1 && ! -d $dst);
- while (@ARGV)
-  {
-   my $src = shift(@ARGV);
-   move($src,$dst);
-  }
+sub mv {
+    my $dst = pop(@ARGV);
+    expand_wildcards();
+    croak("Too many arguments") if (@ARGV > 1 && ! -d $dst);
+    foreach my $src (@ARGV) {
+        move($src,$dst);
+    }
 }
 
 =item cp source... destination
@@ -159,29 +153,25 @@ Multiple sources are allowed if destination is an existing directory.
 
 =cut
 
-sub cp
-{
- my $dst = pop(@ARGV);
- expand_wildcards();
- croak("Too many arguments") if (@ARGV > 1 && ! -d $dst);
- while (@ARGV)
-  {
-   my $src = shift(@ARGV);
-   copy($src,$dst);
-  }
+sub cp {
+    my $dst = pop(@ARGV);
+    expand_wildcards();
+    croak("Too many arguments") if (@ARGV > 1 && ! -d $dst);
+    foreach my $src (@ARGV) {
+        copy($src,$dst);
+    }
 }
 
 =item chmod mode files...
 
-Sets UNIX like permissions 'mode' on all the files.
+Sets UNIX like permissions 'mode' on all the files.  e.g. 0666
 
 =cut 
 
-sub chmod
-{
- my $mode = shift(@ARGV);
- expand_wildcards();
- chmod($mode,@ARGV) || die "Cannot chmod ".join(' ',$mode,@ARGV).":$!";
+sub chmod {
+    my $mode = shift(@ARGV);
+    expand_wildcards();
+    chmod(oct $mode,@ARGV) || die "Cannot chmod ".join(' ',$mode,@ARGV).":$!";
 }
 
 =item mkpath directory...
index 9eb7d29..4aa3738 100644 (file)
@@ -7,8 +7,11 @@ require Exporter;
 use vars qw($VERSION @ISA @EXPORT);
 @ISA = qw(Exporter);
 
-@EXPORT = qw(test_harness);
-$VERSION = '0.01';
+@EXPORT  = qw(test_harness pod2man perllocal_install uninstall 
+              warn_if_old_packlist);
+$VERSION = '0.02';
+
+my $Is_VMS = $^O eq 'VMS';
 
 =head1 NAME
 
@@ -16,7 +19,7 @@ ExtUtils::Command::MM - Commands for the MM's to use in Makefiles
 
 =head1 SYNOPSIS
 
-  perl -MExtUtils::Command::MM -e "function" files...
+  perl "-MExtUtils::Command::MM" -e "function" "--" arguments...
 
 
 =head1 DESCRIPTION
@@ -26,8 +29,6 @@ B<FOR INTERNAL USE ONLY!>  The interface is not stable.
 ExtUtils::Command::MM encapsulates code which would otherwise have to
 be done with large "one" liners.
 
-They all read their input from @ARGV unless otherwise noted.
-
 Any $(FOO) used in the examples are make variables, not Perl.
 
 =over 4
@@ -54,6 +55,203 @@ sub test_harness {
     Test::Harness::runtests(sort { lc $a cmp lc $b } @ARGV);
 }
 
+
+
+=item B<pod2man>
+
+  pod2man( '--option=value',
+           $podfile1 => $manpage1,
+           $podfile2 => $manpage2,
+           ...
+         );
+
+  # or args on @ARGV
+
+pod2man() is a function performing most of the duties of the pod2man
+program.  Its arguments are exactly the same as pod2man as of 5.8.0
+with the addition of:
+
+    --perm_rw   octal permission to set the resulting manpage to
+
+And the removal of:
+
+    --verbose/-v
+    --help/-h
+
+If no arguments are given to pod2man it will read from @ARGV.
+
+=cut
+
+sub pod2man {
+    require Pod::Man;
+    require Getopt::Long;
+
+    my %options = ();
+
+    # We will cheat and just use Getopt::Long.  We fool it by putting
+    # our arguments into @ARGV.  Should be safe.
+    local @ARGV = @_ ? @_ : @ARGV;
+    Getopt::Long::config ('bundling_override');
+    Getopt::Long::GetOptions (\%options, 
+                'section|s=s', 'release|r=s', 'center|c=s',
+                'date|d=s', 'fixed=s', 'fixedbold=s', 'fixeditalic=s',
+                'fixedbolditalic=s', 'official|o', 'quotes|q=s', 'lax|l',
+                'name|n=s', 'perm_rw:i'
+    );
+
+    # If there's no files, don't bother going further.
+    return 0 unless @ARGV;
+
+    # Official sets --center, but don't override things explicitly set.
+    if ($options{official} && !defined $options{center}) {
+        $options{center} = 'Perl Programmers Reference Guide';
+    }
+
+    # This isn't a valid Pod::Man option and is only accepted for backwards
+    # compatibility.
+    delete $options{lax};
+
+    my $parser = Pod::Man->new(%options);
+
+    do {{  # so 'next' works
+        my ($pod, $man) = splice(@ARGV, 0, 2);
+
+        next if ((-e $man) &&
+                 (-M $man < -M $pod) &&
+                 (-M $man < -M "Makefile"));
+
+        print "Manifying $man\n";
+
+        $parser->parse_from_file($pod, $man)
+          or do { warn("Could not install $man\n");  next };
+
+        if (length $options{perm_rw}) {
+            chmod(oct($options{perm_rw}), $man)
+              or do { warn("chmod $options{perm_rw} $man: $!\n"); next };
+        }
+    }} while @ARGV;
+
+    return 1;
+}
+
+
+=item B<warn_if_old_packlist>
+
+  perl "-MExtUtils::Command::MM" -e warn_if_old_packlist <somefile>
+
+Displays a warning that an old packlist file was found.  Reads the
+filename from @ARGV.
+
+=cut
+
+sub warn_if_old_packlist {
+    my $packlist = $ARGV[0];
+
+    return unless -f $packlist;
+    print <<"PACKLIST_WARNING";
+WARNING: I have found an old package in
+    $packlist.
+Please make sure the two installations are not conflicting
+PACKLIST_WARNING
+
+}
+
+
+=item B<perllocal_install>
+
+    perl "-MExtUtils::Command::MM" -e perllocal_install 
+        <type> <module name> <key> <value> ...
+
+    # VMS only, key/value pairs come on STDIN
+    perl "-MExtUtils::Command::MM" -e perllocal_install
+        <type> <module name> < <key> <value> ...
+
+Prints a fragment of POD suitable for appending to perllocal.pod.
+Arguments are read from @ARGV.
+
+'type' is the type of what you're installing.  Usually 'Module'.
+
+'module name' is simply the name of your module.  (Foo::Bar)
+
+Key/value pairs are extra information about the module.  Fields include:
+
+    installed into      which directory your module was out into
+    LINKTYPE            dynamic or static linking
+    VERSION             module version number
+    EXE_FILES           any executables installed in a space seperated 
+                        list
+
+=cut
+
+sub perllocal_install {
+    my($type, $name) = splice(@ARGV, 0, 2);
+
+    # VMS feeds args as a piped file on STDIN since it usually can't
+    # fit all the args on a single command line.
+    @ARGV = split /\|/, <STDIN> if $Is_VMS;
+
+    my $pod;
+    $pod = sprintf <<POD, scalar localtime;
+ =head2 %s: C<$type> L<$name|$name>
+ =over 4
+POD
+
+    do {
+        my($key, $val) = splice(@ARGV, 0, 2);
+
+        $pod .= <<POD
+ =item *
+ C<$key: $val>
+POD
+
+    } while(@ARGV);
+
+    $pod .= "=back\n\n";
+    $pod =~ s/^ //mg;
+    print $pod;
+
+    return 1;
+}
+
+=item B<uninstall>
+
+    perl "-MExtUtils::Command::MM" -e uninstall <packlist>
+
+A wrapper around ExtUtils::Install::uninstall().  Warns that
+uninstallation is deprecated and doesn't actually perform the
+uninstallation.
+
+=cut
+
+sub uninstall {
+    my($packlist) = shift;
+
+    require ExtUtils::Install;
+
+    print <<'WARNING';
+
+Uninstall is unsafe and deprecated, the uninstallation was not performed.
+We will show what would have been done.
+
+WARNING
+
+    ExtUtils::Install::uninstall($packlist, 1, 1);
+
+    print <<'WARNING';
+
+Uninstall is unsafe and deprecated, the uninstallation was not performed.
+Please check the list above carefully, there may be errors.
+Remove the appropriate files manually.
+Sorry for the inconvenience.
+
+WARNING
+
+}
+
 =back
 
 =cut
index b8fb4e3..757679a 100644 (file)
@@ -2,14 +2,15 @@ package ExtUtils::Install;
 
 use 5.00503;
 use vars qw(@ISA @EXPORT $VERSION);
-$VERSION = 1.29;
+$VERSION = 1.31;
 
 use Exporter;
 use Carp ();
 use Config qw(%Config);
 @ISA = ('Exporter');
 @EXPORT = ('install','uninstall','pm_to_blib', 'install_default');
-$Is_VMS = $^O eq 'VMS';
+$Is_VMS     = $^O eq 'VMS';
+$Is_MacPerl = $^O eq 'MacOS';
 
 my $splitchar = $^O eq 'VMS' ? '|' : ($^O eq 'os2' || $^O eq 'dos') ? ';' : ':';
 my @PERL_ENV_LIB = split $splitchar, defined $ENV{'PERL5LIB'} ? $ENV{'PERL5LIB'} : $ENV{'PERLLIB'} || '';
@@ -20,33 +21,64 @@ my $Inc_uninstall_warn_handler;
 my $INSTALL_ROOT = $ENV{PERL_INSTALL_ROOT};
 
 use File::Spec;
+my $Curdir = File::Spec->curdir;
+my $Updir  = File::Spec->updir;
 
-sub install_rooted_file {
-    if (defined $INSTALL_ROOT) {
-       File::Spec->catfile($INSTALL_ROOT, $_[0]);
-    } else {
-       $_[0];
-    }
-}
 
-sub install_rooted_dir {
-    if (defined $INSTALL_ROOT) {
-       File::Spec->catdir($INSTALL_ROOT, $_[0]);
-    } else {
-       $_[0];
-    }
-}
+=head1 NAME
 
-#our(@EXPORT, @ISA, $Is_VMS);
-#use strict;
+ExtUtils::Install - install files from here to there
 
-sub forceunlink {
-    chmod 0666, $_[0];
-    unlink $_[0] or Carp::croak("Cannot forceunlink $_[0]: $!")
-}
+=head1 SYNOPSIS
+
+  use ExtUtils::Install;
+
+  install({ 'blib/lib' => 'some/install/dir' } );
+
+  uninstall($packlist);
+
+  pm_to_blib({ 'lib/Foo/Bar.pm' => 'blib/lib/Foo/Bar.pm' });
+
+
+=head1 DESCRIPTION
+
+Handles the installing and uninstalling of perl modules, scripts, man
+pages, etc...
+
+Both install() and uninstall() are specific to the way
+ExtUtils::MakeMaker handles the installation and deinstallation of
+perl modules. They are not designed as general purpose tools.
+
+=head2 Functions
+
+=over 4
+
+=item B<install>
+
+    install(\%from_to);
+    install(\%from_to, $verbose, $dont_execute);
+
+Copies each directory tree of %from_to to its corresponding value
+preserving timestamps and permissions.
+
+There are two keys with a special meaning in the hash: "read" and
+"write".  These contain packlist files.  After the copying is done,
+install() will write the list of target files to $from_to{write}. If
+$from_to{read} is given the contents of this file will be merged into
+the written file. The read and the written file may be identical, but
+on AFS it is quite likely that people are installing to a different
+directory than the one where the files later appear.
+
+If $verbose is true, will print out each file removed.  Default is
+false.
+
+If $dont_execute is true it will only print what it was going to do
+without actually doing it.  Default is false.
+
+=cut
 
 sub install {
-    my($hash,$verbose,$nonono,$inc_uninstall) = @_;
+    my($from_to,$verbose,$nonono,$inc_uninstall) = @_;
     $verbose ||= 0;
     $nonono  ||= 0;
 
@@ -57,32 +89,31 @@ sub install {
     use File::Find qw(find);
     use File::Path qw(mkpath);
     use File::Compare qw(compare);
-    use File::Spec;
 
-    my(%hash) = %$hash;
+    my(%from_to) = %$from_to;
     my(%pack, $dir, $warn_permissions);
     my($packlist) = ExtUtils::Packlist->new();
     # -w doesn't work reliably on FAT dirs
     $warn_permissions++ if $^O eq 'MSWin32';
     local(*DIR);
     for (qw/read write/) {
-       $pack{$_}=$hash{$_};
-       delete $hash{$_};
+       $pack{$_}=$from_to{$_};
+       delete $from_to{$_};
     }
     my($source_dir_or_file);
-    foreach $source_dir_or_file (sort keys %hash) {
+    foreach $source_dir_or_file (sort keys %from_to) {
        #Check if there are files, and if yes, look if the corresponding
        #target directory is writable for us
        opendir DIR, $source_dir_or_file or next;
        for (readdir DIR) {
-           next if $_ eq "." || $_ eq ".." || $_ eq ".exists";
-               my $targetdir = install_rooted_dir($hash{$source_dir_or_file});
+           next if $_ eq $Curdir || $_ eq $Updir || $_ eq ".exists";
+            my $targetdir = install_rooted_dir($from_to{$source_dir_or_file});
            if (-w $targetdir ||
                mkpath($targetdir)) {
                last;
            } else {
                warn "Warning: You do not have permissions to " .
-                   "install into $hash{$source_dir_or_file}"
+                   "install into $from_to{$source_dir_or_file}"
                    unless $warn_permissions++;
            }
        }
@@ -92,8 +123,7 @@ sub install {
     $packlist->read($tmpfile) if (-f $tmpfile);
     my $cwd = cwd();
 
-    my($source);
-    MOD_INSTALL: foreach $source (sort keys %hash) {
+    MOD_INSTALL: foreach my $source (sort keys %from_to) {
        #copy the tree to the target directory without altering
        #timestamp and permission and remember for the .packlist
        #file. The packlist file contains the absolute paths of the
@@ -104,29 +134,37 @@ sub install {
        #there are any files in arch. So we depend on having ./blib/arch
        #hardcoded here.
 
-       my $targetroot = install_rooted_dir($hash{$source});
+       my $targetroot = install_rooted_dir($from_to{$source});
 
-       if ($source eq "blib/lib" and
-           exists $hash{"blib/arch"} and
-           directory_not_empty("blib/arch")) {
-           $targetroot = install_rooted_dir($hash{"blib/arch"});
-            print "Files found in blib/arch: installing files in blib/lib into architecture dependent library tree\n";
+        my $blib_lib  = File::Spec->catdir('blib', 'lib');
+        my $blib_arch = File::Spec->catdir('blib', 'arch');
+       if ($source eq $blib_lib and
+           exists $from_to{$blib_arch} and
+           directory_not_empty($blib_arch)) {
+           $targetroot = install_rooted_dir($from_to{$blib_arch});
+            print "Files found in $blib_arch: installing files in $blib_lib into architecture dependent library tree\n";
        }
-       chdir($source) or next;
+
+        chdir $source or next;
        find(sub {
-           my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
-                         $atime,$mtime,$ctime,$blksize,$blocks) = stat;
+           my ($mode,$size,$atime,$mtime) = (stat)[2,7,8,9];
            return unless -f _;
            return if $_ eq ".exists";
            my $targetdir  = File::Spec->catdir($targetroot, $File::Find::dir);
            my $targetfile = File::Spec->catfile($targetdir, $_);
+            my $sourcedir  = File::Spec->catdir($source, $File::Find::dir);
+            my $sourcefile = File::Spec->catfile($sourcedir, $_);
+
+            my $save_cwd = cwd;
+            chdir $cwd;  # in case the target is relative
+                         # 5.5.3's File::Find missing no_chdir option.
 
            my $diff = 0;
            if ( -f $targetfile && -s _ == $size) {
                # We have a good chance, we can skip this one
-               $diff = compare($_,$targetfile);
+               $diff = compare($sourcefile, $targetfile);
            } else {
-               print "$_ differs\n" if $verbose>1;
+               print "$sourcefile differs\n" if $verbose>1;
                $diff++;
            }
 
@@ -137,7 +175,7 @@ sub install {
                    mkpath($targetdir,0,0755) unless $nonono;
                    print "mkpath($targetdir,0,0755)\n" if $verbose>1;
                }
-               copy($_,$targetfile) unless $nonono;
+               copy($sourcefile, $targetfile) unless $nonono;
                print "Installing $targetfile\n";
                utime($atime,$mtime + $Is_VMS,$targetfile) unless $nonono>1;
                print "utime($atime,$mtime,$targetfile)\n" if $verbose>1;
@@ -147,17 +185,20 @@ sub install {
            } else {
                print "Skipping $targetfile (unchanged)\n" if $verbose;
            }
-           
-           if (! defined $inc_uninstall) { # it's called 
-           } elsif ($inc_uninstall == 0){
-               inc_uninstall($_,$File::Find::dir,$verbose,1); # nonono set to 1
-           } else {
-               inc_uninstall($_,$File::Find::dir,$verbose,0); # nonono set to 0
+
+           if (defined $inc_uninstall) {
+               inc_uninstall($sourcefile,$File::Find::dir,$verbose, 
+                              $inc_uninstall ? 0 : 1);
            }
+
            # Record the full pathname.
            $packlist->{$targetfile}++;
 
-       }, ".");
+            # File::Find can get confused if you chdir in here.
+            chdir $save_cwd;
+
+        # File::Find seems to always be Unixy except on MacPerl :(
+       }, $Is_MacPerl ? $Curdir : '.' );
        chdir($cwd) or Carp::croak("Couldn't chdir to $cwd: $!");
     }
     if ($pack{'write'}) {
@@ -168,6 +209,30 @@ sub install {
     }
 }
 
+sub install_rooted_file {
+    if (defined $INSTALL_ROOT) {
+       File::Spec->catfile($INSTALL_ROOT, $_[0]);
+    } else {
+       $_[0];
+    }
+}
+
+
+sub install_rooted_dir {
+    if (defined $INSTALL_ROOT) {
+       File::Spec->catdir($INSTALL_ROOT, $_[0]);
+    } else {
+       $_[0];
+    }
+}
+
+
+sub forceunlink {
+    chmod 0666, $_[0];
+    unlink $_[0] or Carp::croak("Cannot forceunlink $_[0]: $!")
+}
+
+
 sub directory_not_empty ($) {
   my($dir) = @_;
   my $files = 0;
@@ -181,6 +246,28 @@ sub directory_not_empty ($) {
   return $files;
 }
 
+
+=item B<install_default> I<DISCOURAGED>
+
+    install_default();
+    install_default($fullext);
+
+Calls install() with arguments to copy a module from blib/ to the
+default site installation location.
+
+$fullext is the name of the module converted to a directory
+(ie. Foo::Bar would be Foo/Bar).  If $fullext is not specified, it
+will attempt to read it from @ARGV.
+
+This is primarily useful for install scripts.
+
+B<NOTE> This function is not really useful because of the hard-coded
+install location with no way to control site vs core vs vendor
+directories and the strange way in which the module name is given.
+Consider its use discouraged.
+
+=cut
+
 sub install_default {
   @_ < 2 or die "install_default should be called with 0 or 1 argument";
   my $FULLEXT = @_ ? shift : $ARGV[0];
@@ -205,9 +292,28 @@ sub install_default {
          },1,0,0);
 }
 
+
+=item B<uninstall>
+
+    uninstall($packlist_file);
+    uninstall($packlist_file, $verbose, $dont_execute);
+
+Removes the files listed in a $packlist_file.
+
+If $verbose is true, will print out each file removed.  Default is
+false.
+
+If $dont_execute is true it will only print what it was going to do
+without actually doing it.  Default is false.
+
+=cut
+
 sub uninstall {
     use ExtUtils::Packlist;
     my($fil,$verbose,$nonono) = @_;
+    $verbose ||= 0;
+    $nonono  ||= 0;
+
     die "no packlist file found: $fil" unless -f $fil;
     # my $my_req = $self->catfile(qw(auto ExtUtils Install forceunlink.al));
     # require $my_req; # Hairy, but for the first
@@ -229,7 +335,7 @@ sub inc_uninstall {
                                                  privlibexp
                                                  sitearchexp
                                                  sitelibexp)}) {
-       next if $dir eq ".";
+       next if $dir eq $Curdir;
        next if $seen_dir{$dir}++;
        my($targetfile) = File::Spec->catfile($dir,$libdir,$file);
        next unless -f $targetfile;
@@ -251,7 +357,10 @@ sub inc_uninstall {
            if ($verbose) {
                $Inc_uninstall_warn_handler ||= new ExtUtils::Install::Warn;
                $libdir =~ s|^\./||s ; # That's just cosmetics, no need to port. It looks prettier.
-               $Inc_uninstall_warn_handler->add("$libdir/$file",$targetfile);
+               $Inc_uninstall_warn_handler->add(
+                                     File::Spec->catfile($libdir, $file),
+                                     $targetfile
+                                    );
            }
            # if not verbose, we just say nothing
        } else {
@@ -274,6 +383,24 @@ sub run_filter {
     close CMD or die "Filter command '$cmd' failed for $src";
 }
 
+
+=item B<pm_to_blib>
+
+    pm_to_blib(\%from_to, $autosplit_dir);
+    pm_to_blib(\%from_to, $autosplit_dir, $filter_cmd);
+
+Copies each key of %from_to to its corresponding value efficiently.
+Filenames with the extension .pm are autosplit into the $autosplit_dir.
+
+$filter_cmd is an optional shell command to run each .pm file through
+prior to splitting and copying.  Input is the contents of the module,
+output the new module contents.
+
+You can have an environment variable PERL_INSTALL_ROOT set which will
+be prepended as a directory to each installed file (and directory).
+
+=cut
+
 sub pm_to_blib {
     my($fromto,$autodir,$pm_filter) = @_;
 
@@ -297,41 +424,62 @@ sub pm_to_blib {
      }
 
     mkpath($autodir,0,0755);
-    foreach (keys %$fromto) {
-       my $dest = $fromto->{$_};
-       next if -f $dest && -M $dest < -M $_;
+    while(my($from, $to) = each %$fromto) {
+       next if -f $to && -M $to < -M $from;
 
        # When a pm_filter is defined, we need to pre-process the source first
        # to determine whether it has changed or not.  Therefore, only perform
        # the comparison check when there's no filter to be ran.
        #    -- RAM, 03/01/2001
 
-       my $need_filtering = defined $pm_filter && length $pm_filter && /\.pm$/;
+       my $need_filtering = defined $pm_filter && length $pm_filter && 
+                             $from =~ /\.pm$/;
 
-       if (!$need_filtering && 0 == compare($_,$dest)) {
-           print "Skip $dest (unchanged)\n";
+       if (!$need_filtering && 0 == compare($from,$to)) {
+           print "Skip $to (unchanged)\n";
            next;
        }
-       if (-f $dest){
-           forceunlink($dest);
+       if (-f $to){
+           forceunlink($to);
        } else {
-           mkpath(dirname($dest),0,0755);
+           mkpath(dirname($to),0,0755);
        }
        if ($need_filtering) {
-           run_filter($pm_filter, $_, $dest);
-           print "$pm_filter <$_ >$dest\n";
+           run_filter($pm_filter, $from, $to);
+           print "$pm_filter <$from >$to\n";
        } else {
-           copy($_,$dest);
-           print "cp $_ $dest\n";
+           copy($from,$to);
+           print "cp $from $to\n";
        }
-       my($mode,$atime,$mtime) = (stat)[2,8,9];
-       utime($atime,$mtime+$Is_VMS,$dest);
-       chmod(0444 | ( $mode & 0111 ? 0111 : 0 ),$dest);
-       next unless /\.pm$/;
-       autosplit($dest,$autodir);
+       my($mode,$atime,$mtime) = (stat $from)[2,8,9];
+       utime($atime,$mtime+$Is_VMS,$to);
+       chmod(0444 | ( $mode & 0111 ? 0111 : 0 ),$to);
+       next unless $from =~ /\.pm$/;
+       _autosplit($to,$autodir);
     }
 }
 
+
+=begin _private
+
+=item _autosplit
+
+From 1.0307 back, AutoSplit will sometimes leave an open filehandle to
+the file being split.  This causes problems on systems with mandatory
+locking (ie. Windows).  So we wrap it and close the filehandle.
+
+=end _private
+
+=cut
+
+sub _autosplit {
+    my $retval = autosplit(@_);
+    close *AutoSplit::IN if defined *AutoSplit::IN{IO};
+
+    return $retval;
+}
+
+
 package ExtUtils::Install::Warn;
 
 sub new { bless {}, shift }
@@ -342,87 +490,57 @@ sub add {
 }
 
 sub DESTROY {
-       unless(defined $INSTALL_ROOT) {
-               my $self = shift;
-               my($file,$i,$plural);
-               foreach $file (sort keys %$self) {
-               $plural = @{$self->{$file}} > 1 ? "s" : "";
-               print "## Differing version$plural of $file found. You might like to\n";
-               for (0..$#{$self->{$file}}) {
-                       print "rm ", $self->{$file}[$_], "\n";
-                       $i++;
-               }
-               }
-               $plural = $i>1 ? "all those files" : "this file";
-               print "## Running 'make install UNINST=1' will unlink $plural for you.\n";
-       }
+    unless(defined $INSTALL_ROOT) {
+        my $self = shift;
+        my($file,$i,$plural);
+        foreach $file (sort keys %$self) {
+            $plural = @{$self->{$file}} > 1 ? "s" : "";
+            print "## Differing version$plural of $file found. You might like to\n";
+            for (0..$#{$self->{$file}}) {
+                print "rm ", $self->{$file}[$_], "\n";
+                $i++;
+            }
+        }
+        $plural = $i>1 ? "all those files" : "this file";
+        print "## Running 'make install UNINST=1' will unlink $plural for you.\n";
+    }
 }
 
-1;
+=back
 
-__END__
 
-=head1 NAME
+=head1 ENVIRONMENT
 
-ExtUtils::Install - install files from here to there
+=over 4
 
-=head1 SYNOPSIS
+=item B<PERL_INSTALL_ROOT>
 
-B<use ExtUtils::Install;>
+Will be prepended to each install path.
 
-B<install($hashref,$verbose,$nonono);>
+=back
 
-B<uninstall($packlistfile,$verbose,$nonono);>
+=head1 AUTHOR
 
-B<pm_to_blib($hashref);>
+Original author lost in the mists of time.  Probably the same as Makemaker.
 
-=head1 DESCRIPTION
+Currently maintained by Michael G Schwern <F<schwern@pobox.com>>
 
-Both install() and uninstall() are specific to the way
-ExtUtils::MakeMaker handles the installation and deinstallation of
-perl modules. They are not designed as general purpose tools.
+Send patches and ideas to <F<makemaker@perl.org>>.
 
-install() takes three arguments. A reference to a hash, a verbose
-switch and a don't-really-do-it switch. The hash ref contains a
-mapping of directories: each key/value pair is a combination of
-directories to be copied. Key is a directory to copy from, value is a
-directory to copy to. The whole tree below the "from" directory will
-be copied preserving timestamps and permissions.
+Send bug reports via http://rt.cpan.org/.  Please send your
+generated Makefile along with your report.
 
-There are two keys with a special meaning in the hash: "read" and
-"write". After the copying is done, install will write the list of
-target files to the file named by C<$hashref-E<gt>{write}>. If there is
-another file named by C<$hashref-E<gt>{read}>, the contents of this file will
-be merged into the written file. The read and the written file may be
-identical, but on AFS it is quite likely that people are installing to a
-different directory than the one where the files later appear.
-
-install_default() takes one or less arguments.  If no arguments are 
-specified, it takes $ARGV[0] as if it was specified as an argument.  
-The argument is the value of MakeMaker's C<FULLEXT> key, like F<Tk/Canvas>.  
-This function calls install() with the same arguments as the defaults 
-the MakeMaker would use.
-
-The argument-less form is convenient for install scripts like
-
-  perl -MExtUtils::Install -e install_default Tk/Canvas
-
-Assuming this command is executed in a directory with a populated F<blib> 
-directory, it will proceed as if the F<blib> was build by MakeMaker on 
-this machine.  This is useful for binary distributions.
-
-uninstall() takes as first argument a file containing filenames to be
-unlinked. The second argument is a verbose switch, the third is a
-no-don't-really-do-it-now switch.
-
-pm_to_blib() takes a hashref as the first argument and copies all keys
-of the hash to the corresponding values efficiently. Filenames with
-the extension pm are autosplit. Second argument is the autosplit
-directory.  If third argument is not empty, it is taken as a filter command
-to be ran on each .pm file, the output of the command being what is finally
-copied, and the source for auto-splitting.
+For more up-to-date information, see http://www.makemaker.org.
+
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or 
+modify it under the same terms as Perl itself.
+
+See F<http://www.perl.com/perl/misc/Artistic.html>
 
-You can have an environment variable PERL_INSTALL_ROOT set which will
-be prepended as a directory to each installed file (and directory).
 
 =cut
+
+1;
index de79088..8604f82 100644 (file)
@@ -7,12 +7,18 @@ use File::Spec;
 require ExtUtils::Liblist::Kid;
 @ISA = qw(ExtUtils::Liblist::Kid File::Spec);
 
+# Backwards compatibility with old interface.
+sub ext {
+    goto &ExtUtils::Liblist::Kid::ext;
+}
+
 sub lsdir {
   shift;
   my $rex = qr/$_[1]/;
   opendir DIR, $_[0];
-  grep /$rex/, readdir DIR;
+  my @out = grep /$rex/, readdir DIR;
   closedir DIR;
+  return @out;
 }
 
 __END__
@@ -23,9 +29,12 @@ ExtUtils::Liblist - determine libraries to use and how to use them
 
 =head1 SYNOPSIS
 
-C<require ExtUtils::Liblist;>
+  require ExtUtils::Liblist;
+
+  $MM->ext($potential_libs, $verbose, $need_names);
 
-C<ExtUtils::Liblist::ext($self, $potential_libs, $verbose, $need_names);>
+  # Usually you can get away with:
+  ExtUtils::Liblist->ext($potential_libs, $verbose, $need_names)
 
 =head1 DESCRIPTION
 
index a7e4c2d..d17eb87 100644 (file)
@@ -24,6 +24,8 @@ sub ext {
 
 sub _unix_os2_ext {
     my($self,$potential_libs, $verbose, $give_libs) = @_;
+    $verbose ||= 0;
+
     if ($^O =~ 'os2' and $Config{perllibs}) { 
        # Dynamic libraries are not transitive, so we may need including
        # the libraries linked against perl.dll again.
@@ -34,8 +36,8 @@ sub _unix_os2_ext {
     return ("", "", "", "", ($give_libs ? [] : ())) unless $potential_libs;
     warn "Potential libraries are '$potential_libs':\n" if $verbose;
 
-    my($so)   = $Config{'so'};
-    my($libs) = $Config{'perllibs'};
+    my($so)   = $Config{so};
+    my($libs) = defined $Config{perllibs} ? $Config{perllibs} : $Config{libs};
     my $Config_libext = $Config{lib_ext} || ".a";
 
 
@@ -157,7 +159,7 @@ sub _unix_os2_ext {
 
            # what do we know about this library...
            my $is_dyna = ($fullname !~ /\Q$Config_libext\E\z/);
-           my $in_perl = ($libs =~ /\B-l\Q$ {thislib}\E\b/s);
+           my $in_perl = ($libs =~ /\B-l\Q${thislib}\E\b/s);
 
            # Do not add it into the list if it is already linked in
            # with the main perl executable.
@@ -212,6 +214,7 @@ sub _win32_ext {
     require Text::ParseWords;
 
     my($self, $potential_libs, $verbose, $give_libs) = @_;
+    $verbose ||= 0;
 
     # If user did not supply a list, we punt.
     # (caller should probably use the list in $Config{libs})
@@ -340,7 +343,7 @@ sub _win32_ext {
 
        # give up
        warn "Note (probably harmless): "
-                    ."No library found for '$thislib'\n"
+                    ."No library found for $thislib\n"
            unless $found_lib>0;
 
     }
@@ -364,9 +367,11 @@ sub _win32_ext {
 
 sub _vms_ext {
   my($self, $potential_libs,$verbose,$give_libs) = @_;
+  $verbose ||= 0;
+
   my(@crtls,$crtlstr);
   my($dbgqual) = $self->{OPTIMIZE} || $Config{'optimize'} ||
-                 $self->{CCFLAS}   || $Config{'ccflags'};
+                 $self->{CCFLAGS}   || $Config{'ccflags'};
   @crtls = ( ($dbgqual =~ m-/Debug-i ? $Config{'dbgprefix'} : '')
               . 'PerlShr/Share' );
   push(@crtls, grep { not /\(/ } split /\s+/, $Config{'perllibs'});
@@ -398,8 +403,8 @@ sub _vms_ext {
   my(@dirs,@libs,$dir,$lib,%found,@fndlibs,$ldlib);
   my $cwd = cwd();
   my($so,$lib_ext,$obj_ext) = @Config{'so','lib_ext','obj_ext'};
-  # List of common Unix library names and there VMS equivalents
-  # (VMS equivalent of '' indicates that the library is automatially
+  # List of common Unix library names and their VMS equivalents
+  # (VMS equivalent of '' indicates that the library is automatically
   # searched by the linker, and should be skipped here.)
   my(@flibs, %libs_seen);
   my %libmap = ( 'm' => '', 'f77' => '', 'F77' => '', 'V77' => '', 'c' => '',
index 61dde53..a916b62 100644 (file)
@@ -2,16 +2,17 @@
 \bRCS\b
 \bCVS\b
 ,v$
+\B\.svn\b
 
 # Avoid Makemaker generated and utility files.
-^MANIFEST\.bak
-^Makefile$
-^blib/
-^MakeMaker-\d
-^pm_to_blib$
+\bMANIFEST\.bak
+\bMakefile$
+\bblib/
+\bMakeMaker-\d
+\bpm_to_blib$
 
 # Avoid temp and backup files.
 ~$
 \.old$
 \#$
-^\.#
+\b\.#
index fb48ae2..20c6bd6 100644 (file)
@@ -3,6 +3,7 @@ package ExtUtils::MM_Any;
 use strict;
 use vars qw($VERSION @ISA);
 $VERSION = 0.04;
+@ISA = qw(File::Spec);
 
 use Config;
 use File::Spec;
@@ -41,95 +42,372 @@ B<THIS MAY BE TEMPORARY!>
 These are methods which are by their nature cross-platform and should
 always be cross-platform.
 
-=head2 File::Spec wrappers  B<DEPRECATED>
+=head2 File::Spec wrappers
 
-The following methods are deprecated wrappers around File::Spec
-functions.  They exist from before File::Spec did and in fact are from
-which File::Spec sprang.
+ExtUtils::MM_Any is a subclass of File::Spec.  The methods noted here
+override File::Spec.
 
-They are all deprecated.  Please use File::Spec directly.
+=over 4
+
+=item catfile
+
+File::Spec <= 0.83 has a bug where the file part of catfile is not
+canonicalized.  This override fixes that bug.
+
+=cut
+
+sub catfile {
+    my $self = shift;
+    return $self->canonpath($self->SUPER::catfile(@_));
+}
+
+=back
+
+=head1 Thought To Be Cross-Platform Methods
+
+These are methods which are thought to be cross-platform by virtue of
+having been written in a way to avoid incompatibilities.  They may
+require partial overrides.
 
 =over 4
 
-=item canonpath
+=item B<split_command>
+
+    my @cmds = $MM->split_command($cmd, @args);
+
+Most OS have a maximum command length they can execute at once.  Large
+modules can easily generate commands well past that limit.  Its
+necessary to split long commands up into a series of shorter commands.
+
+split_command() will return a series of @cmds each processing part of
+the args.  Collectively they will process all the arguments.  Each
+individual line in @cmds will not be longer than the
+$self->max_exec_len being careful to take into account macro expansion.
+
+$cmd should include any switches and repeated initial arguments.
+
+If no @args are given, no @cmds will be returned.
+
+Pairs of arguments will always be preserved in a single command, this
+is a heuristic for things like pm_to_blib and pod2man which work on
+pairs of arguments.  This makes things like this safe:
+
+    $self->split_command($cmd, %pod2man);
+
 
 =cut
 
-sub canonpath {
-    shift;
-    return File::Spec->canonpath(@_);;
+sub split_command {
+    my($self, $cmd, @args) = @_;
+
+    my @cmds = ();
+    return(@cmds) unless @args;
+
+    # If the command was given as a here-doc, there's probably a trailing
+    # newline.
+    chomp $cmd;
+
+    # set aside 20% for macro expansion.
+    my $len_left = int($self->max_exec_len * 0.80);
+    $len_left -= length $self->_expand_macros($cmd);
+
+    do {
+        my $arg_str = '';
+        my @next_args;
+        while( @next_args = splice(@args, 0, 2) ) {
+            # Two at a time to preserve pairs.
+            my $next_arg_str = "\t  ". join ' ', @next_args, "\n";
+
+            if( !length $arg_str ) {
+                $arg_str .= $next_arg_str
+            }
+            elsif( length($arg_str) + length($next_arg_str) > $len_left ) {
+                unshift @args, @next_args;
+                last;
+            }
+            else {
+                $arg_str .= $next_arg_str;
+            }
+        }
+        chop $arg_str;
+
+        push @cmds, $self->escape_newlines("$cmd\n$arg_str");
+    } while @args;
+
+    return @cmds;
 }
 
-=item catdir
+
+sub _expand_macros {
+    my($self, $cmd) = @_;
+
+    $cmd =~ s{\$\((\w+)\)}{
+        defined $self->{$1} ? $self->{$1} : "\$($1)"
+    }e;
+    return $cmd;
+}
+
+
+=item B<echo>
+
+    my @commands = $MM->echo($text);
+    my @commands = $MM->echo($text, $file);
+    my @commands = $MM->echo($text, $file, $appending);
+
+Generates a set of @commands which print the $text to a $file.
+
+If $file is not given, output goes to STDOUT.
+
+If $appending is true the $file will be appended to rather than
+overwritten.
 
 =cut
 
-sub catdir {
-    shift;
-    return File::Spec->catdir(@_);
+sub echo {
+    my($self, $text, $file, $appending) = @_;
+    $appending ||= 0;
+
+    my @cmds = map { '$(NOECHO) $(ECHO) '.$self->quote_literal($_) } 
+               split /\n/, $text;
+    if( $file ) {
+        my $redirect = $appending ? '>>' : '>';
+        $cmds[0] .= " $redirect $file";
+        $_ .= " >> $file" foreach @cmds[1..$#cmds];
+    }
+
+    return @cmds;
 }
 
-=item catfile
+
+=item init_VERSION
+
+    $mm->init_VERSION
+
+Initialize macros representing versions of MakeMaker and other tools
+
+MAKEMAKER: path to the MakeMaker module.
+
+MM_VERSION: ExtUtils::MakeMaker Version
+
+MM_REVISION: ExtUtils::MakeMaker version control revision (for backwards 
+             compat)
+
+VERSION: version of your module
+
+VERSION_MACRO: which macro represents the version (usually 'VERSION')
+
+VERSION_SYM: like version but safe for use as an RCS revision number
+
+DEFINE_VERSION: -D line to set the module version when compiling
+
+XS_VERSION: version in your .xs file.  Defaults to $(VERSION)
+
+XS_VERSION_MACRO: which macro represents the XS version.
+
+XS_DEFINE_VERSION: -D line to set the xs version when compiling.
+
+Called by init_main.
 
 =cut
 
-sub catfile {
-    shift;
-    return File::Spec->catfile(@_);
+sub init_VERSION {
+    my($self) = shift;
+
+    $self->{MAKEMAKER}  = $INC{'ExtUtils/MakeMaker.pm'};
+    $self->{MM_VERSION} = $ExtUtils::MakeMaker::VERSION;
+    $self->{MM_REVISION}= $ExtUtils::MakeMaker::Revision;
+    $self->{VERSION_FROM} ||= '';
+
+    if ($self->{VERSION_FROM}){
+        $self->{VERSION} = $self->parse_version($self->{VERSION_FROM});
+        if( $self->{VERSION} eq 'undef' ) {
+            require Carp;
+            Carp::carp("WARNING: Setting VERSION via file ".
+                       "'$self->{VERSION_FROM}' failed\n");
+        }
+    }
+
+    # strip blanks
+    if (defined $self->{VERSION}) {
+        $self->{VERSION} =~ s/^\s+//;
+        $self->{VERSION} =~ s/\s+$//;
+    }
+    else {
+        $self->{VERSION} = '';
+    }
+
+
+    $self->{VERSION_MACRO}  = 'VERSION';
+    ($self->{VERSION_SYM} = $self->{VERSION}) =~ s/\W/_/g;
+    $self->{DEFINE_VERSION} = '-D$(VERSION_MACRO)=\"$(VERSION)\"';
+
+
+    # Graham Barr and Paul Marquess had some ideas how to ensure
+    # version compatibility between the *.pm file and the
+    # corresponding *.xs file. The bottomline was, that we need an
+    # XS_VERSION macro that defaults to VERSION:
+    $self->{XS_VERSION} ||= $self->{VERSION};
+
+    $self->{XS_VERSION_MACRO}  = 'XS_VERSION';
+    $self->{XS_DEFINE_VERSION} = '-D$(XS_VERSION_MACRO)=\"$(XS_VERSION)\"';
+
 }
 
-=item curdir
+=item wraplist
+
+Takes an array of items and turns them into a well-formatted list of
+arguments.  In most cases this is simply something like:
+
+    FOO \
+    BAR \
+    BAZ
 
 =cut
 
-my $Curdir = File::Spec->curdir;
-sub curdir {
-    return $Curdir;
+sub wraplist {
+    my $self = shift;
+    return join " \\\n\t", @_;
 }
 
-=item file_name_is_absolute
+=item manifypods
+
+Defines targets and routines to translate the pods into manpages and
+put them into the INST_* directories.
 
 =cut
 
-sub file_name_is_absolute {
-    shift;
-    return File::Spec->file_name_is_absolute(@_);
+sub manifypods {
+    my $self          = shift;
+
+    my $POD2MAN_EXE_macro = $self->POD2MAN_EXE_macro();
+    my $manifypods_target = $self->manifypods_target();
+
+    return <<END_OF_TARGET;
+
+# --- Begin manifypods section:
+$POD2MAN_EXE_macro
+
+$manifypods_target
+
+# --- End manifypods section --- #
+
+END_OF_TARGET
+
 }
 
-=item path
+
+=item manifypods_target
+
+  my $manifypods_target = $self->manifypods_target;
+
+Generates the manifypods target.  This target generates man pages from
+all POD files in MAN1PODS and MAN3PODS.
 
 =cut
 
-sub path {
-    return File::Spec->path();
+sub manifypods_target {
+    my($self) = shift;
+
+    my $man1pods      = '';
+    my $man3pods      = '';
+    my $dependencies  = '';
+
+    # populate manXpods & dependencies:
+    foreach my $name (keys %{$self->{MAN1PODS}}, keys %{$self->{MAN3PODS}}) {
+        $dependencies .= " \\\n\t$name";
+    }
+
+    foreach my $name (keys %{$self->{MAN3PODS}}) {
+        $dependencies .= " \\\n\t$name"
+    }
+
+    my $manify = <<END;
+manifypods : pure_all $dependencies
+END
+
+    my @man_cmds;
+    foreach my $section (qw(1 3)) {
+        my $pods = $self->{"MAN${section}PODS"};
+        push @man_cmds, $self->split_command(<<CMD, %$pods);
+       \$(NOECHO) \$(POD2MAN_EXE) --section=$section --perm_rw=\$(PERM_RW)
+CMD
+    }
+
+    $manify .= join '', map { "$_\n" } @man_cmds;
+
+    return $manify;
 }
 
-=item rootdir
+
+=item makemakerdflt_target
+
+  my $make_frag = $mm->makemakerdflt_target
+
+Returns a make fragment with the makemakerdeflt_target specified.
+This target is the first target in the Makefile, is the default target
+and simply points off to 'all' just in case any make variant gets
+confused or something gets snuck in before the real 'all' target.
 
 =cut
 
-my $Rootdir = File::Spec->rootdir;
-sub rootdir {
-    return $Rootdir;
+sub makemakerdflt_target {
+    return <<'MAKE_FRAG';
+makemakerdflt: all
+       $(NOECHO) $(NOOP)
+MAKE_FRAG
+
 }
 
-=item updir
+
+=item special_targets
+
+  my $make_frag = $mm->special_targets
+
+Returns a make fragment containing any targets which have special
+meaning to make.  For example, .SUFFIXES and .PHONY.
 
 =cut
 
-my $Updir = File::Spec->updir;
-sub updir {
-    return $Updir;
+sub special_targets {
+    my $make_frag = <<'MAKE_FRAG';
+.SUFFIXES: .xs .c .C .cpp .i .s .cxx .cc $(OBJ_EXT)
+
+.PHONY: all config static dynamic test linkext manifest
+
+MAKE_FRAG
+
+    $make_frag .= <<'MAKE_FRAG' if $ENV{CLEARCASE_ROOT};
+.NO_CONFIG_REC: Makefile
+
+MAKE_FRAG
+
+    return $make_frag;
 }
 
-=back
+=item POD2MAN_EXE_macro
 
-=head1 Thought To Be Cross-Platform Methods
+  my $pod2man_exe_macro = $self->POD2MAN_EXE_macro
 
-These are methods which are thought to be cross-platform by virtue of
-having been written in a way to avoid incompatibilities.
+Returns a definition for the POD2MAN_EXE macro.  This is a program
+which emulates the pod2man utility.  You can add more switches to the
+command by simply appending them on the macro.
+
+Typical usage:
+
+    $(POD2MAN_EXE) --section=3 --perm_rw=$(PERM_RW) podfile man_page
+
+=cut
+
+sub POD2MAN_EXE_macro {
+    my $self = shift;
+
+# Need the trailing '--' so perl stops gobbling arguments and - happens
+# to be an alternative end of line seperator on VMS so we quote it
+    return <<'END_OF_DEF';
+POD2MAN_EXE = $(PERLRUN) "-MExtUtils::Command::MM" -e pod2man "--"
+END_OF_DEF
+}
 
-=over 4
 
 =item test_via_harness
 
@@ -167,12 +445,324 @@ sub test_via_script {
     return qq{\t$perl "-I\$(INST_LIB)" "-I\$(INST_ARCHLIB)" $script\n};
 }
 
+=item libscan
+
+  my $wanted = $self->libscan($path);
+
+Takes a path to a file or dir and returns an empty string if we don't
+want to include this file in the library.  Otherwise it returns the
+the $path unchanged.
+
+Mainly used to exclude RCS, CVS, and SCCS directories from
+installation.
+
+=cut
+
+sub libscan {
+    my($self,$path) = @_;
+    my($dirs,$file) = ($self->splitpath($path))[1,2];
+    return '' if grep /^RCS|CVS|SCCS|\.svn$/, 
+                     $self->splitdir($dirs), $file;
+
+    return $path;
+}
+
+=item tool_autosplit
+
+Defines a simple perl call that runs autosplit. May be deprecated by
+pm_to_blib soon.
+
+=cut
+
+sub tool_autosplit {
+    my($self, %attribs) = @_;
+
+    my $maxlen = $attribs{MAXLEN} ? '$$AutoSplit::Maxlen=$attribs{MAXLEN};' 
+                                  : '';
+
+    my $asplit = $self->oneliner(sprintf <<'PERL_CODE', $maxlen);
+use AutoSplit; %s autosplit($$ARGV[0], $$ARGV[1], 0, 1, 1)
+PERL_CODE
+
+    return sprintf <<'MAKE_FRAG', $asplit;
+# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto
+AUTOSPLITFILE = %s
+
+MAKE_FRAG
+
+}
+
+
+=item all_target
+
+Generate the default target 'all'.
+
+=cut
+
+sub all_target {
+    my $self = shift;
+
+    return <<'MAKE_EXT';
+all :: pure_all
+       $(NOECHO) $(NOOP)
+MAKE_EXT
+
+}
+
+
+=item metafile_target
+
+    my $target = $mm->metafile_target;
+
+Generate the metafile target.
+
+Writes the file META.yml, YAML encoded meta-data about the module.  The
+format follows Module::Build's as closely as possible.  Additionally, we
+include:
+
+    version_from
+    installdirs
+
+=cut
+
+sub metafile_target {
+    my $self = shift;
+
+    my $prereq_pm = '';
+    while( my($mod, $ver) = each %{$self->{PREREQ_PM}} ) {
+        $prereq_pm .= sprintf "    %-30s %s\n", "$mod:", $ver;
+    }
+    
+    my $meta = <<YAML;
+#XXXXXXX This is a prototype!!!  It will change in the future!!! XXXXX#
+name:         $self->{DISTNAME}
+version:      $self->{VERSION}
+version_from: $self->{VERSION_FROM}
+installdirs:  $self->{INSTALLDIRS}
+requires:
+$prereq_pm
+distribution_type: module
+generated_by: ExtUtils::MakeMaker version $ExtUtils::MakeMaker::VERSION
+YAML
+
+    my @write_meta = $self->echo($meta, 'META.yml');
+    return sprintf <<'MAKE_FRAG', join "\n\t", @write_meta;
+metafile :
+       %s
+MAKE_FRAG
+
+}
+
+
+=item metafile_addtomanifest_target
+
+  my $target = $mm->metafile_addtomanifest_target
+
+Adds the META.yml file to the MANIFEST.
+
+=cut
+
+sub metafile_addtomanifest_target {
+    my $self = shift;
+
+    my $add_meta = $self->oneliner(<<'CODE', ['-MExtUtils::Manifest=maniadd']);
+maniadd({q{META.yml} => q{Module meta-data in YAML}});
+CODE
+
+    return sprintf <<'MAKE_FRAG', $add_meta;
+metafile_addtomanifest:
+       $(NOECHO) %s
+MAKE_FRAG
+
+}
+
+
+=back
+
+=head2 Abstract methods
+
+Methods which cannot be made cross-platform and each subclass will
+have to do their own implementation.
+
+=over 4
+
+=item oneliner
+
+  my $oneliner = $MM->oneliner($perl_code);
+  my $oneliner = $MM->oneliner($perl_code, \@switches);
+
+This will generate a perl one-liner safe for the particular platform
+you're on based on the given $perl_code and @switches (a -e is
+assumed) suitable for using in a make target.  It will use the proper
+shell quoting and escapes.
+
+$(PERLRUN) will be used as perl.
+
+Any newlines in $perl_code will be escaped.  Leading and trailing
+newlines will be stripped.  Makes this idiom much easier:
+
+    my $code = $MM->oneliner(<<'CODE', [...switches...]);
+some code here
+another line here
+CODE
+
+Usage might be something like:
+
+    # an echo emulation
+    $oneliner = $MM->oneliner('print "Foo\n"');
+    $make = '$oneliner > somefile';
+
+All dollar signs must be doubled in the $perl_code if you expect them
+to be interpreted normally, otherwise it will be considered a make
+macro.  Also remember to quote make macros else it might be used as a
+bareword.  For example:
+
+    # Assign the value of the $(VERSION_FROM) make macro to $vf.
+    $oneliner = $MM->oneliner('$$vf = "$(VERSION_FROM)"');
+
+Its currently very simple and may be expanded sometime in the figure
+to include more flexible code and switches.
+
+
+=item B<quote_literal>
+
+    my $safe_text = $MM->quote_literal($text);
+
+This will quote $text so it is interpreted literally in the shell.
+
+For example, on Unix this would escape any single-quotes in $text and
+put single-quotes around the whole thing.
+
+
+=item B<escape_newlines>
+
+    my $escaped_text = $MM->escape_newlines($text);
+
+Shell escapes newlines in $text.
+
+
+=item max_exec_len
+
+    my $max_exec_len = $MM->max_exec_len;
+
+Calculates the maximum command size the OS can exec.  Effectively,
+this is the max size of a shell command line.
+
+=for _private
+$self->{_MAX_EXEC_LEN} is set by this method, but only for testing purposes.
+
+=item B<init_others>
+
+    $MM->init_others();
+
+Initializes the macro definitions used by tools_other() and places them
+in the $MM object.
+
+If there is no description, its the same as the parameter to
+WriteMakefile() documented in ExtUtils::MakeMaker.
+
+Defines at least these macros.
+
+  Macro             Description
+
+  NOOP              
+  NOECHO                                        
+
+  MAKEFILE
+  FIRST_MAKEFILE
+  MAKEFILE_OLD
+  MAKE_APERL_FILE   File used by MAKE_APERL
+
+  SHELL             Program used to run
+                    shell commands
+
+  RM_F              Remove a file 
+  RM_RF             Remove a directory          
+  TOUCH             Update a file's timestamp   
+  TEST_F            Test for a file's existence 
+  CP                Copy a file                 
+  MV                Move a file                 
+  CHMOD             Change permissions on a     
+                    file
+
+  UMASK_NULL        Nullify umask
+  DEV_NULL          Supress all command output
+
+=item init_DIRFILESEP
+
+  $MM->init_DIRFILESEP;
+  my $dirfilesep = $MM->{DIRFILESEP};
+
+Initializes the DIRFILESEP macro which is the seperator between the
+directory and filename in a filepath.  ie. / on Unix, \ on Win32 and
+nothing on VMS.
+
+For example:
+
+    # instead of $(INST_ARCHAUTODIR)/extralibs.ld
+    $(INST_ARCHAUTODIR)$(DIRFILESEP)extralibs.ld
+
+Something of a hack but it prevents a lot of code duplication between
+MM_* variants.
+
+Do not use this as a seperator between directories.  Some operating
+systems use different seperators between subdirectories as between
+directories and filenames (for example:  VOLUME:[dir1.dir2]file on VMS).
+
+=item init_linker
+
+    $mm->init_linker;
+
+Initialize macros which have to do with linking.
+
+PERL_ARCHIVE: path to libperl.a equivalent to be linked to dynamic
+extensions.
+
+PERL_ARCHIVE_AFTER: path to a library which should be put on the
+linker command line I<after> the external libraries to be linked to
+dynamic extensions.  This may be needed if the linker is one-pass, and
+Perl includes some overrides for C RTL functions, such as malloc().
+
+EXPORT_LIST: name of a file that is passed to linker to define symbols
+to be exported.
+
+Some OSes do not need these in which case leave it blank.
+
+
+=item init_platform
+
+    $mm->init_platform
+
+Initialize any macros which are for platform specific use only.
+
+A typical one is the version number of your OS specific mocule.
+(ie. MM_Unix_VERSION or MM_VMS_VERSION).
+
+=item platform_constants
+
+    my $make_frag = $mm->platform_constants
+
+Returns a make fragment defining all the macros initialized in
+init_platform() rather than put them in constants().
+
+=cut
+
+sub init_platform {
+    return '';
+}
+
+sub platform_constants {
+    return '';
+}
+
+
 =back
 
 =head1 AUTHOR
 
-Michael G Schwern <schwern@pobox.com> with code from ExtUtils::MM_Unix
-and ExtUtils::MM_Win32.
+Michael G Schwern <schwern@pobox.com> and the denizens of
+makemaker@perl.org with code from ExtUtils::MM_Unix and
+ExtUtils::MM_Win32.
 
 
 =cut
index 5118747..4f4a3e5 100644 (file)
@@ -28,18 +28,20 @@ use vars qw(@ISA $VERSION);
 $VERSION = 1.03;
 
 
-=item perl_archive
+=item init_linker
 
-This is internal method that returns path to libperl.a equivalent
-to be linked to dynamic extensions. UNIX does not have one, but at
-least BeOS has one.
+libperl.a equivalent to be linked to dynamic extensions.
 
 =cut
 
-sub perl_archive
-  {
-  return File::Spec->catdir('$(PERL_INC)',$Config{libperl});
-  }
+sub init_linker {
+    my($self) = shift;
+
+    $self->{PERL_ARCHIVE} ||= 
+      File::Spec->catdir('$(PERL_INC)',$Config{libperl});
+    $self->{PERL_ARCHIVE_AFTER} ||= '';
+    $self->{EXPORT_LIST}  ||= '';
+}
 
 =back
 
index 3c37ffd..120e1bb 100644 (file)
@@ -10,7 +10,28 @@ require ExtUtils::MM_Any;
 require ExtUtils::MM_Unix;
 @ISA = qw( ExtUtils::MM_Any ExtUtils::MM_Unix );
 
-$VERSION = 1.04;
+$VERSION = 1.05;
+
+
+=head1 NAME
+
+ExtUtils::MM_Cygwin - methods to override UN*X behaviour in ExtUtils::MakeMaker
+
+=head1 SYNOPSIS
+
+ use ExtUtils::MM_Cygwin; # Done internally by ExtUtils::MakeMaker if needed
+
+=head1 DESCRIPTION
+
+See ExtUtils::MM_Unix for a documentation of the methods provided there.
+
+=over 4
+
+=item cflags (o)
+
+if configured for dynamic loading, triggers #define EXT in EXTERN.h
+
+=cut
 
 sub cflags {
     my($self,$libperl)=@_;
@@ -31,97 +52,45 @@ PERLTYPE = $self->{PERLTYPE}
 
 }
 
-sub manifypods {
-    my($self, %attribs) = @_;
-    return "\nmanifypods : pure_all\n\t$self->{NOECHO}\$(NOOP)\n" unless
-        %{$self->{MAN3PODS}} or %{$self->{MAN1PODS}};
-    my($dist);
-    my($pod2man_exe);
-    if (defined $self->{PERL_SRC}) {
-        $pod2man_exe = File::Spec->catfile($self->{PERL_SRC},'pod','pod2man');
-    } else {
-        $pod2man_exe = File::Spec->catfile($Config{scriptdirexp},'pod2man');
-    }
-    unless ($self->perl_script($pod2man_exe)) {
-        # No pod2man but some MAN3PODS to be installed
-        print <<END;
 
-Warning: I could not locate your pod2man program. Please make sure,
-         your pod2man program is in your PATH before you execute 'make'
+=item replace_manpage_separator (o)
 
-END
-        $pod2man_exe = "-S pod2man";
-    }
-    my(@m) = ();
-    push @m,
-qq[POD2MAN_EXE = $pod2man_exe\n],
-qq[POD2MAN = \$(PERL) -we '%m=\@ARGV;for (keys %m){' \\\n],
-q[-e 'next if -e $$m{$$_} && -M $$m{$$_} < -M $$_ && -M $$m{$$_} < -M "],
- $self->{MAKEFILE}, q[";' \\
--e 'print "Manifying $$m{$$_}\n"; $$m{$$_} =~ s/::/./g;' \\
--e 'system(qq[$(PERLRUN) $(POD2MAN_EXE) ].qq[$$_>$$m{$$_}])==0 or warn "Couldn\\047t install $$m{$$_}\n";' \\
--e 'chmod(oct($(PERM_RW))), $$m{$$_} or warn "chmod $(PERM_RW) $$m{$$_}: $$!\n";}'
-];
-    push @m, "\nmanifypods : pure_all ";
-    push @m, join " \\\n\t", keys %{$self->{MAN1PODS}},
-                             keys %{$self->{MAN3PODS}};
-
-    push(@m,"\n");
-    if (%{$self->{MAN1PODS}} || %{$self->{MAN3PODS}}) {
-        grep { $self->{MAN1PODS}{$_} =~ s/::/./g } keys %{$self->{MAN1PODS}};
-        grep { $self->{MAN3PODS}{$_} =~ s/::/./g } keys %{$self->{MAN3PODS}};
-        push @m, "\t$self->{NOECHO}\$(POD2MAN) \\\n\t";
-        push @m, join " \\\n\t", %{$self->{MAN1PODS}}, %{$self->{MAN3PODS}};
-    }
-    join('', @m);
+replaces strings '::' with '.' in MAN*POD man page names
+
+=cut
+
+sub replace_manpage_separator {
+    my($self, $man) = @_;
+    $man =~ s{/+}{.}g;
+    return $man;
 }
 
-sub perl_archive {
+=item init_linker
+
+points to libperl.a
+
+=cut
+
+sub init_linker {
+    my $self = shift;
+
     if ($Config{useshrplib} eq 'true') {
         my $libperl = '$(PERL_INC)' .'/'. "$Config{libperl}";
         if( $] >= 5.007 ) {
             $libperl =~ s/a$/dll.a/;
         }
-        return $libperl;
+        $self->{PERL_ARCHIVE} = $libperl;
     } else {
-        return '$(PERL_INC)' .'/'. ("$Config{libperl}" or "libperl.a");
+        $self->{PERL_ARCHIVE} = 
+          '$(PERL_INC)' .'/'. ("$Config{libperl}" or "libperl.a");
     }
-}
-
-1;
-__END__
-
-=head1 NAME
-
-ExtUtils::MM_Cygwin - methods to override UN*X behaviour in ExtUtils::MakeMaker
-
-=head1 SYNOPSIS
-
- use ExtUtils::MM_Cygwin; # Done internally by ExtUtils::MakeMaker if needed
-
-=head1 DESCRIPTION
 
-See ExtUtils::MM_Unix for a documentation of the methods provided there.
-
-=over 4
-
-=item canonpath
-
-replaces backslashes with forward ones.  then acts as *nixish.
-
-=item cflags
-
-if configured for dynamic loading, triggers #define EXT in EXTERN.h
-
-=item manifypods
-
-replaces strings '::' with '.' in man page names
-
-=item perl_archive
-
-points to libperl.a
+    $self->{PERL_ARCHIVE_AFTER} ||= '';
+    $self->{EXPORT_LIST}  ||= '';
+}
 
 =back
 
 =cut
 
+1;
index 7af868e..93e01f2 100644 (file)
@@ -32,6 +32,8 @@ Unless otherwise stated, it works just like ExtUtils::MM_Unix
 
 =item B<replace_manpage_separator>
 
+Generates Foo__Bar.3 style man page names
+
 =cut
 
 sub replace_manpage_separator {
@@ -52,4 +54,5 @@ Michael G Schwern <schwern@pobox.com> with code from ExtUtils::MM_Unix
 L<ExtUtils::MM_Unix>, L<ExtUtils::MakeMaker>
 
 =cut
+
 1;
index 576d744..a83e37f 100644 (file)
@@ -12,13 +12,12 @@ require ExtUtils::MM_Unix;
 @ISA = qw( ExtUtils::MM_Any ExtUtils::MM_Unix );
 
 use vars qw($VERSION);
-$VERSION = '1.03';
+$VERSION = '1.04';
 
 use Config;
 use Cwd 'cwd';
 require Exporter;
 use File::Basename;
-use File::Spec;
 use vars qw(%make_data);
 
 my $Mac_FS = eval { require Mac::FileSpec::Unixish };
@@ -37,6 +36,8 @@ ExtUtils::MM_MacOS - methods to override UN*X behaviour in ExtUtils::MakeMaker
 
 MM_MacOS currently only produces an approximation to the correct Makefile.
 
+=over 4
+
 =cut
 
 sub new {
@@ -51,7 +52,7 @@ sub new {
 
     mkdir("Obj", 0777) unless -d "Obj";
 
-    $self = {} unless (defined $self);
+    $self = {} unless defined $self;
 
     check_hints($self);
 
@@ -61,7 +62,8 @@ sub new {
        if (ref $self->{CONFIGURE} eq 'CODE') {
            $self = { %$self, %{&{$self->{CONFIGURE}}}};
        } else {
-           Carp::croak "Attribute 'CONFIGURE' to WriteMakefile() not a code reference\n";
+            require Carp;
+           Carp::croak("Attribute 'CONFIGURE' to WriteMakefile() not a code reference\n");
        }
     }
 
@@ -78,7 +80,7 @@ sub new {
     }
 
     $ExtUtils::MakeMaker::Recognized_Att_Keys{$_} = 1
-       for map { $_ . 'Optimize' } qw(MWC MWCPPC MWC68K MPW MRC MRC SC);
+      for map { $_ . 'Optimize' } qw(MWC MWCPPC MWC68K MPW MRC MRC SC);
 
     if (defined $ExtUtils::MakeMaker::Parent[-2]){
         $self->{PARENT} = $ExtUtils::MakeMaker::Parent[-2];
@@ -86,7 +88,7 @@ sub new {
         for $key (@ExtUtils::MakeMaker::Prepend_parent) {
             next unless defined $self->{PARENT}{$key};
             $self->{$key} = $self->{PARENT}{$key};
-            unless ($^O eq 'VMS' && $key =~ /PERL$/) {
+            if ($key !~ /PERL$/) {
                 $self->{$key} = $self->catdir("..",$self->{$key})
                   unless $self->file_name_is_absolute($self->{$key});
             } else {
@@ -130,7 +132,7 @@ sub new {
 # This Makefile is for the $self->{NAME} extension to perl.
 #
 # It was generated automatically by MakeMaker version
-# $VERSION (Revision: $Revision) from the contents of
+# $ExtUtils::MakeMaker::VERSION (Revision: $ExtUtils::MakeMaker::Revision) from the contents of
 # Makefile.PL. Don't edit this file, edit Makefile.PL instead.
 #
 #      ANY CHANGES MADE HERE WILL BE LOST!
@@ -158,10 +160,10 @@ END
            pasthru c_o xs_c xs_o top_targets linkext 
            dynamic_bs dynamic_lib static_lib manifypods
            installbin subdirs dist_basics dist_core
-           dist_dir dist_test dist_ci install force perldepend makefile
-           staticmake test pm_to_blib selfdocument 
+           distdir dist_test dist_ci install force perldepend makefile
+           staticmake test pm_to_blib selfdocument
            const_loadlibs const_cccmd
-    /) 
+    /)
     {
        $self->{SKIPHASH}{$_} = 2;
     }
@@ -169,7 +171,7 @@ END
        unless grep /rulez/, @ExtUtils::MakeMaker::MM_Sections;
 
     if ($self->{PARENT}) {
-       for (qw/install dist dist_basics dist_core dist_dir dist_test dist_ci/) {
+       for (qw/install dist dist_basics dist_core distdir dist_test dist_ci/) {
            $self->{SKIPHASH}{$_} = 1;
        }
     }
@@ -182,7 +184,8 @@ END
 
     my $section;
     foreach $section ( @ExtUtils::MakeMaker::MM_Sections ){
-       next if ($self->{SKIPHASH}{$section} == 2);
+       next if defined $self->{SKIPHASH}{$section} &&
+                $self->{SKIPHASH}{$section} == 2;
        print "Processing Makefile '$section' section\n" if ($Verbose >= 2);
        $self->{ABSTRACT_FROM} = macify($self->{ABSTRACT_FROM})
                if $self->{ABSTRACT_FROM};
@@ -242,7 +245,7 @@ sub guess_name {
 
 =item macify
 
-Translate relative path names into Mac names.
+Translate relative Unix filepaths into Mac names.
 
 =cut
 
@@ -268,7 +271,7 @@ sub macify {
 
 =item patternify
 
-Translate to Mac names & patterns
+Translate Unix filepaths and shell globs to Mac style.
 
 =cut
 
@@ -291,7 +294,7 @@ sub patternify {
 
 =item init_main
 
-Initializes some of NAME, FULLEXT, BASEEXT, ROOTEXT, DLBASE, PERL_SRC,
+Initializes some of NAME, FULLEXT, BASEEXT, DLBASE, PERL_SRC,
 PERL_LIB, PERL_ARCHLIB, PERL_INC, INSTALLDIRS, INST_*, INSTALL*,
 PREFIX, CONFIG, AR, AR_STATIC_ARGS, LD, OBJ_EXT, LIB_EXT, MAP_TARGET,
 LIBPERL_A, VERSION_FROM, VERSION, DISTNAME, VERSION_SYM.
@@ -306,14 +309,10 @@ sub init_main {
     # NAME    = The perl module name for this extension (eg DBD::Oracle).
     # FULLEXT = Pathname for extension directory (eg DBD/Oracle).
     # BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT.
-    # ROOTEXT = Directory part of FULLEXT with trailing :.
     ($self->{FULLEXT} =
      $self->{NAME}) =~ s!::!:!g ;                   #eg. BSD:Foo:Socket
     ($self->{BASEEXT} =
      $self->{NAME}) =~ s!.*::!! ;                           #eg. Socket
-    ($self->{ROOTEXT} =
-     $self->{FULLEXT}) =~ s#:?\Q$self->{BASEEXT}\E$## ;      #eg. BSD:Foo
-    $self->{ROOTEXT} .= ":" if ($self->{ROOTEXT});
 
     # --- Initialize PERL_LIB, INST_LIB, PERL_SRC
 
@@ -339,21 +338,15 @@ sub init_main {
        }
     }
     if ($self->{PERL_SRC}){
-       $self->{MACPERL_SRC}  = File::Spec->catdir("$self->{PERL_SRC}","macos:");
-       $self->{MACPERL_LIB}  ||= File::Spec->catdir("$self->{MACPERL_SRC}","lib");
-       $self->{PERL_LIB}     ||= File::Spec->catdir("$self->{PERL_SRC}","lib");
+       $self->{PERL_LIB}     ||= $self->catdir("$self->{PERL_SRC}","lib");
        $self->{PERL_ARCHLIB} = $self->{PERL_LIB};
        $self->{PERL_INC}     = $self->{PERL_SRC};
-       $self->{MACPERL_INC}  = $self->{MACPERL_SRC};
     } else {
 # hmmmmmmm ... ?
-    $self->{PERL_LIB} ||= "$ENV{MACPERL}site_perl";
-       $self->{PERL_ARCHLIB} = $self->{PERL_LIB};
-       $self->{PERL_INC}     = $ENV{MACPERL};
-#      die <<END;
-#On MacOS, we need to build under the Perl source directory or have the MacPerl SDK
-#installed in the MacPerl folder.
-#END
+        $self->{PERL_LIB}    ||= "$ENV{MACPERL}site_perl";
+       $self->{PERL_ARCHLIB} =  $self->{PERL_LIB};
+       $self->{PERL_INC}     =  $ENV{MACPERL};
+        $self->{PERL_SRC}     = '';
     }
 
     $self->{INSTALLDIRS} = "perl";
@@ -368,12 +361,13 @@ sub init_main {
     # hm ... do we really care?  at all?
 #    warn "Warning: PERL_LIB ($self->{PERL_LIB}) seems not to be a perl library directory
 #        (Exporter.pm not found)"
-#      unless -f File::Spec->catfile("$self->{PERL_LIB}","Exporter.pm") ||
+#      unless -f $self->catfile("$self->{PERL_LIB}","Exporter.pm") ||
 #        $self->{NAME} eq "ExtUtils::MakeMaker";
 
     # Determine VERSION and VERSION_FROM
     ($self->{DISTNAME}=$self->{NAME}) =~ s#(::)#-#g unless $self->{DISTNAME};
     if ($self->{VERSION_FROM}){
+        # XXX replace with parse_version() override
        local *FH;
        open(FH,macify($self->{VERSION_FROM})) or
            die "Could not open '$self->{VERSION_FROM}' (attribute VERSION_FROM): $!";
@@ -410,18 +404,32 @@ sub init_main {
     # XS_VERSION macro that defaults to VERSION:
     $self->{XS_VERSION} ||= $self->{VERSION};
 
+
+    $self->{DEFINE} .= " \$(XS_DEFINE_VERSION) \$(DEFINE_VERSION)";
+
+    # Preprocessor definitions may be useful
+    $self->{DEFINE} =~ s/-D/-d /g; 
+
+    # UN*X includes probably are not useful
+    $self->{DEFINE} =~ s/-I\S+/_include($1)/eg;
+
+
+    if ($self->{INC}) {
+        # UN*X includes probably are not useful
+       $self->{INC} =~ s/-I(\S+)/_include($1)/eg;
+    }
+
+
     # --- Initialize Perl Binary Locations
 
     # Find Perl 5. The only contract here is that both 'PERL' and 'FULLPERL'
     # will be working versions of perl 5. miniperl has priority over perl
     # for PERL to ensure that $(PERL) is usable while building ./ext/*
     my ($component,@defpath);
-    foreach $component ($self->{PERL_SRC}, File::Spec->path(), $Config::Config{binexp}) {
+    foreach $component ($self->{PERL_SRC}, $self->path(), $Config::Config{binexp}) {
        push @defpath, $component if defined $component;
     }
     $self->{PERL} = "$self->{PERL_SRC}miniperl";
-    $self->{FULLPERL} = "$self->{PERL_SRC}perl";
-    $self->{MAKEFILE} = "Makefile.mk";
 }
 
 =item init_others
@@ -457,6 +465,51 @@ sub init_others {  # --- Initialize Other Attributes
        }
     }
     $self->{SOURCE} = $src;
+    $self->{FULLPERL} = "$self->{PERL_SRC}perl";
+    $self->{MAKEFILE}       = "Makefile.mk";
+    $self->{FIRST_MAKEFILE} = $self->{MAKEFILE};
+    $self->{MAKEFILE_OLD}   = $self->{MAKEFILE}.'.old';
+
+    $self->{'DEV_NULL'} ||= ' \xB3 Dev:Null';
+
+    return 1;
+}
+
+=item init_platform
+
+Add MACPERL_SRC MACPERL_LIB
+
+=item platform_constants
+
+Add MACPERL_SRC MACPERL_LIB MACLIBS_68K MACLIBS_PPC MACLIBS_SC MACLIBS_MRC
+MACLIBS_ALL_68K MACLIBS_ALL_PPC MACLIBS_SHARED
+
+XXX Few are initialized.  How many of these are ever used?
+
+=cut
+
+sub init_platform {
+    my $self = shift;
+
+    $self->{MACPERL_SRC}  = $self->catdir("$self->{PERL_SRC}","macos:");
+    $self->{MACPERL_LIB}  ||= $self->catdir("$self->{MACPERL_SRC}","lib");
+    $self->{MACPERL_INC}  = $self->{MACPERL_SRC};
+}
+
+
+
+sub platform_constants {
+    my $self = shift;
+
+    foreach my $macro (qw(MACPERL_SRC MACPERL_LIB MACLIBS_68K MACLIBS_PPC 
+                          MACLIBS_SC  MACLIBS_MRC MACLIBS_ALL_68K 
+                          MACLIBS_ALL_PPC MACLIBS_SHARED))
+    {
+        next unless defined $self->{$macro};
+        $make_frag .= "$macro = $self->{$macro}\n";
+    }
+
+    return $make_frag;
 }
 
 
@@ -474,7 +527,7 @@ sub init_dirscan {  # --- File and Directory Lists (.xs .pm .pod etc)
     # in case we don't find it below!
     if ($self->{VERSION_FROM}) {
         my $version_from = macify($self->{VERSION_FROM});
-        $pm{$version_from} = File::Spec->catfile('$(INST_LIBDIR)',
+        $pm{$version_from} = $self->catfile('$(INST_LIBDIR)',
             $version_from);
     }
 
@@ -494,7 +547,7 @@ sub init_dirscan {  # --- File and Directory Lists (.xs .pm .pod etc)
        } elsif ($name =~ /\.h$/i){
            $h{$name} = 1;
        } elsif ($name =~ /\.(p[ml]|pod)$/){
-           $pm{$name} = File::Spec->catfile('$(INST_LIBDIR)',$name);
+           $pm{$name} = $self->catfile('$(INST_LIBDIR)',$name);
        } elsif ($name =~ /\.PL$/ && $name ne "Makefile.PL") {
            ($pl_files{$name} = $name) =~ s/\.PL$// ;
        }
@@ -523,8 +576,8 @@ sub init_dirscan {  # --- File and Directory Lists (.xs .pm .pod etc)
     #
     # In this way the 'lib' directory is seen as the root of the actual
     # perl library whereas the others are relative to INST_LIBDIR
-    # (which includes ROOTEXT). This is a subtle distinction but one
-    # that's important for nested modules.
+    # This is a subtle distinction but one that's important for nested 
+    # modules.
 
     $self->{PMLIBDIRS} = ['lib', $self->{BASEEXT}]
        unless $self->{PMLIBDIRS};
@@ -544,7 +597,7 @@ sub init_dirscan {  # --- File and Directory Lists (.xs .pm .pod etc)
        require File::Find;
        File::Find::find(sub {
            if (-d $_){
-               if ($_ eq "CVS" || $_ eq "RCS"){
+               unless ($self->libscan($_)){
                    $File::Find::prune = 1;
                }
                return;
@@ -553,7 +606,7 @@ sub init_dirscan {  # --- File and Directory Lists (.xs .pm .pod etc)
            my($striplibpath,$striplibname);
            $prefix =  '$(INST_LIB)' if (($striplibpath = $path) =~ s:^(\W*)lib\W:$1:);
            ($striplibname,$striplibpath) = fileparse($striplibpath);
-           my($inst) = File::Spec->catfile($prefix,$striplibpath,$striplibname);
+           my($inst) = $self->catfile($prefix,$striplibpath,$striplibname);
            local($_) = $inst; # for backwards compatibility
            $inst = $self->libscan($inst);
            print "libscan($path) => '$inst'\n" if ($Verbose >= 2);
@@ -578,103 +631,39 @@ sub init_dirscan {       # --- File and Directory Lists (.xs .pm .pod etc)
     }
 }
 
-=item libscan (o)
-
-Takes a path to a file that is found by init_dirscan and returns false
-if we don't want to include this file in the library. Mainly used to
-exclude RCS, CVS, and SCCS directories from installation.
 
-=cut
-
-# ';
-
-sub libscan {
-    my($self,$path) = @_;
-    return '' if $path =~ m/:(RCS|CVS|SCCS):/ ;
-    $path;
-}
+=item init_VERSION (o)
 
-=item constants (o)
-
-Initializes lots of constants and .SUFFIXES and .PHONY
+Change DEFINE_VERSION and XS_DEFINE_VERSION
 
 =cut
 
-sub constants {
-    my($self) = @_;
-    my(@m,$tmp);
-
-    for $tmp (qw/
-             NAME DISTNAME NAME_SYM VERSION VERSION_SYM XS_VERSION
-             INST_LIB INST_ARCHLIB PERL_LIB PERL_SRC MACPERL_SRC MACPERL_LIB PERL FULLPERL
-             XSPROTOARG MACLIBS_68K MACLIBS_PPC MACLIBS_SC MACLIBS_MRC MACLIBS_ALL_68K MACLIBS_ALL_PPC MACLIBS_SHARED SOURCE TYPEMAPS
-             / ) {
-       next unless defined $self->{$tmp};
-       if ($tmp eq 'TYPEMAPS' && ref $self->{$tmp}) {
-           push @m, sprintf "$tmp = %s\n", join " ", @{$self->{$tmp}};
-       } else {
-           push @m, "$tmp = $self->{$tmp}\n";
-       }
-    }
+sub init_VERSION {
+    my $self = shift;
 
-    push @m, q{
-MODULES = }.join(" \\\n\t", sort keys %{$self->{PM}})."\n";
-    push @m, "PMLIBDIRS = @{$self->{PMLIBDIRS}}\n" if @{$self->{PMLIBDIRS}};
+    $self->SUPER::init_VERSION;
 
-    push @m, '
+    $self->{DEFINE_VERSION}    = '-d $(VERSION_MACRO)="¶"$(VERSION)¶""';
+    $self->{XS_DEFINE_VERSION} = '-d $(XS_VERSION_MACRO)="¶"$(XS_VERSION)¶""';
+}
 
-.INCLUDE : $(MACPERL_SRC)BuildRules.mk
 
-';
+=item special_targets (o)
 
-    push @m, qq{
-VERSION_MACRO = VERSION
-DEFINE_VERSION = -d \$(VERSION_MACRO)="¶"\$(VERSION)¶""
-XS_VERSION_MACRO = XS_VERSION
-XS_DEFINE_VERSION = -d \$(XS_VERSION_MACRO)="¶"\$(XS_VERSION)¶""
-};
+Add .INCLUDE
 
-    $self->{DEFINE} .= " \$(XS_DEFINE_VERSION) \$(DEFINE_VERSION)";
+=cut
 
-    push @m, qq{
-MAKEMAKER = $INC{'ExtUtils/MakeMaker.pm'}
-MM_VERSION = $ExtUtils::MakeMaker::VERSION
-};
-
-    push @m, q{
-# FULLEXT = Pathname for extension directory (eg DBD:Oracle).
-# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT.
-# ROOTEXT = Directory part of FULLEXT (eg DBD)
-# DLBASE  = Basename part of dynamic library. May be just equal BASEEXT.
-};
-
-    if ($self->{DEFINE}) {
-       $self->{DEFINE} =~ s/-D/-d /g; # Preprocessor definitions may be useful
-       $self->{DEFINE} =~ s/-I\S+/_include($1)/eg; # UN*X includes probably are not useful
-    }
-    if ($self->{INC}) {
-       $self->{INC} =~ s/-I(\S+)/_include($1)/eg; # UN*X includes probably are not useful
-    }
-    for $tmp (qw/
-             FULLEXT BASEEXT ROOTEXT DEFINE INC
-             / ) {
-       next unless defined $self->{$tmp};
-       push @m, "$tmp = $self->{$tmp}\n";
-    }
+sub special_targets {
+    my $self = shift;
 
-    push @m, "
-# Handy lists of source code files:
-XS_FILES= ".join(" \\\n\t", sort keys %{$self->{XS}})."
-C_FILES = ".join(" \\\n\t", @{$self->{C}})."
-H_FILES = ".join(" \\\n\t", @{$self->{H}})."
-";
+    my $make_frag = $self->SUPER::special_targets;
 
-    push @m, '
+    return $make_frag . <<'MAKE_FRAG';
+.INCLUDE : $(MACPERL_SRC)BuildRules.mk $(MACPERL_SRC)ExtBuildRules.mk
 
-.INCLUDE : $(MACPERL_SRC)ExtBuildRules.mk
-';
+MAKE_FRAG
 
-    join('',@m);
 }
 
 =item static (o)
@@ -765,32 +754,56 @@ sub clean {
 # Delete temporary files but do not touch installed files. We don\'t delete
 # the Makefile here so a later make realclean still has a makefile to use.
 
-clean ::
+clean :: clean_subdirs
 ');
-    # clean subdirectories first
-    for $dir (@{$self->{DIR}}) {
-       push @m, 
-"      Set OldEcho \{Echo\}
-       Set Echo 0
-       Directory $dir
-       If \"\`Exists -f $self->{MAKEFILE}\`\" != \"\"
-           \$(MAKE) clean
-       End
-       Set Echo \{OldEcho\}
-       ";
-    }
 
     my(@otherfiles) = values %{$self->{XS}}; # .c files from *.xs files
     push(@otherfiles, patternify($attribs{FILES})) if $attribs{FILES};
     push @m, "\t\$(RM_RF) @otherfiles\n";
     # See realclean and ext/utils/make_ext for usage of Makefile.old
     push(@m,
-        "\t\$(MV) $self->{MAKEFILE} $self->{MAKEFILE}.old\n");
+        "\t\$(MV) \$(FIRST_MAKEFILE) \$(MAKEFILE_OLD)\n");
     push(@m,
         "\t$attribs{POSTOP}\n")   if $attribs{POSTOP};
     join("", @m);
 }
 
+=item clean_subdirs_target
+
+MacOS semantics for changing directories and checking for existence
+very different than everyone else.
+
+=cut
+
+sub clean_subdirs_target {
+    my($self) = shift;
+
+    # No subdirectories, no cleaning.
+    return <<'NOOP_FRAG' unless @{$self->{DIR}};
+clean_subdirs :
+       $(NOECHO)$(NOOP)
+NOOP_FRAG
+
+
+    my $clean = "clean_subdirs :\n";
+
+    for my $dir (@{$self->{DIR}}) {
+        $clean .= sprintf <<'MAKE_FRAG', $dir;
+       Set OldEcho {Echo}
+       Set Echo 0
+       Directory %s
+       If "`Exists -f $(FIRST_MAKEFILE)`" != ""
+           $(MAKE) clean
+       End
+       Set Echo {OldEcho}
+       
+MAKE_FRAG
+    }
+
+    return $clean;
+}
+
+
 =item realclean (o)
 
 Defines the realclean target.
@@ -804,28 +817,50 @@ sub realclean {
 # Delete temporary files (via clean) and also delete installed files
 realclean purge ::  clean
 ');
-    # realclean subdirectories first (already cleaned)
-    my $sub = 
-"      Set OldEcho \{Echo\}
+
+    my(@otherfiles) = ('$(FIRST_MAKEFILE)', '$(MAKEFILE_OLD)'); # Makefiles last
+    push(@otherfiles, patternify($attribs{FILES})) if $attribs{FILES};
+    push(@m, "\t\$(RM_RF) @otherfiles\n") if @otherfiles;
+    push(@m, "\t$attribs{POSTOP}\n")       if $attribs{POSTOP};
+    join("", @m);
+}
+
+
+=item realclean_subdirs_target
+
+MacOS semantics for changing directories and checking for existence
+very different than everyone else.
+
+=cut
+
+sub realclean_subdirs_target {
+    my $self = shift;
+
+    return <<'NOOP_FRAG' unless @{$self->{DIR}};
+realclean_subdirs :
+       $(NOECHO)$(NOOP)
+NOOP_FRAG
+
+    my $rclean = "realclean_subdirs :\n";
+
+    foreach my $dir (@{$self->{DIR}}){
+        $rclean .= sprintf <<'RCLEAN', $dir, 
+       Set OldEcho \{Echo\}
        Set Echo 0
        Directory %s
-       If \"\`Exists -f %s\`\" != \"\"
+       If \"\`Exists -f $(FIRST_MAKEFILE)\`\" != \"\"
            \$(MAKE) realclean
        End
        Set Echo \{OldEcho\}
-       ";
-    foreach(@{$self->{DIR}}){
-       push(@m, sprintf($sub,$_,"$self->{MAKEFILE}.old","-f $self->{MAKEFILE}.old"));
-       push(@m, sprintf($sub,$_,"$self->{MAKEFILE}",''));
+
+RCLEAN
+
     }
-    my(@otherfiles) = ($self->{MAKEFILE},
-                      "$self->{MAKEFILE}.old"); # Makefiles last
-    push(@otherfiles, patternify($attribs{FILES})) if $attribs{FILES};
-    push(@m, "\t\$(RM_RF) @otherfiles\n") if @otherfiles;
-    push(@m, "\t$attribs{POSTOP}\n")       if $attribs{POSTOP};
-    join("", @m);
+
+    return $rclean;
 }
 
+
 =item rulez (o)
 
 =cut
@@ -863,7 +898,7 @@ sub processPL {
        foreach $target (@$list) {
        push @m, "
 ProcessPL :: $target
-\t$self->{NOECHO}\$(NOOP)
+\t$(NOECHO)\$(NOOP)
 
 $target :: $plfile
 \t\$(PERL) -I\$(MACPERL_LIB) -I\$(PERL_LIB) $plfile $target
@@ -875,15 +910,16 @@ $target :: $plfile
 
 sub cflags {
     my($self,$libperl) = @_;
-    my $optimize;
+    my $optimize = '';
 
     for (map { $_ . "Optimize" } qw(MWC MWCPPC MWC68K MPW MRC MRC SC)) {
-       $optimize .= "$_ = $self->{$_}" if exists $self->{$_};
+        $optimize .= "$_ = $self->{$_}" if exists $self->{$_};
     }
 
     return $self->{CFLAGS} = $optimize;
 }
 
+
 sub _include {  # for Unix-style includes, with -I instead of -i
        my($inc) = @_;
        require File::Spec::Unix;
@@ -896,45 +932,8 @@ sub _include {  # for Unix-style includes, with -I instead of -i
        }
 }
 
-# yes, these are just copies of the same routines in
-# MakeMaker.pm, but with paths changed.
-sub check_hints {
-    my($self) = @_;
-    # We allow extension-specific hints files.
-
-    return unless -d ":hints";
-
-    # First we look for the best hintsfile we have
-    my($hint)="${^O}_$Config{osvers}";
-    $hint =~ s/\./_/g;
-    $hint =~ s/_$//;
-    return unless $hint;
-
-    # Also try without trailing minor version numbers.
-    while (1) {
-        last if -f ":hints:$hint.pl";      # found
-    } continue {
-        last unless $hint =~ s/_[^_]*$//; # nothing to cut off
-    }
-    my $hint_file = ":hints:$hint.pl";
-
-    return unless -f $hint_file;    # really there
-
-    _run_hintfile($self, $hint_file);
-}
+=back
 
-sub _run_hintfile {
-    no strict 'vars';
-    local($self) = shift;       # make $self available to the hint file.
-    my($hint_file) = shift;
+=cut
 
-    local $@;
-    print STDERR "Processing hints file $hint_file\n";
-    my $ret = do $hint_file;
-    unless( defined $ret ) {
-        print STDERR $@ if $@;
-    }
-}
 1;
-
-__END__
index 7f13dd0..40c4823 100644 (file)
@@ -37,17 +37,34 @@ my $GCC      = 1 if $Config{'cc'} =~ /^gcc/i;
 my $DMAKE    = 1 if $Config{'make'} =~ /^dmake/i;
 
 
-sub init_others {
-    my ($self) = @_;
-    $self->SUPER::init_others(@_);
+=item init_platform (o)
+
+Add Netware macros.
+
+LIBPTH, BASE_IMPORT, NLM_VERSION, MPKTOOL, TOOLPATH, BOOT_SYMBOL,
+NLM_SHORT_NAME, INCLUDE, PATH, MM_NW5_REVISION
+
+
+=item platform_constants
+
+Add Netware macros initialized above to the Makefile.
+
+=cut
+
+sub init_platform {
+    my($self) = shift;
+
+    # To get Win32's setup.
+    $self->SUPER::init_platform;
 
     # incpath is copied to makefile var INCLUDE in constants sub, here just 
     # make it empty
     my $libpth = $Config{'libpth'};
     $libpth =~ s( )(;);
     $self->{'LIBPTH'} = $libpth;
+
     $self->{'BASE_IMPORT'} = $Config{'base_import'};
+
     # Additional import file specified from Makefile.pl
     if($self->{'base_import'}) {
         $self->{'BASE_IMPORT'} .= ', ' . $self->{'base_import'};
@@ -56,188 +73,61 @@ sub init_others {
     $self->{'NLM_VERSION'} = $Config{'nlm_version'};
     $self->{'MPKTOOL'} = $Config{'mpktool'};
     $self->{'TOOLPATH'}        = $Config{'toolpath'};
-}
-
-
-=item constants (o)
-
-Initializes lots of constants and .SUFFIXES and .PHONY
-
-=cut
-
-sub const_cccmd {
-    my($self,$libperl)=@_;
-    return $self->{CONST_CCCMD} if $self->{CONST_CCCMD};
-    return '' unless $self->needs_linking();
-    return $self->{CONST_CCCMD} = <<'MAKE_FRAG';
-CCCMD = $(CC) $(CCFLAGS) $(INC) $(OPTIMIZE) \
-       $(PERLTYPE) $(MPOLLUTE) -o $@ \
-       -DVERSION=\"$(VERSION)\" -DXS_VERSION=\"$(XS_VERSION)\"
-MAKE_FRAG
-
-}
-
-sub constants {
-    my($self) = @_;
-    my(@m,$tmp);
-
-# Added LIBPTH, BASE_IMPORT, ABSTRACT, NLM_VERSION BOOT_SYMBOL, NLM_SHORT_NAME
-# for NETWARE
-
-    for $tmp (qw/
-
-             AR_STATIC_ARGS NAME DISTNAME NAME_SYM VERSION
-             VERSION_SYM XS_VERSION INST_BIN INST_LIB
-             INST_ARCHLIB INST_SCRIPT PREFIX  INSTALLDIRS
-             INSTALLPRIVLIB INSTALLARCHLIB INSTALLSITELIB
-             INSTALLSITEARCH INSTALLBIN INSTALLSCRIPT PERL_LIB
-             PERL_ARCHLIB SITELIBEXP SITEARCHEXP LIBPERL_A MYEXTLIB
-             FIRST_MAKEFILE MAKE_APERL_FILE PERLMAINCC PERL_SRC
-             PERL_INC PERL FULLPERL LIBPTH BASE_IMPORT PERLRUN
-              FULLPERLRUN PERLRUNINST FULLPERLRUNINST
-              FULL_AR PERL_CORE NLM_VERSION MPKTOOL TOOLPATH
-
-             / ) {
-       next unless defined $self->{$tmp};
-       push @m, "$tmp = $self->{$tmp}\n";
-    }
 
     (my $boot = $self->{'NAME'}) =~ s/:/_/g;
     $self->{'BOOT_SYMBOL'}=$boot;
-    push @m, "BOOT_SYMBOL = $self->{'BOOT_SYMBOL'}\n";
 
     # If the final binary name is greater than 8 chars,
     # truncate it here.
     if(length($self->{'BASEEXT'}) > 8) {
         $self->{'NLM_SHORT_NAME'} = substr($self->{'BASEEXT'},0,8);
-        push @m, "NLM_SHORT_NAME = $self->{'NLM_SHORT_NAME'}\n";
     }
 
-    push @m, qq{
-VERSION_MACRO = VERSION
-DEFINE_VERSION = -D\$(VERSION_MACRO)=\\\"\$(VERSION)\\\"
-XS_VERSION_MACRO = XS_VERSION
-XS_DEFINE_VERSION = -D\$(XS_VERSION_MACRO)=\\\"\$(XS_VERSION)\\\"
-};
-
     # Get the include path and replace the spaces with ;
     # Copy this to makefile as INCLUDE = d:\...;d:\;
-    (my $inc = $Config{'incpath'}) =~ s/([ ]*)-I/;/g;
-
-    # Get the additional include path from the user through the command prompt
-    # and append to INCLUDE
-#    $self->{INC} = '';
-    push @m, "INC = $self->{'INC'}\n";
-
-    push @m, qq{
-INCLUDE = $inc;
-};
+    ($self->{INCLUDE} = $Config{'incpath'}) =~ s/([ ]*)-I/;/g;
 
     # Set the path to CodeWarrior binaries which might not have been set in
     # any other place
-    push @m, qq{
-PATH = \$(PATH);\$(TOOLPATH)
-};
-
-    push @m, qq{
-MAKEMAKER = $INC{'ExtUtils/MakeMaker.pm'}
-MM_VERSION = $ExtUtils::MakeMaker::VERSION
-};
-
-    push @m, q{
-# FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle).
-# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle)
-# PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar)
-# DLBASE  = Basename part of dynamic library. May be just equal BASEEXT.
-};
-
-    for $tmp (qw/
-             FULLEXT BASEEXT PARENT_NAME DLBASE VERSION_FROM INC DEFINE OBJECT
-             LDFROM LINKTYPE
-             / ) {
-       next unless defined $self->{$tmp};
-       push @m, "$tmp = $self->{$tmp}\n";
-    }
-
-    push @m, "
-# Handy lists of source code files:
-XS_FILES= ".join(" \\\n\t", sort keys %{$self->{XS}})."
-C_FILES = ".join(" \\\n\t", @{$self->{C}})."
-O_FILES = ".join(" \\\n\t", @{$self->{O_FILES}})."
-H_FILES = ".join(" \\\n\t", @{$self->{H}})."
-MAN1PODS = ".join(" \\\n\t", sort keys %{$self->{MAN1PODS}})."
-MAN3PODS = ".join(" \\\n\t", sort keys %{$self->{MAN3PODS}})."
-";
-
-    for $tmp (qw/
-             INST_MAN1DIR        INSTALLMAN1DIR MAN1EXT
-             INST_MAN3DIR        INSTALLMAN3DIR MAN3EXT
-             /) {
-       next unless defined $self->{$tmp};
-       push @m, "$tmp = $self->{$tmp}\n";
-    }
-
-    push @m, qq{
-.USESHELL :
-} if $DMAKE;
+    $self->{PATH} = '$(PATH);$(TOOLPATH)';
 
-    push @m, q{
-.NO_CONFIG_REC: Makefile
-} if $ENV{CLEARCASE_ROOT};
-
-    # why not q{} ? -- emacs
-    push @m, qq{
-# work around a famous dec-osf make(1) feature(?):
-makemakerdflt: all
-
-.SUFFIXES: .xs .c .C .cpp .cxx .cc \$(OBJ_EXT)
+    $self->{MM_NW5_VERSION} = $VERSION;
+}
 
-.PHONY: all config static dynamic test linkext manifest
+sub platform_constants {
+    my($self) = shift;
+    my $make_frag = '';
 
-# Where is the Config information that we are using/depend on
-CONFIGDEP = \$(PERL_ARCHLIB)\\Config.pm \$(PERL_INC)\\config.h
-};
+    # Setup Win32's constants.
+    $make_frag .= $self->SUPER::platform_constants;
 
-    my @parentdir = split(/::/, $self->{PARENT_NAME});
-    push @m, q{
-# Where to put things:
-INST_LIBDIR      = }. File::Spec->catdir('$(INST_LIB)',@parentdir)        .q{
-INST_ARCHLIBDIR  = }. File::Spec->catdir('$(INST_ARCHLIB)',@parentdir)    .q{
+    foreach my $macro (qw(LIBPTH BASE_IMPORT NLM_VERSION MPKTOOL 
+                          TOOLPATH BOOT_SYMBOL NLM_SHORT_NAME INCLUDE PATH
+                          MM_NW5_VERSION
+                      ))
+    {
+        next unless defined $self->{$macro};
+        $make_frag .= "$macro = $self->{$macro}\n";
+    }
 
-INST_AUTODIR     = }. File::Spec->catdir('$(INST_LIB)','auto','$(FULLEXT)')       .q{
-INST_ARCHAUTODIR = }. File::Spec->catdir('$(INST_ARCHLIB)','auto','$(FULLEXT)')   .q{
-};
+    return $make_frag;
+}
 
-    if ($self->has_link_code()) {
-       push @m, '
-INST_STATIC  = $(INST_ARCHAUTODIR)\$(BASEEXT)$(LIB_EXT)
-INST_DYNAMIC = $(INST_ARCHAUTODIR)\$(DLBASE).$(DLEXT)
-INST_BOOT    = $(INST_ARCHAUTODIR)\$(BASEEXT).bs
-';
-    } else {
-       push @m, '
-INST_STATIC  =
-INST_DYNAMIC =
-INST_BOOT    =
-';
-    }
 
-    $tmp = $self->export_list;
-    push @m, "
-EXPORT_LIST = $tmp
-";
-    $tmp = $self->perl_archive;
-    push @m, "
-PERL_ARCHIVE = $tmp
-";
+=item const_cccmd (o)
 
-    push @m, q{
-TO_INST_PM = }.join(" \\\n\t", sort keys %{$self->{PM}}).q{
+=cut
 
-PM_TO_BLIB = }.join(" \\\n\t", %{$self->{PM}}).q{
-};
+sub const_cccmd {
+    my($self,$libperl)=@_;
+    return $self->{CONST_CCCMD} if $self->{CONST_CCCMD};
+    return '' unless $self->needs_linking();
+    return $self->{CONST_CCCMD} = <<'MAKE_FRAG';
+CCCMD = $(CC) $(CCFLAGS) $(INC) $(OPTIMIZE) \
+       $(PERLTYPE) $(MPOLLUTE) -o $@ \
+       -DVERSION=\"$(VERSION)\" -DXS_VERSION=\"$(XS_VERSION)\"
+MAKE_FRAG
 
-    join('',@m);
 }
 
 
@@ -251,7 +141,7 @@ sub static_lib {
     return '' unless $self->has_link_code;
 
     my $m = <<'END';
-$(INST_STATIC): $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)\.exists
+$(INST_STATIC): $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DIRFILESEP).exists
        $(RM_RF) $@
 END
 
@@ -274,12 +164,12 @@ END
 
     $m .= sprintf <<'END', $ar_arg;
        $(AR) %s
-       $(NOECHO)echo "$(EXTRALIBS)" > $(INST_ARCHAUTODIR)\extralibs.ld
+       $(NOECHO) $(ECHO) "$(EXTRALIBS)" > $(INST_ARCHAUTODIR)\extralibs.ld
        $(CHMOD) 755 $@
 END
 
     $m .= <<'END' if $self->{PERL_SRC};
-       $(NOECHO)echo "$(EXTRALIBS)" >> $(PERL_SRC)\ext.libs
+       $(NOECHO) $(ECHO) "$(EXTRALIBS)" >> $(PERL_SRC)\ext.libs
     
     
 END
@@ -313,16 +203,16 @@ INST_DYNAMIC_DEP = '.$inst_dynamic_dep.'
 
 # Create xdc data for an MT safe NLM in case of mpk build
 $(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP)
-       @echo Export boot_$(BOOT_SYMBOL) > $(BASEEXT).def
-       @echo $(BASE_IMPORT) >> $(BASEEXT).def
-       @echo Import @$(PERL_INC)\perl.imp >> $(BASEEXT).def
+       $(NOECHO) $(ECHO) Export boot_$(BOOT_SYMBOL) > $(BASEEXT).def
+       $(NOECHO) $(ECHO) $(BASE_IMPORT) >> $(BASEEXT).def
+       $(NOECHO) $(ECHO) Import @$(PERL_INC)\perl.imp >> $(BASEEXT).def
 MAKE_FRAG
 
 
     if ( $self->{CCFLAGS} =~ m/ -DMPK_ON /) {
         $m .= <<'MAKE_FRAG';
        $(MPKTOOL) $(XDCFLAGS) $(BASEEXT).xdc
-       @echo xdcdata $(BASEEXT).xdc >> $(BASEEXT).def
+       $(NOECHO) $(ECHO) xdcdata $(BASEEXT).xdc >> $(BASEEXT).def
 MAKE_FRAG
     }
 
index fb72f5f..47ecba8 100644 (file)
@@ -32,16 +32,20 @@ the semantics.
 
 =over 4
 
+=item init_dist (o)
+
+Define TO_UNIX to convert OS2 linefeeds to Unix style.
+
 =cut
 
-sub dist {
-    my($self, %attribs) = @_;
+sub init_dist {
+    my($self) = @_;
 
-    $attribs{TO_UNIX} ||= sprintf <<'MAKE_TEXT', $self->{NOECHO};
-%s$(TEST_F) tmp.zip && $(RM) tmp.zip; $(ZIP) -ll -mr tmp.zip $(DISTVNAME) && unzip -o tmp.zip && $(RM) tmp.zip
+    $self->{TO_UNIX} ||= <<'MAKE_TEXT';
+$(NOECHO) $(TEST_F) tmp.zip && $(RM) tmp.zip; $(ZIP) -ll -mr tmp.zip $(DISTVNAME) && unzip -o tmp.zip && $(RM) tmp.zip
 MAKE_TEXT
 
-    return $self->SUPER::dist(%attribs);
+    $self->SUPER::init_dist;
 }
 
 sub dlsyms {
@@ -117,38 +121,23 @@ sub maybe_command {
     return;
 }
 
-sub perl_archive {
-    return "\$(PERL_INC)/libperl\$(LIB_EXT)";
-}
+=item init_linker
 
-=item perl_archive_after
-
-This is an internal method that returns path to a library which
-should be put on the linker command line I<after> the external libraries
-to be linked to dynamic extensions.  This may be needed if the linker
-is one-pass, and Perl includes some overrides for C RTL functions,
-such as malloc().
+=cut
 
-=cut 
+sub init_linker {
+    my $self = shift;
 
-sub perl_archive_after
-{
- return "\$(PERL_INC)/libperl_override\$(LIB_EXT)" unless $OS2::is_aout;
- return "";
-}
+    $self->{PERL_ARCHIVE} = "\$(PERL_INC)/libperl\$(LIB_EXT)";
 
-sub export_list
-{
my ($self) = @_;
return "$self->{BASEEXT}.def";
+    $self->{PERL_ARCHIVE_AFTER} = !$OS2::is_aout 
+      ? "\$(PERL_INC)/libperl_override\$(LIB_EXT)"
     : '';
   $self->{EXPORT_LIST} = '$(BASEEXT).def';
 }
 
-1;
-
-__END__
-
-=pod
-
 =back
 
 =cut
+
+1;
index 59384a2..2bfddcf 100644 (file)
@@ -49,4 +49,6 @@ Michael G Schwern <schwern@pobox.com> with code from ExtUtils::MM_Unix
 
 L<ExtUtils::MM_Win32>, L<ExtUtils::MakeMaker>
 
+=cut
+
 1;
index c5bb19e..87d93bf 100644 (file)
@@ -6,30 +6,41 @@ use strict;
 
 use Exporter ();
 use Carp;
-use Config;
+use Config         qw(%Config);
 use File::Basename qw(basename dirname fileparse);
-use File::Spec;
 use DirHandle;
-use strict;
+
 use vars qw($VERSION @ISA
-            $Is_Mac $Is_OS2 $Is_VMS $Is_Win32 $Is_Dos $Is_VOS
+            $Is_Mac $Is_OS2 $Is_VMS $Is_Win32 $Is_Win95  $Is_Dos $Is_VOS
+            $Is_QNX $Is_AIX $Is_OSF $Is_IRIX  $Is_NetBSD 
+            $Is_SunOS4 $Is_Solaris $Is_SunOS
             $Verbose %pm %static $Xsubpp_Version
             %Config_Override
            );
 
 use ExtUtils::MakeMaker qw($Verbose neatvalue);
 
-$VERSION = '1.33';
+$VERSION = '1.35';
 
 require ExtUtils::MM_Any;
 @ISA = qw(ExtUtils::MM_Any);
 
-$Is_OS2   = $^O eq 'os2';
-$Is_Mac   = $^O eq 'MacOS';
-$Is_Win32 = $^O eq 'MSWin32' || $Config{osname} eq 'NetWare';
-$Is_Dos   = $^O eq 'dos';
-$Is_VOS   = $^O eq 'vos';
-$Is_VMS   = $^O eq 'VMS';
+$Is_OS2     = $^O eq 'os2';
+$Is_Mac     = $^O eq 'MacOS';
+$Is_Win32   = $^O eq 'MSWin32' || $Config{osname} eq 'NetWare';
+$Is_Win95   = $Is_Win32 && Win32::IsWin95();
+$Is_Dos     = $^O eq 'dos';
+$Is_VOS     = $^O eq 'vos';
+$Is_VMS     = $^O eq 'VMS';
+$Is_QNX     = $^O eq 'qnx';
+$Is_AIX     = $^O eq 'aix';
+$Is_OSF     = $^O eq 'dec_osf';
+$Is_IRIX    = $^O eq 'irix';
+$Is_NetBSD  = $^O eq 'netbsd';
+$Is_SunOS4  = $^O eq 'sunos';
+$Is_Solaris = $^O eq 'solaris';
+$Is_SunOS   = $Is_SunOS4 || $Is_Solaris;
+
 
 =head1 NAME
 
@@ -65,7 +76,8 @@ will be overridable via the MY class.
 
 The following description of methods is still under
 development. Please refer to the code for not suitably documented
-sections and complain loudly to the makemaker mailing list.
+sections and complain loudly to the makemaker@perl.org mailing list.
+Better yet, provide a patch.
 
 Not all of the methods below are overridable in a
 Makefile.PL. Overridable methods are marked as (o). All methods are
@@ -75,102 +87,15 @@ L<ExtUtils::MM_VMS>) and L<ExtUtils::MM_OS2>).
 =cut
 
 # So we don't have to keep calling the methods over and over again,
-# we have these globals to cache the values.  They have to be global
-# else the SelfLoaded methods can't see them.
-use vars qw($Curdir $Rootdir $Updir);
-$Curdir  = File::Spec->curdir;
-$Rootdir = File::Spec->rootdir;
-$Updir   = File::Spec->updir;
-
-sub c_o;
-sub clean;
-sub const_cccmd;
-sub const_config;
-sub const_loadlibs;
-sub constants;
-sub depend;
-sub dir_target;
-sub dist;
-sub dist_basics;
-sub dist_ci;
-sub dist_core;
-sub dist_dir;
-sub dist_test;
-sub dlsyms;
-sub dynamic;
-sub dynamic_bs;
-sub dynamic_lib;
-sub exescan;
-sub export_list;
-sub extliblist;
-sub find_perl;
-sub fixin;
-sub force;
-sub guess_name;
-sub has_link_code;
-sub init_dirscan;
-sub init_main;
-sub init_others;
-sub install;
-sub installbin;
-sub libscan;
-sub linkext;
-sub lsdir;
-sub macro;
-sub makeaperl;
-sub makefile;
-sub manifypods;
-sub maybe_command;
-sub maybe_command_in_dirs;
-sub needs_linking;
-sub nicetext;
-sub parse_abstract;
-sub parse_version;
-sub pasthru;
-sub perl_archive;
-sub perl_archive_after;
-sub perl_script;
-sub perldepend;
-sub pm_to_blib;
-sub ppd;
-sub post_constants;
-sub post_initialize;
-sub postamble;
-sub prefixify;
-sub processPL;
-sub quote_paren;
-sub realclean;
-sub replace_manpage_separator;
-sub static;
-sub static_lib;
-sub staticmake;
-sub subdir_x;
-sub subdirs;
-sub test;
-sub test_via_harness;
-sub test_via_script;
-sub tool_autosplit;
-sub tool_xsubpp;
-sub tools_other;
-sub top_targets;
-sub writedoc;
-sub xs_c;
-sub xs_cpp;
-sub xs_o;
-sub xsubpp_version;
-
-#use SelfLoader;
-
-# SelfLoader not smart enough to avoid autoloading DESTROY
-sub DESTROY { }
-
-#1;
-
-#__DATA__
-
-=head2 SelfLoaded methods
+# we have these globals to cache the values.  Faster and shrtr.
+my $Curdir  = __PACKAGE__->curdir;
+my $Rootdir = __PACKAGE__->rootdir;
+my $Updir   = __PACKAGE__->updir;
 
-=over 2
+
+=head2 Methods
+
+=over 4
 
 =item c_o (o)
 
@@ -343,27 +268,11 @@ sub clean {
 # Delete temporary files but do not touch installed files. We don\'t delete
 # the Makefile here so a later make realclean still has a makefile to use.
 
-clean ::
+clean :: clean_subdirs
 ');
-    # clean subdirectories first
-    for $dir (@{$self->{DIR}}) {
-       if ($Is_Win32  &&  Win32::IsWin95()) {
-           push @m, <<EOT;
-       cd $dir
-       \$(TEST_F) $self->{MAKEFILE}
-       \$(MAKE) clean
-       cd ..
-EOT
-       }
-       else {
-           push @m, <<EOT;
-       -cd $dir && \$(TEST_F) $self->{MAKEFILE} && \$(MAKE) clean
-EOT
-       }
-    }
 
     my(@otherfiles) = values %{$self->{XS}}; # .c files from *.xs files
-    if ( $^O eq 'qnx' ) {
+    if ( $Is_QNX ) {
       my @errfiles = @{$self->{C}};
       for ( @errfiles ) {
        s/.c$/.err/;
@@ -386,15 +295,47 @@ EOT
         push(@otherfiles, qw[core core.*perl.*.? *perl.core]);
     }
 
-    push @m, "\t-$self->{RM_RF} @otherfiles\n";
+    push @m, "\t-\$(RM_RF) @otherfiles\n";
     # See realclean and ext/utils/make_ext for usage of Makefile.old
     push(@m,
-        "\t-$self->{MV} $self->{MAKEFILE} $self->{MAKEFILE}.old \$(DEV_NULL)\n");
+        "\t-\$(MV) \$(FIRST_MAKEFILE) \$(MAKEFILE_OLD) \$(DEV_NULL)\n");
     push(@m,
         "\t$attribs{POSTOP}\n")   if $attribs{POSTOP};
     join("", @m);
 }
 
+
+=item clean_subdirs_target
+
+  my $make_frag = $MM->clean_subdirs_target;
+
+Returns the clean_subdirs target.  This is used by the clean target to
+call clean on any subdirectories which contain Makefiles.
+
+=cut
+
+sub clean_subdirs_target {
+    my($self) = shift;
+
+    # No subdirectories, no cleaning.
+    return <<'NOOP_FRAG' unless @{$self->{DIR}};
+clean_subdirs :
+       $(NOECHO) $(NOOP)
+NOOP_FRAG
+
+
+    my $clean = "clean_subdirs :\n";
+
+    for my $dir (@{$self->{DIR}}) {
+        $clean .= sprintf <<'MAKE_FRAG', $dir;
+       -cd %s && $(TEST_F) $(FIRST_MAKEFILE) && $(MAKE) clean
+MAKE_FRAG
+    }
+
+    return $clean;
+}
+
+
 =item const_cccmd (o)
 
 Returns the full compiler call for C programs and stores the
@@ -430,7 +371,7 @@ sub const_config {
     my(%once_only);
     foreach $m (@{$self->{CONFIG}}){
        # SITE*EXP macros are defined in &constants; avoid duplicates here
-       next if $once_only{$m} or $m eq 'sitelibexp' or $m eq 'sitearchexp';
+       next if $once_only{$m};
        $self->{uc $m} = quote_paren($self->{uc $m});
        push @m, uc($m) , ' = ' , $self->{uc $m}, "\n";
        $once_only{$m} = 1;
@@ -466,53 +407,54 @@ sub const_loadlibs {
 
 =item constants (o)
 
-Initializes lots of constants and .SUFFIXES and .PHONY
+  my $make_frag = $mm->constants;
+
+Prints out macros for lots of constants.
 
 =cut
 
 sub constants {
     my($self) = @_;
-    my(@m,$tmp);
+    my @m = ();
 
-    for $tmp (qw/
+    for my $macro (qw/
 
-             AR_STATIC_ARGS NAME DISTNAME NAME_SYM VERSION
-             VERSION_SYM XS_VERSION 
-             INST_ARCHLIB INST_SCRIPT INST_BIN INST_LIB
+              AR_STATIC_ARGS DIRFILESEP
+              NAME NAME_SYM 
+              VERSION    VERSION_MACRO    VERSION_SYM DEFINE_VERSION
+              XS_VERSION XS_VERSION_MACRO             XS_DEFINE_VERSION
+              INST_ARCHLIB INST_SCRIPT INST_BIN INST_LIB
               INSTALLDIRS
-              PREFIX          SITEPREFIX      VENDORPREFIX
-             INSTALLPRIVLIB  INSTALLSITELIB  INSTALLVENDORLIB
-             INSTALLARCHLIB  INSTALLSITEARCH INSTALLVENDORARCH
+              DESTDIR PREFIX
+              PERLPREFIX      SITEPREFIX      VENDORPREFIX
+              INSTALLPRIVLIB  INSTALLSITELIB  INSTALLVENDORLIB
+              INSTALLARCHLIB  INSTALLSITEARCH INSTALLVENDORARCH
               INSTALLBIN      INSTALLSITEBIN  INSTALLVENDORBIN  INSTALLSCRIPT 
-              PERL_LIB        PERL_ARCHLIB 
-              SITELIBEXP      SITEARCHEXP 
+              PERL_LIB    
+              PERL_ARCHLIB
               LIBPERL_A MYEXTLIB
-             FIRST_MAKEFILE MAKE_APERL_FILE PERLMAINCC PERL_SRC
-             PERL_INC PERL FULLPERL PERLRUN FULLPERLRUN PERLRUNINST 
-              FULLPERLRUNINST ABSPERL ABSPERLRUN ABSPERLRUNINST
-              FULL_AR PERL_CORE NOOP NOECHO
+              FIRST_MAKEFILE MAKEFILE_OLD MAKE_APERL_FILE 
+              PERLMAINCC PERL_SRC PERL_INC 
+              PERL            FULLPERL          ABSPERL
+              PERLRUN         FULLPERLRUN       ABSPERLRUN
+              PERLRUNINST     FULLPERLRUNINST   ABSPERLRUNINST
+              PERL_CORE
+              PERM_RW PERM_RWX
 
              / ) 
     {
-       next unless defined $self->{$tmp};
+       next unless defined $self->{$macro};
 
         # pathnames can have sharp signs in them; escape them so
         # make doesn't think it is a comment-start character.
-        $self->{$tmp} =~ s/#/\\#/g;
-       push @m, "$tmp = $self->{$tmp}\n";
+        $self->{$macro} =~ s/#/\\#/g;
+       push @m, "$macro = $self->{$macro}\n";
     }
 
     push @m, qq{
-VERSION_MACRO = VERSION
-DEFINE_VERSION = -D\$(VERSION_MACRO)=\\\"\$(VERSION)\\\"
-XS_VERSION_MACRO = XS_VERSION
-XS_DEFINE_VERSION = -D\$(XS_VERSION_MACRO)=\\\"\$(XS_VERSION)\\\"
-PERL_MALLOC_DEF = -DPERL_EXTMALLOC_DEF -Dmalloc=Perl_malloc -Dfree=Perl_mfree -Drealloc=Perl_realloc -Dcalloc=Perl_calloc
-};
-
-    push @m, qq{
-MAKEMAKER = $INC{'ExtUtils/MakeMaker.pm'}
-MM_VERSION = $ExtUtils::MakeMaker::VERSION
+MAKEMAKER   = $self->{MAKEMAKER}
+MM_VERSION  = $self->{MM_VERSION}
+MM_REVISION = $self->{MM_REVISION}
 };
 
     push @m, q{
@@ -522,115 +464,75 @@ MM_VERSION = $ExtUtils::MakeMaker::VERSION
 # DLBASE  = Basename part of dynamic library. May be just equal BASEEXT.
 };
 
-    for $tmp (qw/
+    for my $macro (qw/
              FULLEXT BASEEXT PARENT_NAME DLBASE VERSION_FROM INC DEFINE OBJECT
              LDFROM LINKTYPE PM_FILTER
              / ) 
     {
-       next unless defined $self->{$tmp};
-       push @m, "$tmp = $self->{$tmp}\n";
+       next unless defined $self->{$macro};
+       push @m, "$macro = $self->{$macro}\n";
     }
 
     push @m, "
 # Handy lists of source code files:
-XS_FILES= ".join(" \\\n\t", sort keys %{$self->{XS}})."
-C_FILES = ".join(" \\\n\t", @{$self->{C}})."
-O_FILES = ".join(" \\\n\t", @{$self->{O_FILES}})."
-H_FILES = ".join(" \\\n\t", @{$self->{H}})."
-MAN1PODS = ".join(" \\\n\t", sort keys %{$self->{MAN1PODS}})."
-MAN3PODS = ".join(" \\\n\t", sort keys %{$self->{MAN3PODS}})."
+XS_FILES = ".$self->wraplist(sort keys %{$self->{XS}})."
+C_FILES  = ".$self->wraplist(@{$self->{C}})."
+O_FILES  = ".$self->wraplist(@{$self->{O_FILES}})."
+H_FILES  = ".$self->wraplist(@{$self->{H}})."
+MAN1PODS = ".$self->wraplist(sort keys %{$self->{MAN1PODS}})."
+MAN3PODS = ".$self->wraplist(sort keys %{$self->{MAN3PODS}})."
 ";
 
-    for $tmp (qw/
-             INST_MAN1DIR  MAN1EXT 
+    for my $macro (qw/
+             INST_MAN1DIR  MAN1EXT
               INSTALLMAN1DIR INSTALLSITEMAN1DIR INSTALLVENDORMAN1DIR
              INST_MAN3DIR  MAN3EXT
               INSTALLMAN3DIR INSTALLSITEMAN3DIR INSTALLVENDORMAN3DIR
              /) 
     {
-       next unless defined $self->{$tmp};
-       push @m, "$tmp = $self->{$tmp}\n";
+       next unless defined $self->{$macro};
+       push @m, "$macro = $self->{$macro}\n";
     }
 
-    for $tmp (qw(
-               PERM_RW PERM_RWX
-               )
-            ) 
-    {
-        my $method = lc($tmp);
-       # warn "self[$self] method[$method]";
-        push @m, "$tmp = ", $self->$method(), "\n";
-    }
 
     push @m, q{
-.NO_CONFIG_REC: Makefile
-} if $ENV{CLEARCASE_ROOT};
-
-    # why not q{} ? -- emacs
-    push @m, qq{
-# work around a famous dec-osf make(1) feature(?):
-makemakerdflt: all
+# Where is the Config information that we are using/depend on
+CONFIGDEP = $(PERL_ARCHLIB)$(DIRFILESEP)Config.pm $(PERL_INC)$(DIRFILESEP)config.h
+};
 
-.SUFFIXES: .xs .c .C .cpp .i .s .cxx .cc \$(OBJ_EXT)
 
-# Nick wanted to get rid of .PRECIOUS. I don't remember why. I seem to recall, that
-# some make implementations will delete the Makefile when we rebuild it. Because
-# we call false(1) when we rebuild it. So make(1) is not completely wrong when it
-# does so. Our milage may vary.
-# .PRECIOUS: Makefile    # seems to be not necessary anymore
+    push @m, qq{
+# Where to build things
+INST_LIBDIR      = $self->{INST_LIBDIR}
+INST_ARCHLIBDIR  = $self->{INST_ARCHLIBDIR}
 
-.PHONY: all config static dynamic test linkext manifest
+INST_AUTODIR     = $self->{INST_AUTODIR}
+INST_ARCHAUTODIR = $self->{INST_ARCHAUTODIR}
 
-# Where is the Config information that we are using/depend on
-CONFIGDEP = \$(PERL_ARCHLIB)/Config.pm \$(PERL_INC)/config.h
+INST_STATIC      = $self->{INST_STATIC}
+INST_DYNAMIC     = $self->{INST_DYNAMIC}
+INST_BOOT        = $self->{INST_BOOT}
 };
 
-    my @parentdir = split(/::/, $self->{PARENT_NAME});
-    push @m, q{
-# Where to put things:
-INST_LIBDIR      = }. File::Spec->catdir('$(INST_LIB)',@parentdir)        .q{
-INST_ARCHLIBDIR  = }. File::Spec->catdir('$(INST_ARCHLIB)',@parentdir)    .q{
 
-INST_AUTODIR     = }. File::Spec->catdir('$(INST_LIB)','auto','$(FULLEXT)')       .q{
-INST_ARCHAUTODIR = }. File::Spec->catdir('$(INST_ARCHLIB)','auto','$(FULLEXT)')   .q{
+    push @m, qq{
+# Extra linker info
+EXPORT_LIST        = $self->{EXPORT_LIST}
+PERL_ARCHIVE       = $self->{PERL_ARCHIVE}
+PERL_ARCHIVE_AFTER = $self->{PERL_ARCHIVE_AFTER}
 };
 
-    if ($self->has_link_code()) {
-       push @m, '
-INST_STATIC  = $(INST_ARCHAUTODIR)/$(BASEEXT)$(LIB_EXT)
-INST_DYNAMIC = $(INST_ARCHAUTODIR)/$(DLBASE).$(DLEXT)
-INST_BOOT    = $(INST_ARCHAUTODIR)/$(BASEEXT).bs
-';
-    } else {
-       push @m, '
-INST_STATIC  =
-INST_DYNAMIC =
-INST_BOOT    =
-';
-    }
-
-    $tmp = $self->export_list;
-    push @m, "
-EXPORT_LIST = $tmp
-";
-    $tmp = $self->perl_archive;
-    push @m, "
-PERL_ARCHIVE = $tmp
-";
-    $tmp = $self->perl_archive_after;
     push @m, "
-PERL_ARCHIVE_AFTER = $tmp
-";
 
-    push @m, q{
-TO_INST_PM = }.join(" \\\n\t", sort keys %{$self->{PM}}).q{
+TO_INST_PM = ".$self->wraplist(sort keys %{$self->{PM}})."
 
-PM_TO_BLIB = }.join(" \\\n\t", %{$self->{PM}}).q{
-};
+PM_TO_BLIB = ".$self->wraplist(%{$self->{PM}})."
+";
 
     join('',@m);
 }
 
+
 =item depend (o)
 
 Same as macro for the depend attribute.
@@ -669,8 +571,8 @@ sub dir_target {
     my($self,@dirs) = @_;
     my(@m,$dir,$targdir);
     foreach $dir (@dirs) {
-       my($src) = File::Spec->catfile($self->{PERL_INC},'perl.h');
-       my($targ) = File::Spec->catfile($dir,'.exists');
+       my($src) = $self->catfile($self->{PERL_INC},'perl.h');
+       my($targ) = $self->catfile($dir,'.exists');
        # catfile may have adapted syntax of $dir to target OS, so...
        if ($Is_VMS) { # Just remove file name; dirspec is often in macro
            ($targdir = $targ) =~ s:/?\.exists\z::;
@@ -681,53 +583,109 @@ sub dir_target {
        next if $self->{DIR_TARGET}{$self}{$targdir}++;
        push @m, qq{
 $targ :: $src
-       $self->{NOECHO}\$(MKPATH) $targdir
-       $self->{NOECHO}\$(EQUALIZE_TIMESTAMP) $src $targ
+       \$(NOECHO) \$(MKPATH) $targdir
+       \$(NOECHO) \$(EQUALIZE_TIMESTAMP) $src $targ
 };
        push(@m, qq{
-       -$self->{NOECHO}\$(CHMOD) \$(PERM_RWX) $targdir
+       -\$(NOECHO) \$(CHMOD) \$(PERM_RWX) $targdir
 }) unless $Is_VMS;
     }
     join "", @m;
 }
 
-=item dist (o)
+=item init_dist
+
+  $mm->init_dist;
 
 Defines a lot of macros for distribution support.
 
+  macro         description                     default
+
+  TAR           tar command to use              tar
+  TARFLAGS      flags to pass to TAR            cvf
+
+  ZIP           zip command to use              zip
+  ZIPFLAGS      flags to pass to ZIP            -r
+
+  COMPRESS      compression command to          gzip --best
+                use for tarfiles
+  SUFFIX        suffix to put on                .gz 
+                compressed files
+
+  SHAR          shar command to use             shar
+
+  PREOP         extra commands to run before
+                making the archive 
+  POSTOP        extra commands to run after
+                making the archive
+
+  TO_UNIX       a command to convert linefeeds
+                to Unix style in your archive 
+
+  CI            command to checkin your         ci -u
+                sources to version control
+  RCS_LABEL     command to label your sources   rcs -Nv$(VERSION_SYM): -q
+                just after CI is run
+
+  DIST_CP       $how argument to manicopy()     best
+                when the distdir is created
+
+  DIST_DEFAULT  default target to use to        tardist
+                create a distribution
+
+  DISTVNAME     name of the resulting archive   $(DISTNAME)-$(VERSION)
+                (minus suffixes)
+
+=cut
+
+sub init_dist {
+    my $self = shift;
+
+    $self->{TAR}      ||= 'tar';
+    $self->{TARFLAGS} ||= 'cvf';
+    $self->{ZIP}      ||= 'zip';
+    $self->{ZIPFLAGS} ||= '-r';
+    $self->{COMPRESS} ||= 'gzip --best';
+    $self->{SUFFIX}   ||= '.gz';
+    $self->{SHAR}     ||= 'shar';
+    $self->{PREOP}    ||= '$(NOECHO) $(NOOP)'; # eg update MANIFEST
+    $self->{POSTOP}   ||= '$(NOECHO) $(NOOP)'; # eg remove the distdir
+    $self->{TO_UNIX}  ||= '$(NOECHO) $(NOOP)';
+
+    $self->{CI}       ||= 'ci -u';
+    $self->{RCS_LABEL}||= 'rcs -Nv$(VERSION_SYM): -q';
+    $self->{DIST_CP}  ||= 'best';
+    $self->{DIST_DEFAULT} ||= 'tardist';
+
+    ($self->{DISTNAME} = $self->{NAME}) =~ s{::}{-}g unless $self->{DISTNAME};
+    $self->{DISTVNAME} ||= $self->{DISTNAME}.'-'.$self->{VERSION};
+
+}
+
+=item dist (o)
+
+  my $dist_macros = $mm->dist(%overrides);
+
+Generates a make fragment defining all the macros initialized in
+init_dist.
+
+%overrides can be used to override any of the above.
+
 =cut
 
 sub dist {
     my($self, %attribs) = @_;
 
-    # VERSION should be sanitised before use as a file name
-    $attribs{VERSION}  ||= '$(VERSION)';
-    $attribs{NAME}     ||= '$(DISTNAME)';
-    $attribs{TAR}      ||= 'tar';
-    $attribs{TARFLAGS} ||= 'cvf';
-    $attribs{ZIP}      ||= 'zip';
-    $attribs{ZIPFLAGS} ||= '-r';
-    $attribs{COMPRESS} ||= 'gzip --best';
-    $attribs{SUFFIX}   ||= '.gz';
-    $attribs{SHAR}     ||= 'shar';
-    $attribs{PREOP}    ||= "$self->{NOECHO}\$(NOOP)"; # eg update MANIFEST
-    $attribs{POSTOP}   ||= "$self->{NOECHO}\$(NOOP)"; # eg remove the distdir
-    $attribs{TO_UNIX}  ||= "$self->{NOECHO}\$(NOOP)";
-
-    $attribs{CI}       ||= 'ci -u';
-    $attribs{RCS_LABEL}||= 'rcs -Nv$(VERSION_SYM): -q';
-    $attribs{DIST_CP}  ||= 'best';
-    $attribs{DIST_DEFAULT} ||= 'tardist';
-
-    $attribs{DISTVNAME} ||= "$attribs{NAME}-$attribs{VERSION}";
-
-    # We've already printed out VERSION and NAME variables.
-    delete $attribs{VERSION};
-    delete $attribs{NAME};
-
     my $make = '';
-    while(my($var, $value) = each %attribs) {
-        $make .= "$var = $value\n";
+    foreach my $key (qw( 
+            TAR TARFLAGS ZIP ZIPFLAGS COMPRESS SUFFIX SHAR
+            PREOP POSTOP TO_UNIX
+            CI RCS_LABEL DIST_CP DIST_DEFAULT
+            DISTNAME DISTVNAME
+           ))
+    {
+        my $value = $attribs{$key} || $self->{$key};
+        $make .= "$key = $value\n";
     }
 
     return $make;
@@ -770,35 +728,116 @@ Defines a check in target for RCS.
 
 sub dist_ci {
     my($self) = shift;
-    my @m;
-    push @m, q{
+    return q{
 ci :
        $(PERLRUN) "-MExtUtils::Manifest=maniread" \\
-               -e "@all = keys %{ maniread() };" \\
-               -e 'print("Executing $(CI) @all\n"); system("$(CI) @all");' \\
-               -e 'print("Executing $(RCS_LABEL) ...\n"); system("$(RCS_LABEL) @all");'
+         -e "@all = keys %{ maniread() };" \\
+         -e "print("Executing $(CI) @all\n"); system(qq{$(CI) @all});" \\
+         -e "print("Executing $(RCS_LABEL) ...\n"); system(qq{$(RCS_LABEL) @all});"
 };
-    join "", @m;
 }
 
 =item dist_core (o)
 
-Defines the targets dist, tardist, zipdist, uutardist, shdist
+  my $dist_make_fragment = $MM->dist_core;
+
+Puts the targets necessary for 'make dist' together into one make
+fragment.
 
 =cut
 
 sub dist_core {
     my($self) = shift;
-    my @m;
-    push @m, q{
+
+    my $make_frag = '';
+    foreach my $target (qw(dist tardist uutardist tarfile zipdist zipfile 
+                           shdist))
+    {
+        my $method = $target.'_target';
+        $make_frag .= "\n";
+        $make_frag .= $self->$method();
+    }
+
+    return $make_frag;
+}
+
+
+=item B<dist_target>
+
+  my $make_frag = $MM->dist_target;
+
+Returns the 'dist' target to make an archive for distribution.  This
+target simply checks to make sure the Makefile is up-to-date and
+depends on $(DIST_DEFAULT).
+
+=cut
+
+sub dist_target {
+    my($self) = shift;
+
+    my $date_check = $self->oneliner(<<'CODE', ['-l']);
+print 'Warning: Makefile possibly out of date with $(VERSION_FROM)'
+  if -e '$(VERSION_FROM)' and -M '$(VERSION_FROM)' < -M '$(FIRST_MAKEFILE)';
+CODE
+
+    return sprintf <<'MAKE_FRAG', $date_check;
 dist : $(DIST_DEFAULT)
-       }.$self->{NOECHO}.q{$(PERL) -le 'print "Warning: Makefile possibly out of date with $$vf" if ' \
-           -e '-e ($$vf="$(VERSION_FROM)") and -M $$vf < -M "}.$self->{MAKEFILE}.q{";'
+       $(NOECHO) %s
+MAKE_FRAG
+}
+
+=item B<tardist_target>
 
+  my $make_frag = $MM->tardist_target;
+
+Returns the 'tardist' target which is simply so 'make tardist' works.
+The real work is done by the dynamically named tardistfile_target()
+method, tardist should have that as a dependency.
+
+=cut
+
+sub tardist_target {
+    my($self) = shift;
+
+    return <<'MAKE_FRAG';
 tardist : $(DISTVNAME).tar$(SUFFIX)
+       $(NOECHO) $(NOOP)
+MAKE_FRAG
+}
+
+=item B<zipdist_target>
+
+  my $make_frag = $MM->zipdist_target;
+
+Returns the 'zipdist' target which is simply so 'make zipdist' works.
+The real work is done by the dynamically named zipdistfile_target()
+method, zipdist should have that as a dependency.
+
+=cut
+
+sub zipdist_target {
+    my($self) = shift;
 
+    return <<'MAKE_FRAG';
 zipdist : $(DISTVNAME).zip
+       $(NOECHO) $(NOOP)
+MAKE_FRAG
+}
+
+=item B<tarfile_target>
+
+  my $make_frag = $MM->tarfile_target;
+
+The name of this target is the name of the tarball generated by
+tardist.  This target does the actual work of turning the distdir into
+a tarball.
 
+=cut
+
+sub tarfile_target {
+    my($self) = shift;
+
+    return <<'MAKE_FRAG';
 $(DISTVNAME).tar$(SUFFIX) : distdir
        $(PREOP)
        $(TO_UNIX)
@@ -806,39 +845,84 @@ $(DISTVNAME).tar$(SUFFIX) : distdir
        $(RM_RF) $(DISTVNAME)
        $(COMPRESS) $(DISTVNAME).tar
        $(POSTOP)
+MAKE_FRAG
+}
+
+=item zipfile_target
 
+  my $make_frag = $MM->zipfile_target;
+
+The name of this target is the name of the zip file generated by
+zipdist.  This target does the actual work of turning the distdir into
+a zip file.
+
+=cut
+
+sub zipfile_target {
+    my($self) = shift;
+
+    return <<'MAKE_FRAG';
 $(DISTVNAME).zip : distdir
        $(PREOP)
        $(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME)
        $(RM_RF) $(DISTVNAME)
        $(POSTOP)
+MAKE_FRAG
+}
+
+=item uutardist_target
+
+  my $make_frag = $MM->uutardist_target;
+
+Converts the tarfile into a uuencoded file
+
+=cut
+
+sub uutardist_target {
+    my($self) = shift;
 
+    return <<'MAKE_FRAG';
 uutardist : $(DISTVNAME).tar$(SUFFIX)
-       uuencode $(DISTVNAME).tar$(SUFFIX) \\
-               $(DISTVNAME).tar$(SUFFIX) > \\
-               $(DISTVNAME).tar$(SUFFIX)_uu
+       uuencode $(DISTVNAME).tar$(SUFFIX) $(DISTVNAME).tar$(SUFFIX) > $(DISTVNAME).tar$(SUFFIX)_uu
+MAKE_FRAG
+}
+
+
+=item shdist_target
+
+  my $make_frag = $MM->shdist_target;
+
+Converts the distdir into a shell archive.
+
+=cut
+
+sub shdist_target {
+    my($self) = shift;
 
+    return <<'MAKE_FRAG';
 shdist : distdir
        $(PREOP)
        $(SHAR) $(DISTVNAME) > $(DISTVNAME).shar
        $(RM_RF) $(DISTVNAME)
        $(POSTOP)
-};
-    join "", @m;
+MAKE_FRAG
 }
 
-=item dist_dir
+=item distdir
 
 Defines the scratch directory target that will hold the distribution
 before tar-ing (or shar-ing).
 
 =cut
 
-sub dist_dir {
+# For backwards compatibility.
+*dist_dir = *distdir;
+
+sub distdir {
     my($self) = shift;
 
     return <<'MAKE_FRAG';
-distdir :
+distdir : metafile metafile_addtomanifest
        $(RM_RF) $(DISTVNAME)
        $(PERLRUN) "-MExtUtils::Manifest=manicopy,maniread" \
                -e "manicopy(maniread(),'$(DISTVNAME)', '$(DIST_CP)');"
@@ -877,7 +961,7 @@ files.
 sub dlsyms {
     my($self,%attribs) = @_;
 
-    return '' unless ($^O eq 'aix' && $self->needs_linking() );
+    return '' unless ($Is_AIX && $self->needs_linking() );
 
     my($funcs) = $attribs{DL_FUNCS} || $self->{DL_FUNCS} || {};
     my($vars)  = $attribs{DL_VARS} || $self->{DL_VARS} || [];
@@ -918,9 +1002,8 @@ sub dynamic {
     '
 ## $(INST_PM) has been moved to the all: target.
 ## It remains here for awhile to allow for old usage: "make dynamic"
-#dynamic :: '.$self->{MAKEFILE}.' $(INST_DYNAMIC) $(INST_BOOT) $(INST_PM)
-dynamic :: '.$self->{MAKEFILE}.' $(INST_DYNAMIC) $(INST_BOOT)
-       '.$self->{NOECHO}.'$(NOOP)
+dynamic :: $(FIRST_MAKEFILE) $(INST_DYNAMIC) $(INST_BOOT)
+       $(NOECHO) $(NOOP)
 ';
 }
 
@@ -936,25 +1019,25 @@ sub dynamic_bs {
 BOOTSTRAP =
 ' unless $self->has_link_code();
 
-    return '
-BOOTSTRAP = '."$self->{BASEEXT}.bs".'
+    return <<'MAKE_FRAG';
+BOOTSTRAP = $(BASEEXT).bs
 
 # As Mkbootstrap might not write a file (if none is required)
 # we use touch to prevent make continually trying to remake it.
 # The DynaLoader only reads a non-empty file.
-$(BOOTSTRAP): '."$self->{MAKEFILE} $self->{BOOTDEP}".' $(INST_ARCHAUTODIR)/.exists
-       '.$self->{NOECHO}.'echo "Running Mkbootstrap for $(NAME) ($(BSLOADLIBS))"
-       '.$self->{NOECHO}.'$(PERLRUN) \
+$(BOOTSTRAP): $(FIRST_MAKEFILE) $(BOOTDEP) $(INST_ARCHAUTODIR)$(DIRFILESEP).exists
+       $(NOECHO) $(ECHO) "Running Mkbootstrap for $(NAME) ($(BSLOADLIBS))"
+       $(NOECHO) $(PERLRUN) \
                "-MExtUtils::Mkbootstrap" \
-               -e "Mkbootstrap(\'$(BASEEXT)\',\'$(BSLOADLIBS)\');"
-       '.$self->{NOECHO}.'$(TOUCH) $(BOOTSTRAP)
+               -e "Mkbootstrap('$(BASEEXT)','$(BSLOADLIBS)');"
+       $(NOECHO) $(TOUCH) $(BOOTSTRAP)
        $(CHMOD) $(PERM_RW) $@
 
-$(INST_BOOT): $(BOOTSTRAP) $(INST_ARCHAUTODIR)/.exists
-       '."$self->{NOECHO}$self->{RM_RF}".' $(INST_BOOT)
-       -'.$self->{CP}.' $(BOOTSTRAP) $(INST_BOOT)
+$(INST_BOOT): $(BOOTSTRAP) $(INST_ARCHAUTODIR)$(DIRFILESEP).exists
+       $(NOECHO) $(RM_RF) $(INST_BOOT)
+       -$(CP) $(BOOTSTRAP) $(INST_BOOT)
        $(CHMOD) $(PERM_RW) $@
-';
+MAKE_FRAG
 }
 
 =item dynamic_lib (o)
@@ -973,7 +1056,7 @@ sub dynamic_lib {
     my($inst_dynamic_dep) = $attribs{INST_DYNAMIC_DEP} || "";
     my($armaybe) = $attribs{ARMAYBE} || $self->{ARMAYBE} || ":";
     my($ldfrom) = '$(LDFROM)';
-    $armaybe = 'ar' if ($^O eq 'dec_osf' and $armaybe eq ':');
+    $armaybe = 'ar' if ($Is_OSF and $armaybe eq ':');
     my(@m);
     my $ld_opt = $Is_OS2 ? '$(OPTIMIZE) ' : '';        # Useful on other systems too?
     push(@m,'
@@ -983,17 +1066,17 @@ ARMAYBE = '.$armaybe.'
 OTHERLDFLAGS = '.$ld_opt.$otherldflags.'
 INST_DYNAMIC_DEP = '.$inst_dynamic_dep.'
 
-$(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)/.exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(PERL_ARCHIVE_AFTER) $(INST_DYNAMIC_DEP)
+$(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)$(DIRFILESEP).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(PERL_ARCHIVE_AFTER) $(INST_DYNAMIC_DEP)
 ');
     if ($armaybe ne ':'){
        $ldfrom = 'tmp$(LIB_EXT)';
        push(@m,'       $(ARMAYBE) cr '.$ldfrom.' $(OBJECT)'."\n");
        push(@m,'       $(RANLIB) '."$ldfrom\n");
     }
-    $ldfrom = "-all $ldfrom -none" if ($^O eq 'dec_osf');
+    $ldfrom = "-all $ldfrom -none" if $Is_OSF;
 
     # The IRIX linker doesn't use LD_RUN_PATH
-    my $ldrun = $^O eq 'irix' && $self->{LD_RUN_PATH} ?         
+    my $ldrun = $Is_IRIX && $self->{LD_RUN_PATH} ?         
                        qq{-rpath "$self->{LD_RUN_PATH}"} : '';
 
     # For example in AIX the shared objects/libraries from previous builds
@@ -1006,7 +1089,7 @@ $(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)/.exists
 
     my $libs = '$(LDLOADLIBS)';
 
-    if ($^O eq 'netbsd') {
+    if ($Is_NetBSD) {
        # Use nothing on static perl platforms, and to the flags needed
        # to link against the shared libperl library on shared perl
        # platforms.  We peek at lddlflags to see if we need -Wl,-R
@@ -1065,34 +1148,54 @@ sub find_perl {
     my($self, $ver, $names, $dirs, $trace) = @_;
     my($name, $dir);
     if ($trace >= 2){
-       print "Looking for perl $ver by these names:
+        print "Looking for perl $ver by these names:
 @$names
 in these dirs:
 @$dirs
 ";
     }
+
+    my $stderr_duped = 0;
+    local *STDERR_COPY;
+    if( open(STDERR_COPY, '>&STDERR') ) {
+        $stderr_duped = 1;
+    }
+    else {
+        warn <<WARNING;
+find_perl() can't dup STDERR: $!
+You might see some garbage while we search for Perl
+WARNING
+    }
+
     foreach $name (@$names){
-       foreach $dir (@$dirs){
-           next unless defined $dir; # $self->{PERL_SRC} may be undefined
-           my ($abs, $val);
-           if (File::Spec->file_name_is_absolute($name)) { # /foo/bar
-               $abs = $name;
-           } elsif (File::Spec->canonpath($name) eq File::Spec->canonpath(basename($name))) { # foo
-               $abs = File::Spec->catfile($dir, $name);
-           } else { # foo/bar
-               $abs = File::Spec->canonpath(File::Spec->catfile($Curdir, $name));
-           }
-           print "Checking $abs\n" if ($trace >= 2);
-           next unless $self->maybe_command($abs);
-           print "Executing $abs\n" if ($trace >= 2);
-           $val = `$abs -e 'require $ver; print "VER_OK\n" ' 2>&1`;
-           if ($val =~ /VER_OK/) {
-               print "Using PERL=$abs\n" if $trace;
-               return $abs;
-           } elsif ($trace >= 2) {
-               print "Result: `$val'\n";
-           }
-       }
+        foreach $dir (@$dirs){
+            next unless defined $dir; # $self->{PERL_SRC} may be undefined
+            my ($abs, $val);
+            if ($self->file_name_is_absolute($name)) {     # /foo/bar
+                $abs = $name;
+            } elsif ($self->canonpath($name) eq 
+                     $self->canonpath(basename($name))) {  # foo
+                $abs = $self->catfile($dir, $name);
+            } else {                                            # foo/bar
+                $abs = $self->catfile($Curdir, $name);
+            }
+            print "Checking $abs\n" if ($trace >= 2);
+            next unless $self->maybe_command($abs);
+            print "Executing $abs\n" if ($trace >= 2);
+
+            # To avoid using the unportable 2>&1 to supress STDERR,
+            # we close it before running the command.
+            close STDERR if $stderr_duped;
+            $val = `$abs -e "require $ver; print qq{VER_OK\n}"`;
+            open STDERR, '>&STDERR_COPY' if $stderr_duped;
+
+            if ($val =~ /^VER_OK/) {
+                print "Using PERL=$abs\n" if $trace;
+                return $abs;
+            } elsif ($trace >= 2) {
+                print "Result: '$val'\n";
+            }
+        }
     }
     print STDOUT "Unable to find a perl $ver (by these names: @$names, in these dirs: @$dirs)\n";
     0; # false and not empty
@@ -1154,13 +1257,13 @@ sub fixin { # stolen from the pink Camel book, more or less
                 $interpreter = $Config{perlpath};
             }
        } else {
-           my(@absdirs) = reverse grep {File::Spec->file_name_is_absolute} File::Spec->path;
+           my(@absdirs) = reverse grep {$self->file_name_is_absolute} $self->path;
            $interpreter = '';
            my($dir);
            foreach $dir (@absdirs) {
                if ($self->maybe_command($cmd)) {
                    warn "Ignoring $interpreter in $file\n" if $Verbose && $interpreter;
-                   $interpreter = File::Spec->catfile($dir,$cmd);
+                   $interpreter = $self->catfile($dir,$cmd);
                }
            }
        }
@@ -1227,7 +1330,7 @@ sub force {
     my($self) = shift;
     '# Phony target to force checking subdirectories.
 FORCE:
-       '.$self->{NOECHO}.'$(NOOP)
+       $(NOECHO) $(NOOP)
 ';
 }
 
@@ -1273,7 +1376,10 @@ sub has_link_code {
 
 =item init_dirscan
 
-Initializes DIR, XS, PM, C, O_FILES, H, PL_FILES, MAN*PODS, EXE_FILES.
+Scans the directory structure and initializes DIR, XS, XS_FILES, PM,
+C, C_FILES, O_FILES, H, H_FILES, PL_FILES, MAN*PODS, EXE_FILES.
+
+Called by init_main.
 
 =cut
 
@@ -1296,7 +1402,7 @@ sub init_dirscan {        # --- File and Directory Lists (.xs .pm .pod etc)
        next unless $self->libscan($name);
        if (-d $name){
            next if -l $name; # We do not support symlinks at all
-           $dir{$name} = $name if (-f File::Spec->catfile($name,"Makefile.PL"));
+           $dir{$name} = $name if (-f $self->catfile($name,"Makefile.PL"));
        } elsif ($name =~ /\.xs\z/){
            my($c); ($c = $name) =~ s/\.xs\z/.c/;
            $xs{$name} = $c;
@@ -1316,10 +1422,10 @@ sub init_dirscan {      # --- File and Directory Lists (.xs .pm .pod etc)
                ($pl_files{$name} = $name) =~ s/[._]pl\z//i ;
            }
            else { 
-                $pm{$name} = File::Spec->catfile($self->{INST_LIBDIR},$name); 
+                $pm{$name} = $self->catfile($self->{INST_LIBDIR},$name); 
             }
        } elsif ($name =~ /\.(p[ml]|pod)\z/){
-           $pm{$name} = File::Spec->catfile($self->{INST_LIBDIR},$name);
+           $pm{$name} = $self->catfile($self->{INST_LIBDIR},$name);
        }
     }
 
@@ -1349,14 +1455,14 @@ sub init_dirscan {      # --- File and Directory Lists (.xs .pm .pod etc)
     # (which includes PARENT_NAME). This is a subtle distinction but one
     # that's important for nested modules.
 
-    if ($Is_VMS) {
-      # avoid logical name collisions by adding directory syntax
-      $self->{PMLIBDIRS} = ['./lib', './' . $self->{BASEEXT}]
-       unless $self->{PMLIBDIRS};
-    }
-    else {
-      $self->{PMLIBDIRS} = ['lib', $self->{BASEEXT}]
-       unless $self->{PMLIBDIRS};
+    unless( $self->{PMLIBDIRS} ) {
+        if( $Is_VMS ) {
+            # Avoid logical name vs directory collisions
+            $self->{PMLIBDIRS} = ['./lib', "./$self->{BASEEXT}"];
+        }
+        else {
+            $self->{PMLIBDIRS} = ['lib', $self->{BASEEXT}];
+        }
     }
 
     #only existing directories that aren't in $dir are allowed
@@ -1376,7 +1482,7 @@ sub init_dirscan {        # --- File and Directory Lists (.xs .pm .pod etc)
        require File::Find;
         File::Find::find(sub {
             if (-d $_){
-                if ($_ eq "CVS" || $_ eq "RCS"){
+                unless ($self->libscan($_)){
                     $File::Find::prune = 1;
                 }
                 return;
@@ -1391,7 +1497,7 @@ sub init_dirscan {        # --- File and Directory Lists (.xs .pm .pod etc)
            $prefix =  $self->{INST_LIB} 
                 if ($striplibpath = $path) =~ s:^(\W*)lib\W:$1:i;
 
-           my($inst) = File::Spec->catfile($prefix,$striplibpath);
+           my($inst) = $self->catfile($prefix,$striplibpath);
            local($_) = $inst; # for backwards compatibility
            $inst = $self->libscan($inst);
            print "libscan($path) => '$inst'\n" if ($Verbose >= 2);
@@ -1400,14 +1506,17 @@ sub init_dirscan {      # --- File and Directory Lists (.xs .pm .pod etc)
        }, @{$self->{PMLIBDIRS}});
     }
 
-    $self->{DIR} = [sort keys %dir] unless $self->{DIR};
-    $self->{XS}  = \%xs             unless $self->{XS};
-    $self->{PM}  = \%pm             unless $self->{PM};
-    $self->{C}   = [sort keys %c]   unless $self->{C};
-    my(@o_files) = @{$self->{C}};
-    $self->{O_FILES} = [grep s/\.c(pp|xx|c)?\z/$self->{OBJ_EXT}/i, @o_files] ;
-    $self->{H}   = [sort keys %h]   unless $self->{H};
-    $self->{PL_FILES} = \%pl_files unless $self->{PL_FILES};
+    $self->{PM}  ||= \%pm;
+    $self->{PL_FILES} ||= \%pl_files;
+
+    $self->{DIR} ||= [sort keys %dir];
+
+    $self->{XS}  ||= \%xs;
+    $self->{C}   ||= [sort keys %c];
+    my @o_files = @{$self->{C}};
+    $self->{O_FILES} = [grep s/\.c(pp|xx|c)?\z/$self->{OBJ_EXT}/i, @o_files];
+                            
+    $self->{H}   ||= [sort keys %h];
 
     # Set up names of manual pages to generate from pods
     my %pods;
@@ -1426,7 +1535,7 @@ sub init_dirscan {        # --- File and Directory Lists (.xs .pm .pod etc)
                my($ispod)=0;
                if (open(FH,"<$name")) {
                    while (<FH>) {
-                       if (/^=\w/) {
+                       if (/^=(?:head\d+|item|pod)\b/) {
                            $ispod=1;
                            last;
                        }
@@ -1439,7 +1548,7 @@ sub init_dirscan {        # --- File and Directory Lists (.xs .pm .pod etc)
                next unless $ispod;
                if ($pods{MAN1}) {
                    $self->{MAN1PODS}->{$name} =
-                     File::Spec->catfile("\$(INST_MAN1DIR)", basename($name).".\$(MAN1EXT)");
+                     $self->catfile("\$(INST_MAN1DIR)", basename($name).".\$(MAN1EXT)");
                }
            }
        }
@@ -1455,7 +1564,7 @@ sub init_dirscan {        # --- File and Directory Lists (.xs .pm .pod etc)
                my($ispod)=0;
                if (open(FH,"<$name")) {
                    while (<FH>) {
-                       if (/^=\w/) {
+                       if (/^=head1\s+\w+/) {
                            $ispod=1;
                            last;
                        }
@@ -1480,18 +1589,34 @@ sub init_dirscan {      # --- File and Directory Lists (.xs .pm .pod etc)
            }
            my($manpagename) = $name;
            $manpagename =~ s/\.p(od|m|l)\z//;
-           unless ($manpagename =~ s!^\W*lib\W+!!s) { # everything below lib is ok
-               $manpagename = File::Spec->catfile(split(/::/,$self->{PARENT_NAME}),$manpagename);
+           # everything below lib is ok
+           if($self->{PARENT_NAME} && $manpagename !~ s!^\W*lib\W+!!s) {
+               $manpagename = $self->catfile(
+                                split(/::/,$self->{PARENT_NAME}),$manpagename
+                               );
            }
            if ($pods{MAN3}) {
                $manpagename = $self->replace_manpage_separator($manpagename);
                $self->{MAN3PODS}->{$name} =
-                 File::Spec->catfile("\$(INST_MAN3DIR)", "$manpagename.\$(MAN3EXT)");
+                 $self->catfile("\$(INST_MAN3DIR)", "$manpagename.\$(MAN3EXT)");
            }
        }
     }
 }
 
+=item init_DIRFILESEP
+
+Using / for Unix.  Called by init_main.
+
+=cut
+
+sub init_DIRFILESEP {
+    my($self) = shift;
+
+    $self->{DIRFILESEP} = '/';
+}
+    
+
 =item init_main
 
 Initializes AR, AR_STATIC_ARGS, BASEEXT, CONFIG, DISTNAME, DLBASE,
@@ -1499,7 +1624,7 @@ EXE_EXT, FULLEXT, FULLPERL, FULLPERLRUN, FULLPERLRUNINST, INST_*,
 INSTALL*, INSTALLDIRS, LD, LIB_EXT, LIBPERL_A, MAP_TARGET, NAME,
 OBJ_EXT, PARENT_NAME, PERL, PERL_ARCHLIB, PERL_INC, PERL_LIB,
 PERL_SRC, PERLRUN, PERLRUNINST, PREFIX, VERSION,
-VERSION_FROM, VERSION_SYM, XS_VERSION.
+VERSION_SYM, XS_VERSION.
 
 =cut
 
@@ -1515,7 +1640,7 @@ sub init_main {
 ### Only UNIX:
 ###    ($self->{FULLEXT} =
 ###     $self->{NAME}) =~ s!::!/!g ; #eg. BSD/Foo/Socket
-    $self->{FULLEXT} = File::Spec->catdir(split /::/, $self->{NAME});
+    $self->{FULLEXT} = $self->catdir(split /::/, $self->{NAME});
 
 
     # Copied from DynaLoader:
@@ -1550,17 +1675,17 @@ sub init_main {
     unless ($self->{PERL_SRC}){
        my($dir);
        foreach $dir ($Updir,
-                      File::Spec->catdir($Updir,$Updir),
-                      File::Spec->catdir($Updir,$Updir,$Updir),
-                      File::Spec->catdir($Updir,$Updir,$Updir,$Updir),
-                      File::Spec->catdir($Updir,$Updir,$Updir,$Updir,$Updir))
+                  $self->catdir($Updir,$Updir),
+                  $self->catdir($Updir,$Updir,$Updir),
+                  $self->catdir($Updir,$Updir,$Updir,$Updir),
+                  $self->catdir($Updir,$Updir,$Updir,$Updir,$Updir))
         {
            if (
-               -f File::Spec->catfile($dir,"config_h.SH")
+               -f $self->catfile($dir,"config_h.SH")
                &&
-               -f File::Spec->catfile($dir,"perl.h")
+               -f $self->catfile($dir,"perl.h")
                &&
-               -f File::Spec->catfile($dir,"lib","Exporter.pm")
+               -f $self->catfile($dir,"lib","Exporter.pm")
               ) {
                $self->{PERL_SRC}=$dir ;
                last;
@@ -1572,28 +1697,28 @@ sub init_main {
       $self->{PERL_CORE} and !$self->{PERL_SRC};
 
     if ($self->{PERL_SRC}){
-       $self->{PERL_LIB}     ||= File::Spec->catdir("$self->{PERL_SRC}","lib");
+       $self->{PERL_LIB}     ||= $self->catdir("$self->{PERL_SRC}","lib");
 
         if (defined $Cross::platform) {
             $self->{PERL_ARCHLIB} = 
-              File::Spec->catdir("$self->{PERL_SRC}","xlib",$Cross::platform);
+              $self->catdir("$self->{PERL_SRC}","xlib",$Cross::platform);
             $self->{PERL_INC}     = 
-              File::Spec->catdir("$self->{PERL_SRC}","xlib",$Cross::platform, 
+              $self->catdir("$self->{PERL_SRC}","xlib",$Cross::platform, 
                                  $Is_Win32?("CORE"):());
         }
         else {
             $self->{PERL_ARCHLIB} = $self->{PERL_LIB};
             $self->{PERL_INC}     = ($Is_Win32) ? 
-              File::Spec->catdir($self->{PERL_LIB},"CORE") : $self->{PERL_SRC};
+              $self->catdir($self->{PERL_LIB},"CORE") : $self->{PERL_SRC};
         }
 
        # catch a situation that has occurred a few times in the past:
        unless (
-               -s File::Spec->catfile($self->{PERL_SRC},'cflags')
+               -s $self->catfile($self->{PERL_SRC},'cflags')
                or
                $Is_VMS
                &&
-               -s File::Spec->catfile($self->{PERL_SRC},'perlshr_attr.opt')
+               -s $self->catfile($self->{PERL_SRC},'perlshr_attr.opt')
                or
                $Is_Mac
                or
@@ -1618,20 +1743,20 @@ from the perl source tree.
         my $old = $self->{PERL_LIB} || $self->{PERL_ARCHLIB} || $self->{PERL_INC};
        $self->{PERL_LIB}     ||= $Config{privlibexp};
        $self->{PERL_ARCHLIB} ||= $Config{archlibexp};
-       $self->{PERL_INC}     = File::Spec->catdir("$self->{PERL_ARCHLIB}","CORE"); # wild guess for now
+       $self->{PERL_INC}     = $self->catdir("$self->{PERL_ARCHLIB}","CORE"); # wild guess for now
        my $perl_h;
 
-       if (not -f ($perl_h = File::Spec->catfile($self->{PERL_INC},"perl.h"))
+       if (not -f ($perl_h = $self->catfile($self->{PERL_INC},"perl.h"))
            and not $old){
            # Maybe somebody tries to build an extension with an
            # uninstalled Perl outside of Perl build tree
            my $found;
            for my $dir (@INC) {
-             $found = $dir, last if -e File::Spec->catdir($dir, "Config.pm");
+             $found = $dir, last if -e $self->catdir($dir, "Config.pm");
            }
            if ($found) {
              my $inc = dirname $found;
-             if (-e File::Spec->catdir($inc, "perl.h")) {
+             if (-e $self->catdir($inc, "perl.h")) {
                $self->{PERL_LIB}          = $found;
                $self->{PERL_ARCHLIB}      = $found;
                $self->{PERL_INC}          = $inc;
@@ -1643,7 +1768,7 @@ EOP
            }
        }
        
-       unless(-f ($perl_h = File::Spec->catfile($self->{PERL_INC},"perl.h")))
+       unless(-f ($perl_h = $self->catfile($self->{PERL_INC},"perl.h")))
         {
            die qq{
 Error: Unable to locate installed Perl libraries or Perl source code.
@@ -1669,10 +1794,6 @@ usually solves this kind of problem.
     # MakeMaker.
     $self->{INSTALLDIRS} ||= "site";
 
-
-    $self->init_INST;
-    $self->init_INSTALL;
-
     $self->{MAN1EXT} ||= $Config{man1ext};
     $self->{MAN3EXT} ||= $Config{man3ext};
 
@@ -1682,8 +1803,8 @@ usually solves this kind of problem.
     $self->{CONFIG} = [] unless (ref $self->{CONFIG});
     push(@{$self->{CONFIG}}, @ExtUtils::MakeMaker::Get_from_Config);
     push(@{$self->{CONFIG}}, 'shellflags') if $Config{shellflags};
-    my(%once_only,$m);
-    foreach $m (@{$self->{CONFIG}}){
+    my(%once_only);
+    foreach my $m (@{$self->{CONFIG}}){
        next if $once_only{$m};
        print STDOUT "CONFIG key '$m' does not exist in Config.pm\n"
                unless exists $Config{$m};
@@ -1712,47 +1833,16 @@ usually solves this kind of problem.
     # make a simple check if we find Exporter
     warn "Warning: PERL_LIB ($self->{PERL_LIB}) seems not to be a perl library directory
         (Exporter.pm not found)"
-       unless -f File::Spec->catfile("$self->{PERL_LIB}","Exporter.pm") ||
+       unless -f $self->catfile("$self->{PERL_LIB}","Exporter.pm") ||
         $self->{NAME} eq "ExtUtils::MakeMaker";
-
-    # Determine VERSION and VERSION_FROM
-    ($self->{DISTNAME}=$self->{NAME}) =~ s#(::)#-#g unless $self->{DISTNAME};
-    if ($self->{VERSION_FROM}){
-       $self->{VERSION} = $self->parse_version($self->{VERSION_FROM});
-        if( $self->{VERSION} eq 'undef' ) {
-           carp "WARNING: Setting VERSION via file ".
-                 "'$self->{VERSION_FROM}' failed\n";
-        }
-    }
-
-    # strip blanks
-    if (defined $self->{VERSION}) {
-       $self->{VERSION} =~ s/^\s+//;
-       $self->{VERSION} =~ s/\s+$//;
-    }
-    else {
-        $self->{VERSION} = '';
-    }
-    ($self->{VERSION_SYM} = $self->{VERSION}) =~ s/\W/_/g;
-
-    $self->{DISTVNAME} = "$self->{DISTNAME}-$self->{VERSION}";
-
-    # Graham Barr and Paul Marquess had some ideas how to ensure
-    # version compatibility between the *.pm file and the
-    # corresponding *.xs file. The bottomline was, that we need an
-    # XS_VERSION macro that defaults to VERSION:
-    $self->{XS_VERSION} ||= $self->{VERSION};
-
-
-    # --- Initialize Perl Binary Locations
-    $self->init_PERL;
 }
 
 =item init_others
 
 Initializes EXTRALIBS, BSLOADLIBS, LDLOADLIBS, LIBS, LD_RUN_PATH,
-OBJECT, BOOTDEP, PERLMAINCC, LDFROM, LINKTYPE, NOOP, FIRST_MAKEFILE,
-MAKEFILE, NOECHO, RM_F, RM_RF, TEST_F, TOUCH, CP, MV, CHMOD, UMASK_NULL
+OBJECT, BOOTDEP, PERLMAINCC, LDFROM, LINKTYPE, SHELL, NOOP,
+FIRST_MAKEFILE, MAKEFILE_OLD, NOECHO, RM_F, RM_RF, TEST_F,
+TOUCH, CP, MV, CHMOD, UMASK_NULL
 
 =cut
 
@@ -1764,9 +1854,9 @@ sub init_others { # --- Initialize Other Attributes
     # undefined. In any case we turn it into an anon array:
 
     # May check $Config{libs} too, thus not empty.
-    $self->{LIBS}=[''] unless $self->{LIBS};
+    $self->{LIBS} = [$self->{LIBS}] unless ref $self->{LIBS};
 
-    $self->{LIBS}=[$self->{LIBS}] if ref \$self->{LIBS} eq 'SCALAR';
+    $self->{LIBS} = [''] unless @{$self->{LIBS}} && defined $self->{LIBS}[0];
     $self->{LD_RUN_PATH} = "";
     my($libs);
     foreach $libs ( @{$self->{LIBS}} ){
@@ -1802,36 +1892,61 @@ sub init_others {       # --- Initialize Other Attributes
                         : ($Config{usedl} ? 'dynamic' : 'static');
     };
 
-    # These get overridden for VMS and maybe some other systems
-    $self->{NOOP}  ||= '$(SHELL) -c true';
-    $self->{FIRST_MAKEFILE} ||= "Makefile";
-    $self->{MAKEFILE} ||= $self->{FIRST_MAKEFILE};
-    $self->{MAKE_APERL_FILE} ||= "Makefile.aperl";
-    $self->{NOECHO} = '@' unless defined $self->{NOECHO};
-    $self->{RM_F}  ||= "rm -f";
-    $self->{RM_RF} ||= "rm -rf";
-    $self->{TOUCH} ||= "touch";
-    $self->{TEST_F} ||= "test -f";
-    $self->{CP} ||= "cp";
-    $self->{MV} ||= "mv";
-    $self->{CHMOD} ||= "chmod";
-    $self->{UMASK_NULL} ||= "umask 0";
-    $self->{DEV_NULL} ||= "> /dev/null 2>&1";
+    $self->{NOOP}               ||= '$(SHELL) -c true';
+    $self->{NOECHO}             = '@' unless defined $self->{NOECHO};
+
+    $self->{MAKEFILE}           ||= 'Makefile';
+    $self->{FIRST_MAKEFILE}     ||= $self->{MAKEFILE};
+    $self->{MAKEFILE_OLD}       ||= '$(FIRST_MAKEFILE).old';
+    $self->{MAKE_APERL_FILE}    ||= '$(FIRST_MAKEFILE).aperl';
+
+    $self->{SHELL}              ||= $Config{sh} || '/bin/sh';
+
+    $self->{ECHO}       ||= 'echo';
+    $self->{RM_F}       ||= "rm -f";
+    $self->{RM_RF}      ||= "rm -rf";
+    $self->{TOUCH}      ||= "touch";
+    $self->{TEST_F}     ||= "test -f";
+    $self->{CP}         ||= "cp";
+    $self->{MV}         ||= "mv";
+    $self->{CHMOD}      ||= "chmod";
+    $self->{MKPATH}     ||= '$(PERLRUN) "-MExtUtils::Command" -e mkpath';
+    $self->{EQUALIZE_TIMESTAMP} ||= 
+      '$(PERLRUN) "-MExtUtils::Command" -e eqtime';
+
+    $self->{UNINST}     ||= 0;
+    $self->{VERBINST}   ||= 0;
+    $self->{MOD_INSTALL} ||= 
+      $self->oneliner(<<'CODE', ['-MExtUtils::Install']);
+install({@ARGV}, '$(VERBINST)', 0, '$(UNINST)');
+CODE
+    $self->{DOC_INSTALL} ||= 
+      '$(PERLRUN) "-MExtUtils::Command::MM" -e perllocal_install';
+    $self->{UNINSTALL}   ||= 
+      '$(PERLRUN) "-MExtUtils::Command::MM" -e uninstall';
+    $self->{WARN_IF_OLD_PACKLIST} ||= 
+      '$(PERLRUN) "-MExtUtils::Command::MM" -e warn_if_old_packlist';
+
+    $self->{UMASK_NULL}         ||= "umask 0";
+    $self->{DEV_NULL}           ||= "> /dev/null 2>&1";
+
+    return 1;
 }
 
 =item init_INST
 
     $mm->init_INST;
 
-Called by init_main.  Sets up all INST_* variables.
+Called by init_main.  Sets up all INST_* variables except those related
+to XS code.  Those are handled in init_xs.
 
 =cut
 
 sub init_INST {
     my($self) = shift;
 
-    $self->{INST_ARCHLIB} ||= File::Spec->catdir($Curdir,"blib","arch");
-    $self->{INST_BIN}     ||= File::Spec->catdir($Curdir,'blib','bin');
+    $self->{INST_ARCHLIB} ||= $self->catdir($Curdir,"blib","arch");
+    $self->{INST_BIN}     ||= $self->catdir($Curdir,'blib','bin');
 
     # INST_LIB typically pre-set if building an extension after
     # perl has been built and installed. Setting INST_LIB allows
@@ -1840,30 +1955,30 @@ sub init_INST {
        if ($self->{PERL_CORE}) {
             if (defined $Cross::platform) {
                 $self->{INST_LIB} = $self->{INST_ARCHLIB} = 
-                  File::Spec->catdir($self->{PERL_LIB},"..","xlib",
+                  $self->catdir($self->{PERL_LIB},"..","xlib",
                                      $Cross::platform);
             }
             else {
                 $self->{INST_LIB} = $self->{INST_ARCHLIB} = $self->{PERL_LIB};
             }
        } else {
-           $self->{INST_LIB} = File::Spec->catdir($Curdir,"blib","lib");
+           $self->{INST_LIB} = $self->catdir($Curdir,"blib","lib");
        }
     }
 
     my @parentdir = split(/::/, $self->{PARENT_NAME});
-    $self->{INST_LIBDIR} = File::Spec->catdir($self->{INST_LIB},@parentdir);
-    $self->{INST_ARCHLIBDIR} = File::Spec->catdir($self->{INST_ARCHLIB},
+    $self->{INST_LIBDIR} = $self->catdir($self->{INST_LIB},@parentdir);
+    $self->{INST_ARCHLIBDIR} = $self->catdir($self->{INST_ARCHLIB},
                                                   @parentdir);
-    $self->{INST_AUTODIR} = File::Spec->catdir($self->{INST_LIB},'auto',
+    $self->{INST_AUTODIR} = $self->catdir($self->{INST_LIB},'auto',
                                                $self->{FULLEXT});
-    $self->{INST_ARCHAUTODIR} = File::Spec->catdir($self->{INST_ARCHLIB},
+    $self->{INST_ARCHAUTODIR} = $self->catdir($self->{INST_ARCHLIB},
                                                    'auto',$self->{FULLEXT});
 
-    $self->{INST_SCRIPT} ||= File::Spec->catdir($Curdir,'blib','script');
+    $self->{INST_SCRIPT} ||= $self->catdir($Curdir,'blib','script');
 
-    $self->{INST_MAN1DIR} ||= File::Spec->catdir($Curdir,'blib','man1');
-    $self->{INST_MAN3DIR} ||= File::Spec->catdir($Curdir,'blib','man3');
+    $self->{INST_MAN1DIR} ||= $self->catdir($Curdir,'blib','man1');
+    $self->{INST_MAN3DIR} ||= $self->catdir($Curdir,'blib','man3');
 
     return 1;
 }
@@ -1873,7 +1988,7 @@ sub init_INST {
     $mm->init_INSTALL;
 
 Called by init_main.  Sets up all INSTALL_* variables (except
-INSTALLDIRS) and PREFIX.
+INSTALLDIRS) and *PREFIX.
 
 =cut
 
@@ -1884,9 +1999,9 @@ sub init_INSTALL {
 
     if( $Config{usevendorprefix} ) {
         $Config_Override{installvendorman1dir} =
-          File::Spec->catdir($Config{vendorprefixexp}, 'man', 'man$(MAN1EXT)');
+          $self->catdir($Config{vendorprefixexp}, 'man', 'man1');
         $Config_Override{installvendorman3dir} =
-          File::Spec->catdir($Config{vendorprefixexp}, 'man', 'man$(MAN3EXT)');
+          $self->catdir($Config{vendorprefixexp}, 'man', 'man3');
     }
     else {
         $Config_Override{installvendorman1dir} = '';
@@ -1905,32 +2020,42 @@ sub init_INSTALL {
     # it up.
     unless( $Config{installsiteman1dir} ) {
         $Config_Override{installsiteman1dir} = 
-          File::Spec->catdir($sprefix, 'man', 'man$(MAN1EXT)');
+          $self->catdir($sprefix, 'man', 'man1');
     }
 
     unless( $Config{installsiteman3dir} ) {
         $Config_Override{installsiteman3dir} = 
-          File::Spec->catdir($sprefix, 'man', 'man$(MAN3EXT)');
+          $self->catdir($sprefix, 'man', 'man3');
     }
 
     unless( $Config{installsitebin} ) {
         $Config_Override{installsitebin} =
-          File::Spec->catdir($sprefix, 'bin');
+          $self->catdir($sprefix, 'bin');
     }
 
-    my $u_prefix  = $self->{PREFIX}       || '';
-    my $u_sprefix = $self->{SITEPREFIX}   || $u_prefix;
-    my $u_vprefix = $self->{VENDORPREFIX} || $u_prefix;
+    $self->{PREFIX}       ||= '';
+
+    if( $self->{PREFIX} ) {
+        @{$self}{qw(PERLPREFIX SITEPREFIX VENDORPREFIX)} =
+          ('$(PREFIX)') x 3;
+    }
+    else {
+        $self->{PERLPREFIX}   ||= $iprefix;
+        $self->{SITEPREFIX}   ||= $sprefix;
+        $self->{VENDORPREFIX} ||= $vprefix;
+    }
 
-    $self->{PREFIX}       ||= $u_prefix  || $iprefix;
-    $self->{SITEPREFIX}   ||= $u_sprefix || $sprefix;
-    $self->{VENDORPREFIX} ||= $u_vprefix || $vprefix;
+    # Add DESTDIR.
+    $self->{DESTDIR} ||= '';
+    foreach my $prefix (qw(PREFIX PERLPREFIX SITEPREFIX VENDORPREFIX)) {
+        $self->{$prefix} = '$(DESTDIR)'.$self->{$prefix};
+    }
 
     my $arch    = $Config{archname};
     my $version = $Config{version};
 
     # default style
-    my $libstyle = 'lib/perl5';
+    my $libstyle = $Config{installstyle} || 'lib/perl5';
     my $manstyle = '';
 
     if( $self->{LIBSTYLE} ) {
@@ -1948,73 +2073,73 @@ sub init_INSTALL {
     my %bin_layouts = 
     (
         bin         => { s => $iprefix,
-                         r => $u_prefix,
+                         t => 'perl',
                          d => 'bin' },
         vendorbin   => { s => $vprefix,
-                         r => $u_vprefix,
+                         t => 'vendor',
                          d => 'bin' },
         sitebin     => { s => $sprefix,
-                         r => $u_sprefix,
+                         t => 'site',
                          d => 'bin' },
         script      => { s => $iprefix,
-                         r => $u_prefix,
+                         t => 'perl',
                          d => 'bin' },
     );
     
     my %man_layouts =
     (
         man1dir         => { s => $iprefix,
-                             r => $u_prefix,
-                             d => 'man/man$(MAN1EXT)',
+                             t => 'perl',
+                             d => 'man/man1',
                              style => $manstyle, },
         siteman1dir     => { s => $sprefix,
-                             r => $u_sprefix,
-                             d => 'man/man$(MAN1EXT)',
+                             t => 'site',
+                             d => 'man/man1',
                              style => $manstyle, },
         vendorman1dir   => { s => $vprefix,
-                             r => $u_vprefix,
-                             d => 'man/man$(MAN1EXT)',
+                             t => 'vendor',
+                             d => 'man/man1',
                              style => $manstyle, },
 
         man3dir         => { s => $iprefix,
-                             r => $u_prefix,
-                             d => 'man/man$(MAN3EXT)',
+                             t => 'perl',
+                             d => 'man/man3',
                              style => $manstyle, },
         siteman3dir     => { s => $sprefix,
-                             r => $u_sprefix,
-                             d => 'man/man$(MAN3EXT)',
+                             t => 'site',
+                             d => 'man/man3',
                              style => $manstyle, },
         vendorman3dir   => { s => $vprefix,
-                             r => $u_vprefix,
-                             d => 'man/man$(MAN3EXT)',
+                             t => 'vendor',
+                             d => 'man/man3',
                              style => $manstyle, },
     );
 
     my %lib_layouts =
     (
         privlib     => { s => $iprefix,
-                         r => $u_prefix,
+                         t => 'perl',
                          d => '',
                          style => $libstyle, },
         vendorlib   => { s => $vprefix,
-                         r => $u_vprefix,
+                         t => 'vendor',
                          d => '',
                          style => $libstyle, },
         sitelib     => { s => $sprefix,
-                         r => $u_sprefix,
+                         t => 'site',
                          d => 'site_perl',
                          style => $libstyle, },
         
         archlib     => { s => $iprefix,
-                         r => $u_prefix,
+                         t => 'perl',
                          d => "$version/$arch",
                          style => $libstyle },
         vendorarch  => { s => $vprefix,
-                         r => $u_vprefix,
+                         t => 'vendor',
                          d => "$version/$arch",
                          style => $libstyle },
         sitearch    => { s => $sprefix,
-                         r => $u_sprefix,
+                         t => 'site',
                          d => "site_perl/$version/$arch",
                          style => $libstyle },
     );
@@ -2027,7 +2152,7 @@ sub init_INSTALL {
 
             if( $var =~ /arch/ ) {
                 $self->{$Installvar} ||= 
-                  File::Spec->catdir($self->{LIB}, $Config{archname});
+                  $self->catdir($self->{LIB}, $Config{archname});
             }
             else {
                 $self->{$Installvar} ||= $self->{LIB};
@@ -2035,10 +2160,15 @@ sub init_INSTALL {
         }
     }
 
+    my %type2prefix = ( perl    => 'PERLPREFIX',
+                        site    => 'SITEPREFIX',
+                        vendor  => 'VENDORPREFIX'
+                      );
 
     my %layouts = (%bin_layouts, %man_layouts, %lib_layouts);
     while( my($var, $layout) = each(%layouts) ) {
-        my($s, $r, $d, $style) = @{$layout}{qw(s r d style)};
+        my($s, $t, $d, $style) = @{$layout}{qw(s t d style)};
+        my $r = '$('.$type2prefix{$t}.')';
 
         print STDERR "Prefixing $var\n" if $Verbose >= 2;
 
@@ -2046,22 +2176,34 @@ sub init_INSTALL {
         my $Installvar = uc $installvar;
         next if $self->{$Installvar};
 
-        if( $r ) {
-            $d = "$style/$d" if $style;
-            $self->prefixify($installvar, $s, $r, $d);
-        }
-        else {
-            $self->{$Installvar} = $Config_Override{$installvar} || 
-                                   $Config{$installvar};
-        }
+        $d = "$style/$d" if $style;
+        $self->prefixify($installvar, $s, $r, $d);
 
         print STDERR "  $Installvar == $self->{$Installvar}\n" 
           if $Verbose >= 2;
     }
 
+    # Generate these if they weren't figured out.
+    $self->{VENDORARCHEXP} ||= $self->{INSTALLVENDORARCH};
+    $self->{VENDORLIBEXP}  ||= $self->{INSTALLVENDORLIB};
+
     return 1;
 }
 
+=item init_linker
+
+Unix has no need of special linker flags.
+
+=cut
+
+sub init_linker {
+    my($self) = shift;
+    $self->{PERL_ARCHIVE} ||= '';
+    $self->{PERL_ARCHIVE_AFTER} ||= '';
+    $self->{EXPORT_LIST}  ||= '';
+}
+
+
 =begin _protected
 
 =item init_lib2arch
@@ -2114,6 +2256,7 @@ Called by init_main.  Sets up ABSPERL, PERL, FULLPERL and all the
 
     PERL is allowed to be miniperl
     FULLPERL must be a complete perl
+
     ABSPERL is PERL converted to an absolute path
 
     *PERLRUN contains everything necessary to run perl, find it's
@@ -2135,8 +2278,12 @@ sub init_PERL {
     }
 
     # Build up a set of file names (not command names).
-    my $thisperl = File::Spec->canonpath($^X);
+    my $thisperl = $self->canonpath($^X);
     $thisperl .= $Config{exe_ext} unless $thisperl =~ m/$Config{exe_ext}$/i;
+
+    # We need a relative path to perl when in the core.
+    $thisperl = $self->abs2rel($thisperl) if $self->{PERL_CORE};
+
     my @perls = ($thisperl);
     push @perls, map { "$_$Config{exe_ext}" }
                      ('perl', 'perl5', "perl$Config{version}");
@@ -2164,11 +2311,11 @@ sub init_PERL {
     # sometimes.
     $self->{ABSPERL} = $self->{PERL};
     my $has_mcr = $self->{ABSPERL} =~ s/^MCR\s*//;
-    if( File::Spec->file_name_is_absolute($self->{ABSPERL}) ) {
+    if( $self->file_name_is_absolute($self->{ABSPERL}) ) {
         $self->{ABSPERL} = '$(PERL)';
     }
     else {
-        $self->{ABSPERL} = File::Spec->rel2abs($self->{ABSPERL});
+        $self->{ABSPERL} = $self->rel2abs($self->{ABSPERL});
         $self->{ABSPERL} = 'MCR '.$self->{ABSPERL} if $has_mcr;
     }
 
@@ -2177,10 +2324,12 @@ sub init_PERL {
 
     # How do we run perl?
     foreach my $perl (qw(PERL FULLPERL ABSPERL)) {
-        $self->{$perl.'RUN'}  = "\$($perl)";
+        my $run  = $perl.'RUN';
+
+        $self->{$run}  = "\$($perl)";
 
         # Make sure perl can find itself before it's installed.
-        $self->{$perl.'RUN'} .= q{ "-I$(PERL_LIB)" "-I$(PERL_ARCHLIB)"} 
+        $self->{$run} .= q{ "-I$(PERL_LIB)" "-I$(PERL_ARCHLIB)"} 
           if $self->{UNINSTALLED_PERL} || $self->{PERL_CORE};
 
         $self->{$perl.'RUNINST'} = 
@@ -2190,6 +2339,39 @@ sub init_PERL {
     return 1;
 }
 
+
+=item init_platform (o)
+
+Add MM_Unix_VERSION.
+
+=item platform_constants (o)
+
+=cut
+
+sub init_platform {
+    my($self) = shift;
+
+    $self->{MM_Unix_VERSION} = $VERSION;
+    $self->{PERL_MALLOC_DEF} = '-DPERL_EXTMALLOC_DEF -Dmalloc=Perl_malloc '.
+                               '-Dfree=Perl_mfree -Drealloc=Perl_realloc '.
+                               '-Dcalloc=Perl_calloc';
+
+}
+
+sub platform_constants {
+    my($self) = shift;
+    my $make_frag = '';
+
+    foreach my $macro (qw(MM_Unix_VERSION PERL_MALLOC_DEF))
+    {
+        next unless defined $self->{$macro};
+        $make_frag .= "$macro = $self->{$macro}\n";
+    }
+
+    return $make_frag;
+}
+
+
 =item init_PERM
 
   $mm->init_PERM
@@ -2201,12 +2383,38 @@ Called by init_main.  Initializes PERL_*
 sub init_PERM {
     my($self) = shift;
 
-    $self->{PERM_RW}  = 644;
-    $self->{PERM_RWX} = 755;
+    $self->{PERM_RW}  = 644  unless defined $self->{PERM_RW};
+    $self->{PERM_RWX} = 755  unless defined $self->{PERM_RWX};
 
     return 1;
 }
-    
+
+
+=item init_xs
+
+    $mm->init_xs
+
+Sets up macros having to do with XS code.  Currently just INST_STATIC,
+INST_DYNAMIC and INST_BOOT.
+
+=cut
+
+sub init_xs {
+    my $self = shift;
+
+    if ($self->has_link_code()) {
+        $self->{INST_STATIC}  = 
+          $self->catfile('$(INST_ARCHAUTODIR)', '$(BASEEXT)$(LIB_EXT)');
+        $self->{INST_DYNAMIC} = 
+          $self->catfile('$(INST_ARCHAUTODIR)', '$(DLBASE).$(DLEXT)');
+        $self->{INST_BOOT}    = 
+          $self->catfile('$(INST_ARCHAUTODIR)', '$(BASEEXT).bs');
+    } else {
+        $self->{INST_STATIC}  = '';
+        $self->{INST_DYNAMIC} = '';
+        $self->{INST_BOOT}    = '';
+    }
+}    
 
 =item install (o)
 
@@ -2230,43 +2438,44 @@ install_vendor :: all pure_vendor_install doc_vendor_install
 pure_install :: pure_$(INSTALLDIRS)_install
 
 doc_install :: doc_$(INSTALLDIRS)_install
-       }.$self->{NOECHO}.q{echo Appending installation info to $(INSTALLARCHLIB)/perllocal.pod
 
 pure__install : pure_site_install
-       @echo INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
+       $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
 
 doc__install : doc_site_install
-       @echo INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
+       $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
 
 pure_perl_install ::
-       }.$self->{NOECHO}.q{$(MOD_INSTALL) \
-               read }.File::Spec->catfile('$(PERL_ARCHLIB)','auto','$(FULLEXT)','.packlist').q{ \
-               write }.File::Spec->catfile('$(INSTALLARCHLIB)','auto','$(FULLEXT)','.packlist').q{ \
+       $(NOECHO) $(MOD_INSTALL) \
+               read }.$self->catfile('$(PERL_ARCHLIB)','auto','$(FULLEXT)','.packlist').q{ \
+               write }.$self->catfile('$(INSTALLARCHLIB)','auto','$(FULLEXT)','.packlist').q{ \
                $(INST_LIB) $(INSTALLPRIVLIB) \
                $(INST_ARCHLIB) $(INSTALLARCHLIB) \
                $(INST_BIN) $(INSTALLBIN) \
                $(INST_SCRIPT) $(INSTALLSCRIPT) \
                $(INST_MAN1DIR) $(INSTALLMAN1DIR) \
                $(INST_MAN3DIR) $(INSTALLMAN3DIR)
-       }.$self->{NOECHO}.q{$(WARN_IF_OLD_PACKLIST) \
-               }.File::Spec->catdir('$(SITEARCHEXP)','auto','$(FULLEXT)').q{
+       $(NOECHO) $(WARN_IF_OLD_PACKLIST) \
+               }.$self->catdir('$(SITEARCHEXP)','auto','$(FULLEXT)').q{
 
 
 pure_site_install ::
-       }.$self->{NOECHO}.q{$(MOD_INSTALL) \
-               read }.File::Spec->catfile('$(SITEARCHEXP)','auto','$(FULLEXT)','.packlist').q{ \
-               write }.File::Spec->catfile('$(INSTALLSITEARCH)','auto','$(FULLEXT)','.packlist').q{ \
+       $(NOECHO) $(MOD_INSTALL) \
+               read }.$self->catfile('$(SITEARCHEXP)','auto','$(FULLEXT)','.packlist').q{ \
+               write }.$self->catfile('$(INSTALLSITEARCH)','auto','$(FULLEXT)','.packlist').q{ \
                $(INST_LIB) $(INSTALLSITELIB) \
                $(INST_ARCHLIB) $(INSTALLSITEARCH) \
                $(INST_BIN) $(INSTALLSITEBIN) \
                $(INST_SCRIPT) $(INSTALLSCRIPT) \
                $(INST_MAN1DIR) $(INSTALLSITEMAN1DIR) \
                $(INST_MAN3DIR) $(INSTALLSITEMAN3DIR)
-       }.$self->{NOECHO}.q{$(WARN_IF_OLD_PACKLIST) \
-               }.File::Spec->catdir('$(PERL_ARCHLIB)','auto','$(FULLEXT)').q{
+       $(NOECHO) $(WARN_IF_OLD_PACKLIST) \
+               }.$self->catdir('$(PERL_ARCHLIB)','auto','$(FULLEXT)').q{
 
 pure_vendor_install ::
-       }.$self->{NOECHO}.q{$(MOD_INSTALL) \
+       $(NOECHO) $(MOD_INSTALL) \
+               read }.$self->catfile('$(VENDORARCHEXP)','auto','$(FULLEXT)','.packlist').q{ \
+               write }.$self->catfile('$(INSTALLVENDORARCH)','auto','$(FULLEXT)','.packlist').q{ \
                $(INST_LIB) $(INSTALLVENDORLIB) \
                $(INST_ARCHLIB) $(INSTALLVENDORARCH) \
                $(INST_BIN) $(INSTALLVENDORBIN) \
@@ -2275,26 +2484,37 @@ pure_vendor_install ::
                $(INST_MAN3DIR) $(INSTALLVENDORMAN3DIR)
 
 doc_perl_install ::
-       -}.$self->{NOECHO}.q{$(MKPATH) $(INSTALLARCHLIB)
-       -}.$self->{NOECHO}.q{$(DOC_INSTALL) \
+       $(NOECHO) $(ECHO) Appending installation info to $(INSTALLARCHLIB)/perllocal.pod
+       -$(NOECHO) $(MKPATH) $(INSTALLARCHLIB)
+       -$(NOECHO) $(DOC_INSTALL) \
                "Module" "$(NAME)" \
                "installed into" "$(INSTALLPRIVLIB)" \
                LINKTYPE "$(LINKTYPE)" \
                VERSION "$(VERSION)" \
                EXE_FILES "$(EXE_FILES)" \
-               >> }.File::Spec->catfile('$(INSTALLARCHLIB)','perllocal.pod').q{
+               >> }.$self->catfile('$(INSTALLARCHLIB)','perllocal.pod').q{
 
 doc_site_install ::
-       -}.$self->{NOECHO}.q{$(MKPATH) $(INSTALLARCHLIB)
-       -}.$self->{NOECHO}.q{$(DOC_INSTALL) \
+       $(NOECHO) $(ECHO) Appending installation info to $(INSTALLSITEARCH)/perllocal.pod
+       -$(NOECHO) $(MKPATH) $(INSTALLSITEARCH)
+       -$(NOECHO) $(DOC_INSTALL) \
                "Module" "$(NAME)" \
                "installed into" "$(INSTALLSITELIB)" \
                LINKTYPE "$(LINKTYPE)" \
                VERSION "$(VERSION)" \
                EXE_FILES "$(EXE_FILES)" \
-               >> }.File::Spec->catfile('$(INSTALLSITEARCH)','perllocal.pod').q{
+               >> }.$self->catfile('$(INSTALLSITEARCH)','perllocal.pod').q{
 
 doc_vendor_install ::
+       $(NOECHO) $(ECHO) Appending installation info to $(INSTALLVENDORARCH)/perllocal.pod
+       -$(NOECHO) $(MKPATH) $(INSTALLVENDORARCH)
+       -$(NOECHO) $(DOC_INSTALL) \
+               "Module" "$(NAME)" \
+               "installed into" "$(INSTALLVENDORLIB)" \
+               LINKTYPE "$(LINKTYPE)" \
+               VERSION "$(VERSION)" \
+               EXE_FILES "$(EXE_FILES)" \
+               >> }.$self->catfile('$(INSTALLVENDORARCH)','perllocal.pod').q{
 
 };
 
@@ -2302,12 +2522,13 @@ doc_vendor_install ::
 uninstall :: uninstall_from_$(INSTALLDIRS)dirs
 
 uninstall_from_perldirs ::
-       }.$self->{NOECHO}.
-       q{$(UNINSTALL) }.File::Spec->catfile('$(PERL_ARCHLIB)','auto','$(FULLEXT)','.packlist').q{
+       $(NOECHO) $(UNINSTALL) }.$self->catfile('$(PERL_ARCHLIB)','auto','$(FULLEXT)','.packlist').q{
 
 uninstall_from_sitedirs ::
-       }.$self->{NOECHO}.
-       q{$(UNINSTALL) }.File::Spec->catfile('$(SITEARCHEXP)','auto','$(FULLEXT)','.packlist').q{
+       $(NOECHO) $(UNINSTALL) }.$self->catfile('$(SITEARCHEXP)','auto','$(FULLEXT)','.packlist').q{
+
+uninstall_from_vendordirs ::
+       $(NOECHO) $(UNINSTALL) }.$self->catfile('$(VENDORARCHEXP)','auto','$(FULLEXT)','.packlist').q{
 };
 
     join("",@m);
@@ -2326,7 +2547,7 @@ sub installbin {
     my(@m, $from, $to, %fromto, @to);
     push @m, $self->dir_target(qw[$(INST_SCRIPT)]);
     for $from (@{$self->{EXE_FILES}}) {
-       my($path)= File::Spec->catfile('$(INST_SCRIPT)', basename($from));
+       my($path)= $self->catfile('$(INST_SCRIPT)', basename($from));
        local($_) = $path; # for backwards compatibility
        $to = $self->libscan($path);
        print "libscan($from) => '$to'\n" if ($Verbose >=2);
@@ -2342,41 +2563,26 @@ EXE_FILES = @{$self->{EXE_FILES}}
     -e "MY->fixin(shift)"
 }).qq{
 pure_all :: @to
-       $self->{NOECHO}\$(NOOP)
+       \$(NOECHO) \$(NOOP)
 
 realclean ::
-       $self->{RM_F} @to
+       \$(RM_F) @to
 });
 
     while (($from,$to) = each %fromto) {
        last unless defined $from;
        my $todir = dirname($to);
        push @m, "
-$to: $from $self->{MAKEFILE} " . File::Spec->catdir($todir,'.exists') . "
-       $self->{NOECHO}$self->{RM_F} $to
-       $self->{CP} $from $to
+$to: $from \$(FIRST_MAKEFILE) " . $self->catdir($todir,'.exists') . "
+       \$(NOECHO) \$(RM_F) $to
+       \$(CP) $from $to
        \$(FIXIN) $to
-       -$self->{NOECHO}\$(CHMOD) \$(PERM_RWX) $to
+       -\$(NOECHO) \$(CHMOD) \$(PERM_RWX) $to
 ";
     }
     join "", @m;
 }
 
-=item libscan (o)
-
-Takes a path to a file that is found by init_dirscan and returns false
-if we don't want to include this file in the library. Mainly used to
-exclude RCS, CVS, and SCCS directories from installation.
-
-=cut
-
-# ';
-
-sub libscan {
-    my($self,$path) = @_;
-    return '' if $path =~ m:\b(RCS|CVS|SCCS)\b: ;
-    $path;
-}
 
 =item linkext (o)
 
@@ -2391,7 +2597,7 @@ sub linkext {
       $attribs{LINKTYPE} : '$(LINKTYPE)';
     "
 linkext :: $linktype
-       $self->{NOECHO}\$(NOOP)
+       \$(NOECHO) \$(NOOP)
 ";
 }
 
@@ -2462,10 +2668,10 @@ $(MAP_TARGET) :: static $(MAKE_APERL_FILE)
        $(MAKE) -f $(MAKE_APERL_FILE) $@
 
 $(MAKE_APERL_FILE) : $(FIRST_MAKEFILE)
-       }.$self->{NOECHO}.q{echo Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET)
-       }.$self->{NOECHO}.q{$(PERLRUNINST) \
+       $(NOECHO) $(ECHO) Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET)
+       $(NOECHO) $(PERLRUNINST) \
                Makefile.PL DIR=}, $dir, q{ \
-               MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \
+               FIRST_MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \
                MAKEAPERL=1 NORECURS=1 CCCDLFLAGS=};
 
        foreach (@ARGV){
@@ -2593,10 +2799,10 @@ MAP_PRELIBS   = $Config{perllibs} $Config{cryptlib}
 
         if (! -f $libperl and ! -f $lperl) {
           # We did not find a static libperl. Maybe there is a shared one?
-          if ($^O eq 'solaris' or $^O eq 'sunos') {
+          if ($Is_SunOS) {
             $lperl  = $libperl = "$dir/$Config{libperl}";
             # SUNOS ld does not take the full path to a shared library
-            $libperl = '' if $^O eq 'sunos';
+            $libperl = '' if $Is_SunOS4;
           }
         }
 
@@ -2615,10 +2821,10 @@ LLIBPERL    = $llibperl
 ";
 
     push @m, "
-\$(INST_ARCHAUTODIR)/extralibs.all: \$(INST_ARCHAUTODIR)/.exists ".join(" \\\n\t", @$extra)."
-       $self->{NOECHO}$self->{RM_F} \$\@
-       $self->{NOECHO}\$(TOUCH) \$\@
-";
+\$(INST_ARCHAUTODIR)/extralibs.all: \$(INST_ARCHAUTODIR)\$(DIRFILESEP).exists ".join(" \\\n\t", @$extra).'
+       $(NOECHO) $(RM_F)  $@
+       $(NOECHO) $(TOUCH) $@
+';
 
     my $catfile;
     foreach $catfile (@$extra){
@@ -2628,10 +2834,10 @@ LLIBPERL    = $llibperl
 push @m, "
 \$(MAP_TARGET) :: $tmp/perlmain\$(OBJ_EXT) \$(MAP_LIBPERL) \$(MAP_STATIC) \$(INST_ARCHAUTODIR)/extralibs.all
        \$(MAP_LINKCMD) -o \$\@ \$(OPTIMIZE) $tmp/perlmain\$(OBJ_EXT) \$(LDFROM) \$(MAP_STATIC) \$(LLIBPERL) `cat \$(INST_ARCHAUTODIR)/extralibs.all` \$(MAP_PRELIBS)
-       $self->{NOECHO}echo 'To install the new \"\$(MAP_TARGET)\" binary, call'
-       $self->{NOECHO}echo '    make -f $makefilename inst_perl MAP_TARGET=\$(MAP_TARGET)'
-       $self->{NOECHO}echo 'To remove the intermediate files say'
-       $self->{NOECHO}echo '    make -f $makefilename map_clean'
+       \$(NOECHO) \$(ECHO) 'To install the new \"\$(MAP_TARGET)\" binary, call'
+       \$(NOECHO) \$(ECHO) '    make -f $makefilename inst_perl MAP_TARGET=\$(MAP_TARGET)'
+       \$(NOECHO) \$(ECHO) 'To remove the intermediate files say'
+       \$(NOECHO) \$(ECHO) '    make -f $makefilename map_clean'
 
 $tmp/perlmain\$(OBJ_EXT): $tmp/perlmain.c
 ";
@@ -2639,25 +2845,25 @@ $tmp/perlmain\$(OBJ_EXT): $tmp/perlmain.c
 
     push @m, qq{
 $tmp/perlmain.c: $makefilename}, q{
-       }.$self->{NOECHO}.q{echo Writing $@
-       }.$self->{NOECHO}.q{$(PERL) $(MAP_PERLINC) "-MExtUtils::Miniperl" \\
+       $(NOECHO) $(ECHO) Writing $@
+       $(NOECHO) $(PERL) $(MAP_PERLINC) "-MExtUtils::Miniperl" \\
                -e "writemain(grep s#.*/auto/##s, split(q| |, q|$(MAP_STATIC)|))" > $@t && $(MV) $@t $@
 
 };
-    push @m, "\t",$self->{NOECHO}.q{$(PERL) $(INSTALLSCRIPT)/fixpmain
+    push @m, "\t", q{$(NOECHO) $(PERL) $(INSTALLSCRIPT)/fixpmain
 } if (defined (&Dos::UseLFN) && Dos::UseLFN()==0);
 
 
     push @m, q{
 doc_inst_perl:
-       }.$self->{NOECHO}.q{echo Appending installation info to $(INSTALLARCHLIB)/perllocal.pod
-       -}.$self->{NOECHO}.q{$(MKPATH) $(INSTALLARCHLIB)
-       -}.$self->{NOECHO}.q{$(DOC_INSTALL) \
+       $(NOECHO) $(ECHO) Appending installation info to $(INSTALLARCHLIB)/perllocal.pod
+       -$(NOECHO) $(MKPATH) $(INSTALLARCHLIB)
+       -$(NOECHO) $(DOC_INSTALL) \
                "Perl binary" "$(MAP_TARGET)" \
                MAP_STATIC "$(MAP_STATIC)" \
                MAP_EXTRA "`cat $(INST_ARCHAUTODIR)/extralibs.all`" \
                MAP_LIBPERL "$(MAP_LIBPERL)" \
-               >> }.File::Spec->catfile('$(INSTALLARCHLIB)','perllocal.pod').q{
+               >> }.$self->catfile('$(INSTALLARCHLIB)','perllocal.pod').q{
 
 };
 
@@ -2665,7 +2871,7 @@ doc_inst_perl:
 inst_perl: pure_inst_perl doc_inst_perl
 
 pure_inst_perl: $(MAP_TARGET)
-       }.$self->{CP}.q{ $(MAP_TARGET) }.File::Spec->catfile('$(INSTALLBIN)','$(MAP_TARGET)').q{
+       }.$self->{CP}.q{ $(MAP_TARGET) }.$self->catfile('$(INSTALLBIN)','$(MAP_TARGET)').q{
 
 clean :: map_clean
 
@@ -2695,15 +2901,15 @@ $(OBJECT) : $(FIRST_MAKEFILE)
     push @m, q{
 # We take a very conservative approach here, but it\'s worth it.
 # We move Makefile to Makefile.old here to avoid gnu make looping.
-}.$self->{MAKEFILE}.q{ : Makefile.PL $(CONFIGDEP)
-       }.$self->{NOECHO}.q{echo "Makefile out-of-date with respect to $?"
-       }.$self->{NOECHO}.q{echo "Cleaning current config before rebuilding Makefile..."
-       -}.$self->{NOECHO}.q{$(RM_F) }."$self->{MAKEFILE}.old".q{
-       -}.$self->{NOECHO}.q{$(MV) }."$self->{MAKEFILE} $self->{MAKEFILE}.old".q{
-       -$(MAKE) -f }.$self->{MAKEFILE}.q{.old clean $(DEV_NULL) || $(NOOP)
+$(FIRST_MAKEFILE) : Makefile.PL $(CONFIGDEP) $(VERSION_FROM)
+       $(NOECHO) $(ECHO) "Makefile out-of-date with respect to $?"
+       $(NOECHO) $(ECHO) "Cleaning current config before rebuilding Makefile..."
+       $(NOECHO) $(RM_F) $(MAKEFILE_OLD)
+       $(NOECHO) $(MV)   $(FIRST_MAKEFILE) $(MAKEFILE_OLD)
+       -$(MAKE) -f $(MAKEFILE_OLD) clean $(DEV_NULL) || $(NOOP)
        $(PERLRUN) Makefile.PL }.join(" ",map(qq["$_"],@ARGV)).q{
-       }.$self->{NOECHO}.q{echo "==> Your Makefile has been rebuilt. <=="
-       }.$self->{NOECHO}.q{echo "==> Please rerun the make command.  <=="
+       $(NOECHO) $(ECHO) "==> Your Makefile has been rebuilt. <=="
+       $(NOECHO) $(ECHO) "==> Please rerun the make command.  <=="
        false
 
 };
@@ -2711,58 +2917,6 @@ $(OBJECT) : $(FIRST_MAKEFILE)
     join "", @m;
 }
 
-=item manifypods (o)
-
-Defines targets and routines to translate the pods into manpages and
-put them into the INST_* directories.
-
-=cut
-
-sub manifypods {
-    my($self, %attribs) = @_;
-    return "\nmanifypods : pure_all\n\t$self->{NOECHO}\$(NOOP)\n" unless
-       %{$self->{MAN3PODS}} or %{$self->{MAN1PODS}};
-    my($dist);
-    my($pod2man_exe);
-    if (defined $self->{PERL_SRC}) {
-       $pod2man_exe = File::Spec->catfile($self->{PERL_SRC},'pod','pod2man');
-    } else {
-       $pod2man_exe = File::Spec->catfile($Config{scriptdirexp},'pod2man');
-    }
-    unless ($pod2man_exe = $self->perl_script($pod2man_exe)) {
-      # Maybe a build by uninstalled Perl?
-      $pod2man_exe = File::Spec->catfile($self->{PERL_INC}, "pod", "pod2man");
-    }
-    unless ($pod2man_exe = $self->perl_script($pod2man_exe)) {
-       # No pod2man but some MAN3PODS to be installed
-       print <<END;
-
-Warning: I could not locate your pod2man program. Please make sure,
-         your pod2man program is in your PATH before you execute 'make'
-
-END
-        $pod2man_exe = "-S pod2man";
-    }
-    my(@m);
-    push @m,
-qq[POD2MAN_EXE = $pod2man_exe\n],
-qq[POD2MAN = \$(PERL) -we '%m=\@ARGV;for (keys %m){' \\\n],
-q[-e 'next if -e $$m{$$_} && -M $$m{$$_} < -M $$_ && -M $$m{$$_} < -M "],
- $self->{MAKEFILE}, q[";' \\
--e 'print "Manifying $$m{$$_}\n";' \\
--e 'system(q[$(PERLRUN) $(POD2MAN_EXE) ].qq[$$_>$$m{$$_}])==0 or warn "Couldn\\047t install $$m{$$_}\n";' \\
--e 'chmod(oct($(PERM_RW)), $$m{$$_}) or warn "chmod $(PERM_RW) $$m{$$_}: $$!\n";}'
-];
-    push @m, "\nmanifypods : pure_all ";
-    push @m, join " \\\n\t", keys %{$self->{MAN1PODS}}, keys %{$self->{MAN3PODS}};
-
-    push(@m,"\n");
-    if (%{$self->{MAN1PODS}} || %{$self->{MAN3PODS}}) {
-       push @m, "\t$self->{NOECHO}\$(POD2MAN) \\\n\t";
-       push @m, join " \\\n\t", %{$self->{MAN1PODS}}, %{$self->{MAN3PODS}};
-    }
-    join('', @m);
-}
 
 =item maybe_command
 
@@ -2776,44 +2930,6 @@ sub maybe_command {
     return;
 }
 
-=item maybe_command_in_dirs
-
-method under development. Not yet used. Ask Ilya :-)
-
-=cut
-
-sub maybe_command_in_dirs {    # $ver is optional argument if looking for perl
-# Ilya's suggestion. Not yet used, want to understand it first, but at least the code is here
-    my($self, $names, $dirs, $trace, $ver) = @_;
-    my($name, $dir);
-    foreach $dir (@$dirs){
-       next unless defined $dir; # $self->{PERL_SRC} may be undefined
-       foreach $name (@$names){
-           my($abs,$tryabs);
-           if (File::Spec->file_name_is_absolute($name)) { # /foo/bar
-               $abs = $name;
-           } elsif (File::Spec->canonpath($name) eq File::Spec->canonpath(basename($name))) { # bar
-               $abs = File::Spec->catfile($dir, $name);
-           } else { # foo/bar
-               $abs = File::Spec->catfile($Curdir, $name);
-           }
-           print "Checking $abs for $name\n" if ($trace >= 2);
-           next unless $tryabs = $self->maybe_command($abs);
-           print "Substituting $tryabs instead of $abs\n"
-               if ($trace >= 2 and $tryabs ne $abs);
-           $abs = $tryabs;
-           if (defined $ver) {
-               print "Executing $abs\n" if ($trace >= 2);
-               if (`$abs -e 'require $ver; print "VER_OK\n" ' 2>&1` =~ /VER_OK/) {
-                   print "Using PERL=$abs\n" if $trace;
-                   return $abs;
-               }
-           } else { # Do not look for perl
-               return $abs;
-           }
-       }
-    }
-}
 
 =item needs_linking (o)
 
@@ -2826,7 +2942,7 @@ sub needs_linking {
     my($self) = shift;
     my($child,$caller);
     $caller = (caller(0))[3];
-    confess("Needs_linking called too early") if 
+    confess("needs_linking called too early") if 
       $caller =~ /^ExtUtils::MakeMaker::/;
     return $self->{NEEDS_LINKING} if defined $self->{NEEDS_LINKING};
     if ($self->has_link_code or $self->{MAKEAPERL}){
@@ -2985,10 +3101,10 @@ sub perldepend {
 # We do NOT just update config.h because that is not sufficient.
 # An out of date config.h is not fatal but complains loudly!
 $(PERL_INC)/config.h: $(PERL_SRC)/config.sh
-       -}.$self->{NOECHO}.q{echo "Warning: $(PERL_INC)/config.h out of date with $(PERL_SRC)/config.sh"; false
+       -$(NOECHO) $(ECHO) "Warning: $(PERL_INC)/config.h out of date with $(PERL_SRC)/config.sh"; false
 
 $(PERL_ARCHLIB)/Config.pm: $(PERL_SRC)/config.sh
-       }.$self->{NOECHO}.q{echo "Warning: $(PERL_ARCHLIB)/Config.pm may be out of date with $(PERL_SRC)/config.sh"
+       $(NOECHO) $(ECHO) "Warning: $(PERL_ARCHLIB)/Config.pm may be out of date with $(PERL_SRC)/config.sh"
        cd $(PERL_SRC) && $(MAKE) lib/Config.pm
 } if $self->{PERL_SRC};
 
@@ -3065,7 +3181,7 @@ interpreted as an octal value.
 =cut
 
 sub perm_rw {
-    shift->{PERM_RW} || "644";
+    return shift->{PERM_RW};
 }
 
 =item perm_rwx (o)
@@ -3078,7 +3194,7 @@ See also perl_rw.
 =cut
 
 sub perm_rwx {
-    shift->{PERM_RWX} || "755";
+    return shift->{PERM_RWX};
 }
 
 =item pm_to_blib
@@ -3088,36 +3204,23 @@ destination and autosplits them. See L<ExtUtils::Install/DESCRIPTION>
 
 =cut
 
-sub _pm_to_blib_flush {
-    my ($self, $autodir, $rr, $ra, $rl) = @_;
-    $$rr .= 
-q{     }.$self->{NOECHO}.q[$(PERLRUNINST) "-MExtUtils::Install" \
-       -e "pm_to_blib({qw{].qq[@$ra].q[}},'].$autodir.q{','$(PM_FILTER)')"
-};
-    @$ra = ();
-    $$rl = 0;
-}
-
 sub pm_to_blib {
     my $self = shift;
-    my($autodir) = File::Spec->catdir('$(INST_LIB)','auto');
+    my($autodir) = $self->catdir('$(INST_LIB)','auto');
     my $r = q{
 pm_to_blib: $(TO_INST_PM)
 };
-    my %pm_to_blib = %{$self->{PM}};
-    my @a;
-    my $l = 0;
-    while (my ($pm, $blib) = each %pm_to_blib) {
-       my $la = length $pm;
-       my $lb = length $blib;
-       if ($l + $la + $lb + @a / 2 > 200) { # limit line length
-           _pm_to_blib_flush($self, $autodir, \$r, \@a, \$l);
-        }
-        push @a, $pm, $blib;
-       $l += $la + $lb;
-    }
-    _pm_to_blib_flush($self, $autodir, \$r, \@a, \$l);
-    return $r.q{       }.$self->{NOECHO}.q{$(TOUCH) $@};
+
+    my $pm_to_blib = $self->oneliner(<<CODE, ['-MExtUtils::Install']);
+pm_to_blib({\@ARGV}, '$autodir', '\$(PM_FILTER)')
+CODE
+
+    my @cmds = $self->split_command($pm_to_blib, %{$self->{PM}});
+
+    $r .= join '', map { "\t\$(NOECHO) $_\n" } @cmds;
+    $r .= q{   $(NOECHO) $(TOUCH) $@};
+
+    return $r;
 }
 
 =item post_constants (o)
@@ -3128,7 +3231,6 @@ within Makefile.PL after all constants have been defined.
 =cut
 
 sub post_constants{
-    my($self) = shift;
     "";
 }
 
@@ -3140,7 +3242,6 @@ chunk of text to the Makefile after the object is initialized.
 =cut
 
 sub post_initialize {
-    my($self) = shift;
     "";
 }
 
@@ -3152,7 +3253,6 @@ text to the Makefile at the end.
 =cut
 
 sub postamble {
-    my($self) = shift;
     "";
 }
 
@@ -3182,40 +3282,38 @@ sub ppd {
     my $author = $self->{AUTHOR} || '';
     $author =~ s/</&lt;/g;
     $author =~ s/>/&gt;/g;
-    $author =~ s/@/\\@/g;
-
-    my $make_ppd = sprintf <<'PPD_OUT', $pack_ver, $abstract, $author;
-# Creates a PPD (Perl Package Description) for a binary distribution.
-ppd:
-       @$(PERL) -e "print qq{<SOFTPKG NAME=\"$(DISTNAME)\" VERSION=\"%s\">\n\t<TITLE>$(DISTNAME)</TITLE>\n\t<ABSTRACT>%s</ABSTRACT>\n\t<AUTHOR>%s</AUTHOR>\n}" > $(DISTNAME).ppd
-PPD_OUT
 
+    my $ppd_xml = sprintf <<'PPD_HTML', $pack_ver, $abstract, $author;
+<SOFTPKG NAME="$(DISTNAME)" VERSION="%s">
+    <TITLE>$(DISTNAME)</TITLE>
+    <ABSTRACT>%s</ABSTRACT>
+    <AUTHOR>%s</AUTHOR>
+PPD_HTML
 
-    $make_ppd .= '     @$(PERL) -e "print qq{\t<IMPLEMENTATION>\n';
+    $ppd_xml .= "    <IMPLEMENTATION>\n";
     foreach my $prereq (sort keys %{$self->{PREREQ_PM}}) {
         my $pre_req = $prereq;
         $pre_req =~ s/::/-/g;
         my ($dep_ver) = join ",", (split (/\./, $self->{PREREQ_PM}{$prereq}), 
                                   (0) x 4) [0 .. 3];
-        $make_ppd .= sprintf q{\t\t<DEPENDENCY NAME=\"%s\" VERSION=\"%s\" />\n}, $pre_req, $dep_ver;
-    }
-    $make_ppd .= qq[}" >> \$(DISTNAME).ppd\n];
-
-
-    $make_ppd .= sprintf <<'PPD_OUT', $Config{archname};
-       @$(PERL) -e "print qq{\t\t<OS NAME=\"$(OSNAME)\" />\n\t\t<ARCHITECTURE NAME=\"%s\" />\n
+        $ppd_xml .= sprintf <<'PPD_OUT', $pre_req, $dep_ver;
+        <DEPENDENCY NAME="%s" VERSION="%s" />
 PPD_OUT
 
-    chomp $make_ppd;
+    }
 
+    $ppd_xml .= sprintf <<'PPD_OUT', $Config{archname};
+        <OS NAME="$(OSNAME)" />
+        <ARCHITECTURE NAME="%s" />
+PPD_OUT
 
     if ($self->{PPM_INSTALL_SCRIPT}) {
         if ($self->{PPM_INSTALL_EXEC}) {
-            $make_ppd .= sprintf q{\t\t<INSTALL EXEC=\"%s\">%s</INSTALL>\n},
+            $ppd_xml .= sprintf qq{        <INSTALL EXEC="%s">%s</INSTALL>\n},
                   $self->{PPM_INSTALL_EXEC}, $self->{PPM_INSTALL_SCRIPT};
         }
         else {
-            $make_ppd .= sprintf q{\t\t<INSTALL>%s</INSTALL>\n}, 
+            $ppd_xml .= sprintf qq{        <INSTALL>%s</INSTALL>\n}, 
                   $self->{PPM_INSTALL_SCRIPT};
         }
     }
@@ -3223,13 +3321,20 @@ PPD_OUT
     my ($bin_location) = $self->{BINARY_LOCATION} || '';
     $bin_location =~ s/\\/\\\\/g;
 
-    $make_ppd .= sprintf q{\t\t<CODEBASE HREF=\"%s\" />\n}, $bin_location;
-    $make_ppd .= q{\t</IMPLEMENTATION>\n};
-    $make_ppd .= q{</SOFTPKG>\n};
+    $ppd_xml .= sprintf <<'PPD_XML', $bin_location;
+        <CODEBASE HREF="%s" />
+    </IMPLEMENTATION>
+</SOFTPKG>
+PPD_XML
+
+    my @ppd_cmds = $self->echo($ppd_xml, '$(DISTNAME).ppd');
 
-    $make_ppd .= '}" >> $(DISTNAME).ppd';
+    return sprintf <<'PPD_OUT', join "\n\t", @ppd_cmds;
+# Creates a PPD (Perl Package Description) for a binary distribution.
+ppd:
+       %s
+PPD_OUT
 
-    return $make_ppd;
 }
 
 =item prefixify
@@ -3237,8 +3342,12 @@ PPD_OUT
   $MM->prefixify($var, $prefix, $new_prefix, $default);
 
 Using either $MM->{uc $var} || $Config{lc $var}, it will attempt to
-replace it's $prefix with a $new_prefix.  Should the $prefix fail to
-match it sill simply set it to the $new_prefix + $default.
+replace it's $prefix with a $new_prefix.  
+
+Should the $prefix fail to match I<AND> a PREFIX was given as an
+argument to WriteMakefile() it will set it to the $new_prefix +
+$default.  This is for systems whose file layouts don't neatly fit into
+our ideas of prefixes.
 
 This is for heuristics which attempt to create directory structures
 that mirror those of the installed perl.
@@ -3263,12 +3372,12 @@ sub prefixify {
     print STDERR "  prefixify $var => $path\n" if $Verbose >= 2;
     print STDERR "    from $sprefix to $rprefix\n" if $Verbose >= 2;
 
-    unless( $path =~ s{^\Q$sprefix\E\b}{$rprefix}s ) {
+    if( $path !~ s{^\Q$sprefix\E\b}{$rprefix}s && $self->{ARGS}{PREFIX} ) {
 
         print STDERR "    cannot prefix, using default.\n" if $Verbose >= 2;
         print STDERR "    no default!\n" if !$default && $Verbose >= 2;
 
-        $path = File::Spec->catdir($rprefix, $default) if $default;
+        $path = $self->catdir($rprefix, $default) if $default;
     }
 
     print "    now $path\n" if $Verbose >= 2;
@@ -3294,7 +3403,7 @@ sub processPL {
        foreach $target (@$list) {
        push @m, "
 all :: $target
-       $self->{NOECHO}\$(NOOP)
+       \$(NOECHO) \$(NOOP)
 
 $target :: $plfile
        \$(PERLRUNINST) $plfile $target
@@ -3313,11 +3422,11 @@ but handles simple ones.
 =cut
 
 sub quote_paren {
-    local $_ = shift;
-    s/\$\((.+?)\)/\$\\\\($1\\\\)/g;    # protect $(...)
-    s/(?<!\\)([()])/\\$1/g;            # quote unprotected
-    s/\$\\\\\((.+?)\\\\\)/\$($1)/g;    # unprotect $(...)
-    return $_;
+    my $arg = shift;
+    $arg =~ s/\$\((.+?)\)/\$\\\\($1\\\\)/g;    # protect $(...)
+    $arg =~ s/(?<!\\)([()])/\\$1/g;            # quote unprotected
+    $arg =~ s/\$\\\\\((.+?)\\\\\)/\$($1)/g;    # unprotect $(...)
+    return $arg;
 }
 
 =item realclean (o)
@@ -3332,57 +3441,74 @@ sub realclean {
 
     push(@m,'
 # Delete temporary files (via clean) and also delete installed files
-realclean purge ::  clean
+realclean purge ::  clean realclean_subdirs
+       $(RM_RF) $(INST_AUTODIR) $(INST_ARCHAUTODIR)
+       $(RM_RF) $(DISTVNAME)
 ');
-    # realclean subdirectories first (already cleaned)
-    my $sub;
-    if( $Is_Win32  &&  Win32::IsWin95() ) {
-        $sub = <<'REALCLEAN';
-       -cd %s
-       -$(PERLRUN) -e "exit unless -f shift; system q{$(MAKE) realclean}" %s
-       -cd ..
-REALCLEAN
-    }
-    else {
-        $sub = <<'REALCLEAN';
-       -cd %s && $(TEST_F) %s && $(MAKE) %s realclean
-REALCLEAN
-    }
 
-    foreach(@{$self->{DIR}}){
-       push(@m, sprintf($sub,$_,"$self->{MAKEFILE}.old","-f $self->{MAKEFILE}.old"));
-       push(@m, sprintf($sub,$_,"$self->{MAKEFILE}",''));
-    }
-    push(@m, " $self->{RM_RF} \$(INST_AUTODIR) \$(INST_ARCHAUTODIR)\n");
-    push(@m, " $self->{RM_RF} \$(DISTVNAME)\n");
     if( $self->has_link_code ){
-        push(@m, "     $self->{RM_F} \$(INST_DYNAMIC) \$(INST_BOOT)\n");
-        push(@m, "     $self->{RM_F} \$(INST_STATIC)\n");
+        push(@m, "     \$(RM_F) \$(INST_DYNAMIC) \$(INST_BOOT)\n");
+        push(@m, "     \$(RM_F) \$(INST_STATIC)\n");
     }
+
+    my @files = ();
+    push @files, $attribs{FILES} if $attribs{FILES};
+    push @files, '$(FIRST_MAKEFILE)', '$(MAKEFILE_OLD)';
+
+    # Occasionally files are repeated several times from different sources
+    { my(%f) = map { ($_,1) } @files; @files = keys %f; }
+
     # Issue a several little RM_F commands rather than risk creating a
     # very long command line (useful for extensions such as Encode
     # that have many files).
-    if (keys %{$self->{PM}}) {
-       my $line = "";
-       foreach (values %{$self->{PM}}) {
-           if (length($line) + length($_) > 80) {
-               push @m, "\t$self->{RM_F} $line\n";
-               $line = $_;
-           }
-           else {
-               $line .= " $_"; 
-           }
-       }
-    push @m, "\t$self->{RM_F} $line\n" if $line;
+    my $line = "";
+    foreach my $file (@files) {
+        if (length($line) + length($file) > 200) {
+            push @m, "\t\$(RM_F) $line\n";
+            $line = $file;
+        }
+        else {
+            $line .= " $file"; 
+        }
     }
-    my(@otherfiles) = ($self->{MAKEFILE},
-                      "$self->{MAKEFILE}.old"); # Makefiles last
-    push(@otherfiles, $attribs{FILES}) if $attribs{FILES};
-    push(@m, " $self->{RM_RF} @otherfiles\n") if @otherfiles;
-    push(@m, " $attribs{POSTOP}\n")       if $attribs{POSTOP};
+    push @m, "\t\$(RM_F) $line\n" if $line;
+    push(@m, "\t$attribs{POSTOP}\n")      if $attribs{POSTOP};
+
     join("", @m);
 }
 
+
+=item realclean_subdirs_target
+
+  my $make_frag = $MM->realclean_subdirs_target;
+
+Returns the realclean_subdirs target.  This is used by the realclean
+target to call realclean on any subdirectories which contain Makefiles.
+
+=cut
+
+sub realclean_subdirs_target {
+    my $self = shift;
+
+    return <<'NOOP_FRAG' unless @{$self->{DIR}};
+realclean_subdirs :
+       $(NOECHO) $(NOOP)
+NOOP_FRAG
+
+    my $rclean = "realclean_subdirs :\n";
+
+    foreach my $dir (@{$self->{DIR}}){
+        $rclean .= sprintf <<'RCLEAN', $dir, $dir;
+       -cd %s && $(TEST_F) $(MAKEFILE_OLD) && $(MAKE) -f $(MAKEFILE_OLD) realclean
+       -cd %s && $(TEST_F) $(FIRST_MAKEFILE) && $(MAKE) realclean
+RCLEAN
+
+    }
+
+    return $rclean;
+}
+
+
 =item replace_manpage_separator
 
   my $man_name = $MM->replace_manpage_separator($file_path);
@@ -3400,6 +3526,78 @@ sub replace_manpage_separator {
     return $man;
 }
 
+
+=item oneliner (o)
+
+=cut
+
+sub oneliner {
+    my($self, $cmd, $switches) = @_;
+    $switches = [] unless defined $switches;
+
+    # Strip leading and trailing newlines
+    $cmd =~ s{^\n+}{};
+    $cmd =~ s{\n+$}{};
+
+    $cmd = $self->quote_literal($cmd);
+    $cmd = $self->escape_newlines($cmd);
+
+    $switches = join ' ', @$switches;
+
+    return qq{\$(PERLRUN) $switches -e $cmd};   
+}
+
+
+=item quote_literal
+
+=cut
+
+sub quote_literal {
+    my($self, $text) = @_;
+
+    # I think all we have to quote is single quotes and I think
+    # this is a safe way to do it.
+    $text =~ s{'}{'\\''}g;
+
+    return "'$text'";
+}
+
+
+=item escape_newlines
+
+=cut
+
+sub escape_newlines {
+    my($self, $text) = @_;
+
+    $text =~ s{\n}{\\\n}g;
+
+    return $text;
+}
+
+
+=item max_exec_len
+
+Using POSIX::ARG_MAX.  Otherwise falling back to 4096.
+
+=cut
+
+sub max_exec_len {
+    my $self = shift;
+
+    if (!defined $self->{_MAX_EXEC_LEN}) {
+        if (my $arg_max = eval { require POSIX;  &POSIX::ARG_MAX }) {
+            $self->{_MAX_EXEC_LEN} = $arg_max;
+        }
+        else {      # POSIX minimum exec size
+            $self->{_MAX_EXEC_LEN} = 4096;
+        }
+    }
+
+    return $self->{_MAX_EXEC_LEN};
+}
+
+
 =item static (o)
 
 Defines the static target.
@@ -3413,9 +3611,8 @@ sub static {
     '
 ## $(INST_PM) has been moved to the all: target.
 ## It remains here for awhile to allow for old usage: "make static"
-#static :: '.$self->{MAKEFILE}.' $(INST_STATIC) $(INST_PM)
-static :: '.$self->{MAKEFILE}.' $(INST_STATIC)
-       '.$self->{NOECHO}.'$(NOOP)
+static :: $(FIRST_MAKEFILE) $(INST_STATIC)
+       $(NOECHO) $(NOOP)
 ';
 }
 
@@ -3427,19 +3624,20 @@ Defines how to produce the *.a (or equivalent) files.
 
 sub static_lib {
     my($self) = @_;
-# Come to think of it, if there are subdirs with linkcode, we still have no INST_STATIC
-#    return '' unless $self->needs_linking(); #might be because of a subdir
-
     return '' unless $self->has_link_code;
 
     my(@m);
     push(@m, <<'END');
-$(INST_STATIC): $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)/.exists
+
+$(INST_STATIC): $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DIRFILESEP).exists
        $(RM_RF) $@
 END
+
     # If this extension has its own library (eg SDBM_File)
     # then copy that to $(INST_STATIC) and add $(OBJECT) into it.
-    push(@m, "\t$self->{CP} \$(MYEXTLIB) \$\@\n") if $self->{MYEXTLIB};
+    push(@m, <<'MAKE_FRAG') if $self->{MYEXTLIB};
+       $(CP) $(MYEXTLIB) $@
+MAKE_FRAG
 
     my $ar; 
     if (exists $self->{FULL_AR} && -x $self->{FULL_AR}) {
@@ -3449,20 +3647,19 @@ END
     } else {
         $ar = 'AR';
     }
-    push @m,
-        "\t\$($ar) ".'$(AR_STATIC_ARGS) $@ $(OBJECT) && $(RANLIB) $@'."\n";
-    push @m,
-q{     $(CHMOD) $(PERM_RWX) $@
-       }.$self->{NOECHO}.q{echo "$(EXTRALIBS)" > $(INST_ARCHAUTODIR)/extralibs.ld
-};
+    push @m, sprintf <<'MAKE_FRAG', $ar;
+       $(%s) $(AR_STATIC_ARGS) $@ $(OBJECT) && $(RANLIB) $@
+       $(CHMOD) $(PERM_RWX) $@
+       $(NOECHO) $(ECHO) "$(EXTRALIBS)" > $(INST_ARCHAUTODIR)/extralibs.ld
+MAKE_FRAG
+
     # Old mechanism - still available:
-    push @m,
-"\t$self->{NOECHO}".q{echo "$(EXTRALIBS)" >> $(PERL_SRC)/ext.libs
-}      if $self->{PERL_SRC} && $self->{EXTRALIBS};
-    push @m, "\n";
+    push @m, <<'MAKE_FRAG' if $self->{PERL_SRC} && $self->{EXTRALIBS};
+       $(NOECHO) $(ECHO) "$(EXTRALIBS)" >> $(PERL_SRC)/ext.libs
+MAKE_FRAG
 
-    push @m, $self->dir_target('$(INST_ARCHAUTODIR)');
-    join('', "\n",@m);
+    push @m, "\n", $self->dir_target('$(INST_ARCHAUTODIR)');
+    join('', @m);
 }
 
 =item staticmake (o)
@@ -3480,7 +3677,7 @@ sub staticmake {
     # And as it's not yet built, we add the current extension
     # but only if it has some C code (or XS code, which implies C code)
     if (@{$self->{C}}) {
-       @static = File::Spec->catfile($self->{INST_ARCHLIB},
+       @static = $self->catfile($self->{INST_ARCHLIB},
                                 "auto",
                                 $self->{FULLEXT},
                                 "$self->{BASEEXT}$self->{LIB_EXT}"
@@ -3515,34 +3712,11 @@ Helper subroutine for subdirs
 
 sub subdir_x {
     my($self, $subdir) = @_;
-    my(@m);
-    if ($Is_Win32 && Win32::IsWin95()) {
-       if ($Config{'make'} =~ /dmake/i) {
-           # dmake-specific
-           return <<EOT;
-subdirs ::
-@[
-       cd $subdir
-       \$(MAKE) -f \$(FIRST_MAKEFILE) all \$(PASTHRU)
-       cd ..
-]
-EOT
-        } elsif ($Config{'make'} =~ /nmake/i) {
-           # nmake-specific
-           return <<EOT;
-subdirs ::
-       cd $subdir
-       \$(MAKE) -f \$(FIRST_MAKEFILE) all \$(PASTHRU)
-       cd ..
-EOT
-       }
-    } else {
-       return <<EOT;
+    return sprintf <<'EOT', $subdir;
 
 subdirs ::
-       $self->{NOECHO}cd $subdir && \$(MAKE) -f \$(FIRST_MAKEFILE) all \$(PASTHRU)
+       $(NOECHO)cd %s && $(MAKE) -f $(FIRST_MAKEFILE) all $(PASTHRU)
 EOT
-    }
 }
 
 =item subdirs (o)
@@ -3602,14 +3776,14 @@ testdb :: testdb_\$(LINKTYPE)
 test :: \$(TEST_TYPE)
 ");
 
-    if ($Is_Win32 && Win32::IsWin95()) {
-        push(@m, map(qq{\t$self->{NOECHO}\$(PERLRUN) -e "exit unless -f shift; chdir '$_'; system q{\$(MAKE) test \$(PASTHRU)}" $self->{MAKEFILE}\n}, @{$self->{DIR}}));
+    if ($Is_Win95) {
+        push(@m, map(qq{\t\$(NOECHO) \$(PERLRUN) -e "exit unless -f shift; chdir '$_'; system q{\$(MAKE) test \$(PASTHRU)}" \$(FIRST_MAKEFILE)\n}, @{$self->{DIR}}));
     }
     else {
-        push(@m, map("\t$self->{NOECHO}cd $_ && \$(TEST_F) $self->{MAKEFILE} && \$(MAKE) test \$(PASTHRU)\n", @{$self->{DIR}}));
+        push(@m, map("\t\$(NOECHO) cd $_ && \$(TEST_F) \$(FIRST_MAKEFILE) && \$(MAKE) test \$(PASTHRU)\n", @{$self->{DIR}}));
     }
 
-    push(@m, "\t$self->{NOECHO}echo 'No tests defined for \$(NAME) extension.'\n")
+    push(@m, "\t\$(NOECHO) $(ECHO) 'No tests defined for \$(NAME) extension.'\n")
        unless $tests or -f "test.pl" or @{$self->{DIR}};
     push(@m, "\n");
 
@@ -3666,87 +3840,37 @@ sub test_via_script {
     return $self->SUPER::test_via_script("PERL_DL_NONLAZY=1 $perl", $script);
 }
 
-=item tool_autosplit (o)
-
-Defines a simple perl call that runs autosplit. May be deprecated by
-pm_to_blib soon.
-
-=cut
-
-sub tool_autosplit {
-    my($self, %attribs) = @_;
-    my($asl) = "";
-    $asl = "\$\$AutoSplit::Maxlen=$attribs{MAXLEN};" if $attribs{MAXLEN};
 
-    return sprintf <<'MAKE_FRAG', $asl;
-# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto
-AUTOSPLITFILE = $(PERLRUN) -e 'use AutoSplit; %s autosplit($$ARGV[0], $$ARGV[1], 0, 1, 1) ;'
+=item tools_other (o)
 
-MAKE_FRAG
+    my $make_frag = $MM->tools_other;
 
-}
+Returns a make fragment containing definitions for:
 
-=item tools_other (o)
+SHELL, CHMOD, CP, MV, NOOP, NOECHO, RM_F, RM_RF, TEST_F, TOUCH,
+DEV_NULL, UMASK_NULL, MKPATH, EQUALIZE_TIMESTAMP,
+WARN_IF_OLD_PACKLIST, UNINST, VERBINST, MOD_INSTALL, DOC_INSTALL and
+UNINSTALL
 
-Defines SHELL, LD, TOUCH, CP, MV, RM_F, RM_RF, CHMOD, UMASK_NULL in
-the Makefile. Also defines the perl programs MKPATH,
-WARN_IF_OLD_PACKLIST, MOD_INSTALL. DOC_INSTALL, and UNINSTALL.
+init_others() initializes all these values.
 
 =cut
 
 sub tools_other {
     my($self) = shift;
     my @m;
-    my $bin_sh = $Config{sh} || '/bin/sh';
-    push @m, qq{
-SHELL = $bin_sh
-};
 
-    for (qw/ CHMOD CP LD MV NOOP RM_F RM_RF TEST_F TOUCH UMASK_NULL DEV_NULL/ ) {
-       push @m, "$_ = $self->{$_}\n";
+    for my $tool (qw{ SHELL CHMOD CP MV NOOP NOECHO RM_F RM_RF TEST_F TOUCH 
+                      UMASK_NULL DEV_NULL MKPATH EQUALIZE_TIMESTAMP ECHO
+                      UNINST VERBINST
+                      MOD_INSTALL DOC_INSTALL UNINSTALL
+                      WARN_IF_OLD_PACKLIST
+                    } ) 
+    {
+        next unless defined $self->{$tool};
+        push @m, "$tool = $self->{$tool}\n";
     }
 
-    push @m, q{
-# The following is a portable way to say mkdir -p
-# To see which directories are created, change the if 0 to if 1
-MKPATH = $(PERLRUN) "-MExtUtils::Command" -e mkpath
-
-# This helps us to minimize the effect of the .exists files A yet
-# better solution would be to have a stable file in the perl
-# distribution with a timestamp of zero. But this solution doesn't
-# need any changes to the core distribution and works with older perls
-EQUALIZE_TIMESTAMP = $(PERLRUN) "-MExtUtils::Command" -e eqtime
-};
-
-
-    return join "", @m if $self->{PARENT};
-
-    push @m, q{
-# Here we warn users that an old packlist file was found somewhere,
-# and that they should call some uninstall routine
-WARN_IF_OLD_PACKLIST = $(PERL) -we 'exit unless -f $$ARGV[0];' \\
--e 'print "WARNING: I have found an old package in\n";' \\
--e 'print "\t$$ARGV[0].\n";' \\
--e 'print "Please make sure the two installations are not conflicting\n";'
-
-UNINST=0
-VERBINST=0
-
-MOD_INSTALL = $(PERL) "-I$(INST_LIB)" "-I$(PERL_LIB)" "-MExtUtils::Install" \
--e "install({@ARGV},'$(VERBINST)',0,'$(UNINST)');"
-
-DOC_INSTALL = $(PERL) -e '$$\="\n\n";' \
--e 'print "=head2 ", scalar(localtime), ": C<", shift, ">", " L<", $$arg=shift, "|", $$arg, ">";' \
--e 'print "=over 4";' \
--e 'while (defined($$key = shift) and defined($$val = shift)){print "=item *";print "C<$$key: $$val>";}' \
--e 'print "=back";'
-
-UNINSTALL =   $(PERLRUN) "-MExtUtils::Install" \
--e 'uninstall($$ARGV[0],1,1); print "\nUninstall is deprecated. Please check the";' \
--e 'print " packlist above carefully.\n  There may be errors. Remove the";' \
--e 'print " appropriate files manually.\n  Sorry for the inconveniences.\n"'
-};
-
     return join "", @m;
 }
 
@@ -3759,8 +3883,16 @@ Determines typemaps, xsubpp version, prototype behaviour.
 sub tool_xsubpp {
     my($self) = shift;
     return "" unless $self->needs_linking;
-    my($xsdir)  = File::Spec->catdir($self->{PERL_LIB},"ExtUtils");
-    my(@tmdeps) = File::Spec->catdir('$(XSUBPPDIR)','typemap');
+
+    my $xsdir;
+    foreach my $dir (@INC) {
+        $xsdir = $self->catdir($dir, 'ExtUtils');
+        if( -r $self->catfile($xsdir, "xsubpp") ) {
+            last;
+        }
+    }
+
+    my(@tmdeps) = $self->catdir('$(XSUBPPDIR)','typemap');
     if( $self->{TYPEMAPS} ){
        my $typemap;
        foreach $typemap (@{$self->{TYPEMAPS}}){
@@ -3779,7 +3911,7 @@ sub tool_xsubpp {
     }
 
 
-    my $xsubpp_version = $self->xsubpp_version(File::Spec->catfile($xsdir,"xsubpp"));
+    my $xsubpp_version = $self->xsubpp_version($self->catfile($xsdir,"xsubpp"));
 
     # What are the correct thresholds for version 1 && 2 Paul?
     if ( $xsubpp_version > 1.923 ){
@@ -3862,6 +3994,22 @@ EOM
     return $Xsubpp_Version = "1.0" ;
 }
 
+
+=item all_target
+
+Build man pages, too
+
+=cut
+
+sub all_target {
+    my $self = shift;
+
+    return <<'MAKE_EXT';
+all :: pure_all manifypods
+       $(NOECHO) $(NOOP)
+MAKE_EXT
+}
+
 =item top_targets (o)
 
 Defines the targets all, subdirs, config, and O_FILES
@@ -3874,43 +4022,39 @@ sub top_targets {
     my($self) = shift;
     my(@m);
 
-    push @m, '
-all :: pure_all manifypods
-       '.$self->{NOECHO}.'$(NOOP)
-' 
-         unless $self->{SKIPHASH}{'all'};
+    push @m, $self->all_target, "\n" unless $self->{SKIPHASH}{'all'};
     
     push @m, '
 pure_all :: config pm_to_blib subdirs linkext
-       '.$self->{NOECHO}.'$(NOOP)
+       $(NOECHO) $(NOOP)
 
 subdirs :: $(MYEXTLIB)
-       '.$self->{NOECHO}.'$(NOOP)
+       $(NOECHO) $(NOOP)
 
-config :: '.$self->{MAKEFILE}.' $(INST_LIBDIR)/.exists
-       '.$self->{NOECHO}.'$(NOOP)
+config :: $(FIRST_MAKEFILE) $(INST_LIBDIR)$(DIRFILESEP).exists
+       $(NOECHO) $(NOOP)
 
-config :: $(INST_ARCHAUTODIR)/.exists
-       '.$self->{NOECHO}.'$(NOOP)
+config :: $(INST_ARCHAUTODIR)$(DIRFILESEP).exists
+       $(NOECHO) $(NOOP)
 
-config :: $(INST_AUTODIR)/.exists
-       '.$self->{NOECHO}.'$(NOOP)
+config :: $(INST_AUTODIR)$(DIRFILESEP).exists
+       $(NOECHO) $(NOOP)
 ';
 
     push @m, $self->dir_target(qw[$(INST_AUTODIR) $(INST_LIBDIR) $(INST_ARCHAUTODIR)]);
 
     if (%{$self->{MAN1PODS}}) {
-       push @m, qq[
-config :: \$(INST_MAN1DIR)/.exists
-       $self->{NOECHO}\$(NOOP)
+       push @m, q[
+config :: $(INST_MAN1DIR)$(DIRFILESEP).exists
+       $(NOECHO) $(NOOP)
 
 ];
        push @m, $self->dir_target(qw[$(INST_MAN1DIR)]);
     }
     if (%{$self->{MAN3PODS}}) {
-       push @m, qq[
-config :: \$(INST_MAN3DIR)/.exists
-       $self->{NOECHO}\$(NOOP)
+       push @m, q[
+config :: $(INST_MAN3DIR)$(DIRFILESEP).exists
+       $(NOECHO) $(NOOP)
 
 ];
        push @m, $self->dir_target(qw[$(INST_MAN3DIR)]);
@@ -3990,47 +4134,6 @@ sub xs_o {       # many makes are too dumb to use xs_c then c_o
 ';
 }
 
-=item perl_archive
-
-This is internal method that returns path to libperl.a equivalent
-to be linked to dynamic extensions. UNIX does not have one but other
-OSs might have one.
-
-=cut 
-
-sub perl_archive
-{
- return "";
-}
-
-=item perl_archive_after
-
-This is an internal method that returns path to a library which
-should be put on the linker command line I<after> the external libraries
-to be linked to dynamic extensions.  This may be needed if the linker
-is one-pass, and Perl includes some overrides for C RTL functions,
-such as malloc().
-
-=cut 
-
-sub perl_archive_after
-{
- return "";
-}
-
-=item export_list
-
-This is internal method that returns name of a file that is
-passed to linker to define symbols to be exported.
-UNIX does not have one but OS2 and Win32 do.
-
-=cut 
-
-sub export_list
-{
- return "";
-}
-
 
 1;
 
index 3fedae8..cd68c5e 100644 (file)
@@ -7,18 +7,25 @@ package ExtUtils::MM_VMS;
 
 use strict;
 
-use Carp qw( &carp );
 use Config;
 require Exporter;
-use VMS::Filespec;
+
+BEGIN {
+    # so we can compile the thing on non-VMS platforms.
+    if( $^O eq 'VMS' ) {
+        require VMS::Filespec;
+        VMS::Filespec->import;
+    }
+}
+
 use File::Basename;
-use File::Spec;
 use vars qw($Revision @ISA $VERSION);
-($VERSION) = $Revision = '5.65';
+($VERSION) = '5.66';
+($Revision = substr(q$Revision: 1.82 $, 10)) =~ s/\s+$//;
 
 require ExtUtils::MM_Any;
 require ExtUtils::MM_Unix;
-@ISA = qw( ExtUtils::MM_Any ExtUtils::MM_Unix File::Spec );
+@ISA = qw( ExtUtils::MM_Any ExtUtils::MM_Unix );
 
 use ExtUtils::MakeMaker qw($Verbose neatvalue);
 
@@ -52,9 +59,8 @@ Converts a list into a string wrapped at approximately 80 columns.
 sub wraplist {
     my($self) = shift;
     my($line,$hlen) = ('',0);
-    my($word);
 
-    foreach $word (@_) {
+    foreach my $word (@_) {
       # Perl bug -- seems to occasionally insert extra elements when
       # traversing array (scalar(@array) doesn't show them, but
       # foreach(@array) does) (5.00307)
@@ -160,8 +166,8 @@ sub find_perl {
     local *TCF;
     # Check in relative directories first, so we pick up the current
     # version of Perl if we're running MakeMaker as part of the main build.
-    @sdirs = sort { my($absa) = File::Spec->file_name_is_absolute($a);
-                    my($absb) = File::Spec->file_name_is_absolute($b);
+    @sdirs = sort { my($absa) = $self->file_name_is_absolute($a);
+                    my($absb) = $self->file_name_is_absolute($b);
                     if ($absa && $absb) { return $a cmp $b }
                     else { return $absa ? 1 : ($absb ? -1 : ($a cmp $b)); }
                   } @$dirs;
@@ -187,7 +193,7 @@ sub find_perl {
     }
     foreach $dir (@sdirs){
        next unless defined $dir; # $self->{PERL_SRC} may be undefined
-       $inabs++ if File::Spec->file_name_is_absolute($dir);
+       $inabs++ if $self->file_name_is_absolute($dir);
        if ($inabs == 1) {
            # We've covered relative dirs; everything else is an absolute
            # dir (probably an installed location).  First, we'll try potential
@@ -196,7 +202,7 @@ sub find_perl {
            $inabs++; # Should happen above in next $dir, but just in case . . .
        }
        foreach $name (@snames){
-           if ($name !~ m![/:>\]]!) { push(@cand,File::Spec->catfile($dir,$name)); }
+           if ($name !~ m![/:>\]]!) { push(@cand,$self->catfile($dir,$name)); }
            else                     { push(@cand,$self->fixpath($name,0));    }
        }
     }
@@ -211,9 +217,9 @@ sub find_perl {
             $rslt = `\@temp_mmvms.com` ;
             unlink('temp_mmvms.com');
             if ($rslt =~ /VER_OK/) {
-           print "Using PERL=$name\n" if $trace;
-           return $name;
-       }
+                print "Using PERL=$name\n" if $trace;
+                return $name;
+            }
         }
        next unless $vmsfile = $self->maybe_command($name);
        $vmsfile =~ s/;[\d\-]*$//;  # Clip off version number; we can use a newer version as well
@@ -267,42 +273,6 @@ sub maybe_command {
     return 0;
 }
 
-=item maybe_command_in_dirs (override)
-
-Uses DCL argument quoting on test command line.
-
-=cut
-
-sub maybe_command_in_dirs {    # $ver is optional argument if looking for perl
-    my($self, $names, $dirs, $trace, $ver) = @_;
-    my($name, $dir);
-    foreach $dir (@$dirs){
-       next unless defined $dir; # $self->{PERL_SRC} may be undefined
-       foreach $name (@$names){
-           my($abs,$tryabs);
-           if (File::Spec->file_name_is_absolute($name)) {
-               $abs = $name;
-           } else {
-               $abs = File::Spec->catfile($dir, $name);
-           }
-           print "Checking $abs for $name\n" if ($trace >= 2);
-           next unless $tryabs = $self->maybe_command($abs);
-           print "Substituting $tryabs instead of $abs\n" 
-               if ($trace >= 2 and $tryabs ne $abs);
-           $abs = $tryabs;
-           if (defined $ver) {
-               print "Executing $abs\n" if ($trace >= 2);
-               if (`$abs -e 'require $ver; print "VER_OK\n" ' 2>&1` =~ /VER_OK/) {
-                   print "Using $abs\n" if $trace;
-                   return $abs;
-               }
-           } else { # Do not look for perl
-               return $abs;
-           }
-       }
-    }
-}
-
 =item perl_script (override)
 
 If name passed in doesn't specify a readable file, appends F<.com> or
@@ -332,10 +302,22 @@ sub replace_manpage_separator {
     $man;
 }
 
+=item init_DIRFILESEP
+
+No seperator between a directory path and a filename on VMS.
+
+=cut
+
+sub init_DIRFILESEP {
+    my($self) = shift;
+
+    $self->{DIRFILESEP} = '';
+    return 1;
+}
+
+
 =item init_main (override)
 
-Override DISTVNAME so it uses VERSION_SYM to avoid getting too many
-dots in the name.
 
 =cut
 
@@ -343,7 +325,34 @@ sub init_main {
     my($self) = shift;
 
     $self->SUPER::init_main;
-    $self->{DISTVNAME} = "$self->{DISTNAME}-$self->{VERSION_SYM}";
+
+    $self->{DEFINE} ||= '';
+    if ($self->{DEFINE} ne '') {
+        my(@terms) = split(/\s+/,$self->{DEFINE});
+        my(@defs,@udefs);
+        foreach my $def (@terms) {
+            next unless $def;
+            my $targ = \@defs;
+            if ($def =~ s/^-([DU])//) {    # If it was a Unix-style definition
+                $targ = \@udefs if $1 eq 'U';
+                $def =~ s/='(.*)'$/=$1/;  # then remove shell-protection ''
+                $def =~ s/^'(.*)'$/$1/;   # from entire term or argument
+            }
+            if ($def =~ /=/) {
+                $def =~ s/"/""/g;  # Protect existing " from DCL
+                $def = qq["$def"]; # and quote to prevent parsing of =
+            }
+            push @$targ, $def;
+        }
+
+        $self->{DEFINE} = '';
+        if (@defs)  { 
+            $self->{DEFINE}  = '/Define=(' . join(',',@defs)  . ')'; 
+        }
+        if (@udefs) { 
+            $self->{DEFINE} .= '/Undef=('  . join(',',@udefs) . ')'; 
+        }
+    }
 }
 
 =item init_others (override)
@@ -351,238 +360,203 @@ sub init_main {
 Provide VMS-specific forms of various utility commands, then hand
 off to the default MM_Unix method.
 
+DEV_NULL should probably be overriden with something.
+
+Also changes EQUALIZE_TIMESTAMP to set revision date of target file to
+one second later than source file, since MMK interprets precisely
+equal revision dates for a source and target file as a sign that the
+target needs to be updated.
+
 =cut
 
 sub init_others {
     my($self) = @_;
 
-    $self->{NOOP} = 'Continue';
-    $self->{FIRST_MAKEFILE} ||= 'Descrip.MMS';
-    $self->{MAKE_APERL_FILE} ||= 'Makeaperl.MMS';
-    $self->{MAKEFILE} ||= $self->{FIRST_MAKEFILE};
-    $self->{NOECHO} ||= '@ ';
-    $self->{RM_F} = '$(PERL) -e "foreach (@ARGV) { 1 while ( -d $_ ? rmdir $_ : unlink $_)}"';
-    $self->{RM_RF} = '$(PERLRUN) -e "use File::Path; @dirs = map(VMS::Filespec::unixify($_),@ARGV); rmtree(\@dirs,0,0)"';
-    $self->{TOUCH} = '$(PERL) -e "$t=time; foreach (@ARGV) { -e $_ ? utime($t,$t,@ARGV) : (open(F,qq(>$_)),close F)}"';
-    $self->{CHMOD} = '$(PERL) -e "chmod @ARGV"';  # expect Unix syntax from MakeMaker
+    $self->{NOOP}               = 'Continue';
+    $self->{NOECHO}             ||= '@ ';
+
+    $self->{MAKEFILE}           ||= 'Descrip.MMS';
+    $self->{FIRST_MAKEFILE}     ||= $self->{MAKEFILE};
+    $self->{MAKE_APERL_FILE}    ||= 'Makeaperl.MMS';
+    $self->{MAKEFILE_OLD}       ||= '$(FIRST_MAKEFILE)_old';
+
+    $self->{ECHO}     ||= '$(PERLRUN) -le "print qq{@ARGV}"';
+    $self->{TOUCH}    ||= '$(PERLRUN) "-MExtUtils::Command" -e touch';
+    $self->{CHMOD}    ||= '$(PERLRUN) "-MExtUtils::Command" -e chmod'; 
+    $self->{RM_F}     ||= '$(PERLRUN) "-MExtUtils::Command" -e rm_f';
+    $self->{RM_RF}    ||= '$(PERLRUN) "-MExtUtils::Command" -e rm_rf';
+    $self->{TEST_F}   ||= '$(PERLRUN) "-MExtUtils::Command" -e test_f';
+    $self->{EQUALIZE_TIMESTAMP} ||= '$(PERLRUN) -we "open F,qq{>>$ARGV[1]};close F;utime(0,(stat($ARGV[0]))[9]+1,$ARGV[1])"';
+
+    $self->{MOD_INSTALL} ||= 
+      $self->oneliner(<<'CODE', ['-MExtUtils::Install']);
+install({split(' ',<STDIN>)}, '$(VERBINST)', 0, '$(UNINST)');
+CODE
+
+    $self->{SHELL}    ||= 'Posix';
+
     $self->{CP} = 'Copy/NoConfirm';
     $self->{MV} = 'Rename/NoConfirm';
     $self->{UMASK_NULL} = '! ';  
-    
+
     $self->SUPER::init_others;
+
+    if ($self->{OBJECT} =~ /\s/) {
+        $self->{OBJECT} =~ s/(\\)?\n+\s+/ /g;
+        $self->{OBJECT} = $self->wraplist(
+            map $self->fixpath($_,0), split /,?\s+/, $self->{OBJECT}
+        );
+    }
+
+    $self->{LDFROM} = $self->wraplist(
+        map $self->fixpath($_,0), split /,?\s+/, $self->{LDFROM}
+    );
+}
+
+
+=item init_platform (override)
+
+Add PERL_VMS, MM_VMS_REVISION and MM_VMS_VERSION.
+
+MM_VMS_REVISION is for backwards compatibility before MM_VMS had a
+$VERSION.
+
+=cut
+
+sub init_platform {
+    my($self) = shift;
+
+    $self->{MM_VMS_REVISION} = $Revision;
+    $self->{MM_VMS_VERSION}  = $VERSION;
+    $self->{PERL_VMS} = $self->catdir($self->{PERL_SRC}, 'VMS')
+      if $self->{PERL_SRC};
 }
 
+
+=item platform_constants
+
+=cut
+
+sub platform_constants {
+    my($self) = shift;
+    my $make_frag = '';
+
+    foreach my $macro (qw(PERL_VMS MM_VMS_REVISION MM_VMS_VERSION))
+    {
+        next unless defined $self->{$macro};
+        $make_frag .= "$macro = $self->{$macro}\n";
+    }
+
+    return $make_frag;
+}
+
+
+=item init_VERSION (override)
+
+Override the *DEFINE_VERSION macros with VMS semantics.  Translate the
+MAKEMAKER filepath to VMS style.
+
+=cut
+
+sub init_VERSION {
+    my $self = shift;
+
+    $self->SUPER::init_VERSION;
+
+    $self->{DEFINE_VERSION}    = '"$(VERSION_MACRO)=""$(VERSION)"""';
+    $self->{XS_DEFINE_VERSION} = '"$(XS_VERSION_MACRO)=""$(XS_VERSION)"""';
+    $self->{MAKEMAKER} = vmsify($INC{'ExtUtils/MakeMaker.pm'});
+}
+
+
 =item constants (override)
 
 Fixes up numerous file and directory macros to insure VMS syntax
-regardless of input syntax.  Also adds a few VMS-specific macros
-and makes lists of files comma-separated.
+regardless of input syntax.  Also makes lists of files
+comma-separated.
 
 =cut
 
 sub constants {
     my($self) = @_;
-    my(@m,$def,$macro);
 
     # Be kind about case for pollution
     for (@ARGV) { $_ = uc($_) if /POLLUTE/i; }
 
-    $self->{DEFINE} ||= '';
-    if ($self->{DEFINE} ne '') {
-       my(@terms) = split(/\s+/,$self->{DEFINE});
-       my(@defs,@udefs);
-       foreach $def (@terms) {
-           next unless $def;
-           my $targ = \@defs;
-           if ($def =~ s/^-([DU])//) {       # If it was a Unix-style definition
-               if ($1 eq 'U') { $targ = \@udefs; }
-               $def =~ s/='(.*)'$/=$1/;  # then remove shell-protection ''
-               $def =~ s/^'(.*)'$/$1/;   # from entire term or argument
-           }
-           if ($def =~ /=/) {
-               $def =~ s/"/""/g;  # Protect existing " from DCL
-               $def = qq["$def"]; # and quote to prevent parsing of =
-           }
-           push @$targ, $def;
-       }
-       $self->{DEFINE} = '';
-       if (@defs)  { 
-            $self->{DEFINE}  = '/Define=(' . join(',',@defs)  . ')'; 
-        }
-       if (@udefs) { 
-            $self->{DEFINE} .= '/Undef=('  . join(',',@udefs) . ')'; 
-        }
-    }
-
-    if ($self->{OBJECT} =~ /\s/) {
-       $self->{OBJECT} =~ s/(\\)?\n+\s+/ /g;
-       $self->{OBJECT} = $self->wraplist(map($self->fixpath($_,0),split(/,?\s+/,$self->{OBJECT})));
-    }
-    $self->{LDFROM} = $self->wraplist(map($self->fixpath($_,0),split(/,?\s+/,$self->{LDFROM})));
-
-
-    foreach $macro ( qw [
+    # Cleanup paths for directories in MMS macros.
+    foreach my $macro ( qw [
             INST_BIN INST_SCRIPT INST_LIB INST_ARCHLIB 
             INSTALLPRIVLIB  INSTALLSITELIB  INSTALLVENDORLIB
-           INSTALLARCHLIB  INSTALLSITEARCH INSTALLVENDORARCH
+            INSTALLARCHLIB  INSTALLSITEARCH INSTALLVENDORARCH
             INSTALLBIN      INSTALLSITEBIN  INSTALLVENDORBIN  INSTALLSCRIPT 
             INSTALLMAN1DIR INSTALLSITEMAN1DIR INSTALLVENDORMAN1DIR
             INSTALLMAN3DIR INSTALLSITEMAN3DIR INSTALLVENDORMAN3DIR
             PERL_LIB PERL_ARCHLIB
-            PERL_INC PERL_SRC FULLEXT ] ) {
-       next unless defined $self->{$macro};
+            PERL_INC PERL_SRC ] ) 
+    {
+        next unless defined $self->{$macro};
         next if $macro =~ /MAN/ && $self->{$macro} eq 'none';
-       $self->{$macro} = $self->fixpath($self->{$macro},1);
-    }
-    $self->{PERL_VMS} = File::Spec->catdir($self->{PERL_SRC},q(VMS))
-       if ($self->{PERL_SRC});
-                        
-
-
-    # Fix up file specs
-    foreach $macro ( qw[LIBPERL_A FIRST_MAKEFILE MAKE_APERL_FILE MYEXTLIB] ) {
-       next unless defined $self->{$macro};
-       $self->{$macro} = $self->fixpath($self->{$macro},0);
-    }
-
-    foreach $macro (qw/
-             AR_STATIC_ARGS NAME DISTNAME NAME_SYM VERSION VERSION_SYM 
-              XS_VERSION
-             INST_BIN INST_LIB INST_ARCHLIB INST_SCRIPT 
-              INSTALLDIRS
-              PREFIX          SITEPREFIX      VENDORPREFIX
-             INSTALLPRIVLIB  INSTALLSITELIB  INSTALLVENDORLIB
-             INSTALLARCHLIB  INSTALLSITEARCH INSTALLVENDORARCH
-              INSTALLBIN      INSTALLSITEBIN  INSTALLVENDORBIN  INSTALLSCRIPT 
-             PERL_LIB PERL_ARCHLIB 
-              SITELIBEXP SITEARCHEXP 
-              LIBPERL_A MYEXTLIB
-             FIRST_MAKEFILE MAKE_APERL_FILE PERLMAINCC PERL_SRC PERL_VMS
-             PERL_INC PERL FULLPERL PERLRUN FULLPERLRUN PERLRUNINST
-              FULLPERLRUNINST ABSPERL ABSPERLRUN ABSPERLRUNINST
-              PERL_CORE NOECHO NOOP
-             / ) {
-       next unless defined $self->{$macro};
-       push @m, "$macro = $self->{$macro}\n";
+        $self->{$macro} = $self->fixpath($self->{$macro},1);
     }
 
-
-    push @m, q[
-VERSION_MACRO = VERSION
-DEFINE_VERSION = "$(VERSION_MACRO)=""$(VERSION)"""
-XS_VERSION_MACRO = XS_VERSION
-XS_DEFINE_VERSION = "$(XS_VERSION_MACRO)=""$(XS_VERSION)"""
-
-MAKEMAKER = ],File::Spec->catfile($self->{PERL_LIB},'ExtUtils','MakeMaker.pm'),qq[
-MM_VERSION = $ExtUtils::MakeMaker::VERSION
-MM_REVISION = $ExtUtils::MakeMaker::Revision
-MM_VMS_REVISION = $ExtUtils::MM_VMS::Revision
-
-# FULLEXT = Pathname for extension directory (eg DBD/Oracle).
-# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT.
-# PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar)
-# DLBASE  = Basename part of dynamic library. May be just equal BASEEXT.
-];
-
-    for my $tmp (qw/
-             FULLEXT VERSION_FROM OBJECT LDFROM
-             / ) {
-       next unless defined $self->{$tmp};
-       push @m, "$tmp = ",$self->fixpath($self->{$tmp},0),"\n";
+    # Cleanup paths for files in MMS macros.
+    foreach my $macro ( qw[LIBPERL_A FIRST_MAKEFILE MAKEFILE_OLD 
+                           MAKE_APERL_FILE MYEXTLIB] ) 
+    {
+        next unless defined $self->{$macro};
+        $self->{$macro} = $self->fixpath($self->{$macro},0);
     }
 
-    for my $tmp (qw/
-             BASEEXT PARENT_NAME DLBASE INC DEFINE LINKTYPE
+    # Fixup files for MMS macros
+    # XXX is this list complete?
+    for my $macro (qw/
+                   FULLEXT VERSION_FROM OBJECT LDFROM
              / ) {
-       next unless defined $self->{$tmp};
-       push @m, "$tmp = $self->{$tmp}\n";
+        next unless defined $self->{$macro};
+        $self->{$macro} = $self->fixpath($self->{$macro},0);
     }
 
-    for my $tmp (qw/ XS MAN1PODS MAN3PODS PM /) {
-       # Where is the space coming from? --jhi
-       next unless $self ne " " && defined $self->{$tmp};
-       my(%tmp,$key);
-       for $key (keys %{$self->{$tmp}}) {
-           $tmp{$self->fixpath($key,0)} = $self->fixpath($self->{$tmp}{$key},0);
-       }
-       $self->{$tmp} = \%tmp;
-    }
 
-    for my $tmp (qw/ C O_FILES H /) {
-       next unless defined $self->{$tmp};
-       my(@tmp,$val);
-       for $val (@{$self->{$tmp}}) {
-           push(@tmp,$self->fixpath($val,0));
-       }
-       $self->{$tmp} = \@tmp;
+    for my $macro (qw/ XS MAN1PODS MAN3PODS PM /) {
+        # Where is the space coming from? --jhi
+        next unless $self ne " " && defined $self->{$macro};
+        my %tmp = ();
+        for my $key (keys %{$self->{$macro}}) {
+            $tmp{$self->fixpath($key,0)} = 
+                                     $self->fixpath($self->{$macro}{$key},0);
+        }
+        $self->{$macro} = \%tmp;
     }
 
-    push @m,'
-
-# Handy lists of source code files:
-XS_FILES = ',$self->wraplist(sort keys %{$self->{XS}}),'
-C_FILES  = ',$self->wraplist(@{$self->{C}}),'
-O_FILES  = ',$self->wraplist(@{$self->{O_FILES}} ),'
-H_FILES  = ',$self->wraplist(@{$self->{H}}),'
-MAN1PODS = ',$self->wraplist(sort keys %{$self->{MAN1PODS}}),'
-MAN3PODS = ',$self->wraplist(sort keys %{$self->{MAN3PODS}}),'
-
-';
-
-    for my $tmp (qw/
-             INST_MAN1DIR  MAN1EXT 
-              INSTALLMAN1DIR INSTALLSITEMAN1DIR INSTALLVENDORMAN1DIR
-             INST_MAN3DIR  MAN3EXT
-              INSTALLMAN3DIR INSTALLSITEMAN3DIR INSTALLVENDORMAN3DIR
-             /) {
-       next unless defined $self->{$tmp};
-       push @m, "$tmp = $self->{$tmp}\n";
+    for my $macro (qw/ C O_FILES H /) {
+        next unless defined $self->{$macro};
+        my @tmp = ();
+        for my $val (@{$self->{$macro}}) {
+            push(@tmp,$self->fixpath($val,0));
+        }
+        $self->{$macro} = \@tmp;
     }
 
-push @m,"
-makemakerdflt : all
-       \$(NOECHO) \$(NOOP)
+    return $self->SUPER::constants;
+}
 
-.SUFFIXES :
-.SUFFIXES : \$(OBJ_EXT) .c .cpp .cxx .xs
 
-# Here is the Config.pm that we are using/depend on
-CONFIGDEP = \$(PERL_ARCHLIB)Config.pm, \$(PERL_INC)config.h \$(VERSION_FROM)
+=item special_targets
 
-# Where to put things:
-INST_LIBDIR      = $self->{INST_LIBDIR}
-INST_ARCHLIBDIR  = $self->{INST_ARCHLIBDIR}
+Clear the default .SUFFIXES and put in our own list.
 
-INST_AUTODIR     = $self->{INST_AUTODIR}
-INST_ARCHAUTODIR = $self->{INST_ARCHAUTODIR}
-";
+=cut
 
-    if ($self->has_link_code()) {
-       push @m,'
-INST_STATIC = $(INST_ARCHAUTODIR)$(BASEEXT)$(LIB_EXT)
-INST_DYNAMIC = $(INST_ARCHAUTODIR)$(DLBASE).$(DLEXT)
-INST_BOOT = $(INST_ARCHAUTODIR)$(BASEEXT).bs
-';
-    } else {
-       my $shr = $Config{'dbgprefix'} . 'PERLSHR';
-       push @m,'
-INST_STATIC =
-INST_DYNAMIC =
-INST_BOOT =
-EXPORT_LIST = $(BASEEXT).opt
-PERL_ARCHIVE = ',($ENV{$shr} ? $ENV{$shr} : "Sys\$Share:$shr.$Config{'dlext'}"),'
-';
-    }
+sub special_targets {
+    my $self = shift;
 
-    $self->{TO_INST_PM} = [ sort keys %{$self->{PM}} ];
-    $self->{PM_TO_BLIB} = [ %{$self->{PM}} ];
-    push @m,'
-TO_INST_PM = ',$self->wraplist(@{$self->{TO_INST_PM}}),'
+    my $make_frag .= <<'MAKE_FRAG';
+.SUFFIXES :
+.SUFFIXES : $(OBJ_EXT) .c .cpp .cxx .xs
 
-PM_TO_BLIB = ',$self->wraplist(@{$self->{PM_TO_BLIB}}),'
-';
+MAKE_FRAG
 
-    join('',@m);
+    return $make_frag;
 }
 
 =item cflags (override)
@@ -723,78 +697,6 @@ sub const_cccmd {
     $self->{CONST_CCCMD} = join('',@m);
 }
 
-=item pm_to_blib (override)
-
-DCL I<still> accepts a maximum of 255 characters on a command
-line, so we write the (potentially) long list of file names
-to a temp file, then persuade Perl to read it instead of the
-command line to find args.
-
-=cut
-
-sub pm_to_blib {
-    my($self) = @_;
-    my($autodir) = File::Spec->catdir($self->{INST_LIB},'auto');
-    my(%files) = @{$self->{PM_TO_BLIB}};
-
-    my $m = <<'MAKE_FRAG';
-
-# Dummy target to match Unix target name; we use pm_to_blib.ts as
-# timestamp file to avoid repeated invocations under VMS
-pm_to_blib : pm_to_blib.ts
-       $(NOECHO) $(NOOP)
-
-# As always, keep under DCL's 255-char limit
-pm_to_blib.ts : $(TO_INST_PM)
-MAKE_FRAG
-
-    if( keys %files ) {
-        $m .= <<'MAKE_FRAG';
-       $(NOECHO) $(RM_F) .MM_tmp
-MAKE_FRAG
-
-        my $line = '';
-        while (my($from, $to) = each %files) {
-            $line .= " $from $to";
-            if (length($line) > 128) {
-                $m .= sprintf <<'MAKE_FRAG', $line;
-       $(NOECHO) $(PERL) -e "print '%s'" >>.MM_tmp
-MAKE_FRAG
-                $line = '';
-            }
-        }
-        $m .= sprintf <<'MAKE_FRAG', $line if $line;
-       $(NOECHO) $(PERL) -e "print '%s'" >>.MM_tmp
-MAKE_FRAG
-
-        $m .= sprintf <<'MAKE_FRAG', $autodir;
-       $(PERLRUN) "-MExtUtils::Install" -e "pm_to_blib({split(' ',<STDIN>)},'%s','$(PM_FILTER)')" <.MM_tmp
-       $(NOECHO) $(RM_F) .MM_tmp
-MAKE_FRAG
-
-    }
-    $m .= <<'MAKE_FRAG';
-       $(NOECHO) $(TOUCH) pm_to_blib.ts
-MAKE_FRAG
-
-    return $m;
-}
-
-=item tool_autosplit (override)
-
-Use VMS-style quoting on command line.
-
-=cut
-
-sub tool_autosplit {
-    my($self, %attribs) = @_;
-    my($asl) = "";
-    $asl = "\$AutoSplit::Maxlen=$attribs{MAXLEN};" if $attribs{MAXLEN};
-    q{
-# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto
-AUTOSPLITFILE = $(PERLRUN) -e "use AutoSplit;}.$asl.q{autosplit($ARGV[0], $ARGV[1], 0, 1, 1) ;"
-};
-}
 
 =item tool_sxubpp (override)
 
@@ -805,9 +707,10 @@ Use VMS-style quoting on xsubpp command line.
 sub tool_xsubpp {
     my($self) = @_;
     return '' unless $self->needs_linking;
-    my($xsdir) = File::Spec->catdir($self->{PERL_LIB},'ExtUtils');
+    my($xsdir) = $self->catdir($self->{PERL_LIB},'ExtUtils');
     # drop back to old location if xsubpp is not in new location yet
-    $xsdir = File::Spec->catdir($self->{PERL_SRC},'ext') unless (-f File::Spec->catfile($xsdir,'xsubpp'));
+    $xsdir = $self->catdir($self->{PERL_SRC},'ext') 
+      unless (-f $self->catfile($xsdir,'xsubpp'));
     my(@tmdeps) = '$(XSUBPPDIR)typemap';
     if( $self->{TYPEMAPS} ){
        my $typemap;
@@ -831,7 +734,7 @@ sub tool_xsubpp {
         (!exists($self->{XSOPT}) || $self->{XSOPT} !~ /linenumbers/)) {
         unshift(@tmargs,'-nolinenumbers');
     }
-    my $xsubpp_version = $self->xsubpp_version(File::Spec->catfile($xsdir,'xsubpp'));
+    my $xsubpp_version = $self->xsubpp_version($self->catfile($xsdir,'xsubpp'));
 
     # What are the correct thresholds for version 1 && 2 Paul?
     if ( $xsubpp_version > 1.923 ){
@@ -877,7 +780,7 @@ sub xsubpp_version
     print "Running: $command\n" if $Verbose;
     $version = `$command` ;
     if ($?) {
-       use vmsish 'status';
+       use ExtUtils::MakeMaker::vmsish 'status';
        warn "Running '$command' exits with status $?";
     }
     chop $version ;
@@ -907,7 +810,7 @@ EOM
     print "Running: $command\n" if $Verbose;
     my $text = `$command` ;
     if ($?) {
-       use vmsish 'status';
+       use ExtUtils::MakeMaker::vmsish 'status';
        warn "Running '$command' exits with status $?";
     }
     unlink $file ;
@@ -924,68 +827,68 @@ EOM
 
 =item tools_other (override)
 
-Adds a few MM[SK] macros, and shortens some the installatin commands,
-in order to stay under DCL's 255-character limit.  Also changes
-EQUALIZE_TIMESTAMP to set revision date of target file to one second
-later than source file, since MMK interprets precisely equal revision
-dates for a source and target file as a sign that the target needs
-to be updated.
+Throw in some dubious extra macros for Makefile args.
+
+Also keep around the old $(SAY) macro in case somebody's using it.
 
 =cut
 
 sub tools_other {
     my($self) = @_;
-    qq!
+
+    # XXX Are these necessary?  Does anyone override them?  They're longer
+    # than just typing the literal string.
+    my $extra_tools = <<'EXTRA_TOOLS';
+
 # Assumes \$(MMS) invokes MMS or MMK
 # (It is assumed in some cases later that the default makefile name
 # (Descrip.MMS for MM[SK]) is used.)
 USEMAKEFILE = /Descrip=
 USEMACROS = /Macro=(
 MACROEND = )
-MAKEFILE = Descrip.MMS
-SHELL = Posix
-TOUCH = $self->{TOUCH}
-CHMOD = $self->{CHMOD}
-CP = $self->{CP}
-MV = $self->{MV}
-RM_F  = $self->{RM_F}
-RM_RF = $self->{RM_RF}
-SAY = Write Sys\$Output
-UMASK_NULL = $self->{UMASK_NULL}
-MKPATH = Create/Directory
-EQUALIZE_TIMESTAMP = \$(PERL) -we "open F,qq{>\$ARGV[1]};close F;utime(0,(stat(\$ARGV[0]))[9]+1,\$ARGV[1])"
-!. ($self->{PARENT} ? '' : 
-qq!WARN_IF_OLD_PACKLIST = \$(PERL) -e "if (-f \$ARGV[0]){print qq[WARNING: Old package found (\$ARGV[0]); please check for collisions\\n]}"
-MOD_INSTALL = \$(PERLRUN) "-MExtUtils::Install" -e "install({split(' ',<STDIN>)},1);"
-DOC_INSTALL = \$(PERL) -e "\@ARGV=split(/\\|/,<STDIN>);print '=head2 ',scalar(localtime),': C<',shift,qq[>\\n\\n=over 4\\n\\n];while(\$key=shift && \$val=shift){print qq[=item *\\n\\nC<\$key: \$val>\\n\\n];}print qq[=back\\n\\n]"
-UNINSTALL = \$(PERLRUN) "-MExtUtils::Install" -e "uninstall(\$ARGV[0],1,1);"
-!);
+
+# Just in case anyone is using the old macro.
+SAY = $ECHO
+
+EXTRA_TOOLS
+
+    return $self->SUPER::tools_other . $extra_tools;
 }
 
-=item dist (override)
+=item init_dist (override)
 
-Provide VMSish defaults for some values, then hand off to
-default MM_Unix method.
+VMSish defaults for some values.
 
-=cut
+  macro         description                     default
 
-sub dist {
-    my($self, %attribs) = @_;
-    $attribs{VERSION}      ||= $self->{VERSION_SYM};
-    $attribs{NAME}         ||= $self->{DISTNAME};
-    $attribs{ZIPFLAGS}     ||= '-Vu';
-    $attribs{COMPRESS}     ||= 'gzip';
-    $attribs{SUFFIX}       ||= '-gz';
-    $attribs{SHAR}         ||= 'vms_share';
-    $attribs{DIST_DEFAULT} ||= 'zipdist';
+  ZIPFLAGS      flags to pass to ZIP            -Vu
 
-    # Sanitize these for use in $(DISTVNAME) filespec
-    $attribs{VERSION} =~ s/[^\w\$]/_/g;
-    $attribs{NAME} =~ s/[^\w\$]/-/g;
+  COMPRESS      compression command to          gzip
+                use for tarfiles
+  SUFFIX        suffix to put on                -gz 
+                compressed files
 
-    $attribs{DISTVNAME} ||= '$(DISTNAME)-$(VERSION_SYM)';
+  SHAR          shar command to use             vms_share
 
-    return $self->SUPER::dist(%attribs);
+  DIST_DEFAULT  default target to use to        tardist
+                create a distribution
+
+  DISTVNAME     Use VERSION_SYM instead of      $(DISTNAME)-$(VERSION_SYM)
+                VERSION for the name
+
+=cut
+
+sub init_dist {
+    my($self) = @_;
+    $self->{ZIPFLAGS}     ||= '-Vu';
+    $self->{COMPRESS}     ||= 'gzip';
+    $self->{SUFFIX}       ||= '-gz';
+    $self->{SHAR}         ||= 'vms_share';
+    $self->{DIST_DEFAULT} ||= 'zipdist';
+
+    $self->SUPER::init_dist;
+
+    $self->{DISTVNAME}    = "$self->{DISTNAME}-$self->{VERSION_SYM}";
 }
 
 =item c_o (override)
@@ -1042,62 +945,6 @@ sub xs_o {        # many makes are too dumb to use xs_c then c_o
 ';
 }
 
-=item top_targets (override)
-
-Path seperator differences.
-
-=cut
-
-sub top_targets {
-    my($self) = shift;
-    my(@m);
-    push @m, '
-all :: pure_all manifypods
-       $(NOECHO) $(NOOP)
-
-pure_all :: config pm_to_blib subdirs linkext
-       $(NOECHO) $(NOOP)
-
-subdirs :: $(MYEXTLIB)
-       $(NOECHO) $(NOOP)
-
-config :: $(MAKEFILE) $(INST_LIBDIR).exists
-       $(NOECHO) $(NOOP)
-
-config :: $(INST_ARCHAUTODIR).exists
-       $(NOECHO) $(NOOP)
-
-config :: $(INST_AUTODIR).exists
-       $(NOECHO) $(NOOP)
-';
-
-    push @m, $self->dir_target(qw[$(INST_AUTODIR) $(INST_LIBDIR) $(INST_ARCHAUTODIR)]);
-    if (%{$self->{MAN1PODS}}) {
-       push @m, q[
-config :: $(INST_MAN1DIR).exists
-       $(NOECHO) $(NOOP)
-];
-       push @m, $self->dir_target(qw[$(INST_MAN1DIR)]);
-    }
-    if (%{$self->{MAN3PODS}}) {
-       push @m, q[
-config :: $(INST_MAN3DIR).exists
-       $(NOECHO) $(NOOP)
-];
-       push @m, $self->dir_target(qw[$(INST_MAN3DIR)]);
-    }
-
-    push @m, '
-$(O_FILES) : $(H_FILES)
-' if @{$self->{O_FILES} || []} && @{$self->{H} || []};
-
-    push @m, q{
-help :
-       perldoc ExtUtils::MakeMaker
-};
-
-    join('',@m);
-}
 
 =item dlsyms (override)
 
@@ -1204,7 +1051,7 @@ INST_DYNAMIC_DEP = $inst_dynamic_dep
 
 ";
     push @m, '
-$(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt $(INST_ARCHAUTODIR).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP)
+$(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt $(INST_ARCHAUTODIR)$(DIRFILESEP).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP)
        $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR)
        If F$TrnLNm("',$shr,'").eqs."" Then Define/NoLog/User ',"$shr Sys\$Share:$shr.$Config{'dlext'}",'
        Link $(LDFLAGS) /Shareable=$(MMS$TARGET)$(OTHERLDFLAGS) $(BASEEXT).opt/Option,$(PERL_INC)perlshr_attr.opt/Option
@@ -1231,13 +1078,13 @@ BOOTSTRAP = '."$self->{BASEEXT}.bs".'
 # As MakeMaker mkbootstrap might not write a file (if none is required)
 # we use touch to prevent make continually trying to remake it.
 # The DynaLoader only reads a non-empty file.
-$(BOOTSTRAP) : $(MAKEFILE) '."$self->{BOOTDEP}".' $(INST_ARCHAUTODIR).exists
-       $(NOECHO) $(SAY) "Running mkbootstrap for $(NAME) ($(BSLOADLIBS))"
+$(BOOTSTRAP) : $(FIRST_MAKEFILE) '."$self->{BOOTDEP}".' $(INST_ARCHAUTODIR)$(DIRFILESEP).exists
+       $(NOECHO) $(ECHO) "Running mkbootstrap for $(NAME) ($(BSLOADLIBS))"
        $(NOECHO) $(PERLRUN) -
        -e "use ExtUtils::Mkbootstrap; Mkbootstrap(\'$(BASEEXT)\',\'$(BSLOADLIBS)\');"
        $(NOECHO) $(TOUCH) $(MMS$TARGET)
 
-$(INST_BOOT) : $(BOOTSTRAP) $(INST_ARCHAUTODIR).exists
+$(INST_BOOT) : $(BOOTSTRAP) $(INST_ARCHAUTODIR)$(DIRFILESEP).exists
        $(NOECHO) $(RM_RF) $(INST_BOOT)
        - $(CP) $(BOOTSTRAP) $(INST_BOOT)
 ';
@@ -1261,7 +1108,7 @@ $(INST_STATIC) :
     my(@m,$lib);
     push @m,'
 # Rely on suffix rule for update action
-$(OBJECT) : $(INST_ARCHAUTODIR).exists
+$(OBJECT) : $(INST_ARCHAUTODIR)$(DIRFILESEP).exists
 
 $(INST_STATIC) : $(OBJECT) $(MYEXTLIB)
 ';
@@ -1289,56 +1136,6 @@ $(INST_STATIC) : $(OBJECT) $(MYEXTLIB)
 }
 
 
-=item manifypods (override)
-
-Use VMS-style quoting on command line, and VMS logical name
-to specify fallback location at build time if we can't find pod2man.
-
-=cut
-
-
-sub manifypods {
-    my($self, %attribs) = @_;
-    return "\nmanifypods :\n\t\$(NOECHO) \$(NOOP)\n" unless %{$self->{MAN3PODS}} or %{$self->{MAN1PODS}};
-    my($dist);
-    my($pod2man_exe);
-    if (defined $self->{PERL_SRC}) {
-       $pod2man_exe = File::Spec->catfile($self->{PERL_SRC},'pod','pod2man');
-    } else {
-       $pod2man_exe = File::Spec->catfile($Config{scriptdirexp},'pod2man');
-    }
-    if (not ($pod2man_exe = $self->perl_script($pod2man_exe))) {
-       # No pod2man but some MAN3PODS to be installed
-       print <<END;
-
-Warning: I could not locate your pod2man program.  As a last choice,
-         I will look for the file to which the logical name POD2MAN
-         points when MMK is invoked.
-
-END
-        $pod2man_exe = "pod2man";
-    }
-    my(@m);
-    push @m,
-qq[POD2MAN_EXE = $pod2man_exe\n],
-q[POD2MAN = $(PERLRUN) "-MPod::Man" -we "%m=@ARGV;for(keys %m){" -
--e "Pod::Man->new->parse_from_file($_,$m{$_}) }"
-];
-    push @m, "\nmanifypods : \$(MAN1PODS) \$(MAN3PODS)\n";
-    if (%{$self->{MAN1PODS}} || %{$self->{MAN3PODS}}) {
-       my($pod);
-       foreach $pod (sort keys %{$self->{MAN1PODS}}) {
-           push @m, qq[\t\@- If F\$Search("\$(POD2MAN_EXE)").nes."" Then \$(POD2MAN) ];
-           push @m, "$pod $self->{MAN1PODS}{$pod}\n";
-       }
-       foreach $pod (sort keys %{$self->{MAN3PODS}}) {
-           push @m, qq[\t\@- If F\$Search("\$(POD2MAN_EXE)").nes."" Then \$(POD2MAN) ];
-           push @m, "$pod $self->{MAN3PODS}{$pod}\n";
-       }
-    }
-    join('', @m);
-}
-
 =item processPL (override)
 
 Use VMS-style quoting on command line.
@@ -1380,7 +1177,7 @@ sub installbin {
     my($self) = @_;
     return '' unless $self->{EXE_FILES} && ref $self->{EXE_FILES} eq "ARRAY";
     return '' unless @{$self->{EXE_FILES}};
-    my(@m, $from, $to, %fromto, @to, $line);
+    my(@m, $from, $to, %fromto, @to);
     my(@exefiles) = map { vmsify($_) } @{$self->{EXE_FILES}};
     for $from (@exefiles) {
        my($path) = '$(INST_SCRIPT)' . basename($from);
@@ -1395,7 +1192,8 @@ EXE_FILES = @exefiles
 
 realclean ::
 ";
-    $line = '';  #avoid unitialized var warning
+
+    my $line = '';
     foreach $to (@to) {
        if (length($line) + length($to) > 80) {
            push @m, "\t\$(RM_F) $line\n";
@@ -1412,7 +1210,7 @@ realclean ::
        else                   { ($todir = $to) =~ s/[^\)]+$//; }
        $todir = $self->fixpath($todir,1);
        push @m, "
-$to : $from \$(MAKEFILE) ${todir}.exists
+$to : $from \$(FIRST_MAKEFILE) ${todir}\$(DIRFILESEP).exists
        \$(CP) $from $to
 
 ", $self->dir_target($todir);
@@ -1455,13 +1253,8 @@ sub clean {
     push @m, '
 # Delete temporary files but do not touch installed files. We don\'t delete
 # the Descrip.MMS here so that a later make realclean still has it to use.
-clean ::
+clean :: clean_subdirs
 ';
-    foreach $dir (@{$self->{DIR}}) { # clean subdirectories first
-       my($vmsdir) = $self->fixpath($dir,1);
-       push( @m, '     If F$Search("'.$vmsdir.'$(MAKEFILE)").nes."" Then \\',"\n\t",
-             '$(PERL) -e "chdir ',"'$vmsdir'",'; print `$(MMS)$(MMSQUALIFIERS) clean`;"',"\n");
-    }
     push @m, ' $(RM_F) *.Map *.Dmp *.Lis *.cpp *.$(DLEXT) *$(OBJ_EXT) *$(LIB_EXT) *.Opt $(BOOTSTRAP) $(BASEEXT).bso .MM_Tmp
 ';
 
@@ -1469,24 +1262,28 @@ clean ::
     # Unlink realclean, $attribs{FILES} is a string here; it may contain
     # a list or a macro that expands to a list.
     if ($attribs{FILES}) {
-       my($word,$key,@filist);
-       if (ref $attribs{FILES} eq 'ARRAY') { @filist = @{$attribs{FILES}}; }
-       else { @filist = split /\s+/, $attribs{FILES}; }
-       foreach $word (@filist) {
-           if (($key) = $word =~ m#^\$\((.*)\)$# and ref $self->{$key} eq 'ARRAY') {
-               push(@otherfiles, @{$self->{$key}});
+        my @filelist = ref $attribs{FILES} eq 'ARRAY'
+            ? @{$attribs{FILES}}
+            : split /\s+/, $attribs{FILES};
+
+       foreach my $word (@filelist) {
+           if ($word =~ m#^\$\((.*)\)$# and 
+                ref $self->{$1} eq 'ARRAY') 
+            {
+               push(@otherfiles, @{$self->{$1}});
            }
            else { push(@otherfiles, $word); }
        }
     }
-    push(@otherfiles, qw[ blib $(MAKE_APERL_FILE) extralibs.ld perlmain.c pm_to_blib.ts ]);
-    push(@otherfiles,File::Spec->catfile('$(INST_ARCHAUTODIR)','extralibs.all'));
-    my($file,$line);
-    $line = '';  #avoid unitialized var warning
+    push(@otherfiles, qw[ blib $(MAKE_APERL_FILE) extralibs.ld 
+                          perlmain.c pm_to_blib pm_to_blib.ts ]);
+    push(@otherfiles, $self->catfile('$(INST_ARCHAUTODIR)','extralibs.all'));
+
     # Occasionally files are repeated several times from different sources
-    { my(%of) = map { ($_,1) } @otherfiles; @otherfiles = keys %of; }
+    { my(%of) = map { ($_ => 1) } @otherfiles; @otherfiles = keys %of; }
     
-    foreach $file (@otherfiles) {
+    my $line = '';
+    foreach my $file (@otherfiles) {
        $file = $self->fixpath($file);
        if (length($line) + length($file) > 80) {
            push @m, "\t\$(RM_RF) $line\n";
@@ -1499,6 +1296,39 @@ clean ::
     join('', @m);
 }
 
+
+=item clean_subdirs_target
+
+  my $make_frag = $MM->clean_subdirs_target;
+
+VMS semantics for changing directories and rerunning make very different.
+
+=cut
+
+sub clean_subdirs_target {
+    my($self) = shift;
+
+    # No subdirectories, no cleaning.
+    return <<'NOOP_FRAG' unless @{$self->{DIR}};
+clean_subdirs :
+       $(NOECHO) $(NOOP)
+NOOP_FRAG
+
+
+    my $clean = "clean_subdirs :\n";
+
+    foreach my $dir (@{$self->{DIR}}) { # clean subdirectories first
+       $dir = $self->fixpath($dir,1);
+
+        $clean .= sprintf <<'MAKE_FRAG', $dir, $dir;
+       If F$Search("%s$(FIRST_MAKEFILE)").nes."" Then $(PERLRUN) -e "chdir '%s'; print `$(MMS)$(MMSQUALIFIERS) clean`;"
+MAKE_FRAG
+    }
+
+    return $clean;
+}
+
+
 =item realclean (override)
 
 Guess what we're working around?  Also, use MM[SK] for subdirectories.
@@ -1514,7 +1344,7 @@ realclean :: clean
 ');
     foreach(@{$self->{DIR}}){
        my($vmsdir) = $self->fixpath($_,1);
-       push(@m, '      If F$Search("'."$vmsdir".'$(MAKEFILE)").nes."" Then \\',"\n\t",
+       push(@m, '      If F$Search("'."$vmsdir".'$(FIRST_MAKEFILE)").nes."" Then \\',"\n\t",
              '$(PERL) -e "chdir ',"'$vmsdir'",'; print `$(MMS)$(MMSQUALIFIERS) realclean`;"',"\n");
     }
     push @m, " \$(RM_RF) \$(INST_AUTODIR) \$(INST_ARCHAUTODIR)\n";
@@ -1523,15 +1353,16 @@ realclean :: clean
     # corresponding %$self keys (i.e. they're defined in Descrip.MMS as a
     # combination of macros).  In order to stay below DCL's 255 char limit,
     # we put only 2 on a line.
-    my($file,$line,$fcnt);
-    my(@files) = qw{ $(MAKEFILE) $(MAKEFILE)_old };
+    my($file,$fcnt);
+    my(@files) = qw{ $(FIRST_MAKEFILE) $(MAKEFILE_OLD) };
     if ($self->has_link_code) {
        push(@files,qw{ $(INST_DYNAMIC) $(INST_STATIC) $(INST_BOOT) $(OBJECT) });
     }
-    push(@files, values %{$self->{PM}});
-    $line = '';  #avoid unitialized var warning
+
     # Occasionally files are repeated several times from different sources
     { my(%f) = map { ($_,1) } @files; @files = keys %f; }
+
+    my $line = '';
     foreach $file (@files) {
        $file = $self->fixpath($file);
        if (length($line) + length($file) > 80 || ++$fcnt >= 2) {
@@ -1569,32 +1400,32 @@ realclean :: clean
     join('', @m);
 }
 
+=item zipfile_target (o)
 
-=item dist_core (override)
+=item tarfile_target (o)
 
-Syntax for invoking F<VMS_Share> differs from that for Unix F<shar>,
-so C<shdist> target actions are VMS-specific.
+=item shdist_target (o)
 
-=cut
-
-sub dist_core {
-    my($self) = @_;
-q[
-dist : $(DIST_DEFAULT)
-       $(NOECHO) $(PERL) -le "print 'Warning: $m older than $vf' if -e ($vf = '$(VERSION_FROM)') && -M $vf < -M ($m = '$(MAKEFILE)')"
+Syntax for invoking shar, tar and zip differs from that for Unix.
 
-zipdist : $(DISTVNAME).zip
-       $(NOECHO) $(NOOP)
+=cut
 
-tardist : $(DISTVNAME).tar$(SUFFIX)
-       $(NOECHO) $(NOOP)
+sub zipfile_target {
+    my($self) = shift;
 
+    return <<'MAKE_FRAG';
 $(DISTVNAME).zip : distdir
        $(PREOP)
        $(ZIP) "$(ZIPFLAGS)" $(MMS$TARGET) [.$(DISTVNAME)...]*.*;
        $(RM_RF) $(DISTVNAME)
        $(POSTOP)
+MAKE_FRAG
+}
 
+sub tarfile_target {
+    my($self) = shift;
+
+    return <<'MAKE_FRAG';
 $(DISTVNAME).tar$(SUFFIX) : distdir
        $(PREOP)
        $(TO_UNIX)
@@ -1602,13 +1433,19 @@ $(DISTVNAME).tar$(SUFFIX) : distdir
        $(RM_RF) $(DISTVNAME)
        $(COMPRESS) $(DISTVNAME).tar
        $(POSTOP)
+MAKE_FRAG
+}
+
+sub shdist_target {
+    my($self) = shift;
 
+    return <<'MAKE_FRAG';
 shdist : distdir
        $(PREOP)
-       $(SHAR) [.$(DISTVNAME...]*.*; $(DISTVNAME).share
+       $(SHAR) [.$(DISTVNAME)...]*.*; $(DISTVNAME).share
        $(RM_RF) $(DISTVNAME)
        $(POSTOP)
-];
+MAKE_FRAG
 }
 
 =item dist_test (override)
@@ -1642,18 +1479,18 @@ VMS-style command line quoting in a few cases.
 
 sub install {
     my($self, %attribs) = @_;
-    my(@m,@docfiles);
+    my(@m,@exe_files);
 
     if ($self->{EXE_FILES}) {
        my($line,$file) = ('','');
        foreach $file (@{$self->{EXE_FILES}}) {
            $line .= "$file ";
            if (length($line) > 128) {
-               push(@docfiles,qq[\t\$(NOECHO) \$(PERL) -e "print '$line'" >>.MM_tmp\n]);
+               push(@exe_files,qq[\t\$(NOECHO) \$(ECHO) "$line" >>.MM_tmp\n]);
                $line = '';
            }
        }
-       push(@docfiles,qq[\t\$(NOECHO) \$(PERL) -e "print '$line'" >>.MM_tmp\n]) if $line;
+       push(@exe_files,qq[\t\$(NOECHO) \$(ECHO) "$line" >>.MM_tmp\n]) if $line;
     }
 
     push @m, q[
@@ -1670,77 +1507,82 @@ pure_install :: pure_$(INSTALLDIRS)_install
        $(NOECHO) $(NOOP)
 
 doc_install :: doc_$(INSTALLDIRS)_install
-       $(NOECHO) $(SAY) "Appending installation info to $(INSTALLARCHLIB)perllocal.pod"
+        $(NOECHO) $(NOOP)
 
 pure__install : pure_site_install
-       $(NOECHO) $(SAY) "INSTALLDIRS not defined, defaulting to INSTALLDIRS=site"
+       $(NOECHO) $(ECHO) "INSTALLDIRS not defined, defaulting to INSTALLDIRS=site"
 
 doc__install : doc_site_install
-       $(NOECHO) $(SAY) "INSTALLDIRS not defined, defaulting to INSTALLDIRS=site"
+       $(NOECHO) $(ECHO) "INSTALLDIRS not defined, defaulting to INSTALLDIRS=site"
 
 # This hack brought to you by DCL's 255-character command line limit
 pure_perl_install ::
        $(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'read '.File::Spec->catfile('$(PERL_ARCHLIB)','auto','$(FULLEXT)','.packlist').' '" >.MM_tmp
        $(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'write '.File::Spec->catfile('$(INSTALLARCHLIB)','auto','$(FULLEXT)','.packlist').' '" >>.MM_tmp
-       $(NOECHO) $(PERL) -e "print '$(INST_LIB) $(INSTALLPRIVLIB) '" >>.MM_tmp
-       $(NOECHO) $(PERL) -e "print '$(INST_ARCHLIB) $(INSTALLARCHLIB) '" >>.MM_tmp
-       $(NOECHO) $(PERL) -e "print '$(INST_BIN) $(INSTALLBIN) '" >>.MM_tmp
-       $(NOECHO) $(PERL) -e "print '$(INST_SCRIPT) $(INSTALLSCRIPT) '" >>.MM_tmp
-       $(NOECHO) $(PERL) -e "print '$(INST_MAN1DIR) $(INSTALLMAN1DIR) '" >>.MM_tmp
-       $(NOECHO) $(PERL) -e "print '$(INST_MAN3DIR) $(INSTALLMAN3DIR) '" >>.MM_tmp
-       $(MOD_INSTALL) <.MM_tmp
-       $(NOECHO) Delete/NoLog/NoConfirm .MM_tmp;
-       $(NOECHO) $(WARN_IF_OLD_PACKLIST) ].File::Spec->catfile($self->{SITEARCHEXP},'auto',$self->{FULLEXT},'.packlist').q[
+       $(NOECHO) $(ECHO) "$(INST_LIB) $(INSTALLPRIVLIB) " >>.MM_tmp
+       $(NOECHO) $(ECHO) "$(INST_ARCHLIB) $(INSTALLARCHLIB) " >>.MM_tmp
+       $(NOECHO) $(ECHO) "$(INST_BIN) $(INSTALLBIN) " >>.MM_tmp
+       $(NOECHO) $(ECHO) "$(INST_SCRIPT) $(INSTALLSCRIPT) " >>.MM_tmp
+       $(NOECHO) $(ECHO) "$(INST_MAN1DIR) $(INSTALLMAN1DIR) " >>.MM_tmp
+       $(NOECHO) $(ECHO) "$(INST_MAN3DIR) $(INSTALLMAN3DIR) " >>.MM_tmp
+       $(NOECHO) $(MOD_INSTALL) <.MM_tmp
+       $(NOECHO) $(RM_F) .MM_tmp
+       $(NOECHO) $(WARN_IF_OLD_PACKLIST) ].$self->catfile($self->{SITEARCHEXP},'auto',$self->{FULLEXT},'.packlist').q[
 
 # Likewise
 pure_site_install ::
        $(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'read '.File::Spec->catfile('$(SITEARCHEXP)','auto','$(FULLEXT)','.packlist').' '" >.MM_tmp
        $(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'write '.File::Spec->catfile('$(INSTALLSITEARCH)','auto','$(FULLEXT)','.packlist').' '" >>.MM_tmp
-       $(NOECHO) $(PERL) -e "print '$(INST_LIB) $(INSTALLSITELIB) '" >>.MM_tmp
-       $(NOECHO) $(PERL) -e "print '$(INST_ARCHLIB) $(INSTALLSITEARCH) '" >>.MM_tmp
-       $(NOECHO) $(PERL) -e "print '$(INST_BIN) $(INSTALLSITEBIN) '" >>.MM_tmp
-       $(NOECHO) $(PERL) -e "print '$(INST_SCRIPT) $(INSTALLSCRIPT) '" >>.MM_tmp
-       $(NOECHO) $(PERL) -e "print '$(INST_MAN1DIR) $(INSTALLSITEMAN1DIR) '" >>.MM_tmp
-       $(NOECHO) $(PERL) -e "print '$(INST_MAN3DIR) $(INSTALLSITEMAN3DIR) '" >>.MM_tmp
-       $(MOD_INSTALL) <.MM_tmp
-       $(NOECHO) Delete/NoLog/NoConfirm .MM_tmp;
-       $(NOECHO) $(WARN_IF_OLD_PACKLIST) ].File::Spec->catfile($self->{PERL_ARCHLIB},'auto',$self->{FULLEXT},'.packlist').q[
+       $(NOECHO) $(ECHO) "$(INST_LIB) $(INSTALLSITELIB) " >>.MM_tmp
+       $(NOECHO) $(ECHO) "$(INST_ARCHLIB) $(INSTALLSITEARCH) " >>.MM_tmp
+       $(NOECHO) $(ECHO) "$(INST_BIN) $(INSTALLSITEBIN) " >>.MM_tmp
+       $(NOECHO) $(ECHO) "$(INST_SCRIPT) $(INSTALLSCRIPT) " >>.MM_tmp
+       $(NOECHO) $(ECHO) "$(INST_MAN1DIR) $(INSTALLSITEMAN1DIR) " >>.MM_tmp
+       $(NOECHO) $(ECHO) "$(INST_MAN3DIR) $(INSTALLSITEMAN3DIR) " >>.MM_tmp
+       $(NOECHO) $(MOD_INSTALL) <.MM_tmp
+       $(NOECHO) $(RM_F) .MM_tmp
+       $(NOECHO) $(WARN_IF_OLD_PACKLIST) ].$self->catfile($self->{PERL_ARCHLIB},'auto',$self->{FULLEXT},'.packlist').q[
 
 pure_vendor_install ::
-       $(NOECHO) $(PERL) -e "print '$(INST_LIB) $(INSTALLVENDORLIB) '" >>.MM_tmp
-       $(NOECHO) $(PERL) -e "print '$(INST_ARCHLIB) $(INSTALLVENDORARCH) '" >>.MM_tmp
-       $(NOECHO) $(PERL) -e "print '$(INST_BIN) $(INSTALLVENDORBIN) '" >>.MM_tmp
-       $(NOECHO) $(PERL) -e "print '$(INST_SCRIPT) $(INSTALLSCRIPT) '" >>.MM_tmp
-       $(NOECHO) $(PERL) -e "print '$(INST_MAN1DIR) $(INSTALLVENDORMAN1DIR) '" >>.MM_tmp
-       $(NOECHO) $(PERL) -e "print '$(INST_MAN3DIR) $(INSTALLVENDORMAN3DIR) '" >>.MM_tmp
-       $(MOD_INSTALL) <.MM_tmp
-       $(NOECHO) Delete/NoLog/NoConfirm .MM_tmp;
+       $(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'read '.File::Spec->catfile('$(VENDORARCHEXP)','auto','$(FULLEXT)','.packlist').' '" >.MM_tmp
+       $(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'write '.File::Spec->catfile('$(INSTALLVENDORARCH)','auto','$(FULLEXT)','.packlist').' '" >>.MM_tmp
+       $(NOECHO) $(ECHO) "$(INST_LIB) $(INSTALLVENDORLIB) " >>.MM_tmp
+       $(NOECHO) $(ECHO) "$(INST_ARCHLIB) $(INSTALLVENDORARCH) " >>.MM_tmp
+       $(NOECHO) $(ECHO) "$(INST_BIN) $(INSTALLVENDORBIN) " >>.MM_tmp
+       $(NOECHO) $(ECHO) "$(INST_SCRIPT) $(INSTALLSCRIPT) " >>.MM_tmp
+       $(NOECHO) $(ECHO) "$(INST_MAN1DIR) $(INSTALLVENDORMAN1DIR) " >>.MM_tmp
+       $(NOECHO) $(ECHO) "$(INST_MAN3DIR) $(INSTALLVENDORMAN3DIR) " >>.MM_tmp
+       $(NOECHO) $(MOD_INSTALL) <.MM_tmp
+       $(NOECHO) $(RM_F) .MM_tmp
 
 # Ditto
 doc_perl_install ::
-       $(NOECHO) $(PERL) -e "print 'Module $(NAME)|installed into|$(INSTALLPRIVLIB)|'" >.MM_tmp
-       $(NOECHO) $(PERL) -e "print 'LINKTYPE|$(LINKTYPE)|VERSION|$(VERSION)|EXE_FILES|$(EXE_FILES)|'" >>.MM_tmp
-],@docfiles,
-q%     $(NOECHO) $(PERL) -e "print q[@ARGV=split(/\\|/,<STDIN>);]" >.MM2_tmp
-       $(NOECHO) $(PERL) -e "print q[print '=head2 ',scalar(localtime),': C<',shift,qq[>\\n\\n=over 4\\n\\n];]" >>.MM2_tmp
-       $(NOECHO) $(PERL) -e "print q[while(($key=shift) && ($val=shift)) ]" >>.MM2_tmp
-       $(NOECHO) $(PERL) -e "print q[{print qq[=item *\\n\\nC<$key: $val>\\n\\n];}print qq[=back\\n\\n];]" >>.MM2_tmp
-       $(NOECHO) $(PERL) .MM2_tmp <.MM_tmp >>%.File::Spec->catfile($self->{INSTALLARCHLIB},'perllocal.pod').q[
-       $(NOECHO) Delete/NoLog/NoConfirm .MM_tmp;,.MM2_tmp;
+       $(NOECHO) $(ECHO) "Appending installation info to ].$self->catfile($self->{INSTALLARCHLIB}, 'perllocal.pod').q["
+       $(NOECHO) $(MKPATH) $(INSTALLARCHLIB)
+       $(NOECHO) $(ECHO) "installed into|$(INSTALLPRIVLIB)|" >.MM_tmp
+       $(NOECHO) $(ECHO) "LINKTYPE|$(LINKTYPE)|VERSION|$(VERSION)|EXE_FILES|$(EXE_FILES) " >>.MM_tmp
+],@exe_files,
+q[     $(NOECHO) $(DOC_INSTALL) "Module" "$(NAME)" <.MM_tmp >>].$self->catfile($self->{INSTALLARCHLIB},'perllocal.pod').q[
+       $(NOECHO) $(RM_F) .MM_tmp
 
 # And again
 doc_site_install ::
-       $(NOECHO) $(PERL) -e "print 'Module $(NAME)|installed into|$(INSTALLSITELIB)|'" >.MM_tmp
-       $(NOECHO) $(PERL) -e "print 'LINKTYPE|$(LINKTYPE)|VERSION|$(VERSION)|EXE_FILES|$(EXE_FILES)|'" >>.MM_tmp
-],@docfiles,
-q%     $(NOECHO) $(PERL) -e "print q[@ARGV=split(/\\|/,<STDIN>);]" >.MM2_tmp
-       $(NOECHO) $(PERL) -e "print q[print '=head2 ',scalar(localtime),': C<',shift,qq[>\\n\\n=over 4\\n\\n];]" >>.MM2_tmp
-       $(NOECHO) $(PERL) -e "print q[while(($key=shift) && ($val=shift)) ]" >>.MM2_tmp
-       $(NOECHO) $(PERL) -e "print q[{print qq[=item *\\n\\nC<$key: $val>\\n\\n];}print qq[=back\\n\\n];]" >>.MM2_tmp
-       $(NOECHO) $(PERL) .MM2_tmp <.MM_tmp >>%.File::Spec->catfile($self->{INSTALLARCHLIB},'perllocal.pod').q[
-       $(NOECHO) Delete/NoLog/NoConfirm .MM_tmp;,.MM2_tmp;
+       $(NOECHO) $(ECHO) "Appending installation info to ].$self->catfile($self->{INSTALLSITEARCH}, 'perllocal.pod').q["
+       $(NOECHO) $(MKPATH) $(INSTALLSITEARCH)
+       $(NOECHO) $(ECHO) "installed into|$(INSTALLSITELIB)|" >.MM_tmp
+       $(NOECHO) $(ECHO) "LINKTYPE|$(LINKTYPE)|VERSION|$(VERSION)|EXE_FILES|$(EXE_FILES) " >>.MM_tmp
+],@exe_files,
+q[     $(NOECHO) $(DOC_INSTALL) "Module" "$(NAME)" <.MM_tmp >>].$self->catfile($self->{INSTALLSITEARCH},'perllocal.pod').q[
+       $(NOECHO) $(RM_F) .MM_tmp
 
 doc_vendor_install ::
+       $(NOECHO) $(ECHO) "Appending installation info to ].$self->catfile($self->{INSTALLVENDORARCH}, 'perllocal.pod').q["
+       $(NOECHO) $(MKPATH) $(INSTALLVENDORARCH)
+       $(NOECHO) $(ECHO) "installed into|$(INSTALLVENDORLIB)|" >.MM_tmp
+       $(NOECHO) $(ECHO) "LINKTYPE|$(LINKTYPE)|VERSION|$(VERSION)|EXE_FILES|$(EXE_FILES) " >>.MM_tmp
+],@exe_files,
+q[     $(NOECHO) $(DOC_INSTALL) "Module" "$(NAME)" <.MM_tmp >>].$self->catfile($self->{INSTALLVENDORARCH},'perllocal.pod').q[
+       $(NOECHO) $(RM_F) .MM_tmp
 
 ];
 
@@ -1749,16 +1591,16 @@ uninstall :: uninstall_from_$(INSTALLDIRS)dirs
        $(NOECHO) $(NOOP)
 
 uninstall_from_perldirs ::
-       $(NOECHO) $(UNINSTALL) ].File::Spec->catfile($self->{PERL_ARCHLIB},'auto',$self->{FULLEXT},'.packlist').q[
-       $(NOECHO) $(SAY) "Uninstall is now deprecated and makes no actual changes."
-       $(NOECHO) $(SAY) "Please check the list above carefully for errors, and manually remove"
-       $(NOECHO) $(SAY) "the appropriate files.  Sorry for the inconvenience."
+       $(NOECHO) $(UNINSTALL) ].$self->catfile($self->{PERL_ARCHLIB},'auto',$self->{FULLEXT},'.packlist').q[
+       $(NOECHO) $(ECHO) "Uninstall is now deprecated and makes no actual changes."
+       $(NOECHO) $(ECHO) "Please check the list above carefully for errors, and manually remove"
+       $(NOECHO) $(ECHO) "the appropriate files.  Sorry for the inconvenience."
 
 uninstall_from_sitedirs ::
-       $(NOECHO) $(UNINSTALL) ],File::Spec->catfile($self->{SITEARCHEXP},'auto',$self->{FULLEXT},'.packlist'),"\n",q[
-       $(NOECHO) $(SAY) "Uninstall is now deprecated and makes no actual changes."
-       $(NOECHO) $(SAY) "Please check the list above carefully for errors, and manually remove"
-       $(NOECHO) $(SAY) "the appropriate files.  Sorry for the inconvenience."
+       $(NOECHO) $(UNINSTALL) ],$self->catfile($self->{SITEARCHEXP},'auto',$self->{FULLEXT},'.packlist'),"\n",q[
+       $(NOECHO) $(ECHO) "Uninstall is now deprecated and makes no actual changes."
+       $(NOECHO) $(ECHO) "Please check the list above carefully for errors, and manually remove"
+       $(NOECHO) $(ECHO) "the appropriate files.  Sorry for the inconvenience."
 ];
 
     join('',@m);
@@ -1797,7 +1639,7 @@ $(OBJECT) : $(PERL_INC)util.h, $(PERL_INC)vmsish.h, $(PERL_INC)warnings.h
 
     if ($self->{PERL_SRC}) {
        my(@macros);
-       my($mmsquals) = '$(USEMAKEFILE)[.vms]$(MAKEFILE)';
+       my($mmsquals) = '$(USEMAKEFILE)[.vms]$(FIRST_MAKEFILE)';
        push(@macros,'__AXP__=1') if $Config{'archname'} eq 'VMS_AXP';
        push(@macros,'DECC=1')    if $Config{'vms_cc_type'} eq 'decc';
        push(@macros,'GNUC=1')    if $Config{'vms_cc_type'} eq 'gcc';
@@ -1851,15 +1693,15 @@ $(OBJECT) : $(FIRST_MAKEFILE)
 
     push @m,q[
 # We take a very conservative approach here, but it\'s worth it.
-# We move $(MAKEFILE) to $(MAKEFILE)_old here to avoid gnu make looping.
-$(MAKEFILE) : Makefile.PL $(CONFIGDEP)
-       $(NOECHO) $(SAY) "$(MAKEFILE) out-of-date with respect to $(MMS$SOURCE_LIST)"
-       $(NOECHO) $(SAY) "Cleaning current config before rebuilding $(MAKEFILE) ..."
-       - $(MV) $(MAKEFILE) $(MAKEFILE)_old
-       - $(MMS)$(MMSQUALIFIERS) $(USEMAKEFILE)$(MAKEFILE)_old clean
+# We move $(FIRST_MAKEFILE) to $(MAKEFILE_OLD) here to avoid gnu make looping.
+$(FIRST_MAKEFILE) : Makefile.PL $(CONFIGDEP)
+       $(NOECHO) $(ECHO) "$(FIRST_MAKEFILE) out-of-date with respect to $(MMS$SOURCE_LIST)"
+       $(NOECHO) $(ECHO) "Cleaning current config before rebuilding $(FIRST_MAKEFILE) ..."
+       - $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD)
+       - $(MMS)$(MMSQUALIFIERS) $(USEMAKEFILE)$(MAKEFILE_OLD) clean
        $(PERLRUN) Makefile.PL ],join(' ',map(qq["$_"],@ARGV)),q[
-       $(NOECHO) $(SAY) "$(MAKEFILE) has been rebuilt."
-       $(NOECHO) $(SAY) "Please run $(MMS) to build the extension."
+       $(NOECHO) $(ECHO) "$(FIRST_MAKEFILE) has been rebuilt."
+       $(NOECHO) $(ECHO) "Please run $(MMS) to build the extension."
 ];
 
     join('',@m);
@@ -1899,10 +1741,10 @@ testdb :: testdb_\$(LINKTYPE)
 ";
     foreach(@{$self->{DIR}}){
       my($vmsdir) = $self->fixpath($_,1);
-      push(@m, '       If F$Search("',$vmsdir,'$(MAKEFILE)").nes."" Then $(PERL) -e "chdir ',"'$vmsdir'",
+      push(@m, '       If F$Search("',$vmsdir,'$(FIRST_MAKEFILE)").nes."" Then $(PERL) -e "chdir ',"'$vmsdir'",
            '; print `$(MMS)$(MMSQUALIFIERS) $(PASTHRU2) test`'."\n");
     }
-    push(@m, "\t\$(NOECHO) \$(SAY) \"No tests defined for \$(NAME) extension.\"\n")
+    push(@m, "\t\$(NOECHO) \$(ECHO) \"No tests defined for \$(NAME) extension.\"\n")
         unless $tests or -f "test.pl" or @{$self->{DIR}};
     push(@m, "\n");
 
@@ -1949,7 +1791,7 @@ use vars qw(%olbs);
 
 sub makeaperl {
     my($self, %attribs) = @_;
-    my($makefilename, $searchdirs, $static, $extra, $perlinc, $target, $tmp, $libperl) = 
+    my($makefilename, $searchdirs, $static, $extra, $perlinc, $target, $tmpdir, $libperl) = 
       @attribs{qw(MAKE DIRS STAT EXTRA INCL TARGET TMP LIBPERL)};
     my(@m);
     push @m, "
@@ -1963,10 +1805,10 @@ MAP_TARGET    = $target
     unless ($self->{MAKEAPERL}) {
        push @m, q{
 $(MAKE_APERL_FILE) : $(FIRST_MAKEFILE)
-       $(NOECHO) $(SAY) "Writing ""$(MMS$TARGET)"" for this $(MAP_TARGET)"
+       $(NOECHO) $(ECHO) "Writing ""$(MMS$TARGET)"" for this $(MAP_TARGET)"
        $(NOECHO) $(PERLRUNINST) \
                Makefile.PL DIR=}, $dir, q{ \
-               MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \
+               FIRST_MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \
                MAKEAPERL=1 NORECURS=1 };
 
        push @m, map(q[ \\\n\t\t"$_"], @ARGV),q{
@@ -2091,23 +1933,23 @@ $(MAP_TARGET) :: $(MAKE_APERL_FILE)
     $shrtarget =~ s/^([^.]*)/$1Shr/;
     $shrtarget = $targdir . $shrtarget;
     $target = "Perlshr.$Config{'dlext'}" unless $target;
-    $tmp = "[]" unless $tmp;
-    $tmp = $self->fixpath($tmp,1);
+    $tmpdir = "[]" unless $tmpdir;
+    $tmpdir = $self->fixpath($tmpdir,1);
     if (@optlibs) { $extralist = join(' ',@optlibs); }
     else          { $extralist = ''; }
     # Let ExtUtils::Liblist find the necessary libs for us (but skip PerlShr)
     # that's what we're building here).
     push @optlibs, grep { !/PerlShr/i } split ' ', +($self->ext())[2];
     if ($libperl) {
-       unless (-f $libperl || -f ($libperl = File::Spec->catfile($Config{'installarchlib'},'CORE',$libperl))) {
+       unless (-f $libperl || -f ($libperl = $self->catfile($Config{'installarchlib'},'CORE',$libperl))) {
            print STDOUT "Warning: $libperl not found\n";
            undef $libperl;
        }
     }
     unless ($libperl) {
        if (defined $self->{PERL_SRC}) {
-           $libperl = File::Spec->catfile($self->{PERL_SRC},"libperl$self->{LIB_EXT}");
-       } elsif (-f ($libperl = File::Spec->catfile($Config{'installarchlib'},'CORE',"libperl$self->{LIB_EXT}")) ) {
+           $libperl = $self->catfile($self->{PERL_SRC},"libperl$self->{LIB_EXT}");
+       } elsif (-f ($libperl = $self->catfile($Config{'installarchlib'},'CORE',"libperl$self->{LIB_EXT}")) ) {
        } else {
            print STDOUT "Warning: $libperl not found
     If you're going to build a static perl binary, make sure perl is installed
@@ -2127,41 +1969,43 @@ MAP_LIBPERL = ",$self->fixpath($libperl,0),'
 ';
 
 
-    push @m,"\n${tmp}Makeaperl.Opt : \$(MAP_EXTRA)\n";
+    push @m,"\n${tmpdir}Makeaperl.Opt : \$(MAP_EXTRA)\n";
     foreach (@optlibs) {
        push @m,'       $(NOECHO) $(PERL) -e "print q{',$_,'}" >>$(MMS$TARGET)',"\n";
     }
-    push @m,"\n${tmp}PerlShr.Opt :\n\t";
+    push @m,"\n${tmpdir}PerlShr.Opt :\n\t";
     push @m,'$(NOECHO) $(PERL) -e "print q{$(MAP_SHRTARGET)}" >$(MMS$TARGET)',"\n";
 
-push @m,'
+    push @m,'
 $(MAP_SHRTARGET) : $(MAP_LIBPERL) Makeaperl.Opt ',"${libperldir}Perlshr_Attr.Opt",'
        $(MAP_LINKCMD)/Shareable=$(MMS$TARGET) $(MAP_LIBPERL), Makeaperl.Opt/Option ',"${libperldir}Perlshr_Attr.Opt/Option",'
-$(MAP_TARGET) : $(MAP_SHRTARGET) ',"${tmp}perlmain\$(OBJ_EXT) ${tmp}PerlShr.Opt",'
-       $(MAP_LINKCMD) ',"${tmp}perlmain\$(OBJ_EXT)",', PerlShr.Opt/Option
-       $(NOECHO) $(SAY) "To install the new ""$(MAP_TARGET)"" binary, say"
-       $(NOECHO) $(SAY) "    $(MMS)$(MMSQUALIFIERS)$(USEMAKEFILE)$(MAKEFILE) inst_perl $(USEMACROS)MAP_TARGET=$(MAP_TARGET)$(ENDMACRO)"
-       $(NOECHO) $(SAY) "To remove the intermediate files, say
-       $(NOECHO) $(SAY) "    $(MMS)$(MMSQUALIFIERS)$(USEMAKEFILE)$(MAKEFILE) map_clean"
+$(MAP_TARGET) : $(MAP_SHRTARGET) ',"${tmpdir}perlmain\$(OBJ_EXT) ${tmpdir}PerlShr.Opt",'
+       $(MAP_LINKCMD) ',"${tmpdir}perlmain\$(OBJ_EXT)",', PerlShr.Opt/Option
+       $(NOECHO) $(ECHO) "To install the new ""$(MAP_TARGET)"" binary, say"
+       $(NOECHO) $(ECHO) "    $(MMS)$(MMSQUALIFIERS)$(USEMAKEFILE)$(FIRST_MAKEFILE) inst_perl $(USEMACROS)MAP_TARGET=$(MAP_TARGET)$(ENDMACRO)"
+       $(NOECHO) $(ECHO) "To remove the intermediate files, say
+       $(NOECHO) $(ECHO) "    $(MMS)$(MMSQUALIFIERS)$(USEMAKEFILE)$(FIRST_MAKEFILE) map_clean"
 ';
-    push @m,"\n${tmp}perlmain.c : \$(MAKEFILE)\n\t\$(NOECHO) \$(PERL) -e 1 >${tmp}Writemain.tmp\n";
+    push @m,"\n${tmpdir}perlmain.c : \$(FIRST_MAKEFILE)\n\t\$(NOECHO) \$(PERL) -e 1 >${tmpdir}Writemain.tmp\n";
     push @m, "# More from the 255-char line length limit\n";
     foreach (@staticpkgs) {
-       push @m,'       $(NOECHO) $(PERL) -e "print q{',$_,qq[}" >>${tmp}Writemain.tmp\n];
+       push @m,'       $(NOECHO) $(PERL) -e "print q{',$_,qq[}" >>${tmpdir}Writemain.tmp\n];
     }
-       push @m,'
-       $(NOECHO) $(PERL) $(MAP_PERLINC) -ane "use ExtUtils::Miniperl; writemain(@F)" ',$tmp,'Writemain.tmp >$(MMS$TARGET)
-       $(NOECHO) $(RM_F) ',"${tmp}Writemain.tmp\n";
+
+    push @m, sprintf <<'MAKE_FRAG', $tmpdir, $tmpdir;
+       $(NOECHO) $(PERL) $(MAP_PERLINC) -ane "use ExtUtils::Miniperl; writemain(@F)" %sWritemain.tmp >$(MMS$TARGET)
+       $(NOECHO) $(RM_F) %sWritemain.tmp
+MAKE_FRAG
 
     push @m, q[
 # Still more from the 255-char line length limit
 doc_inst_perl :
-       $(NOECHO) $(PERL) -e "print 'Perl binary $(MAP_TARGET)|'" >.MM_tmp
-       $(NOECHO) $(PERL) -e "print 'MAP_STATIC|$(MAP_STATIC)|'" >>.MM_tmp
-       $(NOECHO) $(PERL) -pl040 -e " " ].File::Spec->catfile('$(INST_ARCHAUTODIR)','extralibs.all'),q[ >>.MM_tmp
-       $(NOECHO) $(PERL) -e "print 'MAP_LIBPERL|$(MAP_LIBPERL)|'" >>.MM_tmp
-       $(DOC_INSTALL) <.MM_tmp >>].File::Spec->catfile('$(INSTALLARCHLIB)','perllocal.pod').q[
-       $(NOECHO) Delete/NoLog/NoConfirm .MM_tmp;
+       $(NOECHO) $(ECHO) "Perl binary $(MAP_TARGET)|" >.MM_tmp
+       $(NOECHO) $(ECHO) "MAP_STATIC|$(MAP_STATIC)|" >>.MM_tmp
+       $(NOECHO) $(PERL) -pl040 -e " " ].$self->catfile('$(INST_ARCHAUTODIR)','extralibs.all'),q[ >>.MM_tmp
+       $(NOECHO) $(ECHO) -e "MAP_LIBPERL|$(MAP_LIBPERL)|" >>.MM_tmp
+       $(NOECHO) $(DOC_INSTALL) <.MM_tmp >>].$self->catfile('$(INSTALLARCHLIB)','perllocal.pod').q[
+       $(NOECHO) $(RM_F) .MM_tmp
 ];
 
     push @m, "
@@ -2176,8 +2020,8 @@ clean :: map_clean
        \$(NOECHO) \$(NOOP)
 
 map_clean :
-       \$(RM_F) ${tmp}perlmain\$(OBJ_EXT) ${tmp}perlmain.c \$(MAKEFILE)
-       \$(RM_F) ${tmp}Makeaperl.Opt ${tmp}PerlShr.Opt \$(MAP_TARGET)
+       \$(RM_F) ${tmpdir}perlmain\$(OBJ_EXT) ${tmpdir}perlmain.c \$(FIRST_MAKEFILE)
+       \$(RM_F) ${tmpdir}Makeaperl.Opt ${tmpdir}PerlShr.Opt \$(MAP_TARGET)
 ";
 
     join '', @m;
@@ -2219,6 +2063,11 @@ used instead.
 
 sub prefixify {
     my($self, $var, $sprefix, $rprefix, $default) = @_;
+
+    # Translate $(PERLPREFIX) to a real path.
+    $rprefix = $self->eliminate_macros($rprefix);
+    $rprefix = VMS::Filespec::vmspath($rprefix) if $rprefix;
+
     $default = VMS::Filespec::vmsify($default) 
       unless $default =~ /\[.*\]/;
 
@@ -2238,7 +2087,7 @@ sub prefixify {
         print STDERR "  prefixify $var => $path\n"     if $Verbose >= 2;
         print STDERR "    from $sprefix to $rprefix\n" if $Verbose >= 2;
 
-        my($path_vol, $path_dirs) = File::Spec->splitpath( $path );
+        my($path_vol, $path_dirs) = $self->splitpath( $path );
         if( $path_vol eq $Config{vms_prefix}.':' ) {
             print STDERR "  $Config{vms_prefix}: seen\n" if $Verbose >= 2;
 
@@ -2275,19 +2124,230 @@ sub _prefixify_default {
 sub _catprefix {
     my($self, $rprefix, $default) = @_;
 
-    my($rvol, $rdirs) = File::Spec->splitpath($rprefix);
+    my($rvol, $rdirs) = $self->splitpath($rprefix);
     if( $rvol ) {
-        return File::Spec->catpath($rvol,
-                                   File::Spec->catdir($rdirs, $default),
+        return $self->catpath($rvol,
+                                   $self->catdir($rdirs, $default),
                                    ''
                                   )
     }
     else {
-        return File::Spec->catdir($rdirs, $default);
+        return $self->catdir($rdirs, $default);
     }
 }
 
 
+=item oneliner (o)
+
+=cut
+
+sub oneliner {
+    my($self, $cmd, $switches) = @_;
+    $switches = [] unless defined $switches;
+
+    # Strip leading and trailing newlines
+    $cmd =~ s{^\n+}{};
+    $cmd =~ s{\n+$}{};
+
+    $cmd = $self->quote_literal($cmd);
+    $cmd = $self->escape_newlines($cmd);
+
+    # Switches must be quoted else they will be lowercased.
+    $switches = join ' ', map { qq{"$_"} } @$switches;
+
+    return qq{\$(PERLRUN) $switches -e $cmd};
+}
+
+
+=item B<echo> (o)
+
+perl trips up on "<foo>" thinking its an input redirect.  So we use the
+native Write sys$output instead.
+
+=cut
+
+sub echo {
+    my($self, $text, $file, $appending) = @_;
+    $appending ||= 0;
+
+    die "The VMS version of echo() cannot currently append" if $appending;
+
+    my @cmds = ("\$(NOECHO) Assign $file Sys\$Output");
+    push @cmds, map { '$(NOECHO) Write Sys$Output '.$self->quote_literal($_) } 
+                split /\n/, $text;
+    push @cmds, '$(NOECHO) Deassign Sys$Output';
+    return @cmds;
+}
+
+
+=item quote_literal
+
+=cut
+
+sub quote_literal {
+    my($self, $text) = @_;
+
+    # I believe this is all we should need.
+    $text =~ s{"}{""}g;
+
+    return qq{"$text"};
+}
+
+=item escape_newlines
+
+=cut
+
+sub escape_newlines {
+    my($self, $text) = @_;
+
+    $text =~ s{\n}{-\n}g;
+
+    return $text;
+}
+
+=item max_exec_len
+
+256 characters.
+
+=cut
+
+sub max_exec_len {
+    my $self = shift;
+
+    return $self->{_MAX_EXEC_LEN} ||= 256;
+}
+
+=item init_linker (o)
+
+=cut
+
+sub init_linker {
+    my $self = shift;
+    $self->{EXPORT_LIST} ||= '$(BASEEXT).opt';
+
+    my $shr = $Config{dbgprefix} . 'PERLSHR';
+    $self->{PERL_ARCHIVE} ||=  $ENV{$shr} ? $ENV{$shr} : "Sys\$Share:$shr.$Config{'dlext'}";
+
+    $self->{PERL_ARCHIVE_AFTER} ||= '';
+}
+
+=item eliminate_macros
+
+Expands MM[KS]/Make macros in a text string, using the contents of
+identically named elements of C<%$self>, and returns the result
+as a file specification in Unix syntax.
+
+NOTE:  This is the cannonical version of the method.  The version in
+File::Spec::VMS is deprecated.
+
+=cut
+
+sub eliminate_macros {
+    my($self,$path) = @_;
+    return '' unless $path;
+    $self = {} unless ref $self;
+
+    if ($path =~ /\s/) {
+      return join ' ', map { $self->eliminate_macros($_) } split /\s+/, $path;
+    }
+
+    my($npath) = unixify($path);
+    # sometimes unixify will return a string with an off-by-one trailing null
+    $npath =~ s{\0$}{};
+
+    my($complex) = 0;
+    my($head,$macro,$tail);
+
+    # perform m##g in scalar context so it acts as an iterator
+    while ($npath =~ m#(.*?)\$\((\S+?)\)(.*)#gs) { 
+        if (defined $self->{$2}) {
+            ($head,$macro,$tail) = ($1,$2,$3);
+            if (ref $self->{$macro}) {
+                if (ref $self->{$macro} eq 'ARRAY') {
+                    $macro = join ' ', @{$self->{$macro}};
+                }
+                else {
+                    print "Note: can't expand macro \$($macro) containing ",ref($self->{$macro}),
+                          "\n\t(using MMK-specific deferred substitutuon; MMS will break)\n";
+                    $macro = "\cB$macro\cB";
+                    $complex = 1;
+                }
+            }
+            else { ($macro = unixify($self->{$macro})) =~ s#/\Z(?!\n)##; }
+            $npath = "$head$macro$tail";
+        }
+    }
+    if ($complex) { $npath =~ s#\cB(.*?)\cB#\${$1}#gs; }
+    $npath;
+}
+
+=item fixpath
+
+Catchall routine to clean up problem MM[SK]/Make macros.  Expands macros
+in any directory specification, in order to avoid juxtaposing two
+VMS-syntax directories when MM[SK] is run.  Also expands expressions which
+are all macro, so that we can tell how long the expansion is, and avoid
+overrunning DCL's command buffer when MM[KS] is running.
+
+If optional second argument has a TRUE value, then the return string is
+a VMS-syntax directory specification, if it is FALSE, the return string
+is a VMS-syntax file specification, and if it is not specified, fixpath()
+checks to see whether it matches the name of a directory in the current
+default directory, and returns a directory or file specification accordingly.
+
+NOTE:  This is the cannonical version of the method.  The version in
+File::Spec::VMS is deprecated.
+
+=cut
+
+sub fixpath {
+    my($self,$path,$force_path) = @_;
+    return '' unless $path;
+    $self = bless {} unless ref $self;
+    my($fixedpath,$prefix,$name);
+
+    if ($path =~ /\s/) {
+      return join ' ',
+             map { $self->fixpath($_,$force_path) }
+            split /\s+/, $path;
+    }
+
+    if ($path =~ m#^\$\([^\)]+\)\Z(?!\n)#s || $path =~ m#[/:>\]]#) { 
+        if ($force_path or $path =~ /(?:DIR\)|\])\Z(?!\n)/) {
+            $fixedpath = vmspath($self->eliminate_macros($path));
+        }
+        else {
+            $fixedpath = vmsify($self->eliminate_macros($path));
+        }
+    }
+    elsif ((($prefix,$name) = ($path =~ m#^\$\(([^\)]+)\)(.+)#s)) && $self->{$prefix}) {
+        my($vmspre) = $self->eliminate_macros("\$($prefix)");
+        # is it a dir or just a name?
+        $vmspre = ($vmspre =~ m|/| or $prefix =~ /DIR\Z(?!\n)/) ? vmspath($vmspre) : '';
+        $fixedpath = ($vmspre ? $vmspre : $self->{$prefix}) . $name;
+        $fixedpath = vmspath($fixedpath) if $force_path;
+    }
+    else {
+        $fixedpath = $path;
+        $fixedpath = vmspath($fixedpath) if $force_path;
+    }
+    # No hints, so we try to guess
+    if (!defined($force_path) and $fixedpath !~ /[:>(.\]]/) {
+        $fixedpath = vmspath($fixedpath) if -d $fixedpath;
+    }
+
+    # Trim off root dirname if it's had other dirs inserted in front of it.
+    $fixedpath =~ s/\.000000([\]>])/$1/;
+    # Special case for VMS absolute directory specs: these will have had device
+    # prepended during trip through Unix syntax in eliminate_macros(), since
+    # Unix syntax has no way to express "absolute from the top of this device's
+    # directory tree".
+    if ($path =~ /^[\[>][^.\-]/) { $fixedpath =~ s/^[^\[<]+//; }
+
+    return $fixedpath;
+}
+
+
 =back
 
 =cut
index 03af82e..da1440f 100644 (file)
@@ -1,5 +1,7 @@
 package ExtUtils::MM_Win32;
 
+use strict;
+
 
 =head1 NAME
 
@@ -15,8 +17,6 @@ See ExtUtils::MM_Unix for a documentation of the methods provided
 there. This package overrides the implementation of these methods, not
 the semantics.
 
-=over 4
-
 =cut 
 
 use Config;
@@ -24,12 +24,12 @@ use File::Basename;
 use File::Spec;
 use ExtUtils::MakeMaker qw( neatvalue );
 
-use vars qw(@ISA $VERSION $BORLAND $GCC $DMAKE $NMAKE $PERLMAKE);
+use vars qw(@ISA $VERSION $BORLAND $GCC $DMAKE $NMAKE);
 
 require ExtUtils::MM_Any;
 require ExtUtils::MM_Unix;
 @ISA = qw( ExtUtils::MM_Any ExtUtils::MM_Unix );
-$VERSION = '1.05';
+$VERSION = '1.06';
 
 $ENV{EMXSHELL} = 'sh'; # to run `commands`
 
@@ -37,7 +37,15 @@ $BORLAND = 1 if $Config{'cc'} =~ /^bcc/i;
 $GCC     = 1 if $Config{'cc'} =~ /^gcc/i;
 $DMAKE = 1 if $Config{'make'} =~ /^dmake/i;
 $NMAKE = 1 if $Config{'make'} =~ /^nmake/i;
-$PERLMAKE = 1 if $Config{'make'} =~ /^pmake/i;
+
+
+=head2 Overridden methods
+
+=over 4
+
+=item B<dlsyms>
+
+=cut
 
 sub dlsyms {
     my($self,%attribs) = @_;
@@ -47,7 +55,6 @@ sub dlsyms {
     my($funclist) = $attribs{FUNCLIST} || $self->{FUNCLIST} || [];
     my($imports)  = $attribs{IMPORTS} || $self->{IMPORTS} || {};
     my(@m);
-    (my $boot = $self->{NAME}) =~ s/:/_/g;
 
     if (not $self->{SKIPHASH}{'dynamic'}) {
        push(@m,"
@@ -69,12 +76,30 @@ $self->{BASEEXT}.def: Makefile.PL
     join('',@m);
 }
 
+=item replace_manpage_separator
+
+Changes the path separator with .
+
+=cut
+
 sub replace_manpage_separator {
     my($self,$man) = @_;
     $man =~ s,/+,.,g;
     $man;
 }
 
+
+=item B<maybe_command>
+
+Since Windows has nothing as simple as an executable bit, we check the
+file extension.
+
+The PATHEXT env variable will be used to get a list of extensions that
+might indicate a command, otherwise .com, .exe, .bat and .cmd will be
+used by default.
+
+=cut
+
 sub maybe_command {
     my($self,$file) = @_;
     my @e = exists($ENV{'PATHEXT'})
@@ -96,313 +121,179 @@ sub maybe_command {
 }
 
 
-sub find_perl {
-    my($self, $ver, $names, $dirs, $trace) = @_;
-    $trace ||= 0;
+=item B<find_tests>
 
-    my($name, $dir);
-    if ($trace >= 2){
-       print "Looking for perl $ver by these names:
-@$names
-in these dirs:
-@$dirs
-";
-    }
-    foreach $dir (@$dirs){
-       next unless defined $dir; # $self->{PERL_SRC} may be undefined
-       foreach $name (@$names){
-           my ($abs, $val);
-           if (File::Spec->file_name_is_absolute($name)) {  # /foo/bar
-               $abs = $name;
-           } elsif (File::Spec->canonpath($name) eq 
-                     File::Spec->canonpath(basename($name))) # foo
-            {
-               $abs = File::Spec->catfile($dir, $name);
-           } else {                                         # foo/bar
-               $abs = File::Spec->canonpath(
-                           File::Spec->catfile(File::Spec->curdir, $name)
-                       );
-           }
-           print "Checking $abs\n" if ($trace >= 2);
-           next unless $self->maybe_command($abs);
-           print "Executing $abs\n" if ($trace >= 2);
-            (my($safe_abs) = $abs) =~ s{(\s)}{\\$1}g;
-           $val = `$safe_abs -e "require $ver;" 2>&1`;
-           if ($? == 0) {
-               print "Using PERL=$abs\n" if $trace;
-               return $abs;
-           } elsif ($trace >= 2) {
-               print "Result: `$val'\n";
-           }
-       }
-    }
-    print STDOUT "Unable to find a perl $ver (by these names: @$names, in these dirs: @$dirs)\n";
-    0; # false and not empty
-}
+The Win9x shell does not expand globs and I'll play it safe and assume
+other Windows variants don't either.
+
+So we do it for them.
 
+=cut
 
-# This code was taken out of MM_Unix to avoid loading File::Glob
-# unless necessary.
 sub find_tests {
     return join(' ', <t\\*.t>);
 }
 
 
-sub init_others
-{
- my ($self) = @_;
- $self->SUPER::init_others;
- $self->{'TOUCH'}  = '$(PERLRUN) -MExtUtils::Command -e touch';
- $self->{'CHMOD'}  = '$(PERLRUN) -MExtUtils::Command -e chmod'; 
- $self->{'CP'}     = '$(PERLRUN) -MExtUtils::Command -e cp';
- $self->{'RM_F'}   = '$(PERLRUN) -MExtUtils::Command -e rm_f';
- $self->{'RM_RF'}  = '$(PERLRUN) -MExtUtils::Command -e rm_rf';
- $self->{'MV'}     = '$(PERLRUN) -MExtUtils::Command -e mv';
- $self->{'NOOP'}   = 'rem';
- $self->{'TEST_F'} = '$(PERLRUN) -MExtUtils::Command -e test_f';
- $self->{'LD'}     = $Config{'ld'} || 'link';
- $self->{'AR'}     = $Config{'ar'} || 'lib';
- $self->{'LDLOADLIBS'} ||= $Config{'libs'};
- # -Lfoo must come first for Borland, so we put it in LDDLFLAGS
- if ($BORLAND) {
-     my $libs = $self->{'LDLOADLIBS'};
-     my $libpath = '';
-     while ($libs =~ s/(?:^|\s)(("?)-L.+?\2)(?:\s|$)/ /) {
-         $libpath .= ' ' if length $libpath;
-         $libpath .= $1;
-     }
-     $self->{'LDLOADLIBS'} = $libs;
-     $self->{'LDDLFLAGS'} ||= $Config{'lddlflags'};
-     $self->{'LDDLFLAGS'} .= " $libpath";
- }
- $self->{'DEV_NULL'} = '> NUL';
+=item B<init_DIRFILESEP>
+
+Using \ for Windows.
+
+=cut
+
+sub init_DIRFILESEP {
+    my($self) = shift;
+
+    # gotta be careful this isn't interpreted as an escape.
+    $self->{DIRFILESEP} = '^\\';
 }
 
+=item B<init_others>
+
+Override some of the Unix specific commands with portable
+ExtUtils::Command ones.
+
+Also provide defaults for LD and AR in case the %Config values aren't
+set.
 
-=item constants (o)
+LDLOADLIBS's default is changed to $Config{libs}.
 
-Initializes lots of constants and .SUFFIXES and .PHONY
+Adjustments are made for Borland's quirks needing -L to come first.
 
 =cut
 
-sub constants {
-    my($self) = @_;
-    my(@m,$tmp);
-
-    for $tmp (qw/
-             AR_STATIC_ARGS NAME DISTNAME NAME_SYM VERSION
-             VERSION_SYM XS_VERSION 
-          INST_BIN INST_LIB INST_ARCHLIB INST_SCRIPT 
-          INSTALLDIRS
-          PREFIX          SITEPREFIX      VENDORPREFIX
-             INSTALLPRIVLIB  INSTALLSITELIB  INSTALLVENDORLIB
-             INSTALLARCHLIB  INSTALLSITEARCH INSTALLVENDORARCH
-          INSTALLBIN      INSTALLSITEBIN  INSTALLVENDORBIN  INSTALLSCRIPT 
-          PERL_LIB        PERL_ARCHLIB 
-          SITELIBEXP      SITEARCHEXP 
-          LIBPERL_A MYEXTLIB
-             FIRST_MAKEFILE MAKE_APERL_FILE PERLMAINCC PERL_SRC
-             PERL_INC PERL FULLPERL PERLRUN FULLPERLRUN PERLRUNINST 
-          FULLPERLRUNINST ABSPERL ABSPERLRUN ABSPERLRUNINST
-          FULL_AR PERL_CORE
-
-             / ) {
-       next unless defined $self->{$tmp};
-       push @m, "$tmp = $self->{$tmp}\n";
+sub init_others {
+    my ($self) = @_;
+
+    # Used in favor of echo because echo won't strip quotes. :(
+    $self->{ECHO}     ||= '$(PERLRUN) -le "print qq{@ARGV}"';
+    $self->{TOUCH}    ||= '$(PERLRUN) -MExtUtils::Command -e touch';
+    $self->{CHMOD}    ||= '$(PERLRUN) -MExtUtils::Command -e chmod'; 
+    $self->{CP}       ||= '$(PERLRUN) -MExtUtils::Command -e cp';
+    $self->{RM_F}     ||= '$(PERLRUN) -MExtUtils::Command -e rm_f';
+    $self->{RM_RF}    ||= '$(PERLRUN) -MExtUtils::Command -e rm_rf';
+    $self->{MV}       ||= '$(PERLRUN) -MExtUtils::Command -e mv';
+    $self->{NOOP}     ||= 'rem';
+    $self->{TEST_F}   ||= '$(PERLRUN) -MExtUtils::Command -e test_f';
+    $self->{DEV_NULL} ||= '> NUL';
+
+    # technically speaking, these should be in init_main()
+    $self->{LD}     ||= $Config{ld} || 'link';
+    $self->{AR}     ||= $Config{ar} || 'lib';
+
+    $self->SUPER::init_others;
+
+    $self->{LDLOADLIBS} ||= $Config{libs};
+    # -Lfoo must come first for Borland, so we put it in LDDLFLAGS
+    if ($BORLAND) {
+        my $libs = $self->{LDLOADLIBS};
+        my $libpath = '';
+        while ($libs =~ s/(?:^|\s)(("?)-L.+?\2)(?:\s|$)/ /) {
+            $libpath .= ' ' if length $libpath;
+            $libpath .= $1;
+        }
+        $self->{LDLOADLIBS} = $libs;
+        $self->{LDDLFLAGS} ||= $Config{lddlflags};
+        $self->{LDDLFLAGS} .= " $libpath";
     }
 
-    push @m, qq{
-VERSION_MACRO = VERSION
-DEFINE_VERSION = -D\$(VERSION_MACRO)=\\\"\$(VERSION)\\\"
-XS_VERSION_MACRO = XS_VERSION
-XS_DEFINE_VERSION = -D\$(XS_VERSION_MACRO)=\\\"\$(XS_VERSION)\\\"
-};
+    return 1;
+}
 
-    push @m, qq{
-MAKEMAKER = $INC{'ExtUtils/MakeMaker.pm'}
-MM_VERSION = $ExtUtils::MakeMaker::VERSION
-};
 
-    push @m, q{
-# FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle).
-# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle)
-# PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar)
-# DLBASE  = Basename part of dynamic library. May be just equal BASEEXT.
-};
+=item init_platform (o)
 
-    for $tmp (qw/
-             FULLEXT BASEEXT PARENT_NAME DLBASE VERSION_FROM INC DEFINE OBJECT
-             LDFROM LINKTYPE
-             / ) {
-       next unless defined $self->{$tmp};
-       push @m, "$tmp = $self->{$tmp}\n";
-    }
+Add MM_Win32_VERSION.
 
-    push @m, "
-# Handy lists of source code files:
-XS_FILES= ".join(" \\\n\t", sort keys %{$self->{XS}})."
-C_FILES = ".join(" \\\n\t", @{$self->{C}})."
-O_FILES = ".join(" \\\n\t", @{$self->{O_FILES}})."
-H_FILES = ".join(" \\\n\t", @{$self->{H}})."
-MAN1PODS = ".join(" \\\n\t", sort keys %{$self->{MAN1PODS}})."
-MAN3PODS = ".join(" \\\n\t", sort keys %{$self->{MAN3PODS}})."
-";
-
-    for $tmp (qw/
-             INST_MAN1DIR  MAN1EXT 
-          INSTALLMAN1DIR INSTALLSITEMAN1DIR INSTALLVENDORMAN1DIR
-             INST_MAN3DIR  MAN3EXT
-          INSTALLMAN3DIR INSTALLSITEMAN3DIR INSTALLVENDORMAN3DIR
-             /) {
-       next unless defined $self->{$tmp};
-       push @m, "$tmp = $self->{$tmp}\n";
-    }
+=item platform_constants (o)
 
-    push @m, qq{
-.USESHELL :
-} if $DMAKE;
+=cut
 
-    push @m, q{
-.NO_CONFIG_REC: Makefile
-} if $ENV{CLEARCASE_ROOT};
+sub init_platform {
+    my($self) = shift;
 
-    # why not q{} ? -- emacs
-    push @m, qq{
-# work around a famous dec-osf make(1) feature(?):
-makemakerdflt: all
+    $self->{MM_Win32_VERSION} = $VERSION;
+}
 
-.SUFFIXES: .xs .c .C .cpp .cxx .cc \$(OBJ_EXT)
+sub platform_constants {
+    my($self) = shift;
+    my $make_frag = '';
 
-# Nick wanted to get rid of .PRECIOUS. I don't remember why. I seem to 
-# recall, that some make implementations will delete the Makefile when we 
-# rebuild it. Because we call false(1) when we rebuild it. So make(1) is 
-# not completely wrong when it does so. Our milage may vary.
-# .PRECIOUS: Makefile    # seems to be not necessary anymore
+    foreach my $macro (qw(MM_Win32_VERSION))
+    {
+        next unless defined $self->{$macro};
+        $make_frag .= "$macro = $self->{$macro}\n";
+    }
 
-.PHONY: all config static dynamic test linkext manifest
+    return $make_frag;
+}
 
-# Where is the Config information that we are using/depend on
-CONFIGDEP = \$(PERL_ARCHLIB)\\Config.pm \$(PERL_INC)\\config.h
-};
 
-    my @parentdir = split(/::/, $self->{PARENT_NAME});
-    push @m, q{
-# Where to put things:
-INST_LIBDIR      = }. File::Spec->catdir('$(INST_LIB)',@parentdir)        .q{
-INST_ARCHLIBDIR  = }. File::Spec->catdir('$(INST_ARCHLIB)',@parentdir)    .q{
+=item special_targets (o)
 
-INST_AUTODIR     = }. File::Spec->catdir('$(INST_LIB)','auto','$(FULLEXT)')       .q{
-INST_ARCHAUTODIR = }. File::Spec->catdir('$(INST_ARCHLIB)','auto','$(FULLEXT)')   .q{
-};
+Add .USESHELL target for dmake.
 
-    if ($self->has_link_code()) {
-       push @m, '
-INST_STATIC  = $(INST_ARCHAUTODIR)\$(BASEEXT)$(LIB_EXT)
-INST_DYNAMIC = $(INST_ARCHAUTODIR)\$(DLBASE).$(DLEXT)
-INST_BOOT    = $(INST_ARCHAUTODIR)\$(BASEEXT).bs
-';
-    } else {
-       push @m, '
-INST_STATIC  =
-INST_DYNAMIC =
-INST_BOOT    =
-';
-    }
+=cut
 
-    $tmp = $self->export_list;
-    push @m, "
-EXPORT_LIST = $tmp
-";
-    $tmp = $self->perl_archive;
-    push @m, "
-PERL_ARCHIVE = $tmp
-";
+sub special_targets {
+    my($self) = @_;
 
-    push @m, q{
-TO_INST_PM = }.join(" \\\n\t", sort keys %{$self->{PM}}).q{
+    my $make_frag = $self->SUPER::special_targets;
 
-PM_TO_BLIB = }.join(" \\\n\t", %{$self->{PM}}).q{
-};
+    $make_frag .= <<'MAKE_FRAG' if $DMAKE;
+.USESHELL :
+MAKE_FRAG
 
-    join('',@m);
+    return $make_frag;
 }
 
 
 =item static_lib (o)
 
-Defines how to produce the *.a (or equivalent) files.
+Changes how to run the linker.
+
+The rest is duplicate code from MM_Unix.  Should move the linker code
+to its own method.
 
 =cut
 
 sub static_lib {
     my($self) = @_;
-# Come to think of it, if there are subdirs with linkcode, we still have no INST_STATIC
-#    return '' unless $self->needs_linking(); #might be because of a subdir
-
     return '' unless $self->has_link_code;
 
     my(@m);
     push(@m, <<'END');
-$(INST_STATIC): $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)\.exists
+$(INST_STATIC): $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DIRFILESEP).exists
        $(RM_RF) $@
 END
+
     # If this extension has its own library (eg SDBM_File)
     # then copy that to $(INST_STATIC) and add $(OBJECT) into it.
-    push(@m, "\t$self->{CP} \$(MYEXTLIB) \$\@\n") if $self->{MYEXTLIB};
+    push @m, <<'MAKE_FRAG' if $self->{MYEXTLIB};
+       $(CP) $(MYEXTLIB) $@
+MAKE_FRAG
 
     push @m,
 q{     $(AR) }.($BORLAND ? '$@ $(OBJECT:^"+")'
                          : ($GCC ? '-ru $@ $(OBJECT)'
                                  : '-out:$@ $(OBJECT)')).q{
-       }.$self->{NOECHO}.q{echo "$(EXTRALIBS)" > $(INST_ARCHAUTODIR)\extralibs.ld
-       $(CHMOD) 755 $@
+       $(CHMOD) $(PERM_RWX) $@
+       $(NOECHO) $(ECHO) "$(EXTRALIBS)" > $(INST_ARCHAUTODIR)\extralibs.ld
 };
 
-# Old mechanism - still available:
+    # Old mechanism - still available:
+    push @m, <<'MAKE_FRAG' if $self->{PERL_SRC} && $self->{EXTRALIBS};
+       $(NOECHO) $(ECHO) "$(EXTRALIBS)" >> $(PERL_SRC)\ext.libs
+MAKE_FRAG
 
-    push @m, "\t$self->{NOECHO}".q{echo "$(EXTRALIBS)" >> $(PERL_SRC)\ext.libs}."\n\n"
-       if $self->{PERL_SRC};
-
-    push @m, $self->dir_target('$(INST_ARCHAUTODIR)');
-    join('', "\n",@m);
+    push @m, "\n", $self->dir_target('$(INST_ARCHAUTODIR)');
+    join('', @m);
 }
 
-=item dynamic_bs (o)
-
-Defines targets for bootstrap files.
-
-=cut
-
-sub dynamic_bs {
-    my($self, %attribs) = @_;
-    return '
-BOOTSTRAP =
-' unless $self->has_link_code();
-
-    return '
-BOOTSTRAP = '."$self->{BASEEXT}.bs".'
-
-# As Mkbootstrap might not write a file (if none is required)
-# we use touch to prevent make continually trying to remake it.
-# The DynaLoader only reads a non-empty file.
-$(BOOTSTRAP): '."$self->{MAKEFILE} $self->{BOOTDEP}".' $(INST_ARCHAUTODIR)\.exists
-       '.$self->{NOECHO}.'echo "Running Mkbootstrap for $(NAME) ($(BSLOADLIBS))"
-       '.$self->{NOECHO}.'$(PERLRUN) \
-               -MExtUtils::Mkbootstrap \
-               -e "Mkbootstrap(\'$(BASEEXT)\',\'$(BSLOADLIBS)\');"
-       '.$self->{NOECHO}.'$(TOUCH) $(BOOTSTRAP)
-       $(CHMOD) 644 $@
-
-$(INST_BOOT): $(BOOTSTRAP) $(INST_ARCHAUTODIR)\.exists
-       '."$self->{NOECHO}$self->{RM_RF}".' $(INST_BOOT)
-       -'.$self->{CP}.' $(BOOTSTRAP) $(INST_BOOT)
-       $(CHMOD) 644 $@
-';
-}
 
 =item dynamic_lib (o)
 
-Defines how to produce the *.so (or equivalent) files.
+Complicated stuff for Win32 that I don't understand. :(
 
 =cut
 
@@ -434,7 +325,7 @@ sub dynamic_lib {
 OTHERLDFLAGS = '.$otherldflags.'
 INST_DYNAMIC_DEP = '.$inst_dynamic_dep.'
 
-$(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)\.exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP)
+$(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)$(DIRFILESEP).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP)
 ');
     if ($GCC) {
       push(@m,  
@@ -456,13 +347,20 @@ $(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)\.exists
       .q{$(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) -def:$(EXPORT_LIST)});
     }
     push @m, '
-       $(CHMOD) 755 $@
+       $(CHMOD) $(PERM_RWX) $@
 ';
 
     push @m, $self->dir_target('$(INST_ARCHAUTODIR)');
     join('',@m);
 }
 
+=item clean
+
+Clean out some extra dll.{base,exp} files which might be generated by
+gcc.  Otherwise, take out all *.pdb files.
+
+=cut
+
 sub clean
 {
     my ($self) = shift;
@@ -476,309 +374,114 @@ END
     return $s;
 }
 
+=item init_linker
 
+=cut
 
-sub perl_archive
-{
-    my ($self) = @_;
-    return '$(PERL_INC)\\'.$Config{'libperl'};
-}
+sub init_linker {
+    my $self = shift;
 
-sub export_list
-{
- my ($self) = @_;
- return "$self->{BASEEXT}.def";
+    $self->{PERL_ARCHIVE}       = "\$(PERL_INC)\\$Config{libperl}";
+    $self->{PERL_ARCHIVE_AFTER} = '';
+    $self->{EXPORT_LIST}        = '$(BASEEXT).def';
 }
 
 
 =item perl_script
 
-Takes one argument, a file name, and returns the file name, if the
-argument is likely to be a perl script. On MM_Unix this is true for
-any ordinary, readable file.
+Checks for the perl program under several common perl extensions.
 
 =cut
 
 sub perl_script {
     my($self,$file) = @_;
     return $file if -r $file && -f _;
-    return "$file.pl" if -r "$file.pl" && -f _;
+    return "$file.pl"  if -r "$file.pl" && -f _;
+    return "$file.plx" if -r "$file.plx" && -f _;
     return "$file.bat" if -r "$file.bat" && -f _;
     return;
 }
 
-=item pm_to_blib
-
-Defines target that copies all files in the hash PM to their
-destination and autosplits them. See L<ExtUtils::Install/DESCRIPTION>
-
-=cut
-
-sub pm_to_blib {
-    my $self = shift;
-    my($autodir) = File::Spec->catdir('$(INST_LIB)','auto');
-    return q{
-pm_to_blib: $(TO_INST_PM)
-       }.$self->{NOECHO}.q{$(PERLRUNINST) -MExtUtils::Install \
-        -e "pm_to_blib(}.
-       ($NMAKE ? 'qw[ <<pmfiles.dat ],'
-               : $DMAKE ? 'qw[ $(mktmp,pmfiles.dat $(PM_TO_BLIB:s,\\,\\\\,)\n) ],'
-                        : '{ qw[$(PM_TO_BLIB)] },'
-        ).q{'}.$autodir.q{','$(PM_FILTER)')"
-}. ($NMAKE ? q{
-$(PM_TO_BLIB)
-<<
-       } : '') . "\t".$self->{NOECHO}.q{$(TOUCH) $@
-};
-}
-
 
-=item tool_autosplit (override)
+=item xs_o (o)
 
-Use Win32 quoting on command line.
+This target is stubbed out.  Not sure why.
 
 =cut
 
-sub tool_autosplit{
-    my($self, %attribs) = @_;
-    my($asl) = "";
-    $asl = "\$AutoSplit::Maxlen=$attribs{MAXLEN};" if $attribs{MAXLEN};
-    q{
-# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto
-AUTOSPLITFILE = $(PERLRUN) -MAutoSplit }.$asl.q{ -e "autosplit($$ARGV[0], $$ARGV[1], 0, 1, 1);"
-};
+sub xs_o {
+    return ''
 }
 
-=item tools_other (o)
 
-Win32 overrides.
+=item pasthru (o)
 
-Defines SHELL, LD, TOUCH, CP, MV, RM_F, RM_RF, CHMOD, UMASK_NULL in
-the Makefile. Also defines the perl programs MKPATH,
-WARN_IF_OLD_PACKLIST, MOD_INSTALL. DOC_INSTALL, and UNINSTALL.
+All we send is -nologo to nmake to prevent it from printing its damned
+banner.
 
 =cut
 
-sub tools_other {
+sub pasthru {
     my($self) = shift;
-    my @m;
-    my $bin_sh = $Config{sh} || 'cmd /c';
-    push @m, qq{
-SHELL = $bin_sh
-} unless $DMAKE;  # dmake determines its own shell 
-
-    for (qw/ CHMOD CP LD MV NOOP RM_F RM_RF TEST_F TOUCH UMASK_NULL DEV_NULL/ ) {
-       push @m, "$_ = $self->{$_}\n";
-    }
-
-    push @m, q{
-# The following is a portable way to say mkdir -p
-# To see which directories are created, change the if 0 to if 1
-MKPATH = $(PERLRUN) -MExtUtils::Command -e mkpath
-
-# This helps us to minimize the effect of the .exists files A yet
-# better solution would be to have a stable file in the perl
-# distribution with a timestamp of zero. But this solution doesn't
-# need any changes to the core distribution and works with older perls
-EQUALIZE_TIMESTAMP = $(PERLRUN) -MExtUtils::Command -e eqtime
-};
-
-
-    return join "", @m if $self->{PARENT};
-
-    push @m, q{
-# Here we warn users that an old packlist file was found somewhere,
-# and that they should call some uninstall routine
-WARN_IF_OLD_PACKLIST = $(PERL) -lwe "exit unless -f $$ARGV[0];" \\
--e "print 'WARNING: I have found an old package in';" \\
--e "print '    ', $$ARGV[0], '.';" \\
--e "print 'Please make sure the two installations are not conflicting';"
-
-UNINST=0
-VERBINST=1
-
-MOD_INSTALL = $(PERL) -I$(INST_LIB) -I$(PERL_LIB) -MExtUtils::Install \
--e "install({ @ARGV },'$(VERBINST)',0,'$(UNINST)');"
-
-DOC_INSTALL = $(PERL) -e "$$\=\"\n\n\";" \
--e "print '=head2 ', scalar(localtime), ': C<', shift, '>', ' L<', $$arg=shift, '|', $$arg, '>';" \
--e "print '=over 4';" \
--e "while (defined($$key = shift) and defined($$val = shift)) { print '=item *';print 'C<', \"$$key: $$val\", '>'; }" \
--e "print '=back';"
-
-UNINSTALL =   $(PERL) -MExtUtils::Install \
--e "uninstall($$ARGV[0],1,1); print \"\nUninstall is deprecated. Please check the";" \
--e "print \" packlist above carefully.\n  There may be errors. Remove the\";" \
--e "print \" appropriate files manually.\n  Sorry for the inconveniences.\n\""
-};
-
-    return join "", @m;
+    return "PASTHRU = " . ($NMAKE ? "-nologo" : "");
 }
 
-=item xs_o (o)
-
-Defines suffix rules to go from XS to object files directly. This is
-only intended for broken make implementations.
-
-=cut
-
-sub xs_o {     # many makes are too dumb to use xs_c then c_o
-    my($self) = shift;
-    return ''
-}
 
-=item top_targets (o)
+=item oneliner (o)
 
-Defines the targets all, subdirs, config, and O_FILES
+These are based on what command.com does on Win98.  They may be wrong
+for other Windows shells, I don't know.
 
 =cut
 
-sub top_targets {
-# --- Target Sections ---
-
-    my($self) = shift;
-    my(@m);
-
-    push @m, '
-all :: pure_all manifypods
-       '.$self->{NOECHO}.'$(NOOP)
-' 
-         unless $self->{SKIPHASH}{'all'};
-    
-    push @m, '
-pure_all :: config pm_to_blib subdirs linkext
-       '.$self->{NOECHO}.'$(NOOP)
-
-subdirs :: $(MYEXTLIB)
-       '.$self->{NOECHO}.'$(NOOP)
-
-config :: '.$self->{MAKEFILE}.' $(INST_LIBDIR)\.exists
-       '.$self->{NOECHO}.'$(NOOP)
+sub oneliner {
+    my($self, $cmd, $switches) = @_;
+    $switches = [] unless defined $switches;
 
-config :: $(INST_ARCHAUTODIR)\.exists
-       '.$self->{NOECHO}.'$(NOOP)
+    # Strip leading and trailing newlines
+    $cmd =~ s{^\n+}{};
+    $cmd =~ s{\n+$}{};
 
-config :: $(INST_AUTODIR)\.exists
-       '.$self->{NOECHO}.'$(NOOP)
-';
-
-    push @m, $self->dir_target(qw[$(INST_AUTODIR) $(INST_LIBDIR) $(INST_ARCHAUTODIR)]);
-
-    if (%{$self->{MAN1PODS}}) {
-       push @m, qq[
-config :: \$(INST_MAN1DIR)\\.exists
-       $self->{NOECHO}\$(NOOP)
-
-];
-       push @m, $self->dir_target(qw[$(INST_MAN1DIR)]);
-    }
-    if (%{$self->{MAN3PODS}}) {
-       push @m, qq[
-config :: \$(INST_MAN3DIR)\\.exists
-       $self->{NOECHO}\$(NOOP)
+    $cmd = $self->quote_literal($cmd);
+    $cmd = $self->escape_newlines($cmd);
 
-];
-       push @m, $self->dir_target(qw[$(INST_MAN3DIR)]);
-    }
-
-    push @m, '
-$(O_FILES): $(H_FILES)
-' if @{$self->{O_FILES} || []} && @{$self->{H} || []};
-
-    push @m, q{
-help:
-       perldoc ExtUtils::MakeMaker
-};
+    $switches = join ' ', @$switches;
 
-    join('',@m);
+    return qq{\$(PERLRUN) $switches -e $cmd};
 }
 
-=item manifypods (o)
 
-We don't want manpage process.
+sub quote_literal {
+    my($self, $text) = @_;
 
-=cut
+    # I don't know if this is correct, but it seems to work on
+    # Win98's command.com
+    $text =~ s{"}{\\"}g;
 
-sub manifypods {
-    my($self) = shift;
-    return "\nmanifypods :\n\t$self->{NOECHO}\$(NOOP)\n";
+    return qq{"$text"};
 }
 
-=item dist_ci (o)
 
-Same as MM_Unix version (changes command-line quoting).
+sub escape_newlines {
+    my($self, $text) = @_;
 
-=cut
+    # Escape newlines
+    $text =~ s{\n}{\\\n}g;
 
-sub dist_ci {
-    my($self) = shift;
-    my @m;
-    push @m, q{
-ci :
-       $(PERLRUN) -MExtUtils::Manifest=maniread \\
-               -e "@all = keys %{ maniread() };" \\
-               -e "print(\"Executing $(CI) @all\n\"); system(\"$(CI) @all\");" \\
-               -e "print(\"Executing $(RCS_LABEL) ...\n\"); system(\"$(RCS_LABEL) @all\");"
-};
-    join "", @m;
+    return $text;
 }
 
-=item dist_core (o)
 
-Same as MM_Unix version (changes command-line quoting).
+=item max_exec_len
 
-=cut
-
-sub dist_core {
-    my($self) = shift;
-    my @m;
-    push @m, q{
-dist : $(DIST_DEFAULT)
-       }.$self->{NOECHO}.q{$(PERL) -le "print \"Warning: Makefile possibly out of date with $$vf\" if " \
-           -e "-e ($$vf=\"$(VERSION_FROM)\") and -M $$vf < -M \"}.$self->{MAKEFILE}.q{\";"
-
-tardist : $(DISTVNAME).tar$(SUFFIX)
-
-zipdist : $(DISTVNAME).zip
-
-$(DISTVNAME).tar$(SUFFIX) : distdir
-       $(PREOP)
-       $(TO_UNIX)
-       $(TAR) $(TARFLAGS) $(DISTVNAME).tar $(DISTVNAME)
-       $(RM_RF) $(DISTVNAME)
-       $(COMPRESS) $(DISTVNAME).tar
-       $(POSTOP)
-
-$(DISTVNAME).zip : distdir
-       $(PREOP)
-       $(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME)
-       $(RM_RF) $(DISTVNAME)
-       $(POSTOP)
-
-uutardist : $(DISTVNAME).tar$(SUFFIX)
-       uuencode $(DISTVNAME).tar$(SUFFIX) \\
-               $(DISTVNAME).tar$(SUFFIX) > \\
-               $(DISTVNAME).tar$(SUFFIX)_uu
-
-shdist : distdir
-       $(PREOP)
-       $(SHAR) $(DISTVNAME) > $(DISTVNAME).shar
-       $(RM_RF) $(DISTVNAME)
-       $(POSTOP)
-};
-    join "", @m;
-}
-
-=item pasthru (o)
-
-Defines the string that is passed to recursive make calls in
-subdirectories.
+Using 31K, a safe number gotten from Windows 2000.
 
 =cut
 
-sub pasthru {
-    my($self) = shift;
-    return "PASTHRU = " . ($NMAKE ? "-nologo" : "");
+sub max_exec_len {
+    my $self = shift;
+
+    return $self->{_MAX_EXEC_LEN} ||= 31 * 1024;
 }
 
 
index 010900f..1854d5d 100644 (file)
@@ -5,7 +5,11 @@ $VERSION = 0.02;
 
 require ExtUtils::MM_Win32;
 @ISA = qw(ExtUtils::MM_Win32);
-use Config;
+
+use Config;\r
+my $DMAKE = 1 if $Config{'make'} =~ /^dmake/i;
+my $NMAKE = 1 if $Config{'make'} =~ /^nmake/i;
+
 
 =head1 NAME
 
@@ -20,6 +24,18 @@ ExtUtils::MM_Win95 - method to customize MakeMaker for Win9X
 This is a subclass of ExtUtils::MM_Win32 containing changes necessary
 to get MakeMaker playing nice with command.com and other Win9Xisms.
 
+=head2 Overriden methods
+
+Most of these make up for limitations in the Win9x command shell.
+Namely the lack of && and that a chdir is global, so you have to chdir
+back at the end.
+
+=over 4
+
+=item dist_test
+
+&& and chdir problem.
+
 =cut
 
 sub dist_test {
@@ -34,38 +50,174 @@ disttest : distdir
 };
 }
 
+=item subdir_x
+
+&& and chdir problem.
+
+Also, dmake has an odd way of making a command series silent.
+
+=cut
+
+sub subdir_x {
+    my($self, $subdir) = @_;
+
+    # Win-9x has nasty problem in command.com that can't cope with
+    # &&.  Also, Dmake has an odd way of making a commandseries silent:
+    if ($DMAKE) {
+      return sprintf <<'EOT', $subdir;
+
+subdirs ::
+@[
+       cd %s
+       $(MAKE) all $(PASTHRU)
+       cd ..
+]
+EOT
+    }
+    else {
+        return sprintf <<'EOT', $subdir;
+
+subdirs ::
+       $(NOECHO)cd %s
+       $(NOECHO)$(MAKE) all $(PASTHRU)
+       $(NOECHO)cd ..
+EOT
+    }
+}
+
+=item xs_c
+
+The && problem.
+
+=cut
+
 sub xs_c {
     my($self) = shift;
     return '' unless $self->needs_linking();
     '
 .xs.c:
-       $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) $(XSUBPP) \\
-           $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.c
+       $(PERLRUN) $(XSUBPP) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.c
        '
 }
 
+
+=item xs_cpp
+
+The && problem
+
+=cut
+
 sub xs_cpp {
     my($self) = shift;
     return '' unless $self->needs_linking();
     '
 .xs.cpp:
-       $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) $(XSUBPP) \\
-           $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.cpp
+       $(PERLRUN) $(XSUBPP) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.cpp
        ';
 }
 
-# many makes are too dumb to use xs_c then c_o
+=item xs_o 
+
+The && problem.
+
+=cut
+
 sub xs_o {
     my($self) = shift;
     return '' unless $self->needs_linking();
-    # having to choose between .xs -> .c -> .o and .xs -> .o confuses dmake
-    return '' if $Config{make} eq 'dmake';
     '
 .xs$(OBJ_EXT):
-       $(PERL) -I$(PERL_ARCHLIB) -I$(PERL_LIB) $(XSUBPP) \\
-           $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.c
+       $(PERLRUN) $(XSUBPP) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.c
        $(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(DEFINE) $*.c
        ';
 }
 
+=item clean_subdirs_target
+
+&& and chdir problem.
+
+=cut
+
+sub clean_subdirs_target {
+    my($self) = shift;
+
+    # No subdirectories, no cleaning.
+    return <<'NOOP_FRAG' unless @{$self->{DIR}};
+clean_subdirs :
+       $(NOECHO)$(NOOP)
+NOOP_FRAG
+
+
+    my $clean = "clean_subdirs :\n";
+
+    for my $dir (@{$self->{DIR}}) {
+        $clean .= sprintf <<'MAKE_FRAG', $dir;
+       cd %s
+       $(TEST_F) $(FIRST_MAKEFILE)
+       $(MAKE) clean
+       cd ..
+MAKE_FRAG
+    }
+
+    return $clean;
+}
+
+
+=item realclean_subdirs_target
+
+&& and chdir problem.
+
+=cut
+
+sub realclean_subdirs_target {
+    my $self = shift;
+
+    return <<'NOOP_FRAG' unless @{$self->{DIR}};
+realclean_subdirs :
+       $(NOECHO)$(NOOP)
+NOOP_FRAG
+
+    my $rclean = "realclean_subdirs :\n";
+
+    foreach my $dir (@{$self->{DIR}}){
+        $rclean .= sprintf <<'RCLEAN', $dir;
+       -cd %s
+       -$(PERLRUN) -e "exit unless -f shift; system q{$(MAKE) realclean}" $(FIRST_MAKEFILE)
+       -cd ..
+RCLEAN
+
+    }
+
+    return $rclean;
+}
+
+
+=item max_exec_len
+
+Setting to 2500, a value obtained by experimentation.
+
+=cut
+
+sub max_exec_len {
+    my $self = shift;
+
+    return $self->{_MAX_EXEC_LEN} ||= 2500;
+}
+
+=back
+
+
+=head1 AUTHOR
+
+Code originally inside MM_Win32.  Original author unknown.  
+
+Currently maintained by Michael G Schwern <schwern@pobox.com>.
+
+Send patches and ideas to <F<makemaker@perl.org>>.
+
+See http://www.makemaker.org.
+
+=cut
+
+
 1;
index 901bd13..87a388a 100644 (file)
@@ -57,109 +57,31 @@ sub WriteMakefile {
 # Basic signatures of the attributes WriteMakefile takes.  Each is the
 # reference type.  Empty value indicate it takes a non-reference
 # scalar.
-my %Att_Sigs =
-(
- ABSTRACT           => '',
- ABSTRACT_FROM      => '',
- AUTHOR             => '',
- BINARY_LOCATION    => '',
+my %Att_Sigs;
+my %Special_Sigs = (
  C                  => 'array',
- CCFLAGS            => '',
  CONFIG             => 'array',
  CONFIGURE          => 'code',
- DEFINE             => '',
  DIR                => 'array',
- DISTNAME           => '',
  DL_FUNCS           => 'hash',
  DL_VARS            => 'array',
  EXCLUDE_EXT        => 'array',
  EXE_FILES          => 'array',
- FIRST_MAKEFILE     => '',
- FULLPERL           => '',
- FULLPERLRUN        => '',
- FULLPERLRUNINST    => '',
  FUNCLIST           => 'array',
  H                  => 'array',
  IMPORTS            => 'hash',
- INC                => '',
  INCLUDE_EXT        => 'array',
- INSTALLARCHLIB     => '',
- INSTALLBIN         => '',
- INSTALLDIRS        => '',
- INSTALLMAN1DIR     => '',
- INSTALLMAN3DIR     => '',
- INSTALLPRIVLIB     => '',
- INSTALLSCRIPT      => '',
- INSTALLSITEARCH    => '',
- INSTALLSITEBIN     => '',
- INSTALLSITELIB     => '',
- INSTALLSITEMAN1DIR => '',
- INSTALLSITEMAN3DIR => '',
- INSTALLVENDORARCH  => '',
- INSTALLVENDORBIN   => '',
- INSTALLVENDORLIB   => '',
- INSTALLVENDORMAN1DIR   => '',
- INSTALLVENDORMAN3DIR   => '',
- INST_ARCHLIB       => '',
- INST_BIN           => '',
- INST_LIB           => '',
- INST_MAN1DIR       => '',
- INST_MAN3DIR       => '',
- INST_SCRIPT        => '',
- _KEEP_AFTER_FLUSH  => '',
- LDDLFLAGS          => '',
- LDFROM             => '',
- LIB                => '',
- LIBPERL_A          => '',
  LIBS               => ['array',''],
- LINKTYPE           => '',
- MAKEAPERL          => '',
- MAKEFILE           => '',
  MAN1PODS           => 'hash',
  MAN3PODS           => 'hash',
- MAP_TARGET         => '',
- MYEXTLIB           => '',
- NAME               => '',
- NEEDS_LINKING      => '',
- NOECHO             => '',
- NORECURS           => '',
- NO_VC              => '',
- OBJECT             => '',
- OPTIMIZE           => '',
- PERL               => '',
- PERL_CORE          => '',
- PERLMAINCC         => '',
- PERL_ARCHLIB       => '',
- PERL_LIB           => '',
- PERL_MALLOC_OK     => '',
- PERLRUN            => '',
- PERLRUNINST        => '',
- PERL_SRC           => '',
- PERM_RW            => '',
- PERM_RWX           => '',
  PL_FILES           => 'hash',
  PM                 => 'hash',
  PMLIBDIRS          => 'array',
- PM_FILTER          => '',
- POLLUTE            => '',
- PPM_INSTALL_EXEC   => '',
- PPM_INSTALL_SCRIPT => '',
- PREFIX             => '',
- PREREQ_FATAL       => '',
  PREREQ_PM          => 'hash',
- PREREQ_PRINT       => '',
- PRINT_PREREQ       => '',
- SITEPREFIX         => '',
  SKIP               => 'array',
  TYPEMAPS           => 'array',
- VENDORPREFIX       => '',
- VERBINST           => '',
- VERSION            => '',
- VERSION_FROM       => '',
  XS                 => 'hash',
- XSOPT              => '',
- XSPROTOARG         => '',
- XS_VERSION         => '',
+ _KEEP_AFTER_FLUSH  => '',
 
  clean      => 'hash',
  depend     => 'hash',
@@ -172,6 +94,9 @@ my %Att_Sigs =
  tool_autosplit => 'hash',
 );
 
+@Att_Sigs{keys %Recognized_Att_Keys} = ('') x keys %Recognized_Att_Keys;
+@Att_Sigs{keys %Special_Sigs} = values %Special_Sigs;
+
 
 sub _verify_att {
     my($att) = @_;
@@ -198,17 +123,24 @@ sub _verify_att {
 }
 
 sub prompt ($;$) {
-    my($mess,$def)=@_;
-    $ISA_TTY = -t STDIN && (-t STDOUT || !(-f STDOUT || -c STDOUT)) ;   # Pipe?
+    my($mess, $def) = @_;
     Carp::confess("prompt function called without an argument") 
         unless defined $mess;
+
+    my $isa_tty = -t STDIN && (-t STDOUT || !(-f STDOUT || -c STDOUT)) ;
+
     my $dispdef = defined $def ? "[$def] " : " ";
     $def = defined $def ? $def : "";
-    my $ans;
+
     local $|=1;
     local $\;
     print "$mess $dispdef";
-    if ($ISA_TTY && !$ENV{PERL_MM_USE_DEFAULT}) {
+
+    my $ans;
+    if ($ENV{PERL_MM_USE_DEFAULT} || (!$isa_tty && eof STDIN)) {
+        print "$def\n";
+    }
+    else {
         $ans = <STDIN>;
         if( defined $ans ) {
             chomp $ans;
@@ -217,9 +149,7 @@ sub prompt ($;$) {
             print "\n";
         }
     }
-    else {
-        print "$def\n";
-    }
+
     return (!defined $ans || $ans eq '') ? $def : $ans;
 }
 
@@ -256,22 +186,24 @@ sub eval_in_x {
     }
 }
 
+
+# package name for the classes into which the first object will be blessed
+my $PACKNAME = 'PACK000';
+
 sub full_setup {
     $Verbose ||= 0;
 
-    # package name for the classes into which the first object will be blessed
-    $PACKNAME = "PACK000";
-
     my @attrib_help = qw/
 
     AUTHOR ABSTRACT ABSTRACT_FROM BINARY_LOCATION
     C CAPI CCFLAGS CONFIG CONFIGURE DEFINE DIR DISTNAME DL_FUNCS DL_VARS
-    EXCLUDE_EXT EXE_FILES FIRST_MAKEFILE 
+    EXCLUDE_EXT EXE_FILES FIRST_MAKEFILE
     FULLPERL FULLPERLRUN FULLPERLRUNINST
     FUNCLIST H IMPORTS
     INST_ARCHLIB INST_SCRIPT INST_BIN INST_LIB INST_MAN1DIR INST_MAN3DIR
     INSTALLDIRS
-    PREFIX          SITEPREFIX      VENDORPREFIX
+    DESTDIR PREFIX
+    PERLPREFIX      SITEPREFIX      VENDORPREFIX
     INSTALLPRIVLIB  INSTALLSITELIB  INSTALLVENDORLIB
     INSTALLARCHLIB  INSTALLSITEARCH INSTALLVENDORARCH
     INSTALLBIN      INSTALLSITEBIN  INSTALLVENDORBIN
@@ -282,7 +214,8 @@ sub full_setup {
     PERL_LIB        PERL_ARCHLIB 
     SITELIBEXP      SITEARCHEXP 
     INC INCLUDE_EXT LDFROM LIB LIBPERL_A LIBS
-    LINKTYPE MAKEAPERL MAKEFILE MAN1PODS MAN3PODS MAP_TARGET MYEXTLIB
+    LINKTYPE MAKEAPERL MAKEFILE_OLD MAN1PODS MAN3PODS MAP_TARGET 
+    MYEXTLIB
     PERL_MALLOC_OK
     NAME NEEDS_LINKING NOECHO NORECURS NO_VC OBJECT OPTIMIZE PERL PERLMAINCC
     PERLRUN PERLRUNINST PERL_CORE
@@ -310,16 +243,24 @@ sub full_setup {
     @MM_Sections = 
         qw(
 
- post_initialize const_config constants tool_autosplit tool_xsubpp
- tools_other dist macro depend cflags const_loadlibs const_cccmd
+ post_initialize const_config constants platform_constants 
+ tool_autosplit tool_xsubpp tools_other 
+
+ makemakerdflt
+
+ dist macro depend cflags const_loadlibs const_cccmd
  post_constants
 
  pasthru
 
- c_o xs_c xs_o top_targets linkext dlsyms dynamic dynamic_bs
+ special_targets
+ c_o xs_c xs_o
+ top_targets linkext dlsyms dynamic dynamic_bs
  dynamic_lib static static_lib manifypods processPL
  installbin subdirs
- clean realclean dist_basics dist_core dist_dir dist_test dist_ci
+ clean_subdirs clean realclean_subdirs realclean 
+ metafile metafile_addtomanifest
+ dist_basics dist_core distdir dist_test dist_ci
  install force perldepend makefile staticmake test ppd
 
           ); # loses section ordering
@@ -352,6 +293,9 @@ sub full_setup {
            exe_ext full_ar
           );
 
+    # 5.5.3 doesn't have any concept of vendor libs
+    push @Get_from_Config, qw( vendorarchexp vendorlibexp ) if $] >= 5.006;
+
     foreach my $item (@attrib_help){
         $Recognized_Att_Keys{$item} = 1;
     }
@@ -371,11 +315,6 @@ sub full_setup {
            MAP_TARGET INST_MAN1DIR INST_MAN3DIR PERL_SRC
            PERL FULLPERL
     );
-
-    my @keep = qw/
-        NEEDS_LINKING HAS_LINK_CODE
-        /;
-    @Keep_after_flush{@keep} = (1) x @keep;
 }
 
 sub writeMakefile {
@@ -402,6 +341,11 @@ sub new {
     my($class,$self) = @_;
     my($key);
 
+    # Store the original args passed to WriteMakefile()
+    foreach my $k (keys %$self) {
+        $self->{ARGS}{$k} = $self->{$k};
+    }
+
     if ("@ARGV" =~ /\bPREREQ_PRINT\b/) {
         require Data::Dumper;
         print Data::Dumper->Dump([$self->{PREREQ_PM}], [qw(PREREQ_PM)]);
@@ -427,10 +371,15 @@ sub new {
 
     my(%unsatisfied) = ();
     foreach my $prereq (sort keys %{$self->{PREREQ_PM}}) {
-        eval "require $prereq";
+        # 5.8.0 has a bug with require Foo::Bar alone in an eval, so an
+        # extra statement is a workaround.
+        eval "require $prereq; 0";
 
         my $pr_version = $prereq->VERSION || 0;
 
+        # convert X.Y_Z alpha version #s to X.YZ for easier comparisons
+        $pr_version =~ s/(\d+)\.(\d+)_(\d+)/$1.$2$3/;
+
         if ($@) {
             warn sprintf "Warning: prerequisite %s %s not found.\n", 
               $prereq, $self->{PREREQ_PM}{$prereq} 
@@ -484,7 +433,7 @@ sub new {
         for $key (@Prepend_parent) {
             next unless defined $self->{PARENT}{$key};
             $self->{$key} = $self->{PARENT}{$key};
-            unless ($^O eq 'VMS' && $key =~ /PERL$/) {
+            unless ($Is_VMS && $key =~ /PERL$/) {
                 $self->{$key} = $self->catdir("..",$self->{$key})
                   unless $self->file_name_is_absolute($self->{$key});
             } else {
@@ -520,7 +469,16 @@ sub new {
 
     ($self->{NAME_SYM} = $self->{NAME}) =~ s/\W+/_/g;
 
-    $self->init_main();
+    $self->init_main;
+    $self->init_VERSION;
+    $self->init_dist;
+    $self->init_INST;
+    $self->init_INSTALL;
+    $self->init_dirscan;
+    $self->init_xs;
+    $self->init_PERL;
+    $self->init_DIRFILESEP;
+    $self->init_linker;
 
     if (! $self->{PERL_SRC} ) {
         require VMS::Filespec if $Is_VMS;
@@ -547,8 +505,8 @@ END
         }
     }
 
-    $self->init_dirscan();
     $self->init_others();
+    $self->init_platform();
     $self->init_PERM();
     my($argv) = neatvalue(\@ARGV);
     $argv =~ s/^\[/(/;
@@ -569,6 +527,8 @@ END
 END
 
     foreach my $key (sort keys %initial_att){
+        next if $key eq 'ARGS';
+
         my($v) = neatvalue($initial_att{$key});
         $v =~ s/(CODE|HASH|ARRAY|SCALAR)\([\dxa-f]+\)/$1\(...\)/;
         $v =~ tr/\n/ /s;
@@ -583,6 +543,7 @@ END
 END
         if (scalar(keys %configure_att) > 0) {
             foreach my $key (sort keys %configure_att){
+               next if $key eq 'ARGS';
                my($v) = neatvalue($configure_att{$key});
                $v =~ s/(CODE|HASH|ARRAY|SCALAR)\([\dxa-f]+\)/$1\(...\)/;
                $v =~ tr/\n/ /s;
@@ -604,7 +565,7 @@ END
     delete $self->{SKIP}; # free memory
 
     if ($self->{PARENT}) {
-        for (qw/install dist dist_basics dist_core dist_dir dist_test dist_ci/) {
+        for (qw/install dist dist_basics dist_core distdir dist_test dist_ci/) {
             $self->{SKIPHASH}{$_} = 1;
         }
     }
@@ -616,6 +577,10 @@ END
     }
 
     foreach my $section ( @MM_Sections ){
+        # Support for new foo_target() methods.
+        my $method = $section;
+        $method .= '_target' unless $self->can($method);
+
         print "Processing Makefile '$section' section\n" if ($Verbose >= 2);
         my($skipit) = $self->skipcheck($section);
         if ($skipit){
@@ -624,7 +589,7 @@ END
             my(%a) = %{$self->{$section} || {}};
             push @{$self->{RESULT}}, "\n# --- MakeMaker $section section:";
             push @{$self->{RESULT}}, "# " . join ", ", %a if $Verbose && %a;
-            push @{$self->{RESULT}}, $self->nicetext($self->$section( %a ));
+            push @{$self->{RESULT}}, $self->nicetext($self->$method( %a ));
         }
     }
 
@@ -638,13 +603,14 @@ sub WriteEmptyMakefile {
 
     my %att = @_;
     my $self = MM->new(\%att);
-    if (-f "$self->{MAKEFILE}.old") {
-      chmod 0666, "$self->{MAKEFILE}.old";
-      unlink "$self->{MAKEFILE}.old" or warn "unlink $self->{MAKEFILE}.old: $!";
+    if (-f $self->{MAKEFILE_OLD}) {
+      chmod 0666, $self->{MAKEFILE_OLD};
+      unlink $self->{MAKEFILE_OLD} or warn "unlink $self->{MAKEFILE_OLD}: $!";
+    }
+    if ( -f $self->{MAKEFILE} ) {
+        _rename($self->{MAKEFILE}, $self->{MAKEFILE_OLD})
+          or warn "rename $self->{MAKEFILE} => $self->{MAKEFILE_OLD}: $!"
     }
-    rename $self->{MAKEFILE}, "$self->{MAKEFILE}.old"
-      or warn "rename $self->{MAKEFILE} $self->{MAKEFILE}.old: $!"
-        if -f $self->{MAKEFILE};
     open MF, '>'.$self->{MAKEFILE} or die "open $self->{MAKEFILE} for write: $!";
     print MF <<'EOP';
 all:
@@ -693,7 +659,9 @@ sub parse_args{
                  (getpwuid($>))[7]
                  ]ex;
         }
-        $self->{uc($name)} = $value;
+
+        # Remember the original args passed it.  It will be useful later.
+        $self->{ARGS}{uc $name} = $self->{uc $name} = $value;
     }
 
     # catch old-style 'potential_libs' and inform user how to 'upgrade'
@@ -738,6 +706,7 @@ sub parse_args{
     }
 
     foreach my $mmkey (sort keys %$self){
+        next if $mmkey eq 'ARGS';
         print STDOUT "  $mmkey => ", neatvalue($self->{$mmkey}), "\n" if $Verbose;
         print STDOUT "'$mmkey' is not a known MakeMaker parameter name.\n"
             unless exists $Recognized_Att_Keys{$mmkey};
@@ -749,7 +718,11 @@ sub check_hints {
     my($self) = @_;
     # We allow extension-specific hints files.
 
-    return unless -d "hints";
+    require File::Spec;
+    my $curdir = File::Spec->curdir;
+
+    my $hint_dir = File::Spec->catdir($curdir, "hints");
+    return unless -d $hint_dir;
 
     # First we look for the best hintsfile we have
     my($hint)="${^O}_$Config{osvers}";
@@ -759,11 +732,11 @@ sub check_hints {
 
     # Also try without trailing minor version numbers.
     while (1) {
-        last if -f "hints/$hint.pl";      # found
+        last if -f File::Spec->catfile($hint_dir, "$hint.pl");  # found
     } continue {
         last unless $hint =~ s/_[^_]*$//; # nothing to cut off
     }
-    my $hint_file = "hints/$hint.pl";
+    my $hint_file = File::Spec->catfile($hint_dir, "$hint.pl");
 
     return unless -f $hint_file;    # really there
 
@@ -775,11 +748,16 @@ sub _run_hintfile {
     local($self) = shift;       # make $self available to the hint file.
     my($hint_file) = shift;
 
-    local $@;
+    local($@, $!);
     print STDERR "Processing hints file $hint_file\n";
-    my $ret = do "./$hint_file";
-    unless( defined $ret ) {
-        print STDERR $@ if $@;
+
+    # Just in case the ./ isn't on the hint file, which File::Spec can
+    # often strip off, we bung the curdir into @INC
+    local @INC = (File::Spec->curdir, @INC);
+    my $ret = do $hint_file;
+    if( !defined $ret ) {
+        my $error = $@ || $!;
+        print STDERR $error;
     }
 }
 
@@ -883,18 +861,31 @@ sub flush {
 
     close FH;
     my($finalname) = $self->{MAKEFILE};
-    rename("MakeMaker.tmp", $finalname);
+    _rename("MakeMaker.tmp", $finalname) or
+      warn "rename MakeMaker.tmp => $finalname: $!";
     chmod 0644, $finalname unless $Is_VMS;
 
+    my %keep = map { ($_ => 1) } qw(NEEDS_LINKING HAS_LINK_CODE);
+
     if ($self->{PARENT} && !$self->{_KEEP_AFTER_FLUSH}) {
         foreach (keys %$self) { # safe memory
-            delete $self->{$_} unless $Keep_after_flush{$_};
+            delete $self->{$_} unless $keep{$_};
         }
     }
 
     system("$Config::Config{eunicefix} $finalname") unless $Config::Config{eunicefix} eq ":";
 }
 
+
+# This is a rename for OS's where the target must be unlinked first.
+sub _rename {
+    my($src, $dest) = @_;
+    chmod 0666, $dest;
+    unlink $dest;
+    return rename $src, $dest;
+}
+
+
 # The following mkbootstrap() is only for installations that are calling
 # the pre-4.1 mkbootstrap() from their old Makefiles. This MakeMaker
 # writes Makefiles, that use ExtUtils::Mkbootstrap directly.
@@ -961,7 +952,7 @@ __END__
 
 =head1 NAME
 
-ExtUtils::MakeMaker - create an extension Makefile
+ExtUtils::MakeMaker - Create a module Makefile
 
 =head1 SYNOPSIS
 
@@ -986,24 +977,7 @@ Makefiles with a single invocation of WriteMakefile().
 
 =head2 How To Write A Makefile.PL
 
-The short answer is: Don't.
-
-        Always begin with h2xs.
-        Always begin with h2xs!
-        ALWAYS BEGIN WITH H2XS!
-
-even if you're not building around a header file, and even if you
-don't have an XS component.
-
-Run h2xs(1) before you start thinking about writing a module. For so
-called pm-only modules that consist of C<*.pm> files only, h2xs has
-the C<-X> switch. This will generate dummy files of all kinds that are
-useful for the module developer.
-
-The medium answer is:
-
-    use ExtUtils::MakeMaker;
-    WriteMakefile( NAME => "Foo::Bar" );
+See ExtUtils::MakeMaker::Tutorial.
 
 The long answer is the rest of the manpage :-)
 
@@ -1077,7 +1051,7 @@ INSTALLDIRS according to the following table:
                                  INSTALLDIRS set to
                            perl        site          vendor
 
-                 PREFIX          SITEPREFIX          VENDORPREFIX
+                 PERLPREFIX      SITEPREFIX          VENDORPREFIX
   INST_ARCHLIB   INSTALLARCHLIB  INSTALLSITEARCH     INSTALLVENDORARCH
   INST_LIB       INSTALLPRIVLIB  INSTALLSITELIB      INSTALLVENDORLIB
   INST_BIN       INSTALLBIN      INSTALLSITEBIN      INSTALLVENDORBIN
@@ -1357,6 +1331,17 @@ be determined by some evaluation method.
 
 Something like C<"-DHAVE_UNISTD_H">
 
+=item DESTDIR
+
+This is the root directory into which the code will be installed.  It
+I<prepends itself to the normal prefix>.  For example, if your code
+would normally go into /usr/local/lib/perl you could set DESTDIR=/tmp
+and installation would go into /tmp/usr/local/lib/perl.
+
+This is primarily of use for people who repackage Perl modules.
+
+From the GNU Makefile conventions.
+
 =item DIR
 
 Ref to array of subdirectories containing Makefile.PLs e.g. [ 'sdbm'
@@ -1364,8 +1349,24 @@ Ref to array of subdirectories containing Makefile.PLs e.g. [ 'sdbm'
 
 =item DISTNAME
 
-Your name for distributing the package (by tar file). This defaults to
-NAME above.
+A safe filename for the package. 
+
+Defaults to NAME above but with :: replaced with -.
+
+For example, Foo::Bar becomes Foo-Bar.
+
+=item DISTVNAME
+
+Your name for distributing the package with the version number
+included.  This is used by 'make dist' to name the resulting archive
+file.
+
+Defaults to DISTNAME-VERSION.
+
+For example, version 1.04 of Foo::Bar becomes Foo-Bar-1.04.
+
+On some OS's where . has special meaning VERSION_SYM may be used in
+place of VERSION.
 
 =item DL_FUNCS
 
@@ -1409,9 +1410,13 @@ again.
 
 =item FIRST_MAKEFILE
 
-The name of the Makefile to be produced. Defaults to the contents of
-MAKEFILE, but can be overridden. This is used for the second Makefile
-that will be produced for the MAP_TARGET.
+The name of the Makefile to be produced.  This is used for the second
+Makefile that will be produced for the MAP_TARGET.
+
+Defaults to 'Makefile' or 'Descrip.MMS' on VMS.
+
+(Note: we couldn't use MAKEFILE because dmake uses this for something
+else).
 
 =item FULLPERL
 
@@ -1576,6 +1581,12 @@ Directory, where executable files should be installed during
 testing. make install will copy the files in INST_SCRIPT to
 INSTALLSCRIPT.
 
+=item LD
+
+Program to be used to link libraries for dynamic loading.
+
+Defaults to $Config{ld}.
+
 =item LDDLFLAGS
 
 Any special flags that might need to be passed to ld to create a
@@ -1636,9 +1647,12 @@ Boolean which tells MakeMaker, that it should include the rules to
 make a perl. This is handled automatically as a switch by
 MakeMaker. The user normally does not need it.
 
-=item MAKEFILE
+=item MAKEFILE_OLD
+
+When 'make clean' or similar is run, the $(FIRST_MAKEFILE) will be
+backed up at this location.
 
-The name of the Makefile to be produced.
+Defaults to $(FIRST_MAKEFILE).old or $(FIRST_MAKEFILE)_old on VMS.
 
 =item MAN1PODS
 
@@ -1680,9 +1694,12 @@ this boolean variable yourself.
 
 =item NOECHO
 
-Defaults to C<@>. By setting it to an empty string you can generate a
-Makefile that echos all commands. Mainly used in debugging MakeMaker
-itself.
+Command so make does not print the literal commands its running.
+
+By setting it to an empty string you can generate a Makefile that
+prints all commands. Mainly used in debugging MakeMaker itself.
+
+Defaults to C<@>.
 
 =item NORECURS
 
@@ -1766,6 +1783,16 @@ nullifies many advantages of Perl's malloc(), such as better usage of
 system resources, error detection, memory usage reporting, catchable failure
 of memory allocations, etc.
 
+=item PERLPREFIX
+
+Directory under which core modules are to be installed.
+
+Defaults to $Config{installprefixexp} falling back to
+$Config{installprefix}, $Config{prefixexp} or $Config{prefix} should
+$Config{installprefixexp} not exist.
+
+Overridden by PREFIX.
+
 =item PERLRUN
 
 Use this instead of $(PERL) when you wish to run perl.  It will set up
@@ -1882,8 +1909,6 @@ which should be sensible for your platform.
 If you specify LIB or any INSTALL* variables they will not be effected
 by the PREFIX.
 
-Defaults to $Config{installprefixexp}.
-
 =item PREREQ_FATAL
 
 Bool. If this parameter is true, failing to have the required modules
@@ -1924,11 +1949,13 @@ RedHatism for C<PREREQ_PRINT>.  The output format is different, though:
 
 =item SITEPREFIX
 
-Like PREFIX, but only for the site install locations.
+Like PERLPREFIX, but only for the site install locations.
+
+Defaults to $Config{siteprefixexp}.  Perls prior to 5.6.0 didn't have
+an explicit siteprefix in the Config.  In those cases
+$Config{installprefix} will be used.
 
-Defaults to PREFIX (if set) or $Config{siteprefixexp}.  Perls prior to
-5.6.0 didn't have an explicit siteprefix in the Config.  In those
-cases $Config{installprefix} will be used.
+Overridable by PREFIX
 
 =item SKIP
 
@@ -1948,9 +1975,11 @@ typemap has lowest precedence.
 
 =item VENDORPREFIX
 
-Like PREFIX, but only for the vendor install locations.
+Like PERLPREFIX, but only for the vendor install locations.
+
+Defaults to $Config{vendorprefixexp}.
 
-Defaults to PREFIX (if set) or $Config{vendorprefixexp}
+Overridable by PREFIX
 
 =item VERBINST
 
@@ -2001,6 +2030,11 @@ would have to do something like
 
 See attribute C<depend> below.
 
+=item VERSION_SYM
+
+A sanitized VERSION with . replaced by _.  For places where . has
+special meaning (some filesystems, RCS labels, etc...)
+
 =item XS
 
 Hashref of .xs files. MakeMaker will default this.  e.g.
@@ -2293,9 +2327,33 @@ in a subdirectory of some other distribution, or is listed as a
 dependency in a CPAN::Bundle, but the functionality is supported by
 different means on the current architecture).
 
+=head2 Other Handy Functions
+
+=over 4
+
+=item prompt
+
+    my $value = prompt($message);
+    my $value = prompt($message, $default);
+
+The C<prompt()> function provides an easy way to request user input
+used to write a makefile.  It displays the $message as a prompt for
+input.  If a $default is provided it will be used as a default.  The
+function returns the $value selected by the user.
+
+If C<prompt()> detects that it is not running interactively and there
+is nothing on STDIN or if the PERL_MM_USE_DEFAULT environment variable
+is set to true, the $default will be used without prompting.  This
+prevents automated processes from blocking on user input. 
+
+If no $default is provided an empty string will be used instead.
+
+=back
+
+
 =head1 ENVIRONMENT
 
-=over 8
+=over 4
 
 =item PERL_MM_OPT
 
@@ -2331,4 +2389,12 @@ generated Makefile along with your report.
 
 For more up-to-date information, see http://www.makemaker.org.
 
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or 
+modify it under the same terms as Perl itself.
+
+See F<http://www.perl.com/perl/misc/Artistic.html>
+
+
 =cut
diff --git a/lib/ExtUtils/MakeMaker/FAQ.pod b/lib/ExtUtils/MakeMaker/FAQ.pod
new file mode 100644 (file)
index 0000000..6d7ba70
--- /dev/null
@@ -0,0 +1,199 @@
+package ExtUtils::MakeMaker::FAQ;
+
+our $VERSION = '0.02';
+
+1;
+__END__
+
+=head1 NAME
+
+ExtUtils::MakeMaker::FAQ - Frequently Asked Questions About MakeMaker
+
+=head1 DESCRIPTION
+
+FAQs, tricks and tips for C<ExtUtils::MakeMaker>.
+
+=head2 Philosophy and History
+
+=over 4
+
+=item Why not just use <insert other build config tool here>?
+
+Why did MakeMaker reinvent the build configuration wheel?  Why not
+just use autoconf or automake or ppm or Ant or ...
+
+There are many reasons, but the major one is cross-platform
+compatibility.
+
+Perl is one of the most ported pieces of software ever.  It works on
+operating systems I've never even heard of (see perlport for details).
+It needs a build tool that can work on all those platforms and with
+any wacky C compilers they might have.
+
+No such build tool existed at the time and I only know of one now
+(Module::Build).
+
+
+=item What's Module::Build and how does it relate to MakeMaker?
+
+Module::Build is a project by Ken Williams to supplant MakeMaker.
+Its primary advantages are:
+
+=over 8
+
+=item * pure perl.  no make, no shell commands
+
+=item * easier to customize
+
+=item * cleaner internals
+
+=item * less cruft
+
+=back
+
+Module::Build is the official heir apparent to MakeMaker and we
+encourage people to work on M::B rather than spending time improving
+MakeMaker.
+
+=back
+
+=head2 XS
+
+=over 4
+
+=item How do I make two or more XS files coexist in the same directory?
+
+Sometimes you need to have two and more XS files in the same package.
+One way to go is to put them into separate directories, but sometimes
+this is not the most suitable solution. The following technique allows
+you to put two (and more) XS files in the same directory.
+
+Let's assume that we have a package C<Cool::Foo>, which includes
+C<Cool::Foo> and C<Cool::Bar> modules each having a separate XS
+file. First we use the following I<Makefile.PL>:
+
+  use ExtUtils::MakeMaker;
+
+  WriteMakefile(
+      NAME             => 'Cool::Foo',
+      VERSION_FROM     => 'Foo.pm',
+      OBJECT              => q/$(O_FILES)/,
+      # ... other attrs ...
+  );
+
+Notice the C<OBJECT> attribute. MakeMaker generates the following
+variables in I<Makefile>:
+
+  # Handy lists of source code files:
+  XS_FILES= Bar.xs \
+       Foo.xs
+  C_FILES = Bar.c \
+       Foo.c
+  O_FILES = Bar.o \
+       Foo.o
+
+Therefore we can use the C<O_FILES> variable to tell MakeMaker to use
+these objects into the shared library.
+
+That's pretty much it. Now write I<Foo.pm> and I<Foo.xs>, I<Bar.pm>
+and I<Bar.xs>, where I<Foo.pm> bootstraps the shared library and
+I<Bar.pm> simply loading I<Foo.pm>.
+
+The only issue left is to how to bootstrap I<Bar.xs>. This is done
+from I<Foo.xs>:
+
+  MODULE = Cool::Foo PACKAGE = Cool::Foo
+
+  BOOT:
+  # boot the second XS file
+  boot_Cool__Bar(aTHX_ cv);
+
+If you have more than two files, this is the place where you should
+boot extra XS files from.
+
+The following four files sum up all the details discussed so far.
+
+  Foo.pm:
+  -------
+  package Cool::Foo;
+
+  require DynaLoader;
+
+  our @ISA = qw(DynaLoader);
+  our $VERSION = '0.01';
+  bootstrap Cool::Foo $VERSION;
+
+  1;
+
+  Bar.pm:
+  -------
+  package Cool::Bar;
+
+  use Cool::Foo; # bootstraps Bar.xs
+
+  1;
+
+  Foo.xs:
+  -------
+  #include "EXTERN.h"
+  #include "perl.h"
+  #include "XSUB.h"
+
+  MODULE = Cool::Foo  PACKAGE = Cool::Foo
+
+  BOOT:
+  # boot the second XS file
+  boot_Cool__Bar(aTHX_ cv);
+
+  MODULE = Cool::Foo  PACKAGE = Cool::Foo  PREFIX = cool_foo_
+
+  void
+  cool_foo_perl_rules()
+
+      CODE:
+      fprintf(stderr, "Cool::Foo says: Perl Rules\n");
+
+  Bar.xs:
+  -------
+  #include "EXTERN.h"
+  #include "perl.h"
+  #include "XSUB.h"
+
+  MODULE = Cool::Bar  PACKAGE = Cool::Bar PREFIX = cool_bar_
+
+  void
+  cool_bar_perl_rules()
+
+      CODE:
+      fprintf(stderr, "Cool::Bar says: Perl Rules\n");
+
+And of course a very basic test:
+
+  test.pl:
+  --------
+  use Test;
+  BEGIN { plan tests => 1 };
+  use Cool::Foo;
+  use Cool::Bar;
+  Cool::Foo::perl_rules();
+  Cool::Bar::perl_rules();
+  ok 1;
+
+This tip has been brought to you by Nick Ing-Simmons and Stas Bekman.
+
+=back
+
+=head1 PATCHING
+
+If you have a question you'd like to see added to the FAQ (whether or
+not you have the answer) please send it to makemaker@perl.org.
+
+=head1 AUTHOR
+
+The denizens of makemaker@perl.org.
+
+=head1 SEE ALSO
+
+L<ExtUtils::MakeMaker>
+
+=cut
diff --git a/lib/ExtUtils/MakeMaker/Tutorial.pod b/lib/ExtUtils/MakeMaker/Tutorial.pod
new file mode 100644 (file)
index 0000000..bbc794a
--- /dev/null
@@ -0,0 +1,124 @@
+package ExtUtils::MakeMaker::Tutorial;
+
+use vars qw($VERSION);
+$VERSION = 0.01;
+
+
+=head1 NAME
+
+ExtUtils::MakeMaker::Tutorial - Writing a module with MakeMaker
+
+=head1 SYNOPSIS
+
+    use ExtUtils::MakeMaker;
+
+    WriteMakefile(
+        NAME            => 'Your::Module',
+        VERSION_FROM    => 'lib/Your/Module.pm'
+    );
+
+=head1 DESCRIPTION
+
+This is a short tutorial on writing a simple module with MakeMaker.
+
+=head2 The Mantra
+
+MakeMaker modules are installed using this simple mantra
+
+        perl Makefile.PL
+        make
+        make test
+        make install
+
+There are lots more commands and options, but the above will do it.
+
+=head2 The Layout
+
+The basic layout of a module looks something like this.
+
+        Makefile.PL
+        MANIFEST
+        lib/Your/Module.pm
+
+That's all that's strictly necessary.  There's additional files you might
+want to add:
+
+        lib/Your/Other/Module.pm
+        t/some_test.t
+        t/some_other_test.t
+        Changes
+        README
+        INSTALL
+        MANIFEST.SKIP
+        bin/some_program
+
+=over 4
+
+=item Makefile.PL
+
+When you run Makefile.PL, it makes a Makefile.  That's the whole point of
+MakeMaker.  The Makefile.PL is a simple module which loads
+ExtUtils::MakeMaker and runs the WriteMakefile() function with a few
+simple arguments.
+
+Here's an example of what you need for a simple module:
+
+    use ExtUtils::MakeMaker;
+
+    WriteMakefile(
+        NAME            => 'Your::Module',
+        VERSION_FROM    => 'lib/Your/Module.pm'
+    );
+
+NAME is the top-level namespace of your module.  VERSION_FROM is the file
+which contains the $VERSION variable for the entire distribution.  Typically
+this is the same as your top-level module.
+
+
+=item MANIFEST
+
+A simple listing of all the files in your distribution.
+
+        Makefile.PL
+        MANIFEST
+        lib/Your/Module.pm
+
+
+=item lib/
+
+This is the directory where your .pm files go.  They are layed out
+according to namespace.  So Foo::Bar is lib/Foo/Bar.pm.
+
+
+=item t/
+
+Tests for your modules go here.  Each test filename ends with a .t.
+So t/foo.t.  'make test' will run these tests.  The directory is flat,
+you cannot, for example, have t/foo/bar.t run by 'make test'.
+
+
+=item Changes
+
+A log of changes you've made to this module.
+
+
+=item README
+
+=item INSTALL
+
+=item MANIFEST.SKIP
+
+=item bin/
+
+=back
+
+=head1 SEE ALSO
+
+L<perlmodstyle> gives stylistic help writing a module.
+
+There are modules to help you through the process of writing a module:
+L<ExtUtils::ModuleMaker>, L<Module::Setup>, L<CPAN::MakeMaker>
+
+=cut
+
+1;
diff --git a/lib/ExtUtils/MakeMaker/vmsish.pm b/lib/ExtUtils/MakeMaker/vmsish.pm
new file mode 100644 (file)
index 0000000..5380ba5
--- /dev/null
@@ -0,0 +1,40 @@
+package ExtUtils::MakeMaker::vmsish;
+
+use vars qw($VERSION);
+$VERSION = 0.01;
+
+my $IsVMS = $^O eq 'VMS';
+
+require vmsish if $IsVMS;
+
+
+sub import {
+    return unless $IsVMS;
+
+    shift;
+    unshift @_, 'vmsish';
+
+    goto &vmsish::import;
+}
+
+1;
+
+
+=head1 NAME
+
+ExtUtils::MakeMaker::vmsish - Platform agnostic vmsish.pm
+
+=head1 SYNOPSIS
+
+  use just like vmsish.pm
+
+=head1 DESCRIPTION
+
+Until 5.8.0, vmsish.pm is only installed on VMS.  This means any code
+which has 'use vmsish' in it won't even compile outside VMS.  This
+makes ExtUtils::MM_VMS very hard to test.
+
+ExtUtils::MakeMaker::vmsish is just a very thin wrapper around vmsish
+which works just like it on VMS and everywhere else it does nothing.
+
+=cut
index 7ca5bdd..df4cb9e 100644 (file)
@@ -14,21 +14,78 @@ use vars qw($VERSION @ISA @EXPORT_OK
 
 $VERSION = 1.38;
 @ISA=('Exporter');
-@EXPORT_OK = ('mkmanifest', 'manicheck', 'fullcheck', 'filecheck', 
-             'skipcheck', 'maniread', 'manicopy');
+@EXPORT_OK = qw(mkmanifest
+                manicheck  filecheck  fullcheck  skipcheck
+                manifind   maniread   manicopy   maniadd
+               );
 
 $Is_MacOS = $^O eq 'MacOS';
-$Is_VMS = $^O eq 'VMS';
+$Is_VMS   = $^O eq 'VMS';
 require VMS::Filespec if $Is_VMS;
 
-$Debug = $ENV{PERL_MM_MANIFEST_DEBUG} || 0;
+$Debug   = $ENV{PERL_MM_MANIFEST_DEBUG} || 0;
 $Verbose = defined $ENV{PERL_MM_MANIFEST_VERBOSE} ?
                    $ENV{PERL_MM_MANIFEST_VERBOSE} : 1;
 $Quiet = 0;
 $MANIFEST = 'MANIFEST';
-$DEFAULT_MSKIP = (File::Spec->splitpath($INC{"ExtUtils/Manifest.pm"}))[1].
+
+my $manifest_mod = $INC{"ExtUtils/Manifest.pm"} ||
+                   ($Is_VMS ? $INC{'extutils/manifest.pm'} : '');
+$DEFAULT_MSKIP = (File::Spec->splitpath($manifest_mod))[1].
                  "$MANIFEST.SKIP";
 
+
+=head1 NAME
+
+ExtUtils::Manifest - utilities to write and check a MANIFEST file
+
+=head1 SYNOPSIS
+
+    use ExtUtils::Manifest qw(...funcs to import...);
+
+    mkmanifest();
+
+    my @missing_files    = manicheck;
+    my @skipped          = skipcheck;
+    my @extra_files      = filecheck;
+    my($missing, $extra) = fullcheck;
+
+    my $found    = manifind();
+
+    my $manifest = maniread();
+
+    manicopy($read,$target);
+
+    maniadd({$file => $comment, ...});
+
+
+=head1 DESCRIPTION
+
+=head2 Functions
+
+ExtUtils::Manifest exports no functions by default.  The following are
+exported on request
+
+=over 4
+
+=item mkmanifest
+
+    mkmanifest();
+
+Writes all files in and below the current directory to your F<MANIFEST>.
+It works similar to
+
+    find . > MANIFEST
+
+All files that match any regular expression in a file F<MANIFEST.SKIP>
+(if it exists) are ignored.
+
+Any existing F<MANIFEST> file will be saved as F<MANIFEST.bak>.  Lines
+from the old F<MANIFEST> file is preserved, including any comments
+that are found in the existing F<MANIFEST> file in the new one.
+
+=cut
+
 sub mkmanifest {
     my $manimiss = 0;
     my $read = (-r 'MANIFEST' && maniread()) or $manimiss++;
@@ -72,6 +129,16 @@ sub clean_up_filename {
   return $filename;
 }
 
+
+=item manifind
+
+    my $found = manifind();
+
+returns a hash reference. The keys of the hash are the files found
+below the current directory.
+
+=cut
+
 sub manifind {
     my $p = shift || {};
     my $found = {};
@@ -98,18 +165,66 @@ sub manifind {
     return $found;
 }
 
-sub fullcheck {
-    return [_check_files()], [_check_manifest()];
-}
+
+=item manicheck
+
+    my @missing_files = manicheck();
+
+checks if all the files within a C<MANIFEST> in the current directory
+really do exist. If C<MANIFEST> and the tree below the current
+directory are in sync it exits silently, returning an empty list.
+Otherwise it returns a list of files which are listed in the
+C<MANIFEST> but missing from the directory, and by default also
+outputs these names to STDERR.
+
+=cut
 
 sub manicheck {
     return _check_files();
 }
 
+
+=item filecheck
+
+    my @extra_files = filecheck();
+
+finds files below the current directory that are not mentioned in the
+C<MANIFEST> file. An optional file C<MANIFEST.SKIP> will be
+consulted. Any file matching a regular expression in such a file will
+not be reported as missing in the C<MANIFEST> file. The list of any
+extraneous files found is returned, and by default also reported to
+STDERR.
+
+=cut
+
 sub filecheck {
     return _check_manifest();
 }
 
+
+=item fullcheck
+
+    my($missing, $extra) = fullcheck();
+
+does both a manicheck() and a filecheck(), returning then as two array
+refs.
+
+=cut
+
+sub fullcheck {
+    return [_check_files()], [_check_manifest()];
+}
+
+
+=item skipcheck
+
+    my @skipped = skipcheck();
+
+lists all the files that are skipped due to your C<MANIFEST.SKIP>
+file.
+
+=cut
+
 sub skipcheck {
     my($p) = @_;
     my $found = manifind();
@@ -173,6 +288,18 @@ sub _check_manifest {
 }
 
 
+=item maniread
+
+    my $manifest = maniread();
+    my $manifest = maniread($manifest_file);
+
+reads a named C<MANIFEST> file (defaults to C<MANIFEST> in the current
+directory) and returns a HASH reference with files being the keys and
+comments being the values of the HASH.  Blank lines and lines which
+start with C<#> in the C<MANIFEST> file are discarded.
+
+=cut
+
 sub maniread {
     my ($mfile) = @_;
     $mfile ||= $MANIFEST;
@@ -234,6 +361,23 @@ sub _maniskip {
     return sub { $_[0] =~ qr{$opts$regex} };
 }
 
+=item manicopy
+
+    manicopy($src, $dest_dir);
+    manicopy($src, $dest_dir, $how);
+
+copies the files that are the keys in the HASH I<%$src> to the
+$dest_dir. The HASH reference $read is typically returned by the
+maniread() function. This function is useful for producing a directory
+tree identical to the intended distribution tree. The third parameter
+$how can be used to specify a different methods of "copying". Valid
+values are C<cp>, which actually copies the files, C<ln> which creates
+hard links, and C<best> which mostly links the files but copies any
+symbolic link to make a tree without any symbolic link. Best is the
+default.
+
+=cut
+
 sub manicopy {
     my($read,$target,$how)=@_;
     croak "manicopy() called without target argument" unless defined $target;
@@ -372,90 +516,48 @@ sub _unmacify {
     $file;
 }
 
-1;
-
-__END__
-
-=head1 NAME
-
-ExtUtils::Manifest - utilities to write and check a MANIFEST file
-
-=head1 SYNOPSIS
-
-    require ExtUtils::Manifest;
-
-    ExtUtils::Manifest::mkmanifest;
 
-    ExtUtils::Manifest::manicheck;
+=item maniadd
 
-    ExtUtils::Manifest::filecheck;
+  maniadd({ $file => $comment, ...});
 
-    ExtUtils::Manifest::fullcheck;
+Adds an entry to an existing F<MANIFEST>.
 
-    ExtUtils::Manifest::skipcheck;
+$file will be normalized (ie. Unixified).  B<UNIMPLEMENTED>
 
-    ExtUtils::Manifest::manifind();
+=cut
 
-    ExtUtils::Manifest::maniread($file);
+sub maniadd {
+    my($additions) = shift;
 
-    ExtUtils::Manifest::manicopy($read,$target,$how);
+    _normalize($additions);
 
-=head1 DESCRIPTION
+    my $manifest = maniread();
+    open(MANIFEST, ">>$MANIFEST") or die "Could not open $MANIFEST: $!";
+    while( my($file, $comment) = each %$additions ) {
+        $comment ||= '';
+        printf MANIFEST "%-40s%s\n", $file, $comment unless
+          exists $manifest->{$file};
+    }
+    close MANIFEST;
+}
 
-mkmanifest() writes all files in and below the current directory to a
-file named in the global variable $ExtUtils::Manifest::MANIFEST (which
-defaults to C<MANIFEST>) in the current directory. It works similar to
-
-    find . -print
-
-but in doing so checks each line in an existing C<MANIFEST> file and
-includes any comments that are found in the existing C<MANIFEST> file
-in the new one. Anything between white space and an end of line within
-a C<MANIFEST> file is considered to be a comment. Filenames and
-comments are separated by one or more TAB characters in the
-output. All files that match any regular expression in a file
-C<MANIFEST.SKIP> (if such a file exists) are ignored.
-
-manicheck() checks if all the files within a C<MANIFEST> in the current
-directory really do exist. If C<MANIFEST> and the tree below the current
-directory are in sync it exits silently, returning an empty list.  Otherwise
-it returns a list of files which are listed in the C<MANIFEST> but missing
-from the directory, and by default also outputs these names to STDERR.
-
-filecheck() finds files below the current directory that are not
-mentioned in the C<MANIFEST> file. An optional file C<MANIFEST.SKIP>
-will be consulted. Any file matching a regular expression in such a
-file will not be reported as missing in the C<MANIFEST> file. The list of
-any extraneous files found is returned, and by default also reported to
-STDERR.
+# UNIMPLEMENTED
+sub _normalize {
+    return;
+}
 
-fullcheck() does both a manicheck() and a filecheck(), returning references
-to two arrays, the first for files manicheck() found to be missing, the
-seond for unexpeced files found by filecheck().
 
-skipcheck() lists all the files that are skipped due to your
-C<MANIFEST.SKIP> file.
+=back
 
-manifind() returns a hash reference. The keys of the hash are the
-files found below the current directory.
+=head2 MANIFEST
 
-maniread($file) reads a named C<MANIFEST> file (defaults to
-C<MANIFEST> in the current directory) and returns a HASH reference
-with files being the keys and comments being the values of the HASH.
-Blank lines and lines which start with C<#> in the C<MANIFEST> file
-are discarded.
+Anything between white space and an end of line within a C<MANIFEST>
+file is considered to be a comment.  Filenames and comments are
+separated by one or more TAB characters in the output. 
 
-C<manicopy($read,$target,$how)> copies the files that are the keys in
-the HASH I<%$read> to the named target directory. The HASH reference
-$read is typically returned by the maniread() function. This
-function is useful for producing a directory tree identical to the
-intended distribution tree. The third parameter $how can be used to
-specify a different methods of "copying". Valid values are C<cp>,
-which actually copies the files, C<ln> which creates hard links, and
-C<best> which mostly links the files but copies any symbolic link to
-make a tree without any symbolic link. Best is the default.
 
-=head1 MANIFEST.SKIP
+=head2 MANIFEST.SKIP
 
 The file MANIFEST.SKIP may contain regular expressions of files that
 should be ignored by mkmanifest() and filecheck(). The regular
@@ -467,6 +569,7 @@ expression to start with a sharp character. A typical example:
     \bRCS\b
     \bCVS\b
     ,v$
+    \B\.svn\b
 
     # Makemaker generated files and dirs.
     ^MANIFEST\.
@@ -485,12 +588,12 @@ used, similar to the example above.  If you want nothing skipped,
 simply make an empty MANIFEST.SKIP file.
 
 
-=head1 EXPORT_OK
+=head2 EXPORT_OK
 
 C<&mkmanifest>, C<&manicheck>, C<&filecheck>, C<&fullcheck>,
 C<&maniread>, and C<&manicopy> are exportable.
 
-=head1 GLOBAL VARIABLES
+=head2 GLOBAL VARIABLES
 
 C<$ExtUtils::Manifest::MANIFEST> defaults to C<MANIFEST>. Changing it
 results in both a different C<MANIFEST> and a different
@@ -554,3 +657,5 @@ L<ExtUtils::MakeMaker> which has handy targets for most of the functionality.
 Andreas Koenig <F<andreas.koenig@anima.de>>
 
 =cut
+
+1;
diff --git a/lib/ExtUtils/NOTES b/lib/ExtUtils/NOTES
new file mode 100644 (file)
index 0000000..837167c
--- /dev/null
@@ -0,0 +1,102 @@
+The Simplified MakeMaker class hierarchy
+****************************************
+
+What most people need to know.
+
+(Subclasses on top.)
+
+               MY
+                |
+        ExtUtils::MakeMaker
+                |
+        ExtUtils::MM_{Current OS}
+                |
+        ExtUtils::MM_Unix
+                |
+        ExtUtils::MM_Any
+
+The object actually used is of the class MY which allows you to
+override bits of MakeMaker inside your Makefile.PL by declaring
+MY::foo() methods.
+
+
+The Real MakeMaker class hierarchy
+**********************************
+
+You wish it was that simple.
+
+Here's how it really works.
+
+               PACK### (created each call to ExtUtils::MakeMaker->new)
+                    .                       |
+                 (mixin)                    |
+                    .                       |
+        MY (created by ExtUtils::MY)        |
+        |                                   |
+    ExtUtils::MY         MM (created by ExtUtils::MM)
+              |          |              |
+              ExtUtils::MM              ExtUtils::MM_{Current OS}
+               |         |                              .
+               |         |                              
+    ExtUtils::Liblist    ExtUtils::MakeMaker            .
+          |                                             
+    ExtUtils::Liblist::Kid                              .
+
+                                                (variable subclass)
+
+                                                        .
+
+    ExtUtils::MM_{NonUnix}. . . . . . . . . . . . . . . .
+            |
+    ExtUtils::MM_Unix . . . . . . . . . . . . . . . . . .
+            |
+    ExtUtils::MM_Any
+
+
+NOTE: Yes, this is a mess.  See
+http://archive.develooper.com/makemaker@perl.org/msg00134.html
+for some history.
+
+NOTE: When ExtUtils::MM is loaded it chooses a superclass for MM from
+amongst the ExtUtils::MM_* modules based on the current operating
+system.
+
+NOTE: ExtUtils::MM_{Current OS} represents one of the ExtUtils::MM_*
+modules except ExtUtils::MM_Any.
+
+NOTE: ExtUtils::MM_{NonUnix} represents all of the ExtUtils::MM_*
+modules except ExtUtils::MM_Any and ExtUtils::MM_Unix.
+
+NOTE: The main object used by MakeMaker is a PACK### object, *not*
+ExtUtils::MakeMaker.  It is, effectively, a subclass of MY,
+ExtUtils::Makemaker, ExtUtils::Liblist and an ExtUtils::MM_* class
+appropriate for your operating system.
+
+NOTE: The methods in MY are simply copied into PACK### rather than
+MY being a superclass of PACK###.  I don't remember the rationale.
+
+NOTE: ExtUtils::Liblist should be removed from the inheritence hiearchy
+and simply be called as functions.
+
+NOTE: Modules like File::Spec and Exporter have been omitted for clarity.
+
+
+The MM_* hierarchy
+******************
+
+                               MM_Win95   MM_NW5
+                                    \      /
+MM_BeOS  MM_Cygwin  MM_OS2  MM_VMS  MM_Win32  MM_DOS  MM_MacOS  MM_UWIN
+      \        |      |         |        /      /       /       /
+       ---------------------------------------------------------
+                           |       |
+                        MM_Unix    |
+                              |    |
+                              MM_Any
+
+NOTE: Each direct MM_Unix subclass is also an MM_Any subclass.  This
+is a temporary hack because MM_Unix overrides some MM_Any methods with
+Unix specific code.  It allows the non-Unix modules to see the
+original MM_Any implementations.
+
+NOTE: Modules like File::Spec and Exporter have been omitted for clarity.
diff --git a/lib/ExtUtils/PATCHING b/lib/ExtUtils/PATCHING
new file mode 100644 (file)
index 0000000..2170be2
--- /dev/null
@@ -0,0 +1,155 @@
+This is a short set of guidelines for those patching
+ExtUtils::MakeMaker.  Its not an iron-clad set of rules, but just
+things which make life easier when reading and integrating a patch.
+
+Lots of information can be found in makemaker.org.
+
+MakerMaker is being maintained until something else can replace it.
+Bugs will be fixed and compatibility improved, but I would like to
+avoid new features.  If you want to add something to MakeMaker,
+consider instead working on Module::Build, MakeMaker's heir apparent.
+
+
+Patching details
+
+- Please use unified diffs.  (diff -u)
+
+- Patches against the latest development snapshot from makemaker.org are 
+  preferred.  Patches against the latest CPAN version are ok, too.
+
+- Post your patch to makemaker@perl.org.
+
+
+Code formatting
+
+- No literal tabs (except where necessary inside Makefile code, obviously).
+
+- 4 character indentation.
+
+- this_style is prefered instead of studlyCaps.
+
+- Private subroutine names (ie. those used only in the same package
+  they're declared in) should start with an underscore (_sekret_method).
+
+- Protected subroutines (ie. ones intended to be used by other modules in
+  ExtUtils::*) should be named normally (no leading underscore) but
+  documented as protected (see Documentation below).
+
+- Do not use indirect object syntax (ie. new Foo::Bar (@args))
+
+- make variables use dollar signs like Perl scalars.  This causes problems
+  when you have to mix them both in a string.  If you find yourself
+  backwacking lots of dollar signs because you have one interpolated
+  perl variable, like this:
+
+    return <<'EOT'
+
+subdirs ::
+       \$(NOECHO)cd $subdir && \$(MAKE) -f \$(FIRST_MAKEFILE) all \$(PASTHRU)
+EOT
+
+  or are switching quoting contexts:
+
+    return <<q{
+subdirs ::
+       $(NOECHO)cd }.$subdir.q{ && $(MAKE) -f $(FIRST_MAKEFILE) all $(PASTHRU)
+};
+
+  consider using sprintf instead.
+
+    return sprintf <<'EOT', $subdir;
+
+subdirs ::
+       $(NOECHO)cd %s && $(MAKE) -f $(FIRST_MAKEFILE) all $(PASTHRU)
+EOT
+
+
+Refactoring and Cleanup
+
+- MakeMaker is a mess.  We like patches which clean things up.
+
+
+Backwards Compatibility
+
+- MakeMaker must be backwards compatible to 5.5.3 (5.005_03).  Avoid any
+  obvious 5.6-isms (threads, warnings.pm, Unicode, our, v1.2.3, attributes
+  open my $fh, lvalue subroutines, any new core modules, etc...).
+
+- MakeMaker should avoid having module dependencies.  Avoid using modules
+  which didn't come with 5.5.3 and avoid using features from newer 
+  versions.  Sometimes this is unavoidable.
+
+
+Cross-Platform Compatibility
+
+- MakeMaker must work on all architectures Perl works on (see perlport.pod)
+  and with many different versions of make.  This means all Unixen 
+  (including Cygwin and MacOS X), Windows (including DOS), MacOS Classic 
+  and VMS.  
+
+- Often when you patch ExtUtils::MM_Unix, similar patches must be done
+  to the other MM_* modules.  If you can, please do this extra work
+  otherwise I have to.  If you can't, that's ok.  We can help.
+
+- If possible, please test your patch on two Very Different architectures.
+  Unix, Windows, MacOS Classic and VMS being Very Different.  Note: Cygwin
+  and OS X are Unixen for our purposes.
+
+- If nothing else, at least try it on two different Unixen or Windows
+  machines (ie. Linux and IRIX or WinNT and Win95).
+
+- HP's TestDrive (www.testdrive.compaq.com) and SourceForge's
+  compile farm (www.sourceforge.net) are good sources of testing
+  machines of many different architectures and platforms.  Accounts are 
+  free.
+
+- If you find yourself writing "do_this if $^O eq 'That'" (ie. checks on
+  the OS type) perhaps your code belongs in one of the non-Unix MM_*
+  modules (ie. MM_Win32, MM_VMS, etc...).  If one does not exist, consider
+  creating one.  Its ok to have an MM_* module with only one method.
+
+- Some shells have very small buffers.  This means command lines must
+  be as small as possible.  20K is the upper limit for Unixen, and 256
+  for VMS.  Not sure what Windows and DOS are limited to, probably 1K.
+  This limit *includes* any files passed into it.  Some modules (such as
+  bioperl) generate enourmous commands because of their large number of
+  files.  If your command is just too long, consider making it an
+  ExtUtils::Command::MM function.
+
+- Most shells quote differently.  If you need to put a perl one-liner
+  in the Makefile, please use oneliner() to generate it.
+
+
+Tests
+
+- Tests would be nice, but I'm not going to pretend testing MakeMaker
+  is easy.  If nothing else, let us know how you tested your patch by
+  hand.
+
+
+Documentation
+
+- Documentation would be nice.
+
+- If the new feature/method is private, please document it with POD
+  wrapped in "=begin/end private" tags.  That way it will be documented,
+  but won't be displayed (future versions of perldoc may have options
+  to display).
+
+    =begin private
+
+    =item _foo_bar
+
+       $mm->_foo_bar
+
+    Blah blah blah
+
+    =end private
+
+    =cut
+
+    sub _foo_bar {
+       ...
+
+- If you're overriding a method, document that its an override and
+  *why* its being overridden.  Don't repeat the original documentation.
diff --git a/lib/ExtUtils/README b/lib/ExtUtils/README
new file mode 100644 (file)
index 0000000..95f66e9
--- /dev/null
@@ -0,0 +1,28 @@
+This is a CPAN distribution of the venerable MakeMaker module.
+
+
+PLEASE NOTE: This distribution does not include the xsubpp or typemap
+programs.  They are extremely specific to your version or Perl, so
+MakeMaker will simply use the one which came with your copy of Perl.
+Do not delete your old ExtUtils/ directory.
+
+
+Known Problems:
+
+(See http://rt.cpan.org for a full list of open problems.)
+
+ActivePerl likely broken if installed in C:\Program Files or other
+prefix with a space in the name.
+
+manifypods target produces command lines too long for some systems
+
+Using the MMS utility on VMS causes lots of extra newlines.  Unknown
+why this is so, might be a bug in MMS.  Problem not seen with MMK.
+
+ActivePerl/Win95 disttest produces "File creation error" from somewhere
+in running Makefile.PL after check_manifest() is run.  Don't know why.
+
+
+See TODO for details.
+
+Please report any bugs via http://rt.cpan.org or to makemaker@perl.org.
diff --git a/lib/ExtUtils/TODO b/lib/ExtUtils/TODO
new file mode 100644 (file)
index 0000000..342ce9e
--- /dev/null
@@ -0,0 +1,49 @@
+Rethink MM_Win32 tests.
+
+Investigate one method per make target.
+
+Test MM_Any and pull some redundant tests out of MM_*.t
+
+Create a way to init MM objects.  (XXX What's wrong with MakeMaker->new?)
+
+Move instmodsh to utils/ in the core.
+
+Handle config files (ie. /etc) and their special PREFIX needs
+(ie. PREFIX=/usr, INSTALLCONFIGDIR=/etc).
+
+Make sure PDL builds
+
+Fix find_perl on Amiga trg@privat.utfors.se
+
+Fix appending of .. when DIRS contains directories not immediately
+below the cwd.
+
+Fill in the IMPORTS docs.
+
+Document "make install UNINST=1"
+
+Remove tar -I Sun-ism from instmodsh.
+
+Consider adding a timeout option to prompt() and env variable.
+
+Unify VMS->find_perl
+
+Consider if VMS->find_perl needs to have pieces put into maybe_command()
+
+Consider if shell escaping all macro data is a good idea.
+
+Move Win32->init_others() ExtUtils::Command overrides into MM_Any.
+
+Figure out and document the 4th arg to ExtUtils::Install::install()
+
+Consider if adding a nativize() routine to replace macify() and
+fixpath() is useful.
+
+Eliminate the above from inside FS::VMS->catfile and catdir.  Make into 
+MM_VMS wrappers.
+
+Add "NO_META" to stop autogeneration (and auto overwrite) of META.yml.
+
+Test ExtUtils::Command::MM
+
+Finish ExtUtils::MakeMaker::Tutorial
\ No newline at end of file
diff --git a/lib/ExtUtils/t/00compile.t b/lib/ExtUtils/t/00compile.t
new file mode 100644 (file)
index 0000000..19cddc5
--- /dev/null
@@ -0,0 +1,53 @@
+#!/usr/bin/perl -w
+
+BEGIN {
+    if( $ENV{PERL_CORE} ) {
+        @INC = ('../lib', 'lib');
+    }
+    else {
+        unshift @INC, 't/lib';
+    }
+}
+chdir 't';
+
+use File::Find;
+use File::Spec;
+use Test::More;
+
+my $Has_Test_Pod;
+BEGIN {
+    $Has_Test_Pod = eval 'use Test::Pod 0.95; 1';
+}
+
+my(@modules);
+
+chdir File::Spec->catdir(File::Spec->updir, 'lib');
+find( sub {
+        return if /~$/;
+        if( $File::Find::dir =~ /^blib|t$/ ) {
+            $File::Find::prune = 1;
+            return;
+        }
+        push @modules, $File::Find::name if /\.pm$/;
+    }, 'ExtUtils'
+);
+
+plan tests => scalar @modules * 2;
+foreach my $file (@modules) {
+    local @INC = @INC;
+    unshift @INC, File::Spec->curdir;
+
+    # This piece of insanity brought to you by non-case preserving
+    # file systems!  We have extutils/command.pm, %INC has 
+    # ExtUtils/Command.pm
+    # Furthermore, 5.8.0 has a bug about require alone in an eval.  Thus
+    # the extra statement.
+    eval q{ require($file); 1 } unless grep { lc $file =~ lc $_ } keys %INC;
+    is( $@, '', "require $file" );
+
+    SKIP: {
+        skip "Test::Pod not installed", 1 unless $Has_Test_Pod;
+        pod_file_ok($file);
+    }
+    
+}
index 2d5b1ee..f7f50fc 100644 (file)
@@ -22,6 +22,12 @@ package Big::Dummy;
 
 $VERSION = 0.01;
 
+=head1 NAME
+
+Big::Dummy - Try "our" hot dog's
+
+=cut
+
 1;
 END
 
@@ -33,7 +39,9 @@ printf "Current package is: %s\n", __PACKAGE__;
 WriteMakefile(
     NAME          => 'Big::Dummy',
     VERSION_FROM  => 'lib/Big/Dummy.pm',
-    PREREQ_PM     => {},
+    PREREQ_PM     => { strict => 0 },
+    ABSTRACT_FROM => 'lib/Big/Dummy.pm',
+    AUTHOR        => 'Michael G Schwern <schwern@pobox.com>',
 );
 END
 
index ff9eec1..7f1a97c 100644 (file)
@@ -12,98 +12,121 @@ BEGIN {
 chdir 't';
 
 BEGIN {
-       1 while unlink 'ecmdfile';
-       # forcibly remove ecmddir/temp2, but don't import mkpath
-       use File::Path ();
-       File::Path::rmtree( 'ecmddir' );
+    1 while unlink 'ecmdfile', 'newfile';
+    # forcibly remove ecmddir/temp2, but don't import mkpath
+    use File::Path ();
+    File::Path::rmtree( 'ecmddir' );
 }
 
 BEGIN {
-       use Test::More tests => 24;
-       use File::Spec;
+    use Test::More tests => 27;
+    use File::Spec;
 }
 
-{
-       # bad neighbor, but test_f() uses exit()
-    *CORE::GLOBAL::exit = '';   # quiet 'only once' warning.
-       *CORE::GLOBAL::exit = sub { return @_ };
-
-       use_ok( 'ExtUtils::Command' );
+BEGIN {
+    # bad neighbor, but test_f() uses exit()
+        *CORE::GLOBAL::exit = '';   # quiet 'only once' warning.
+    *CORE::GLOBAL::exit = sub { return @_ };
+    use_ok( 'ExtUtils::Command' );
+}
 
-       # get a file in the current directory, replace last char with wildcard 
-       my $file;
-       {
-               local *DIR;
-               opendir(DIR, File::Spec->curdir());
-               while ($file = readdir(DIR)) {
-                       $file =~ s/\.\z// if $^O eq 'VMS';
-                       last if $file =~ /^\w/;
-               }
-       }
+{
+    # get a file in the current directory, replace last char with wildcard 
+    my $file;
+    {
+        local *DIR;
+        opendir(DIR, File::Spec->curdir());
+        while ($file = readdir(DIR)) {
+            $file =~ s/\.\z// if $^O eq 'VMS';
+            last if $file =~ /^\w/;
+        }
+        closedir DIR;
+    }
 
 
     # % means 'match one character' on VMS.  Everything else is ?
     my $match_char = $^O eq 'VMS' ? '%' : '?';
-       ($ARGV[0] = $file) =~ s/.\z/$match_char/;
+    ($ARGV[0] = $file) =~ s/.\z/$match_char/;
 
-       # this should find the file
-       ExtUtils::Command::expand_wildcards();
+    # this should find the file
+    ExtUtils::Command::expand_wildcards();
 
-       is( scalar @ARGV, 1, 'found one file' );
-       like( $ARGV[0], qr/$file/, 'expanded wildcard ? successfully' );
+    is( scalar @ARGV, 1, 'found one file' );
+    like( $ARGV[0], qr/$file/, 'expanded wildcard ? successfully' );
 
-       # try it with the asterisk now
-       ($ARGV[0] = $file) =~ s/.{3}\z/\*/;
-       ExtUtils::Command::expand_wildcards();
+    # try it with the asterisk now
+    ($ARGV[0] = $file) =~ s/.{3}\z/\*/;
+    ExtUtils::Command::expand_wildcards();
 
-       ok( (grep { qr/$file/ } @ARGV), 'expanded wildcard * successfully' );
+    ok( (grep { qr/$file/ } @ARGV), 'expanded wildcard * successfully' );
 
-       # concatenate this file with itself
-       # be extra careful the regex doesn't match itself
+    # concatenate this file with itself
+    # be extra careful the regex doesn't match itself
     use TieOut;
-       my $out = tie *STDOUT, 'TieOut';
-       my $self = $0;
-       unless (-f $self) {
-           my ($vol, $dirs, $file) = File::Spec->splitpath($self);
-           my @dirs = File::Spec->splitdir($dirs);
-           unshift(@dirs, File::Spec->updir);
-           $dirs = File::Spec->catdir(@dirs);
-           $self = File::Spec->catpath($vol, $dirs, $file);
-       }
-       @ARGV = ($self, $self);
-
-       cat();
-       is( scalar( $$out =~ s/use_ok\( 'ExtUtils::Command'//g), 2, 
-               'concatenation worked' );
-
-       # the truth value here is reversed -- Perl true is C false
-       @ARGV = ( 'ecmdfile' );
-       ok( test_f(), 'testing non-existent file' );
-
-       @ARGV = ( 'ecmdfile' );
-       cmp_ok( ! test_f(), '==', (-f 'ecmdfile'), 'testing non-existent file' );
-
-       # these are destructive, have to keep setting @ARGV
-       @ARGV = ( 'ecmdfile' );
-       touch();
-
-       @ARGV = ( 'ecmdfile' );
-       ok( test_f(), 'now creating that file' );
-
-       @ARGV = ( 'ecmdfile' );
-       ok( -e $ARGV[0], 'created!' );
-
-       my ($now) = time;
-       utime ($now, $now, $ARGV[0]);
+    my $out = tie *STDOUT, 'TieOut';
+    my $self = $0;
+    unless (-f $self) {
+        my ($vol, $dirs, $file) = File::Spec->splitpath($self);
+        my @dirs = File::Spec->splitdir($dirs);
+        unshift(@dirs, File::Spec->updir);
+        $dirs = File::Spec->catdir(@dirs);
+        $self = File::Spec->catpath($vol, $dirs, $file);
+    }
+    @ARGV = ($self, $self);
+
+    cat();
+    is( scalar( $$out =~ s/use_ok\( 'ExtUtils::Command'//g), 2, 
+        'concatenation worked' );
+
+    # the truth value here is reversed -- Perl true is C false
+    @ARGV = ( 'ecmdfile' );
+    ok( test_f(), 'testing non-existent file' );
+
+    @ARGV = ( 'ecmdfile' );
+    cmp_ok( ! test_f(), '==', (-f 'ecmdfile'), 'testing non-existent file' );
+
+    # these are destructive, have to keep setting @ARGV
+    @ARGV = ( 'ecmdfile' );
+    touch();
+
+    @ARGV = ( 'ecmdfile' );
+    ok( test_f(), 'now creating that file' );
+
+    @ARGV = ( 'ecmdfile' );
+    ok( -e $ARGV[0], 'created!' );
+
+    my ($now) = time;
+    utime ($now, $now, $ARGV[0]);
     sleep 2;
 
-       # Just checking modify time stamp, access time stamp is set
-       # to the beginning of the day in Win95.
+    # Just checking modify time stamp, access time stamp is set
+    # to the beginning of the day in Win95.
     # There's a small chance of a 1 second flutter here.
     my $stamp = (stat($ARGV[0]))[9];
-       cmp_ok( abs($now - $stamp), '<=', 1, 'checking modify time stamp' ) ||
+    cmp_ok( abs($now - $stamp), '<=', 1, 'checking modify time stamp' ) ||
       diag "mtime == $stamp, should be $now";
 
+    @ARGV = qw(newfile);
+    touch();
+
+    my $new_stamp = (stat('newfile'))[9];
+    cmp_ok( abs($new_stamp - $stamp), '>=', 2,  'newer file created' );
+
+    @ARGV = qw(newfile ecmdfile);
+    eqtime();
+
+    $stamp = (stat('ecmdfile'))[9];
+    cmp_ok( abs($new_stamp - $stamp), '<=', 1, 'eqtime' );
+
+    # eqtime use to clear the contents of the file being equalized!
+    open(FILE, '>>ecmdfile') || die $!;
+    print FILE "Foo";
+    close FILE;
+
+    @ARGV = qw(newfile ecmdfile);
+    eqtime();
+    ok( -s 'ecmdfile', "eqtime doesn't clear the file being equalized" );
+
     SKIP: {
         if ($^O eq 'amigaos' || $^O eq 'os2' || $^O eq 'MSWin32' ||
             $^O eq 'NetWare' || $^O eq 'dos' || $^O eq 'cygwin'  ||
@@ -113,21 +136,21 @@ BEGIN {
         }
 
         # change a file to execute-only
-        @ARGV = ( 0100, 'ecmdfile' );
+        @ARGV = ( '0100', 'ecmdfile' );
         ExtUtils::Command::chmod();
 
         is( ((stat('ecmdfile'))[2] & 07777) & 0700,
             0100, 'change a file to execute-only' );
 
         # change a file to read-only
-        @ARGV = ( 0400, 'ecmdfile' );
+        @ARGV = ( '0400', 'ecmdfile' );
         ExtUtils::Command::chmod();
 
         is( ((stat('ecmdfile'))[2] & 07777) & 0700,
             ($^O eq 'vos' ? 0500 : 0400), 'change a file to read-only' );
 
         # change a file to write-only
-        @ARGV = ( 0200, 'ecmdfile' );
+        @ARGV = ( '0200', 'ecmdfile' );
         ExtUtils::Command::chmod();
 
         is( ((stat('ecmdfile'))[2] & 07777) & 0700,
@@ -135,58 +158,58 @@ BEGIN {
     }
 
     # change a file to read-write
-       @ARGV = ( 0600, 'ecmdfile' );
-       ExtUtils::Command::chmod();
+    @ARGV = ( '0600', 'ecmdfile' );
+    ExtUtils::Command::chmod();
 
     is( ((stat('ecmdfile'))[2] & 07777) & 0700,
         ($^O eq 'vos' ? 0700 : 0600), 'change a file to read-write' );
 
-       # mkpath
-       @ARGV = ( File::Spec->join( 'ecmddir', 'temp2' ) );
-       ok( ! -e $ARGV[0], 'temp directory not there yet' );
+    # mkpath
+    @ARGV = ( File::Spec->join( 'ecmddir', 'temp2' ) );
+    ok( ! -e $ARGV[0], 'temp directory not there yet' );
 
-       mkpath();
-       ok( -e $ARGV[0], 'temp directory created' );
+    mkpath();
+    ok( -e $ARGV[0], 'temp directory created' );
 
-       # copy a file to a nested subdirectory
-       unshift @ARGV, 'ecmdfile';
-       cp();
+    # copy a file to a nested subdirectory
+    unshift @ARGV, 'ecmdfile';
+    cp();
 
-       ok( -e File::Spec->join( 'ecmddir', 'temp2', 'ecmdfile' ), 'copied okay' );
+    ok( -e File::Spec->join( 'ecmddir', 'temp2', 'ecmdfile' ), 'copied okay' );
 
-       # cp should croak if destination isn't directory (not a great warning)
-       @ARGV = ( 'ecmdfile' ) x 3;
-       eval { cp() };
+    # cp should croak if destination isn't directory (not a great warning)
+    @ARGV = ( 'ecmdfile' ) x 3;
+    eval { cp() };
 
-       like( $@, qr/Too many arguments/, 'cp croaks on error' );
+    like( $@, qr/Too many arguments/, 'cp croaks on error' );
 
-       # move a file to a subdirectory
-       @ARGV = ( 'ecmdfile', 'ecmddir' );
-       mv();
+    # move a file to a subdirectory
+    @ARGV = ( 'ecmdfile', 'ecmddir' );
+    mv();
 
-       ok( ! -e 'ecmdfile', 'moved file away' );
-       ok( -e File::Spec->join( 'ecmddir', 'ecmdfile' ), 'file in new location' );
+    ok( ! -e 'ecmdfile', 'moved file away' );
+    ok( -e File::Spec->join( 'ecmddir', 'ecmdfile' ), 'file in new location' );
 
-       # mv should also croak with the same wacky warning
-       @ARGV = ( 'ecmdfile' ) x 3;
+    # mv should also croak with the same wacky warning
+    @ARGV = ( 'ecmdfile' ) x 3;
 
-       eval { mv() };
-       like( $@, qr/Too many arguments/, 'mv croaks on error' );
+    eval { mv() };
+    like( $@, qr/Too many arguments/, 'mv croaks on error' );
 
-       # remove some files
-       my @files = @ARGV = ( File::Spec->catfile( 'ecmddir', 'ecmdfile' ),
-       File::Spec->catfile( 'ecmddir', 'temp2', 'ecmdfile' ) );
-       rm_f();
+    # remove some files
+    my @files = @ARGV = ( File::Spec->catfile( 'ecmddir', 'ecmdfile' ),
+    File::Spec->catfile( 'ecmddir', 'temp2', 'ecmdfile' ) );
+    rm_f();
 
-       ok( ! -e $_, "removed $_ successfully" ) for (@ARGV);
+    ok( ! -e $_, "removed $_ successfully" ) for (@ARGV);
 
-       # rm_f dir
-       @ARGV = my $dir = File::Spec->catfile( 'ecmddir' );
-       rm_rf();
-       ok( ! -e $dir, "removed $dir successfully" );
+    # rm_f dir
+    @ARGV = my $dir = File::Spec->catfile( 'ecmddir' );
+    rm_rf();
+    ok( ! -e $dir, "removed $dir successfully" );
 }
 
 END {
-       1 while unlink 'ecmdfile';
-       File::Path::rmtree( 'ecmddir' );
+    1 while unlink 'ecmdfile', 'newfile';
+    File::Path::rmtree( 'ecmddir' );
 }
index d6780ac..5c4aaeb 100644 (file)
@@ -60,7 +60,7 @@ is( $mm->{VERSION}, 0.01,            'VERSION' );
 
 my $config_prefix = $Config{installprefixexp} || $Config{installprefix} ||
                     $Config{prefixexp}        || $Config{prefix};
-is( $mm->{PREFIX}, $config_prefix,   'PREFIX' );
+is( $mm->{PERLPREFIX}, '$(DESTDIR)'.$config_prefix,   'PERLPREFIX' );
 
 is( !!$mm->{PERL_CORE}, !!$ENV{PERL_CORE}, 'PERL_CORE' );
 
index 8af8c30..99c1ae0 100644 (file)
@@ -16,7 +16,7 @@ BEGIN {
 }
 
 use strict;
-use Test::More tests => 26;
+use Test::More tests => 38;
 use MakeMaker::Test::Utils;
 use ExtUtils::MakeMaker;
 use File::Spec;
@@ -38,15 +38,15 @@ my $Updir  = File::Spec->updir;
 ok( chdir 'Big-Dummy', "chdir'd to Big-Dummy" ) ||
   diag("chdir failed: $!");
 
-my $PREFIX = File::Spec->catdir('foo', 'bar');
 my $stdout = tie *STDOUT, 'TieOut' or die;
+
 my $mm = WriteMakefile(
     NAME          => 'Big::Dummy',
     VERSION_FROM  => 'lib/Big/Dummy.pm',
     PREREQ_PM     => {},
     PERL_CORE     => $ENV{PERL_CORE},
-    PREFIX        => $PREFIX,
 );
+
 like( $stdout->read, qr{
                         Writing\ $Makefile\ for\ Big::Liar\n
                         Big::Liar's\ vars\n
@@ -54,15 +54,43 @@ like( $stdout->read, qr{
                         INST_ARCHLIB\ =\ \S+\n
                         Writing\ $Makefile\ for\ Big::Dummy\n
 }x );
-undef $stdout;
-untie *STDOUT;
 
 isa_ok( $mm, 'ExtUtils::MakeMaker' );
 
 is( $mm->{NAME}, 'Big::Dummy',  'NAME' );
 is( $mm->{VERSION}, 0.01,            'VERSION' );
 
-is( $mm->{PREFIX}, $PREFIX,   'PREFIX' );
+foreach my $prefix (qw(PREFIX PERLPREFIX SITEPREFIX VENDORPREFIX)) {
+    unlike( $mm->{$prefix}, qr/\$\(PREFIX\)/ );
+    like( $mm->{$prefix}, qr/^\$\(DESTDIR\)/, 
+                                   "\$(DESTDIR) prepended to $prefix" );
+}
+
+
+my $PREFIX = File::Spec->catdir('foo', 'bar');
+$mm = WriteMakefile(
+    NAME          => 'Big::Dummy',
+    VERSION_FROM  => 'lib/Big/Dummy.pm',
+    PREREQ_PM     => {},
+    PERL_CORE     => $ENV{PERL_CORE},
+    PREFIX        => $PREFIX,
+);
+like( $stdout->read, qr{
+                        Writing\ $Makefile\ for\ Big::Liar\n
+                        Big::Liar's\ vars\n
+                        INST_LIB\ =\ \S+\n
+                        INST_ARCHLIB\ =\ \S+\n
+                        Writing\ $Makefile\ for\ Big::Dummy\n
+}x );
+undef $stdout;
+untie *STDOUT;
+
+is( $mm->{PREFIX}, '$(DESTDIR)'.$PREFIX,   'PREFIX' );
+
+foreach my $prefix (qw(PERLPREFIX SITEPREFIX VENDORPREFIX)) {
+    is( $mm->{$prefix}, '$(DESTDIR)$(PREFIX)', 
+                                       "\$(PREFIX) overrides $prefix" );
+}
 
 is( !!$mm->{PERL_CORE}, !!$ENV{PERL_CORE}, 'PERL_CORE' );
 
@@ -80,36 +108,28 @@ is( $mm_perl_src, $perl_src,     'PERL_SRC' );
 
 
 # Every INSTALL* variable must start with some PREFIX.
-my @Perl_Install = qw(archlib    privlib   bin     script 
-                      man1dir       man3dir);
-my @Site_Install = qw(sitearch   sitelib   sitebin        
-                      siteman1dir siteman3dir);
-my @Vend_Install = qw(vendorarch vendorlib vendorbin 
-                      vendorman1dir vendorman3dir);
-
-foreach my $var (@Perl_Install) {
-    my $prefix = $Is_VMS ? '[.foo.bar' : File::Spec->catdir(qw(foo bar));
-
-    # support for man page skipping
-    $prefix = 'none' if $var =~ /man/ && !$Config{"install$var"};
-    like( $mm->{uc "install$var"}, qr/^\Q$prefix\E/, "PREFIX + $var" );
-}
+my %Install_Vars = (
+ PERL   => [qw(archlib    privlib   bin       man1dir       man3dir   script)],
+ SITE   => [qw(sitearch   sitelib   sitebin   siteman1dir   siteman3dir)],
+ VENDOR => [qw(vendorarch vendorlib vendorbin vendorman1dir vendorman3dir)]
+);
 
-foreach my $var (@Site_Install) {
-    my $prefix = $Is_VMS ? '[.foo.bar' : File::Spec->catdir(qw(foo bar));
+while( my($type, $vars) = each %Install_Vars) {
 
-    like( $mm->{uc "install$var"}, qr/^\Q$prefix\E/, 
-                                                    "SITEPREFIX + $var" );
-}
+    SKIP: foreach my $var (@$vars) {
+        skip "VMS must expand macros in INSTALL* vars", scalar @$vars 
+          if $Is_VMS;
 
-foreach my $var (@Vend_Install) {
-    my $prefix = $Is_VMS ? '[.foo.bar' : File::Spec->catdir(qw(foo bar));
+        my $prefix = '$('.$type.'PREFIX)';
 
-    like( $mm->{uc "install$var"}, qr/^\Q$prefix\E/,
-                                                    "VENDORPREFIX + $var" );
+        # support for man page skipping
+        $prefix = 'none' if $type eq 'PERL' && 
+                            $var =~ /man/ && 
+                            !$Config{"install$var"};
+        like( $mm->{uc "install$var"}, qr/^\Q$prefix\E/, "$prefix + $var" );
+    }
 }
 
-
 # Check that when installman*dir isn't set in Config no man pages
 # are generated.
 {
diff --git a/lib/ExtUtils/t/Install.t b/lib/ExtUtils/t/Install.t
new file mode 100644 (file)
index 0000000..042412b
--- /dev/null
@@ -0,0 +1,68 @@
+#!/usr/bin/perl -w
+
+# Test ExtUtils::Install.
+
+BEGIN {
+    if( $ENV{PERL_CORE} ) {
+        @INC = ('../lib', 'lib');
+    }
+    else {
+        unshift @INC, 't/lib';
+    }
+}
+chdir 't';
+
+use strict;
+use TieOut;
+use File::Path;
+use File::Spec;
+
+use Test::More tests => 18;
+
+BEGIN { use_ok('ExtUtils::Install') }
+
+# Check exports.
+foreach my $func (qw(install uninstall pm_to_blib install_default)) {
+    can_ok(__PACKAGE__, $func);
+}
+
+
+chdir 'Big-Dummy';
+
+my $stdout = tie *STDOUT, 'TieOut';
+pm_to_blib( { 'lib/Big/Dummy.pm' => 'blib/lib/Big/Dummy.pm' },
+            'blib/lib/auto'
+          );
+ok( -d 'blib/lib',              'pm_to_blib created blib dir' );
+ok( -r 'blib/lib/Big/Dummy.pm', '  copied .pm file' );
+ok( -r 'blib/lib/auto',         '  created autosplit dir' );
+is( $stdout->read, "cp lib/Big/Dummy.pm blib/lib/Big/Dummy.pm\n" );
+
+pm_to_blib( { 'lib/Big/Dummy.pm' => 'blib/lib/Big/Dummy.pm' },
+            'blib/lib/auto'
+          );
+ok( -d 'blib/lib',              'second run, blib dir still there' );
+ok( -r 'blib/lib/Big/Dummy.pm', '  .pm file still there' );
+ok( -r 'blib/lib/auto',         '  autosplit still there' );
+is( $stdout->read, "Skip blib/lib/Big/Dummy.pm (unchanged)\n" );
+
+
+install( { 'blib/lib' => 'install-test/lib/perl',
+           read   => 'install-test/packlist',
+           write  => 'install-test/packlist'
+         } );
+ok( -d 'install-test/lib/perl',                 'install made dir' );
+ok( -r 'install-test/lib/perl/Big/Dummy.pm',    '  .pm file installed' );
+ok( -r 'install-test/packlist',                 '  packlist exists' );
+
+open(PACKLIST, 'install-test/packlist' );
+my %packlist = map { chomp;  ($_ => 1) } <PACKLIST>;
+close PACKLIST;
+
+# On case-insensitive filesystems (ie. VMS), the keys of the packlist might 
+# be lowercase. :(
+my $native_dummy = File::Spec->catfile(qw(install-test lib perl Big Dummy.pm));
+is( keys %packlist, 1 );
+is( lc((keys %packlist)[0]), lc $native_dummy, 'packlist written' );
+
+END { rmtree 'blib' }
diff --git a/lib/ExtUtils/t/Liblist.t b/lib/ExtUtils/t/Liblist.t
new file mode 100644 (file)
index 0000000..2ba1653
--- /dev/null
@@ -0,0 +1,35 @@
+#!/usr/bin/perl -w
+
+BEGIN {
+    if( $ENV{PERL_CORE} ) {
+        chdir 't' if -d 't';
+        unshift @INC, '../lib';
+    }
+    else {
+        unshift @INC, 't/lib';
+    }
+}
+chdir 't';
+
+use strict;
+use Test::More tests => 6;
+use Data::Dumper;
+
+BEGIN {
+    use_ok( 'ExtUtils::Liblist' );
+}
+
+ok( defined &ExtUtils::Liblist::ext, 
+    'ExtUtils::Liblist::ext() defined for backwards compat' );
+
+{
+    my @warn;
+    local $SIG{__WARN__} = sub {push @warn, [@_]};
+
+    my @out = ExtUtils::Liblist->ext('-ln0tt43r3_perl');
+    is( @out, 4, 'enough output' );
+    unlike( $out[2], qr/-ln0tt43r3_perl/, 'bogus library not added' );
+    ok( @warn, 'had warning');
+
+    is( grep(/\QNote (probably harmless): No library found for \E(-l)?n0tt43r3_perl/, map { @$_ } @warn), 1 ) || diag Dumper @warn;
+}
index 870e8d4..3161176 100644 (file)
@@ -40,9 +40,16 @@ use File::Basename;
 
 require_ok( 'ExtUtils::MM_BeOS' );
 
-# perl_archive()
+
+# init_linker
 {
-    my $libperl = $Config{libperl} || 'libperl.a';
-    is( MM->perl_archive(), File::Spec->catfile('$(PERL_INC)', $libperl ),
-           'perl_archive() should respect libperl setting' );
+    my $libperl = File::Spec->catfile('$(PERL_INC)', 
+                                      $Config{libperl} || 'libperl.a' );
+    my $export  = '';
+    my $after   = '';
+    $MM->init_linker;
+
+    is( $MM->{PERL_ARCHIVE},        $libperl,   'PERL_ARCHIVE' );
+    is( $MM->{PERL_ARCHIVE_AFTER},  $after,     'PERL_ARCHIVE_AFTER' );
+    is( $MM->{EXPORT_LIST},         $export,    'EXPORT_LIST' );
 }
index 03641d3..bc4165e 100644 (file)
@@ -11,6 +11,7 @@ BEGIN {
 }
 chdir 't';
 
+use strict;
 use Test::More;
 
 BEGIN {
@@ -33,83 +34,81 @@ is( MM->canonpath('/a/../../c'), $path,
        'canonpath() method should work just like the one in File::Spec' );
 
 # test cflags, with the fake package below
-my $args = bless({
+my $MM = bless({
        CFLAGS  => 'fakeflags',
        CCFLAGS => '',
-}, MM);
+}, 'MM');
 
 # with CFLAGS set, it should be returned
-is( $args->cflags(), 'fakeflags',
+is( $MM->cflags(), 'fakeflags',
        'cflags() should return CFLAGS member data, if set' );
 
-delete $args->{CFLAGS};
+delete $MM->{CFLAGS};
 
 # ExtUtils::MM_Cygwin::cflags() calls this, fake the output
 {
     local $SIG{__WARN__} = sub { 
-        # no warnings 'redefine';
         warn @_ unless $_[0] =~ /^Subroutine .* redefined/;
     };
-    sub ExtUtils::MM_Unix::cflags { return $_[1] };
+    *ExtUtils::MM_Unix::cflags = sub { return $_[1] };
 }
 
 # respects the config setting, should ignore whitespace around equal sign
 my $ccflags = $Config{useshrplib} eq 'true' ? ' -DUSEIMPORTLIB' : '';
 {
-    local $args->{NEEDS_LINKING} = 1;
-    $args->cflags(<<FLAGS);
+    local $MM->{NEEDS_LINKING} = 1;
+    $MM->cflags(<<FLAGS);
 OPTIMIZE = opt
 PERLTYPE  =pt
 FLAGS
 }
 
-like( $args->{CFLAGS}, qr/OPTIMIZE = opt/, '... should set OPTIMIZE' );
-like( $args->{CFLAGS}, qr/PERLTYPE = pt/, '... should set PERLTYPE' );
-like( $args->{CFLAGS}, qr/CCFLAGS = $ccflags/, '... should set CCFLAGS' );
+like( $MM->{CFLAGS}, qr/OPTIMIZE = opt/, '... should set OPTIMIZE' );
+like( $MM->{CFLAGS}, qr/PERLTYPE = pt/, '... should set PERLTYPE' );
+like( $MM->{CFLAGS}, qr/CCFLAGS = $ccflags/, '... should set CCFLAGS' );
 
 # test manifypods
-$args = bless({
+$MM = bless({
        NOECHO => 'noecho',
        MAN3PODS => {},
        MAN1PODS => {},
     MAKEFILE => 'Makefile',
 }, 'MM');
-like( $args->manifypods(), qr/pure_all\n\tnoecho/,
+unlike( $MM->manifypods(), qr/foo/,
        'manifypods() should return without PODS values set' );
 
-$args->{MAN3PODS} = { foo => 1 };
-my $out = tie *STDOUT, 'FakeOut';
-{
-    local $SIG{__WARN__} = sub {
-        # no warnings 'redefine';
-        warn @_ unless $_[0] =~ /used only once/;
-    };
-    no warnings 'once';
-    local *MM::perl_script = sub { return };
-    my $res = $args->manifypods();
-    like( $$out, qr/could not locate your pod2man/,
-          '... should warn if pod2man cannot be located' );
-    like( $res, qr/POD2MAN_EXE = -S pod2man/,
-          '... should use default pod2man target' );
-    like( $res, qr/pure_all.+foo/, '... should add MAN3PODS targets' );
-}
+$MM->{MAN3PODS} = { foo => 'foo.1' };
+my $res = $MM->manifypods();
+like( $res, qr/pure_all.*foo.*foo.1/s, '... should add MAN3PODS targets' );
+
 
 SKIP: {
     skip "Only relevent in the core", 2 unless $ENV{PERL_CORE};
-    $args->{PERL_SRC} = File::Spec->updir;
-    $args->{MAN1PODS} = { bar => 1 };
-    $$out = '';
-    $res = $args->manifypods();
+    $MM->{PERL_SRC} = File::Spec->updir;
+    $MM->{MAN1PODS} = { bar => 1 };
+    my $out = tie *STDOUT, 'FakeOut';
+    $res = $MM->manifypods();
     is( $$out, '', '... should not warn if PERL_SRC provided' );
     like( $res, qr/bar \\\n\t1 \\\n\tfoo/,
           '... should join MAN1PODS and MAN3PODS');
 }
 
-# test perl_archive
-my $libperl = $Config{libperl} || 'libperl.a';
-$libperl =~ s/\.a/.dll.a/;
-is( $args->perl_archive(), "\$(PERL_INC)/$libperl",
-       'perl_archive() should respect libperl setting' );
+
+# init_linker
+{
+    my $libperl = $Config{libperl} || 'libperl.a';
+    $libperl =~ s/\.a/.dll.a/ if $] >= 5.007;
+    $libperl = "\$(PERL_INC)/$libperl";
+
+    my $export  = '';
+    my $after   = '';
+    $MM->init_linker;
+
+    is( $MM->{PERL_ARCHIVE},        $libperl,   'PERL_ARCHIVE' );
+    is( $MM->{PERL_ARCHIVE_AFTER},  $after,     'PERL_ARCHIVE_AFTER' );
+    is( $MM->{EXPORT_LIST},         $export,    'EXPORT_LIST' );
+}
+
 
 
 package FakeOut;
index d2046ee..13359d1 100644 (file)
@@ -172,19 +172,20 @@ delete $ENV{PATH} unless $had_path;
           'clean() Makefile target' );
 }
 
-# perl_archive()
+
+# init_linker
 {
     my $libperl = $Config{libperl} || 'libperl.a';
-    is( $MM->perl_archive(), File::Spec->catfile('$(PERL_INC)', $libperl ),
-           'perl_archive() should respect libperl setting' );
-}
+    my $export  = '$(BASEEXT).def';
+    my $after   = '';
+    $MM->init_linker;
 
-# export_list
-{
-    my $mm_w32 = bless { BASEEXT => 'someext' }, 'MM';
-    is( $mm_w32->export_list(), 'someext.def', 'export_list()' );
+    is( $MM->{PERL_ARCHIVE},        $libperl,   'PERL_ARCHIVE' );
+    is( $MM->{PERL_ARCHIVE_AFTER},  $after,     'PERL_ARCHIVE_AFTER' );
+    is( $MM->{EXPORT_LIST},         $export,    'EXPORT_LIST' );
 }
 
+
 # canonpath()
 {
     my $path = 'SYS:/TEMP';
@@ -272,14 +273,6 @@ unlink "${script_name}$script_ext" if -f "${script_name}$script_ext";
 # xs_o() should look into that
 # top_targets() should look into that
 
-# manifypods()
-{
-    my $mm_w32 = bless { NOECHO    => '' }, 'MM';
-    like( $mm_w32->manifypods(),
-          qr/^\nmanifypods :\n\t\$\Q(NOOP)\E\n$/,
-          'manifypods() Makefile target' );
-}
-
 # dist_ci() should look into that
 # dist_core() should look into that
 
index 53b83f3..caf662e 100644 (file)
@@ -247,26 +247,29 @@ ok( ExtUtils::MM_OS2->file_name_is_absolute( '\foo' ),
 ok( ! ExtUtils::MM_OS2->file_name_is_absolute( 'arduk' ), 
        '... but not for paths with no leading slash or volume' );
 
-# perl_archive
-is( ExtUtils::MM_OS2->perl_archive(), '$(PERL_INC)/libperl$(LIB_EXT)', 
-       'perl_archive() should return a static string' );
 
-# perl_archive_after
+$mm->init_linker;
+
+# PERL_ARCHIVE
+is( $mm->{PERL_ARCHIVE}, '$(PERL_INC)/libperl$(LIB_EXT)', 'PERL_ARCHIVE' );
+
+# PERL_ARCHIVE_AFTER
 {
        my $aout = 0;
        local *OS2::is_aout;
        *OS2::is_aout = \$aout;
        
-       isnt( ExtUtils::MM_OS2->perl_archive_after(), '', 
-               'perl_archive_after() should return string without $is_aout set' );
+    $mm->init_linker;
+       isnt( $mm->{PERL_ARCHIVE_AFTER}, '',
+               'PERL_ARCHIVE_AFTER should be empty without $is_aout set' );
        $aout = 1;
-       is( ExtUtils::MM_OS2->perl_archive_after(), '', 
+       is( $mm->{PERL_ARCHIVE_AFTER}, '', 
                '... and blank string if it is set' );
 }
 
-# export_list
-is( ExtUtils::MM_OS2::export_list({ BASEEXT => 'foo' }), 'foo.def', 
-       'export_list() should add .def to BASEEXT member' );
+# EXPORT_LIST
+is( $mm->{EXPORT_LIST}, '$(BASEEXT).def', 
+       'EXPORT_LIST should add .def to BASEEXT member' );
 
 END {
        use File::Path;
index 1e47f1b..1e0e801 100644 (file)
@@ -18,7 +18,7 @@ BEGIN {
         plan skip_all => 'Non-Unix platform';
     }
     else {
-        plan tests => 112;
+        plan tests => 115;
     }
 }
 
@@ -79,14 +79,13 @@ foreach ( qw /
   dist_basics
   dist_ci
   dist_core
-  dist_dir
+  distdir
   dist_test
   dlsyms
   dynamic
   dynamic_bs
   dynamic_lib
   exescan
-  export_list
   extliblist
   find_perl
   fixin
@@ -103,7 +102,6 @@ foreach ( qw /
   makeaperl
   makefile
   manifypods
-  maybe_command_in_dirs
   needs_linking
   pasthru
   perldepend
@@ -165,10 +163,13 @@ is ($t->has_link_code(),1); is ($t->{HAS_LINK_CODE},1);
 ###############################################################################
 # libscan
 
-is ($t->libscan('RCS'),'','libscan on RCS');
-is ($t->libscan('CVS'),'','libscan on CVS');
-is ($t->libscan('SCCS'),'','libscan on SCCS');
-is ($t->libscan('Fatty'),'Fatty','libscan on something not RCS, CVS or SCCS');
+is ($t->libscan('foo/RCS/bar'),     '', 'libscan on RCS');
+is ($t->libscan('CVS/bar/car'),     '', 'libscan on CVS');
+is ($t->libscan('SCCS'),            '', 'libscan on SCCS');
+is ($t->libscan('.svn/something'),  '', 'libscan on Subversion');
+is ($t->libscan('foo/b~r'),         'foo/b~r', 'libscan on file with ~');
+
+is ($t->libscan('Fatty'), 'Fatty', 'libscan on something not a VC file' );
 
 ###############################################################################
 # maybe_command
@@ -214,6 +215,7 @@ is ($t->perl_script($self_name),$self_name, 'we pass as a perl_script()');
 ###############################################################################
 # perm_rw perm_rwx
 
+$t->init_PERM;
 is ($t->perm_rw(),'644', 'perm_rw() is 644');
 is ($t->perm_rwx(),'755', 'perm_rwx() is 755');
 
@@ -231,12 +233,13 @@ foreach (qw/ post_constants postamble post_initialize/)
 is ($t->replace_manpage_separator('Foo/Bar'),'Foo::Bar','manpage_separator'); 
 
 ###############################################################################
-# export_list, perl_archive, perl_archive_after
 
-foreach (qw/ export_list perl_archive perl_archive_after/)
-  {
-  is ($t->$_(),'',"$_() is empty string on Unix"); 
-  }
+$t->init_linker;
+foreach (qw/ EXPORT_LIST PERL_ARCHIVE PERL_ARCHIVE_AFTER /)
+{
+    ok( exists $t->{$_}, "$_ was defined" );
+    is( $t->{$_}, '', "$_ is empty on Unix"); 
+}
 
 
 {
index 303a599..9ae57c6 100644 (file)
@@ -19,7 +19,6 @@ BEGIN {
                    find_perl
                    path
                    maybe_command
-                   maybe_command_in_dirs
                    perl_script
                    file_name_is_absolute
                    replace_manpage_separator
@@ -49,7 +48,7 @@ BEGIN {
                    realclean
                    dist_basics
                    dist_core
-                   dist_dir
+                   distdir
                    dist_test
                    install
                    perldepend
index 8e2b52c..315b915 100644 (file)
@@ -16,7 +16,7 @@ use Test::More;
 
 BEGIN {
        if ($^O =~ /MSWin32/i) {
-               plan tests => 40;
+               plan tests => 42;
        } else {
                plan skip_all => 'This is not Win32';
        }
@@ -84,7 +84,7 @@ delete $ENV{PATHEXT} unless $had_pathext;
 {
     my $my_perl = $1 if $^X  =~ /(.*)/; # are we in -T or -t?
     my( $perl, $path ) = fileparse( $my_perl );
-    like( $MM->find_perl( $], [ $perl ], [ $path ] ), 
+    like( $MM->find_perl( $], [ $perl ], [ $path ], 0 ), \r
           qr/^\Q$my_perl\E$/i, 'find_perl() finds this perl' );
 }
 
@@ -122,32 +122,44 @@ delete $ENV{PATHEXT} unless $had_pathext;
 }
 
 # constants()
+# XXX this test is probably useless now that we can call individual
+# init_* methods and check the keys in $mm_w32 directly
 {
     my $mm_w32 = bless {
         NAME         => 'TestMM_Win32', 
         VERSION      => '1.00',
-        VERSION_FROM => 'TestMM_Win32',
         PM           => { 'MM_Win32.pm' => 1 },
     }, 'MM';
 
     # XXX Hack until we have a proper init method.
     # Flesh out some necessary keys in the MM object.
-    foreach my $key (qw(XS C O_FILES H HTMLLIBPODS HTMLSCRIPTPODS
-                        MAN1PODS MAN3PODS PARENT_NAME)) {
-        $mm_w32->{$key} = '';
-    }
+    @{$mm_w32}{qw(XS MAN1PODS MAN3PODS)} = ({}) x 3;
+    @{$mm_w32}{qw(C O_FILES H)}          = ([]) x 3;
+    @{$mm_w32}{qw(PARENT_NAME)}          = ('') x 3;
+    $mm_w32->{FULLEXT} = 'TestMM_Win32';
+    $mm_w32->{BASEEXT} = 'TestMM_Win32';
+
+    $mm_w32->init_VERSION;
+    $mm_w32->init_linker;
+    $mm_w32->init_INST;
+    $mm_w32->init_xs;
+
     my $s_PM = join( " \\\n\t", sort keys %{$mm_w32->{PM}} );
     my $k_PM = join( " \\\n\t", %{$mm_w32->{PM}} );
 
-    like( $mm_w32->constants(),
-          qr|^NAME\ =\ TestMM_Win32\s+VERSION\ =\ 1\.00.+
-             MAKEMAKER\ =\ \Q$INC{'ExtUtils/MakeMaker.pm'}\E\s+
-             MM_VERSION\ =\ \Q$ExtUtils::MakeMaker::VERSION\E.+
-             VERSION_FROM\ =\ TestMM_Win32.+
-             TO_INST_PM\ =\ \Q$s_PM\E\s+
-             PM_TO_BLIB\ =\ \Q$k_PM\E
-          |xs, 'constants()' );
-
+    my $constants = $mm_w32->constants;
+
+    foreach my $regex (
+         qr|^NAME       \s* = \s* TestMM_Win32 \s* $|xms,
+         qr|^VERSION    \s* = \s* 1\.00 \s* $|xms,
+         qr|^MAKEMAKER  \s* = \s* \Q$INC{'ExtUtils/MakeMaker.pm'}\E \s* $|xms,
+         qr|^MM_VERSION \s* = \s* \Q$ExtUtils::MakeMaker::VERSION\E \s* $|xms,
+         qr|^TO_INST_PM \s* = \s* \Q$s_PM\E \s* $|xms,
+         qr|^PM_TO_BLIB \s* = \s* \Q$k_PM\E \s* $|xms,
+        )
+    {
+        like( $constants, $regex, 'constants() check' );
+    }
 }
 
 # path()
@@ -172,17 +184,17 @@ delete $ENV{PATH} unless $had_path;
           'clean() Makefile target' );
 }
 
-# perl_archive()
+# init_linker
 {
-    my $libperl = $Config{libperl} || 'libperl.a';
-    is( $MM->perl_archive(), File::Spec->catfile('$(PERL_INC)', $libperl ),
-           'perl_archive() should respect libperl setting' );
-}
-
-# export_list
-{
-    my $mm_w32 = bless { BASEEXT => 'someext' }, 'MM';
-    is( $mm_w32->export_list(), 'someext.def', 'export_list()' );
+    my $libperl = File::Spec->catfile('$(PERL_INC)', 
+                                      $Config{libperl} || 'libperl.a');
+    my $export  = '$(BASEEXT).def';
+    my $after   = '';
+    $MM->init_linker;
+
+    is( $MM->{PERL_ARCHIVE},        $libperl,   'PERL_ARCHIVE' );
+    is( $MM->{PERL_ARCHIVE_AFTER},  $after,     'PERL_ARCHIVE_AFTER' );
+    is( $MM->{EXPORT_LIST},         $export,    'EXPORT_LIST' );
 }
 
 # canonpath()
@@ -234,52 +246,9 @@ EOSCRIPT
 unlink "${script_name}$script_ext" if -f "${script_name}$script_ext";
 
 
-# pm_to_blib()
-{
-    like( $MM->pm_to_blib(),
-          qr/^pm_to_blib: \Q$(TO_INST_PM)\E.+\Q$(TOUCH) \E\$@\s+$/ms,
-          'pm_to_blib' );
-}
-
-# tool_autosplit()
-{
-    my %attribs = ( MAXLEN => 255 );
-    like( $MM->tool_autosplit( %attribs ),
-          qr/^\#\ Usage:\ \$\(AUTOSPLITFILE\)
-             \ FileToSplit\ AutoDirToSplitInto.+
-             AUTOSPLITFILE\ =\ \$\(PERLRUN\)\ .+
-             \$AutoSplit::Maxlen=$attribs{MAXLEN};
-          /xms,
-          'tool_autosplit()' );
-}
-
-# tools_other()
-{
-    ( my $mm_w32 = bless { }, 'MM' )->init_others();
-        
-    my $bin_sh = ( $Config{make} =~ /^dmake/i 
-               ? "" : ($Config{sh} || 'cmd /c') . "\n" );
-    $bin_sh = "SHELL = $bin_sh" if $bin_sh;
-
-    my $tools = join "\n", map "$_ = $mm_w32->{ $_ }"
-       => qw(CHMOD CP LD MV NOOP RM_F RM_RF TEST_F TOUCH UMASK_NULL DEV_NULL);
-
-    like( $mm_w32->tools_other(),
-          qr/^\Q$bin_sh$tools/m,
-          'tools_other()' );
-};
-
 # xs_o() should look into that
 # top_targets() should look into that
 
-# manifypods()
-{
-    my $mm_w32 = bless { NOECHO    => '' }, 'MM';
-    like( $mm_w32->manifypods(),
-          qr/^\nmanifypods :\n\t\$\Q(NOOP)\E\n$/,
-          'manifypods() Makefile target' );
-}
-
 # dist_ci() should look into that
 # dist_core() should look into that
 
index 7a488be..4d76b94 100644 (file)
@@ -14,7 +14,7 @@ chdir 't';
 use strict;
 
 # these files help the test run
-use Test::More tests => 33;
+use Test::More tests => 37;
 use Cwd;
 
 # these files are needed for the module itself
@@ -28,12 +28,12 @@ use File::Path;
 # keep track of everything added so it can all be deleted
 my %files;
 sub add_file {
-       my ($file, $data) = @_;
-       $data ||= 'foo';
+    my ($file, $data) = @_;
+    $data ||= 'foo';
     unlink $file;  # or else we'll get multiple versions on VMS
-       open( T, '>'.$file) or return;
-       print T $data;
-       ++$files{$file};
+    open( T, '>'.$file) or return;
+    print T $data;
+    ++$files{$file};
     close T;
 }
 
@@ -58,7 +58,7 @@ sub remove_dir {
 BEGIN { 
     use_ok( 'ExtUtils::Manifest', 
             qw( mkmanifest manicheck filecheck fullcheck 
-                maniread manicopy skipcheck ) ); 
+                maniread manicopy skipcheck maniadd) ); 
 }
 
 my $cwd = Cwd::getcwd();
@@ -173,12 +173,21 @@ like( $warn, qr{^Skipping moretest/quux$}i, 'got skipping warning again' );
 # There was a bug where entries in MANIFEST would be blotted out
 # by MANIFEST.SKIP rules.
 add_file( 'MANIFEST.SKIP' => 'foo' );
-add_file( 'MANIFEST'      => 'foobar'   );
+add_file( 'MANIFEST'      => "foobar\n"   );
 add_file( 'foobar'        => '123' );
 ($res, $warn) = catch_warning( \&manicheck );
 is( $res,  '',      'MANIFEST overrides MANIFEST.SKIP' );
 is( $warn, undef,   'MANIFEST overrides MANIFEST.SKIP, no warnings' );
 
+$files = maniread;
+ok( !$files->{wibble},     'MANIFEST in good state' );
+maniadd({ wibble => undef });
+maniadd({ yarrow => "hock" });
+$files = maniread;
+is( $files->{wibble}, '',    'maniadd() with undef comment' );
+is( $files->{yarrow}, 'hock','          with comment' );
+is( $files->{foobar}, '',    '          preserved old entries' );
+
 
 END {
        # the args are evaluated in scalar context
index 9080434..4e0a607 100644 (file)
@@ -14,12 +14,15 @@ BEGIN {
 }
 
 use strict;
-use Test::More tests => 17;
+use Config;
+
+use Test::More tests => 48;
 use MakeMaker::Test::Utils;
+use File::Find;
 use File::Spec;
-use TieOut;
 
 my $perl = which_perl();
+my $Is_VMS = $^O eq 'VMS';
 
 my $root_dir = 't';
 
@@ -93,20 +96,93 @@ my $make = make_run();
 
 END { unlink 'MANIFEST'; }
 
+
+`$make ppd`;
+is( $?, 0,                      '  exited normally' );
+ok( open(PPD, 'Big-Dummy.ppd'), '  .ppd file generated' );
+my $ppd_html;
+{ local $/; $ppd_html = <PPD> }
+close PPD;
+like( $ppd_html, qr{^<SOFTPKG NAME="Big-Dummy" VERSION="0,01,0,0">}m, 
+                                                           '  <SOFTPKG>' );
+like( $ppd_html, qr{^\s*<TITLE>Big-Dummy</TITLE>}m,        '  <TITLE>'   );
+like( $ppd_html, qr{^\s*<ABSTRACT>Try "our" hot dog's</ABSTRACT>}m,         
+                                                           '  <ABSTRACT>');
+like( $ppd_html, 
+      qr{^\s*<AUTHOR>Michael G Schwern &lt;schwern\@pobox.com&gt;</AUTHOR>}m,
+                                                           '  <AUTHOR>'  );
+like( $ppd_html, qr{^\s*<IMPLEMENTATION>}m,          '  <IMPLEMENTATION>');
+like( $ppd_html, qr{^\s*<DEPENDENCY NAME="strict" VERSION="0,0,0,0" />}m,
+                                                           '  <DEPENDENCY>' );
+like( $ppd_html, qr{^\s*<OS NAME="$Config{osname}" />}m,
+                                                           '  <OS>'      );
+like( $ppd_html, qr{^\s*<ARCHITECTURE NAME="$Config{archname}" />}m,  
+                                                           '  <ARCHITECTURE>');
+like( $ppd_html, qr{^\s*<CODEBASE HREF="" />}m,            '  <CODEBASE>');
+like( $ppd_html, qr{^\s*</IMPLEMENTATION>}m,           '  </IMPLEMENTATION>');
+like( $ppd_html, qr{^\s*</SOFTPKG>}m,                      '  </SOFTPKG>');
+END { unlink 'Big-Dummy.ppd' }
+
+
 my $test_out = `$make test`;
 like( $test_out, qr/All tests successful/, 'make test' );
-is( $?, 0 );
+is( $?, 0,                                 '  exited normally' );
 
 # Test 'make test TEST_VERBOSE=1'
 my $make_test_verbose = make_macro($make, 'test', TEST_VERBOSE => 1);
 $test_out = `$make_test_verbose`;
 like( $test_out, qr/ok \d+ - TEST_VERBOSE/, 'TEST_VERBOSE' );
-like( $test_out, qr/All tests successful/, '  successful' );
-is( $?, 0 );
+like( $test_out, qr/All tests successful/,  '  successful' );
+is( $?, 0,                                  '  exited normally' );
+
+
+my $install_out = `$make install`;
+is( $?, 0, 'install' ) || diag $install_out;
+like( $install_out, qr/^Installing /m );
+like( $install_out, qr/^Writing /m );
+
+ok( -r 'dummy-install',     '  install dir created' );
+my %files = ();
+find( sub { 
+    # do it case-insensitive for non-case preserving OSs
+    $files{lc $_} = $File::Find::name; 
+}, 'dummy-install' );
+ok( $files{'dummy.pm'},     '  Dummy.pm installed' );
+ok( $files{'liar.pm'},      '  Liar.pm installed'  );
+ok( $files{'.packlist'},    '  packlist created'   );
+ok( $files{'perllocal.pod'},'  perllocal.pod created' );
+
+
+SKIP: {
+    skip "VMS install targets do not preserve PREFIX", 8 if $Is_VMS;
+
+    $install_out = `$make install PREFIX=elsewhere`;
+    is( $?, 0, 'install with PREFIX override' ) || diag $install_out;
+    like( $install_out, qr/^Installing /m );
+    like( $install_out, qr/^Writing /m );
+
+    ok( -r 'elsewhere',     '  install dir created' );
+    %files = ();
+    find( sub { $files{$_} = $File::Find::name; }, 'elsewhere' );
+    ok( $files{'Dummy.pm'},     '  Dummy.pm installed' );
+    ok( $files{'Liar.pm'},      '  Liar.pm installed'  );
+    ok( $files{'.packlist'},    '  packlist created'   );
+    ok( $files{'perllocal.pod'},'  perllocal.pod created' );
+}
+
 
 my $dist_test_out = `$make disttest`;
 is( $?, 0, 'disttest' ) || diag($dist_test_out);
 
+# Test META.yml generation
+use ExtUtils::Manifest qw(maniread);
+ok( -f 'META.yml',    'META.yml written' );
+my $manifest = maniread();
+# VMS is non-case preserving, so we can't know what the MANIFEST will
+# look like. :(
+_normalize($manifest);
+is( $manifest->{'meta.yml'}, 'Module meta-data in YAML' );
+
 
 # Make sure init_dirscan doesn't go into the distdir
 @mpl_out = `$perl Makefile.PL "PREFIX=dummy-install"`;
@@ -114,8 +190,7 @@ is( $?, 0, 'disttest' ) || diag($dist_test_out);
 cmp_ok( $?, '==', 0, 'Makefile.PL exited with zero' ) ||
   diag(@mpl_out);
 
-ok( grep(/^Writing $makefile for Big::Dummy/, 
-         @mpl_out) == 1,
+ok( grep(/^Writing $makefile for Big::Dummy/, @mpl_out) == 1,
                                 'init_dirscan skipped distdir') || 
   diag(@mpl_out);
 
@@ -129,3 +204,13 @@ is( $?, 0, 'realclean' ) || diag($realclean_out);
 
 open(STDERR, ">&SAVERR") or die $!;
 close SAVERR;
+
+
+sub _normalize {
+    my $hash = shift;
+
+    while(my($k,$v) = each %$hash) {
+        delete $hash->{$k};
+        $hash->{lc $k} = $v;
+    }
+}
index 62608d7..b74690f 100644 (file)
@@ -11,10 +11,16 @@ BEGIN {
 }
 chdir 't';
 
+use File::Spec;
+
 use Test::More tests => 3;
 
+# Having the CWD in @INC masked a bug in finding hint files
+my $curdir = File::Spec->curdir;
+@INC = grep { $_ ne $curdir && $_ ne '.' } @INC;
+
 mkdir('hints', 0777);
-my $hint_file = "hints/$^O.pl";
+my $hint_file = File::Spec->catfile('hints', "$^O.pl");
 open(HINT, ">$hint_file") || die "Can't write dummy hints file $hint_file: $!";
 print HINT <<'CLOO';
 $self->{CCFLAGS} = 'basset hounds got long ears';
diff --git a/lib/ExtUtils/t/oneliner.t b/lib/ExtUtils/t/oneliner.t
new file mode 100644 (file)
index 0000000..5e0521b
--- /dev/null
@@ -0,0 +1,51 @@
+#!/usr/bin/perl -w
+
+BEGIN {
+    if( $ENV{PERL_CORE} ) {
+        chdir 't' if -d 't';
+        @INC = ('../lib', 'lib');
+    }
+    else {
+        unshift @INC, 't/lib';
+    }
+}
+
+chdir 't';
+
+use MakeMaker::Test::Utils;
+use Test::More tests => 6;
+use File::Spec;
+
+my $TB = Test::More->builder;
+
+BEGIN { use_ok('ExtUtils::MM') }
+
+my $mm = bless { NAME => "Foo" }, 'MM';
+isa_ok($mm, 'ExtUtils::MakeMaker');
+isa_ok($mm, 'ExtUtils::MM_Any');
+
+
+sub try_oneliner {
+    my($code, $switches, $expect, $name) = @_;
+    my $cmd = $mm->oneliner($code, $switches);
+    $cmd =~ s{\$\(PERLRUN\)}{$^X};
+
+    # VMS likes to put newlines at the end of commands if there isn't
+    # one already.
+    $expect =~ s/([^\n])\z/$1\n/ if $^O eq 'VMS';
+
+    $TB->is_eq(scalar `$cmd`, $expect, $name) || $TB->diag("oneliner:\n$cmd");
+}
+
+# Lets see how it deals with quotes.
+try_oneliner(q{print "foo'o", ' bar"ar'}, [],  q{foo'o bar"ar},  'quotes');
+
+# How about dollar signs?
+try_oneliner(q{$PATH = 'foo'; print $PATH},[], q{foo},   'dollar signs' );
+
+# switches?
+try_oneliner(q{print 'foo'}, ['-l'],           "foo\n",       'switches' );
+
+# XXX gotta rethink the newline test.  The Makefile does newline
+# escaping, then the shell.
+
index 0f92a4a..644bc00 100644 (file)
@@ -17,18 +17,24 @@ if( $^O eq 'VMS' ) {
     plan skip_all => 'prefixify works differently on VMS';
 }
 else {
-    plan tests => 2;
+    plan tests => 3;
 }
+use Config;
 use File::Spec;
 use ExtUtils::MM;
 
 my $mm = bless {}, 'MM';
 
 my $default = File::Spec->catdir(qw(this that));
+
 $mm->prefixify('installbin', 'wibble', 'something', $default);
+is( $mm->{INSTALLBIN}, $Config{installbin},
+                                            'prefixify w/defaults');
 
+$mm->{ARGS}{PREFIX} = 'foo';
+$mm->prefixify('installbin', 'wibble', 'something', $default);
 is( $mm->{INSTALLBIN}, File::Spec->catdir('something', $default),
-                                            'prefixify w/defaults');
+                                            'prefixify w/defaults and PREFIX');
 
 {
     undef *ExtUtils::MM_Unix::Config;
diff --git a/lib/ExtUtils/t/prompt.t b/lib/ExtUtils/t/prompt.t
new file mode 100644 (file)
index 0000000..ec9aa10
--- /dev/null
@@ -0,0 +1,56 @@
+#!/usr/bin/perl -w
+
+BEGIN {
+    if( $ENV{PERL_CORE} ) {
+        chdir 't' if -d 't';
+        @INC = ('../lib', 'lib');
+    }
+    else {
+        unshift @INC, 't/lib';
+    }
+}
+
+use strict;
+use Test::More tests => 11;
+use ExtUtils::MakeMaker;
+use TieOut;
+use TieIn;
+
+eval q{
+    prompt();
+};
+like( $@, qr/^Not enough arguments for ExtUtils::MakeMaker::prompt/,
+                                            'no args' );
+
+eval {
+    prompt(undef);
+};
+like( $@, qr/^prompt function called without an argument/, 
+                                            'undef message' );
+
+my $stdout = tie *STDOUT, 'TieOut' or die;
+
+
+$ENV{PERL_MM_USE_DEFAULT} = 1;
+is( prompt("Foo?"), '',     'no default' );
+like( $stdout->read,  qr/^Foo\?\s*\n$/,      '  question' );
+
+is( prompt("Foo?", undef), '',     'undef default' );
+like( $stdout->read,  qr/^Foo\?\s*\n$/,      '  question' );
+
+is( prompt("Foo?", 'Bar!'), 'Bar!',     'default' );
+like( $stdout->read,  qr/^Foo\? \[Bar!\]\s+Bar!\n$/,      '  question' );
+
+
+SKIP: {
+    skip "eof() doesn't honor ties in 5.5.3", 3 if $] < 5.006;
+
+    $ENV{PERL_MM_USE_DEFAULT} = 0;
+    close STDIN;
+    my $stdin = tie *STDIN, 'TieIn' or die;
+    $stdin->write("From STDIN");
+    ok( !-t STDIN,      'STDIN not a tty' );
+
+    is( prompt("Foo?", 'Bar!'), 'From STDIN',     'from STDIN' );
+    like( $stdout->read,  qr/^Foo\? \[Bar!\]\s*$/,      '  question' );
+}
diff --git a/lib/ExtUtils/t/split_command.t b/lib/ExtUtils/t/split_command.t
new file mode 100644 (file)
index 0000000..49e2629
--- /dev/null
@@ -0,0 +1,66 @@
+#!/usr/bin/perl -w
+
+BEGIN {
+    if( $ENV{PERL_CORE} ) {
+        chdir 't' if -d 't';
+        @INC = ('../lib', 'lib');
+    }
+    else {
+        unshift @INC, 't/lib';
+    }
+}
+
+chdir 't';
+
+use ExtUtils::MM;
+use MakeMaker::Test::Utils;
+
+my $Is_VMS   = $^O eq 'VMS';
+my $Is_Win32 = $^O eq 'MSWin32';
+
+use Test::More tests => 7;
+
+my $perl = which_perl;
+my $mm = bless { NAME => "Foo" }, "MM";
+
+# I don't expect anything to have a length shorter than 256 chars.
+cmp_ok( $mm->max_exec_len, '>=', 256,   'max_exec_len' );
+
+my $echo = $mm->oneliner(q{print @ARGV}, ['-l']);
+
+# Force a short command length to make testing split_command easier.
+$mm->{_MAX_EXEC_LEN} = length($echo) + 15;
+is( $mm->max_exec_len, $mm->{_MAX_EXEC_LEN}, '  forced a short max_exec_len' );
+
+my @test_args = qw(foo bar baz yar car har ackapicklerootyjamboree);
+my @cmds = $mm->split_command($echo, @test_args);
+isnt( @cmds, 0 );
+
+@results = _run(@cmds);
+is( join('', @results), join('', @test_args));
+
+
+my %test_args = ( foo => 42, bar => 23, car => 'har' );
+$even_args = $mm->oneliner(q{print !(@ARGV % 2)});
+@cmds = $mm->split_command($even_args, %test_args);
+isnt( @cmds, 0 );
+
+@results = _run(@cmds);
+like( join('', @results ), qr/^1+$/,         'pairs preserved' );
+
+is( $mm->split_command($echo), 0,  'no args means no commands' );
+
+
+sub _run {
+    my @cmds = @_;
+
+    s{\$\(PERLRUN\)}{$perl} foreach @cmds;
+    if( $Is_VMS ) {
+        s{-\n}{} foreach @cmds
+    }
+    elsif( $Is_Win32 ) {
+        s{\\\n}{} foreach @cmds;
+    }
+
+    return map { s/\n+$//; $_ } map { `$_` } @cmds
+}
diff --git a/t/lib/TieIn.pm b/t/lib/TieIn.pm
new file mode 100644 (file)
index 0000000..a240867
--- /dev/null
@@ -0,0 +1,23 @@
+package TieIn;
+
+sub TIEHANDLE {
+    bless( \(my $scalar), $_[0]);
+}
+
+sub write {
+    my $self = shift;
+    $$self .= join '', @_;
+}
+
+sub READLINE {
+    my $self = shift;
+    $$self =~ s/^(.*\n?)//;
+    return $1;
+}
+
+sub EOF {
+    my $self = shift;
+    return !length $$self;
+}
+
+1;