This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Updated Module::Build to 0.35_08
authorDavid Golden <dagolden@cpan.org>
Wed, 18 Nov 2009 05:52:18 +0000 (00:52 -0500)
committerDavid Golden <dagolden@cpan.org>
Wed, 18 Nov 2009 05:52:18 +0000 (00:52 -0500)
0.35_08 - Mon Nov 16 22:38:28 EST 2009

 Bug fixes:

 - Multiple tests were failing due to dependency problems.  Author
   dependencies have been largely removed from core 'requires' into
   optional features.  Feature prereq detection and messaging have been
   expanded and bugs on older Perls have been removed.

0.35_07 - Sat Nov 14 17:14:39 EST 2009

 Bug fixes:

 - Auto-detection of abstract and author fixed for mixed-case POD headers
   (RT#51117) [David Wheeler]

 - resume() was not restoring additions to @INC added in Build.PL
   (RT#50145) [David Golden]

 - When tarball paths are less than 100 characters, disables 'prefix'
   mode of Archive::Tar for maximum compatibility (RT#50571) [David Golden]

0.35_06 - Fri Nov 13 14:51:28 EST 2009

 Enhancements:

 - Added experimental inc/ bundling; see Module::Build::Bundling for
   details.  [David Golden and Eric Wilhelm]

 - Clarified that 'apache' in the license attribute indicates the Apache
   License 2.0 and added 'apache_1_1' for the older version of the license
   (RT#50614) [David Golden]

 Bug fixes:

 - Merging 'requires' and 'build_requires' in Module::Build::Compat could
   lead to duplicate PREREQ_PM entries; now the highest version is used
   for PREREQ_PM. (RT#50948) [David Golden]

 - Module::Build::Compat will now die with an error if advanced,
   non-numeric prerequisites are given, as these are not supported by
   ExtUtils::MakeMaker in PREREQ_PM [David Golden]

 - Made MYMETA generation non-fatal if fields required for META.yml
   are missing [David Golden]

 - Added Pod::Simple to requirements for manpage support; avoids
   problems if a user has a broken Pod::Man/Pod::Simple.  (RT#50081)
   [David Golden]

 - Won't die if installed Pod::Readme is broken [David Golden]

 Other:

 - Fixed Module::Build::Notes POD [David Golden]

 - Some commands had become silent by default, so added a few short status
   messages so users know something actually happened [David Golden]

 - Cleaned up Changes file formatting [David Golden]

 - Removed most PERL_CORE customizations from test files due to
   reorganization of dual-life modules in core (RT#49522) [David Golden]

0.35_05 - Wed Oct 28 17:20:59 EDT 2009

 Bug fixes:

 - Fix test failure in t/actions/installdeps.t when $^X is not the default
   perl [David Golden]

 - Work around $VERSION numbers in ActiveState with multiple underscores
   that prevent Module::Build from installing on Win32 [David Golden]

 - Fix bug cleaning compatibility Makefile when older ExtUtils::Manifest is
   installed [David Golden with help from David Cantrell]

 Other:

 - Suppressed more warnings from tests [David Golden]

 - Add provisional support for 'package NAME VERSION' syntax added in
   Perl 5.11.1 [David Golden]

0.35_04 - Fri Oct 23 11:20:41 EDT 2009

 Bug fixes:

 - Fix test failure if IPC::Cmd isn't installed [David Golden]

 Other:

 - Suppressed warning messages from various tests [David Golden]

0.35_03 - Wed Oct 21 21:20:59 EDT 2009

 *** API CHANGE ***

 - The prepare_metadata() method used to take a YAML::Node object as an
   argument for modification.  The method now takes no arguments and just
   returns a hash reference of metadata. [David Golden]

 Enhancements

 - Command line options may be set via the PERL_MB_OPT environment
   variable (similar to PERL_MM_OPT in ExtUtils::MakeMaker)

 Bug fixes:

 - Updated PPM generation to PPM v4 (RT#49600) [Olivier Mengue]

 - When c_source is specified, the directory scan will include additional,
   less-common C++ extensions (RT49298) [David Golden]

 - When module_name is not supplied, no packlist was being written; fixed
   by guessing module_name from dist_version_from or the directory name
   (just like ExtUtils::Manifest does without NAME) [David Golden]

 - Bumped IO::File prereq to fix binmode failures in PPMMaker on Perl
   prior to 5.8.8 [David Golden]

 Other:

 - Replaced use of YAML.pm with YAML::Tiny; Module::Build::YAML is now
   based on YAML::Tiny as well [David Golden]

 - Reduced amount of console output under normal operation (use --verbose
   to see all output) [David Golden]

0.35_02 - Mon Sep  7 22:37:42 EDT 2009

 Enhancements:

 - Added 'needs_compiler' property.  Defaults to true if XS or c_source
   exist.  If true, ExtUtils::CBuilder is also added to build_requires.
   [David Golden]

 - File::ShareDir automatically added to 'requires' if 'share_dir' is set
   [David Golden]

 - Added 'Build installdeps' action to install needed dependencies via
   a user-configurable command line program.  (Defaults to 'cpan'.)
   [Eric Wilhelm]

 Bug fixes:

 - Failure to detect a compiler will now warn during Build.PL and be a
   fatal error when trying to compile during Build. (RT#48918) [David
   Golden]

 - Fixed directory sorting failure in share_dir.t [David Golden]

 - Property defaults that are data structures were being assigned as
   references to new objects. Changed so that defaults are cloned instead.
   (This mostly affects testing, which often creates multiple objects in the
   same process) [David Golden]

 - Simplified error message on exit under use_tap_harness [suggested by
   David Wheeler]

 - Fixed typemap search to use a dist-level typemap if a typemap is not
   found in the directory with the *.xs file; (was manifesting as warnings
   in Perl 5.6 tests) [David Golden]

 Other:

 - Replaced guts of new_from_context().  Build.PL is now executed in a
   separate process before resume() is called.  (This is generally only of
   interest to Module::Build or toolchain developers) (RT#49350) [David
   Golden, Eric Wilhelm, Ken Williams]

 - Revised test helper classes to fix potential bugs and add new features
   to make writing tests simpler and easier.  Changes incorporated into
   t/README.pod and t/sample.t as examples for new testing. [David Golden]

0.35_01 - Mon Aug 31 12:11:10 EDT 2009

 Enhancements:

 - Generates MYMETA.yml during Build.PL (new standard protocol for
   communicating configuration results between toolchain components)
   [David Golden]

 - Added 'share_dir' property to provide File::ShareDir support;
   set automatically if a directory called 'share' exists
   [David Golden]

 Bug fixes:

 - Fix the t/destinations.t fix. [David Golden, with thanks to Eric Wilhelm]

 - Fix recursive test files in generated Makefile.PL (RT#49254) [Sawyer X]

 - Guard against trying :utf8 when :utf8 isn't available

 - The "test" action now dies when using the 'use_tap_harness'
   option and tests fail, matching the behavior under Test::Harness.
   (RT#49080) [initial patch from David Wheeler; revised by David Golden]

 Other:

 - Added t/README.pod and t/sample.t to guide developers writing new tests
   [David Golden, with some code from Eric Wilhelm]

 - Module::Build::Compat 'passthrough' style has been deprecated.  Using
   'passthrough' will issue warnings on Makefile.PL generation.  See
   Module::Build::Compat documentation for rationale.

79 files changed:
.gitignore
MANIFEST
Porting/Maintainers.pl
cpan/Module-Build/Changes
cpan/Module-Build/lib/Module/Build.pm
cpan/Module-Build/lib/Module/Build/API.pod
cpan/Module-Build/lib/Module/Build/Base.pm
cpan/Module-Build/lib/Module/Build/Bundling.pod [new file with mode: 0644]
cpan/Module-Build/lib/Module/Build/Compat.pm
cpan/Module-Build/lib/Module/Build/Config.pm
cpan/Module-Build/lib/Module/Build/Cookbook.pm
cpan/Module-Build/lib/Module/Build/Dumper.pm
cpan/Module-Build/lib/Module/Build/ModuleInfo.pm
cpan/Module-Build/lib/Module/Build/Notes.pm
cpan/Module-Build/lib/Module/Build/PPMMaker.pm
cpan/Module-Build/lib/Module/Build/Platform/Amiga.pm
cpan/Module-Build/lib/Module/Build/Platform/Default.pm
cpan/Module-Build/lib/Module/Build/Platform/EBCDIC.pm
cpan/Module-Build/lib/Module/Build/Platform/MPEiX.pm
cpan/Module-Build/lib/Module/Build/Platform/MacOS.pm
cpan/Module-Build/lib/Module/Build/Platform/RiscOS.pm
cpan/Module-Build/lib/Module/Build/Platform/Unix.pm
cpan/Module-Build/lib/Module/Build/Platform/VMS.pm
cpan/Module-Build/lib/Module/Build/Platform/VOS.pm
cpan/Module-Build/lib/Module/Build/Platform/Windows.pm
cpan/Module-Build/lib/Module/Build/Platform/aix.pm
cpan/Module-Build/lib/Module/Build/Platform/cygwin.pm
cpan/Module-Build/lib/Module/Build/Platform/darwin.pm
cpan/Module-Build/lib/Module/Build/Platform/os2.pm
cpan/Module-Build/lib/Module/Build/PodParser.pm
cpan/Module-Build/lib/Module/Build/Version.pm
cpan/Module-Build/lib/Module/Build/YAML.pm
cpan/Module-Build/lib/inc/latest.pm [new file with mode: 0644]
cpan/Module-Build/lib/inc/latest/private.pm [new file with mode: 0644]
cpan/Module-Build/t/PL_files.t
cpan/Module-Build/t/README.pod [new file with mode: 0644]
cpan/Module-Build/t/actions/installdeps.t [new file with mode: 0644]
cpan/Module-Build/t/add_property.t
cpan/Module-Build/t/basic.t
cpan/Module-Build/t/bundle_inc.t [new file with mode: 0644]
cpan/Module-Build/t/compat.t
cpan/Module-Build/t/compat/exit.t [changed mode: 0644->0755]
cpan/Module-Build/t/debug.t
cpan/Module-Build/t/destinations.t
cpan/Module-Build/t/ext.t
cpan/Module-Build/t/extend.t
cpan/Module-Build/t/files.t
cpan/Module-Build/t/help.t
cpan/Module-Build/t/install.t
cpan/Module-Build/t/install_extra_target.t
cpan/Module-Build/t/lib/DistGen.pm
cpan/Module-Build/t/lib/MBTest.pm
cpan/Module-Build/t/manifypods.t
cpan/Module-Build/t/mbyaml.t [deleted file]
cpan/Module-Build/t/metadata.t
cpan/Module-Build/t/metadata2.t
cpan/Module-Build/t/moduleinfo.t
cpan/Module-Build/t/mymeta.t [new file with mode: 0644]
cpan/Module-Build/t/new_from_context.t
cpan/Module-Build/t/notes.t
cpan/Module-Build/t/parents.t
cpan/Module-Build/t/perl_mb_opt.t [new file with mode: 0644]
cpan/Module-Build/t/pod_parser.t
cpan/Module-Build/t/ppm.t
cpan/Module-Build/t/properties/module_name.t [new file with mode: 0644]
cpan/Module-Build/t/properties/needs_compiler.t [new file with mode: 0644]
cpan/Module-Build/t/properties/share_dir.t [new file with mode: 0644]
cpan/Module-Build/t/resume.t [new file with mode: 0644]
cpan/Module-Build/t/runthrough.t
cpan/Module-Build/t/sample.t [new file with mode: 0644]
cpan/Module-Build/t/script_dist.t
cpan/Module-Build/t/test_file_exts.t
cpan/Module-Build/t/test_type.t
cpan/Module-Build/t/test_types.t
cpan/Module-Build/t/tilde.t
cpan/Module-Build/t/use_tap_harness.t
cpan/Module-Build/t/versions.t
cpan/Module-Build/t/write_default_maniskip.t
cpan/Module-Build/t/xs.t

index 74b65eb..a20fbf9 100644 (file)
@@ -76,6 +76,7 @@ ext.libs
 /uudmap.h
 /bitcount.h
 
+lib/inc/
 lib/Win32.pm
 lib/Win32API/
 lib/Win32CORE.pm
index b8073eb..2d76a3a 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1519,9 +1519,12 @@ cpan/MIME-Base64/t/quoted-print.t        See whether MIME::QuotedPrint works
 cpan/MIME-Base64/t/unicode.t           See whether MIME::Base64 works
 cpan/MIME-Base64/t/warn.t              See whether MIME::Base64 works
 cpan/Module-Build/Changes                              Module::Build
+cpan/Module-Build/lib/inc/latest.pm                    Module::Build
+cpan/Module-Build/lib/inc/latest/private.pm            Module::Build
 cpan/Module-Build/lib/Module/Build/API.pod             Module::Build
 cpan/Module-Build/lib/Module/Build/Authoring.pod       Module::Build
 cpan/Module-Build/lib/Module/Build/Base.pm             Module::Build
+cpan/Module-Build/lib/Module/Build/Bundling.pod                Module::Build
 cpan/Module-Build/lib/Module/Build/Compat.pm           Module::Build
 cpan/Module-Build/lib/Module/Build/Config.pm           Module::Build
 cpan/Module-Build/lib/Module/Build/Cookbook.pm         Module::Build
@@ -1548,33 +1551,42 @@ cpan/Module-Build/lib/Module/Build/PPMMaker.pm          Module::Build
 cpan/Module-Build/lib/Module/Build/Version.pm          Module::Build
 cpan/Module-Build/lib/Module/Build/YAML.pm             Module::Build
 cpan/Module-Build/scripts/config_data                  Module::Build
+cpan/Module-Build/t/actions/installdeps.t              Module::Build
 cpan/Module-Build/t/add_property.t                     Module::Build
 cpan/Module-Build/t/basic.t                            Module::Build
-cpan/Module-Build/t/bundled/Tie/CPHash.pm              Module::Build.pm
+cpan/Module-Build/t/bundled/Tie/CPHash.pm              Module::Build
+cpan/Module-Build/t/bundle_inc.t                       Module::Build
 cpan/Module-Build/t/compat/exit.t                      Module::Build
 cpan/Module-Build/t/compat.t                           Module::Build
-cpan/Module-Build/t/debug.t                            Module::Build tests
+cpan/Module-Build/t/debug.t                            Module::Build
 cpan/Module-Build/t/destinations.t                     Module::Build
 cpan/Module-Build/t/extend.t                           Module::Build
 cpan/Module-Build/t/ext.t                              Module::Build
 cpan/Module-Build/t/files.t                            Module::Build
 cpan/Module-Build/t/help.t                             Module::Build
-cpan/Module-Build/t/install_extra_target.t             Module::Build tests
+cpan/Module-Build/t/install_extra_target.t             Module::Build
 cpan/Module-Build/t/install.t                          Module::Build
 cpan/Module-Build/t/lib/DistGen.pm                     Module::Build
 cpan/Module-Build/t/lib/MBTest.pm                      Module::Build
 cpan/Module-Build/t/manifypods.t                       Module::Build
-cpan/Module-Build/t/mbyaml.t                           Module::Build
 cpan/Module-Build/t/metadata2.t                                Module::Build
 cpan/Module-Build/t/metadata.t                         Module::Build
 cpan/Module-Build/t/moduleinfo.t                       Module::Build
+cpan/Module-Build/t/mymeta.t                           Module::Build
 cpan/Module-Build/t/new_from_context.t                 Module::Build
 cpan/Module-Build/t/notes.t                            Module::Build
 cpan/Module-Build/t/parents.t                          Module::Build
-cpan/Module-Build/t/PL_files.t                         Module::Build tests
+cpan/Module-Build/t/perl_mb_opt.t                      Module::Build
+cpan/Module-Build/t/PL_files.t                         Module::Build
 cpan/Module-Build/t/pod_parser.t                       Module::Build
 cpan/Module-Build/t/ppm.t                              Module::Build
+cpan/Module-Build/t/properties/module_name.t           Module::Build
+cpan/Module-Build/t/properties/needs_compiler.t                Module::Build
+cpan/Module-Build/t/properties/share_dir.t             Module::Build
+cpan/Module-Build/t/README.pod                         Module::Build
+cpan/Module-Build/t/resume.t                           Module::Build
 cpan/Module-Build/t/runthrough.t                       Module::Build
+cpan/Module-Build/t/sample.t                           Module::Build
 cpan/Module-Build/t/script_dist.t                      Module::Build
 cpan/Module-Build/t/test_file_exts.t                   Module::Build
 cpan/Module-Build/t/test_types.t                       Module::Build
@@ -1582,7 +1594,7 @@ cpan/Module-Build/t/test_type.t                           Module::Build
 cpan/Module-Build/t/tilde.t                            Module::Build
 cpan/Module-Build/t/use_tap_harness.t                  Module::Build
 cpan/Module-Build/t/versions.t                         Module::Build
-cpan/Module-Build/t/write_default_maniskip.t           Module::Build tests
+cpan/Module-Build/t/write_default_maniskip.t           Module::Build
 cpan/Module-Build/t/xs.t                               Module::Build
 cpan/Module-Load-Conditional/lib/Module/Load/Conditional.pm    Module::Conditional
 cpan/Module-Load-Conditional/t/01_Module_Load_Conditional.t    Module::Conditional tests
index e5db2eb..5ffa715 100755 (executable)
@@ -104,7 +104,7 @@ use File::Glob qw(:case);
     SIGNATURE THANKS TODO Todo VERSION WHATSNEW
 );
 
+
 # Each entry in the  %Modules hash roughly represents a distribution,
 # except in the case of CPAN=1, where it *exactly* represents a single
 # CPAN distribution.
@@ -159,7 +159,7 @@ use File::Glob qw(:case);
 # Each key reprepresents a string prefix, with longest prefixes checked
 # first. The first match causes that prefix to be replaced with the
 # corresponding key. For example, with the following MAP:
-#   { 
+#   {
 #     'lib/'    => 'lib/',
 #     ''        => 'lib/Foo/',
 #   },
@@ -167,7 +167,7 @@ use File::Glob qw(:case);
 # these files are mapped as shown:
 #
 #    README     becomes lib/Foo/README
-#    lib/Foo.pm becomes lib/Foo.pm 
+#    lib/Foo.pm becomes lib/Foo.pm
 #
 # The default is dependent on the type of module.
 # For distributions which appear to be stored under ext/, it defaults to:
@@ -176,7 +176,7 @@ use File::Glob qw(:case);
 #
 # otherwise, it's
 #
-#   { 
+#   {
 #     'lib/'    => 'lib/',
 #     ''        => 'lib/Foo/Bar/',
 #   }
@@ -1004,10 +1004,10 @@ use File::Glob qw(:case);
     'Module::Build' =>
        {
        'MAINTAINER'    => 'kwilliams',
-       'DISTRIBUTION'  => 'DAGOLDEN/Module-Build-0.35.tar.gz',
+       'DISTRIBUTION'  => 'DAGOLDEN/Module-Build-0.35_08.tar.gz',
        'FILES'         => q[cpan/Module-Build],
-       'EXCLUDED'      => [ qw{ t/par.t t/signature.t scripts/bundle.pl},
-                            qr!^contrib/! ],
+       'EXCLUDED'      => [ qw{ t/par.t t/signature.t },
+                            qr!^contrib/!,  qr!^devtools! ],
        'CPAN'          => 1,
        'UPSTREAM'      => 'cpan',
        },
index df66502..f0f8d1b 100644 (file)
 Revision history for Perl extension Module::Build.
 
+0.35_08 - Mon Nov 16 22:38:28 EST 2009
+
+ Bug fixes:
+
+ - Multiple tests were failing due to dependency problems.  Author
+   dependencies have been largely removed from core 'requires' into
+   optional features.  Feature prereq detection and messaging have been
+   expanded and bugs on older Perls have been removed.
+
+0.35_07 - Sat Nov 14 17:14:39 EST 2009
+
+ Bug fixes:
+
+ - Auto-detection of abstract and author fixed for mixed-case POD headers
+   (RT#51117) [David Wheeler]
+
+ - resume() was not restoring additions to @INC added in Build.PL
+   (RT#50145) [David Golden]
+
+ - When tarball paths are less than 100 characters, disables 'prefix'
+   mode of Archive::Tar for maximum compatibility (RT#50571) [David Golden]
+
+0.35_06 - Fri Nov 13 14:51:28 EST 2009
+
+ Enhancements:
+
+ - Added experimental inc/ bundling; see Module::Build::Bundling for
+   details.  [David Golden and Eric Wilhelm]
+
+ - Clarified that 'apache' in the license attribute indicates the Apache
+   License 2.0 and added 'apache_1_1' for the older version of the license
+   (RT#50614) [David Golden]
+
+ Bug fixes:
+
+ - Merging 'requires' and 'build_requires' in Module::Build::Compat could
+   lead to duplicate PREREQ_PM entries; now the highest version is used
+   for PREREQ_PM. (RT#50948) [David Golden]
+
+ - Module::Build::Compat will now die with an error if advanced,
+   non-numeric prerequisites are given, as these are not supported by
+   ExtUtils::MakeMaker in PREREQ_PM [David Golden]
+
+ - Made MYMETA generation non-fatal if fields required for META.yml
+   are missing [David Golden]
+
+ - Added Pod::Simple to requirements for manpage support; avoids
+   problems if a user has a broken Pod::Man/Pod::Simple.  (RT#50081)
+   [David Golden]
+
+ - Won't die if installed Pod::Readme is broken [David Golden]
+
+ Other:
+
+ - Fixed Module::Build::Notes POD [David Golden]
+
+ - Some commands had become silent by default, so added a few short status
+   messages so users know something actually happened [David Golden]
+
+ - Cleaned up Changes file formatting [David Golden]
+
+ - Removed most PERL_CORE customizations from test files due to
+   reorganization of dual-life modules in core (RT#49522) [David Golden]
+
+0.35_05 - Wed Oct 28 17:20:59 EDT 2009
+
+ Bug fixes:
+
+ - Fix test failure in t/actions/installdeps.t when $^X is not the default
+   perl [David Golden]
+
+ - Work around $VERSION numbers in ActiveState with multiple underscores
+   that prevent Module::Build from installing on Win32 [David Golden]
+
+ - Fix bug cleaning compatibility Makefile when older ExtUtils::Manifest is
+   installed [David Golden with help from David Cantrell]
+
+ Other:
+
+ - Suppressed more warnings from tests [David Golden]
+
+ - Add provisional support for 'package NAME VERSION' syntax added in
+   Perl 5.11.1 [David Golden]
+
+0.35_04 - Fri Oct 23 11:20:41 EDT 2009
+
+ Bug fixes:
+
+ - Fix test failure if IPC::Cmd isn't installed [David Golden]
+
+ Other:
+
+ - Suppressed warning messages from various tests [David Golden]
+
+0.35_03 - Wed Oct 21 21:20:59 EDT 2009
+
+ *** API CHANGE ***
+
+ - The prepare_metadata() method used to take a YAML::Node object as an
+   argument for modification.  The method now takes no arguments and just
+   returns a hash reference of metadata. [David Golden]
+
+ Enhancements
+
+ - Command line options may be set via the PERL_MB_OPT environment
+   variable (similar to PERL_MM_OPT in ExtUtils::MakeMaker)
+
+ Bug fixes:
+
+ - Updated PPM generation to PPM v4 (RT#49600) [Olivier Mengue]
+
+ - When c_source is specified, the directory scan will include additional,
+   less-common C++ extensions (RT49298) [David Golden]
+
+ - When module_name is not supplied, no packlist was being written; fixed
+   by guessing module_name from dist_version_from or the directory name
+   (just like ExtUtils::Manifest does without NAME) [David Golden]
+
+ - Bumped IO::File prereq to fix binmode failures in PPMMaker on Perl
+   prior to 5.8.8 [David Golden]
+
+ Other:
+
+ - Replaced use of YAML.pm with YAML::Tiny; Module::Build::YAML is now
+   based on YAML::Tiny as well [David Golden]
+
+ - Reduced amount of console output under normal operation (use --verbose
+   to see all output) [David Golden]
+
+0.35_02 - Mon Sep  7 22:37:42 EDT 2009
+
+ Enhancements:
+
+ - Added 'needs_compiler' property.  Defaults to true if XS or c_source
+   exist.  If true, ExtUtils::CBuilder is also added to build_requires.
+   [David Golden]
+
+ - File::ShareDir automatically added to 'requires' if 'share_dir' is set
+   [David Golden]
+
+ - Added 'Build installdeps' action to install needed dependencies via
+   a user-configurable command line program.  (Defaults to 'cpan'.)
+   [Eric Wilhelm]
+
+ Bug fixes:
+
+ - Failure to detect a compiler will now warn during Build.PL and be a
+   fatal error when trying to compile during Build. (RT#48918) [David
+   Golden]
+
+ - Fixed directory sorting failure in share_dir.t [David Golden]
+
+ - Property defaults that are data structures were being assigned as
+   references to new objects. Changed so that defaults are cloned instead.
+   (This mostly affects testing, which often creates multiple objects in the
+   same process) [David Golden]
+
+ - Simplified error message on exit under use_tap_harness [suggested by
+   David Wheeler]
+
+ - Fixed typemap search to use a dist-level typemap if a typemap is not
+   found in the directory with the *.xs file; (was manifesting as warnings
+   in Perl 5.6 tests) [David Golden]
+
+ Other:
+
+ - Replaced guts of new_from_context().  Build.PL is now executed in a
+   separate process before resume() is called.  (This is generally only of
+   interest to Module::Build or toolchain developers) (RT#49350) [David
+   Golden, Eric Wilhelm, Ken Williams]
+
+ - Revised test helper classes to fix potential bugs and add new features
+   to make writing tests simpler and easier.  Changes incorporated into
+   t/README.pod and t/sample.t as examples for new testing. [David Golden]
+
+0.35_01 - Mon Aug 31 12:11:10 EDT 2009
+
+ Enhancements:
+
+ - Generates MYMETA.yml during Build.PL (new standard protocol for
+   communicating configuration results between toolchain components)
+   [David Golden]
+
+ - Added 'share_dir' property to provide File::ShareDir support;
+   set automatically if a directory called 'share' exists
+   [David Golden]
+
+ Bug fixes:
+
+ - Fix the t/destinations.t fix. [David Golden, with thanks to Eric Wilhelm]
+
+ - Fix recursive test files in generated Makefile.PL (RT#49254) [Sawyer X]
+
+ - Guard against trying :utf8 when :utf8 isn't available
+
+ - The "test" action now dies when using the 'use_tap_harness'
+   option and tests fail, matching the behavior under Test::Harness.
+   (RT#49080) [initial patch from David Wheeler; revised by David Golden]
+
+ Other:
+
+ - Added t/README.pod and t/sample.t to guide developers writing new tests
+   [David Golden, with some code from Eric Wilhelm]
+
+ - Module::Build::Compat 'passthrough' style has been deprecated.  Using
+   'passthrough' will issue warnings on Makefile.PL generation.  See
+   Module::Build::Compat documentation for rationale.
+
 0.35 - Thu Aug 27 09:12:02 EDT 2009
 
  Bug fixes:
- - Fix t/destinations.t segfault on 5.6.2
+
+  - Fix t/destinations.t segfault on 5.6.2 [David Golden]
 
 0.34_06 - Sat Aug 22 21:58:26 EDT 2009
 
  Bug fixes:
+
  - Multiple test fixes for OS2 [Ilya Zakharevich]
+
  - Generated.ppd files use :utf8 if possible (RT#48827) [Olivier Mengue]
+
  - Fixed preservation of custom install_paths on resume (RT#41166)
    [David Golden]
+
  - Warn instead of crashing when Pod::Man tries to create files with
    colons on vfat partitions on unix (RT#45544) [David Golden]
 
 0.34_05 - Sun Aug  9 22:31:37 EDT 2009
 
  Bug fixes:
- - When auto_configure_requires is true (the default), Module::Build will 
+
+ - When auto_configure_requires is true (the default), Module::Build will
    only add last 'major' version of Module:Build (e.g. 0.XX) to
    configure_requires to avoid specifying a minor development release not
    available on CPAN [David Golden]
@@ -26,6 +240,7 @@ Revision history for Perl extension Module::Build.
 0.34_04 - Sat Aug  8 11:02:24 EDT 2009
 
  Other:
+
  - Added documentation warning that 'get_options' should be capitalized
    to avoid conflicting with future Module::Build options and changed
    the examples accordingly.
@@ -33,12 +248,17 @@ Revision history for Perl extension Module::Build.
 0.34_03 - Sat Aug  8 07:39:16 EDT 2009
 
  Bug fixes:
+
  - Fixed failing xs.t if /tmp is mounted noexec (RT#47331) [David Golden]
+
  - Fixed failing debug.t on VMS (RT#48362) [Craig Berry]
+
  - Prevent par.t from dying on error in .zip extraction [David Golden]
+
  - Fixed potential runthrough.t failure on 5.6.2 [David Golden]
 
  Other:
+
  - Archive::Tar changed from 'requires' to 'recommends' so non-authors
    without IO::Zlib can still use Module::Build to install modules
    [reported by Matt Trout, fix by David Golden]
@@ -46,22 +266,26 @@ Revision history for Perl extension Module::Build.
 0.340201 - Sun Aug  9 22:11:04 EDT 2009
 
  Other:
+
  - Version bump for Perl core for 5.10.1 release; no other changes
 
 0.34_02 - Sun Jul 26 22:50:40 EDT 2009
 
  Bug-fixes:
+
  - Bundled Module::Build::Version updated to bring into sync with CPAN
    version.pm 0.77 [John Peacock]
 
 0.34_01 - Sat Jul 18 16:32:09 EDT 2009
 
  Enhancements:
+
  - Added --debug flag to trace Build action execution (RT#47933)
    [David Golden]
 
  Bug-fixes:
- - Bundled Module::Build::Version version code updated to fix unsafe use 
+
+ - Bundled Module::Build::Version version code updated to fix unsafe use
    of $@ (RT#47980) [John Peacock]
 
 0.34 - Tue Jul  7 16:56:47 EDT 2009
@@ -71,27 +295,33 @@ Revision history for Perl extension Module::Build.
 0.33_06 - Sun Jul  5 10:11:40 EDT 2009
 
  Bug-fixes:
+
  - Bundled version code will use pure Perl on 5.10.0 to work around
    a corner case involving eval and locale [John Peacock]
+
  - Reversed VMS patch from 0.33_03 [Craig Berry]
+
  - PL_files in Build.PL that are in the bin/scripts directory should not be
-   installed as if they are scripts (fixed for case-tolerant systems). 
+   installed as if they are scripts (fixed for case-tolerant systems).
    [David Golden, reported by Craig Berry]
 
 0.33_05 - Sun Jun 28 22:06:49 EDT 2009
 
  Enhancements:
+
  - New 'auto_configure_requires' parameter (default 1) controls
    whether Module::Build should add itself to configure_requires
    in META.yml if not specified in Build.PL [David Golden]
 
  Bug-fixes:
+
  - The default MANIFEST.SKIP created by the "manifest" action
    was out of date.  It will now use the installed MANIFEST.SKIP
    and add some Module::Build and distribution specific items
    to it. [Michael Schwern]
 
  Other:
+
  - configure_requires do not necessarily need to be in requires
    or build_requires; warning to that effect has been removed
    [David Golden]
@@ -99,99 +329,141 @@ Revision history for Perl extension Module::Build.
 0.33_04 - Fri Jun 26 07:09:06 EDT 2009
 
  Bug-fixes:
+
  - Don't try utf8 YAML I/O on Perl 5.6 [David Golden]
 
  Other:
+
  - configure_requires added to prereq report (RT#47254) [Curtis Jewell]
+
  - updated Module::Build::Version to match forthcoming version.pm 0.77
    (RT#47256) [John Peacock]
+
  - skips xs.t and ppm.t when perl was not compiled with dynamic loading
-   since Module::Buld does not support static linking (RT#46178) 
+   since Module::Buld does not support static linking (RT#46178)
    [David Golden]
+
  - skip failing test in par.t if Archive::Zip is broken [David Golden]
+
  - Added YAML utf8 patch in 0.33_03 changes list
+
  - Added attribution for patches in 0.33_03 changes list
 
 0.33_03 - Mon Jun 22 17:22:56 EDT 2009
 
  Bug-fixes:
- - Removes Module::Build from its own configure/build_requires 
+
+ - Removes Module::Build from its own configure/build_requires
    [David Golden]
+
  - ConfigData->feature() confirms that modules actually load successfully,
    not just that they are present. (RT#43557) [David Golden]
- - Module::Build::Compat handling of INSTALL*LIB (RT#43827) 
+
+ - Module::Build::Compat handling of INSTALL*LIB (RT#43827)
    [Tony Payne, David Golden]
+
  - Module::Build::Compat and recursive test files (RT#39171) [Dave Rolsky]
+
  - Fixed bug linking non-standard XS names on Windows (RT#38065) ["snaury"]
- - Run PL files that don't generate any file (RT#39365) 
+
+ - Run PL files that don't generate any file (RT#39365)
    [Matisse Enzer, David Golden]
+
  - HTML generation failure no longer fatal (RT#36660) [David Golden]
- - realclean might not delete Build.bat on Windows (RT#43863) 
+
+ - realclean might not delete Build.bat on Windows (RT#43863)
    [Roy Ivy, David Golden]
+
  - include_dirs parameter now works correctly when given a single
    string argument (RT#40177) [David Wheeler]
+
  - Lots of spelling fixes in the POD (RT#45528r) [Lars Dieckow]
+
  - On Unix-like systems, tilde expansion is more liberal in username
    characters accepted (RT#33492) [Jon Jensen]
 
  Other
+
  - On MSWin32, bumped File::Spec prereq to 3.30 for a variety of fixes
+
  - Add support for VMS in Unix compatibility mode (RT#42157)
    [John E. Malmberg
- - Added a can_action($name) method (RT#45172) [brian d foy] 
+
+ - Added a can_action($name) method (RT#45172) [brian d foy]
+
  - Documented that subclass methods should not permanently change
    current directory (RT#46919) [David Wheeler]
+
  - META.yml encoded in UTF-8 (RT#43765) [Olivier Mengue]
 
 0.33_02 - Mon Jun 15 12:23:55 EDT 2009
 
  Bug-fixes:
+
  - Fixed tests for bleadperl
 
 0.33_01 - Sat Jun 13 20:24:42 EDT 2009
 
  Bug-fixes:
+
  - Fixed RT#42724: consolidated VMS fixes [patch by Craig Berry]
+
  - Fixed RT#46338: passthrough Makefile.PL cleans Makefile during distclean
+
  - Fixed RT#45700: t/compat.t for HP/UX make
 
  Other:
- - Adds current Module::Build to configure_requires (and build_requires) 
+
+ - Adds current Module::Build to configure_requires (and build_requires)
    if no configure_requires is specified
+
  - Always normalizes version number tuples in META.yml (e.g. 'v1.2.0')
-   (Partially addresses RT#46150) 
- - Normalizes a generated dist_version (e.g. from a .pm file) -- 
+   (Partially addresses RT#46150)
+
+ - Normalizes a generated dist_version (e.g. from a .pm file) --
    dist_version set manually in Build.PL is not normalized
+
  - Documentation update for create_license
+
  - Minor POD cleanup
 
 0.33 - Sun May  3 20:16:34 PDT 2009
 
  Bug-fixes:
+
  - Fixed RT#45462: Compat.pm needs to reference 'Build.com' on VMS
    [patch from John Malmberg]
+
  - Fixed RT#45461: ext.t on VMS [patch from John Malmberg]
+
  - Fixed RT#43861: Module::Build::PPMMaker has broken PPD name
    versioning for v5.10+
 
 0.32_01 - Tue Apr 14 17:14:22 PDT 2009
 
  Bug-fixes:
+
  - Module::Build::Compat had stopped adding "PL_FILES => {}" when no
    PL_files property was set in Build.PL; restored old behavior and fixed
    tests and documentation related to this issue [David Golden]
- - Caches ExtUtils::CBuilder object in a temporary stash instead of properties 
+
+ - Caches ExtUtils::CBuilder object in a temporary stash instead of properties
+
  - Fixed undef resources->license in META.yml (RT #44453).
+
  - Use $^X instead of 'perl' in t/ext.t [David Golden] (RT #43485)
 
  Other:
+
  - Generated META.yml will indicate version 1.4 of the specification
    (RT #37478) [patch from Alexandr Ciornii]
+
  - Archive::Tar now the default for generating tarballs on all platforms
    (avoids problems with incompatible tar binaries)
+
  - dist_dir() now uses dist_name() and dist_version() accessors rather
    than using its properties directly. [brian d foy] (RT #45038)
-   
+
 0.32 - Wed Feb 25 17:40:02 PST 2009
 
  No changes since 0.31_04.
@@ -199,100 +471,129 @@ Revision history for Perl extension Module::Build.
 0.31_04 - Fri Feb 20 11:04:59 PST 2009
 
  Other
- - Bumped Test::Harness prereq to 3.16 for latest PERL5LIB fixes (solves
+
+- Bumped Test::Harness prereq to 3.16 for latest PERL5LIB fixes (solves
    test failures when installing Module::Build using CPANPLUS::Dist::Build)
    [David Golden]
 
 0.31_03 - Sun Feb  8 14:54:01 PST 2009
 
  Enhancements
+
  - added a "prereq_data" action that prints a Perl data structure of
    all prerequisites; can be loaded by external tools using eval()
    [David Golden]
 
  Bug-fixes
+
  - 'fakeinstall' action warns and skips without ExtUtils::Install 1.32+
    [David Golden, reported by Zefram]
+
  - allows Module::Build version mismatch when installing self; works around
    limitations in CPANPLUS::Dist::Build [David Golden]
 
 0.31_02 - Tue Jan 27 09:16:43 PST 2009
 
  Other
+
  - tests now use File::Temp (added to build_requires); appears to fix
    Win32 testing heisenbug on directory removal during high system loads
+
  - use_tap_harness.t will skip unless a release version of TAP::Harness
    is installed
+
  - improved diagnostics to ensure_blib() tests in t/lib/MBTest.pm
 
  Compat
+
  - passthrough Makefile.PL will now play nice with cpantesters' on
    exit(0) (RT#32018) [Eric Wilhelm]
 
  Bug Fixes
+
  - fix for doubling-up of --prefix (RT#19951)
 
 0.31012 - Wed Jan 14 01:36:19 PST 2009
 
  Bug Fixes
+
  - t/tilde.t maybe actually fixed on MSWin32 now.
 
 0.31011 - Mon Jan 12 21:57:04 PST 2009
 
  Bug Fixes
+
  - t/tilde.t had been failing on MSWin32 (RT#42349)
 
 0.3101 - Mon Jan 12 13:52:36 PST 2009
 
  Other
+
  - added 'mirbsd' as a Unix-type OS [BinGOs]
+
  - added 'haiku' as a Unix-type OS (backported from bleadperl)
+
  - skips certain tests on VMS (backported from bleadperl)
+
  - sets $^X to absolute path in tests (backported from bleadperl)
 
 0.31 - Sat Dec 20 15:03:33 2008
 
  Deprecations
+
  - Use of attributes as class methods is deprecated (this was never a
    documented feature and appears to only have worked accidentally.)
 
 0.30_02 - Mon Dec 15 12:23:55 PST 2008
 
  Bug Fixes
+
  - make Software::License dependency "softer".
 
 0.30_01 - Thu Dec 11 18:25:53 PST 2008
 
  New Docs
+
  - Added a recipe for writing a new action to the Cookbook
+
  - Added a recipe for bundling Module::Build to the Cookbook.
 
  Doc Fixes
+
  - Clarified dist_abstract search procedure in API.pod (RT#41056) [Mario
    Domgoergen]
 
  Bug Fixes
+
  - Workaround HARNESS_TIMER env issue in t/compat.t (RT#39635)
+
  - Fix ~ expansion when $HOME is different from /etc/passwd as
    when running sudo.  [rt.cpan.org 39662]
+
  - Fixed a small POD error in the Cookbook. [Damyan Ivanov]
+
  - Unset group/other write permission bits when using Archive::Tar to
    build the dist tarball. (RT#39804) [David Golden]
 
  Enhancements
+
  - We now support a 'create_license' parameter to new() that will
    create a LICENSE file during the 'dist' phase with the full text of
    the license.  This requires Software::License on the author's
    machine.
+
  - Added lgpl2/lgpl3 entries to the supported licenses (RT#40532).
+
  - Support for validating properties with a check subref. [David
    Wheeler]
 
  Test Fixes
+
  - Defend against more stray environment variables interfering
    with the tests.
 
  Other
+
  - Updated our embedded version.pm to 0.76, enhanced documentation on
    dist_version_from.  [John Peacock]
 
@@ -484,11 +785,11 @@ Revision history for Perl extension Module::Build.
    have stopped, but it didn't.  Fixed. [Matthew Cast and David
    Golden]
 
- - Module::Build::Compat adds "require 5.XXXXX" to Makefile.PL when 
+ - Module::Build::Compat adds "require 5.XXXXX" to Makefile.PL when
    'perl' is specified as a 'requires' prerequisite [David Golden]
 
- - Refactored t/compat.t for modularity and transparency; added 
-   labels for all tests; supressed subprocess output to 
+ - Refactored t/compat.t for modularity and transparency; added
+   labels for all tests; supressed subprocess output to
    STDOUT and STDERR [David Golden]
 
  - Fixed bug in perl_version_to_float when version is already a float
@@ -1015,7 +1316,7 @@ Revision history for Perl extension Module::Build.
  - The synonyms 'scripts' and 'prereq' for 'script_files' and
    'requires' were broken in a previous version (0.27_01, probably),
    but now they're fixed. [David Golden]
+
  - Previously, we assumed that any custom subclass of Module::Build
    was located in _build/lib/.  This is only true if the author used
    the subclass() method, though.  We now use %INC to find where the
@@ -2162,13 +2463,13 @@ Revision history for Perl extension Module::Build.
  - Added experimental code to build a .ppd file, in support of
    ActiveState's "Perl Package Manager". [original patch by Dave
    Rolsky]
+
  - For authors who use Module::Signature to sign their distributions,
    we now create the SIGNATURE file right in the distribution
    directory, rather than creating it in the top-level directory and
    copying it into place.  This solves problems related to having
    files get out of date with respect to their signatures.
+
  - We now don't depend on Module::Info to scan for packages during the
    'dist' action anymore, because it's way too aggressive about
    loading other modules that you may not want loaded.  We now just
@@ -2231,12 +2532,12 @@ Revision history for Perl extension Module::Build.
 
  - The distribution directory (e.g. Sample-Module-0.13/ ) will now be
    deleted during the 'clean' or 'realclean' actions.
+
  - During testing of modules, blib/lib and blib/arch are now added as
    absolute paths, not relative.  This helps tests that load the
    modules at runtime and may change the current working directory
    (like Module::Build itself does during testing).
+
  - The $Config{cc} entry on some people's systems is something like
    'ccache gcc', so we now split that string using split_like_shell().
    [Richard Clamp]
@@ -2266,7 +2567,7 @@ Revision history for Perl extension Module::Build.
 
  - When compiling C code, we now respect 'pollute' and 'inc'
    parameters. (XXX - needs docs) [Dave Rolsky]
-   
+
  - Made the creation of the "install map" more generic.  (XXX - needs
    documentation)
 
@@ -2623,7 +2924,7 @@ Revision history for Perl extension Module::Build.
   - Renamed module_name_to_file() to find_module_by_name(), and added
     a parameter specifying the directories to search in.  Previously
     we searched in 'lib' and @INC, which wasn't correct in all
-    situations. 
+    situations.
 
   - Patched the docs to change "Build test" to "./Build test"
     [Elizabeth Mattijsen]
@@ -2817,7 +3118,7 @@ Revision history for Perl extension Module::Build.
   - For the 'Build dist' action, we'll use the 'tar' and 'gzip'
     programs (as specified by Config.pm) on Unix platforms, otherwise
     we'll use Archive::Tar and Compress::Zlib.
+
 0.02  Wed Sep  5 00:53:04 CDT 2001
   - Added POD documentation.
 
index be8c1f7..efae7f9 100644 (file)
@@ -15,7 +15,7 @@ use Module::Build::Base;
 
 use vars qw($VERSION @ISA);
 @ISA = qw(Module::Build::Base);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 
 # Okay, this is the brute-force method of finding out what kind of
@@ -167,24 +167,24 @@ This illustrates initial configuration and the running of three
 'actions'.  In this case the actions run are 'build' (the default
 action), 'test', and 'install'.  Other actions defined so far include:
 
-  build                          manpages    
-  clean                          pardist     
-  code                           ppd         
-  config_data                    ppmdist     
-  diff                           prereq_data 
-  dist                           prereq_report
-  distcheck                      pure_install
-  distclean                      realclean   
-  distdir                        retest      
-  distmeta                       skipcheck   
-  distsign                       test        
-  disttest                       testall     
-  docs                           testcover   
-  fakeinstall                    testdb      
-  help                           testpod     
-  html                           testpodcoverage
-  install                        versioninstall
-  manifest                                   
+  build                          manifest
+  clean                          manpages
+  code                           pardist
+  config_data                    ppd
+  diff                           ppmdist
+  dist                           prereq_data
+  distcheck                      prereq_report
+  distclean                      pure_install
+  distdir                        realclean
+  distmeta                       retest
+  distsign                       skipcheck
+  disttest                       test
+  docs                           testall
+  fakeinstall                    testcover
+  help                           testdb
+  html                           testpod
+  install                        testpodcoverage
+  installdeps                    versioninstall
 
 
 You can run the 'help' action for a complete list of actions.
@@ -318,7 +318,7 @@ tarball of the files listed in F<MANIFEST> and compress the tarball using
 GZIP compression.
 
 By default, this action will use the C<Archive::Tar> module. However, you can
-force it to use binary "tar" and "gzip" executables by supplying an explicit 
+force it to use binary "tar" and "gzip" executables by supplying an explicit
 C<tar> (and optional C<gzip>) parameter:
 
   ./Build dist --tar C:\path\to\tar.exe --gzip C:\path\to\zip.exe
@@ -355,8 +355,8 @@ F<META.yml> is a file containing various bits of I<metadata> about the
 distribution.  The metadata includes the distribution name, version,
 abstract, prerequisites, license, and various other data about the
 distribution.  This file is created as F<META.yml> in YAML format.
-It is recommended that the C<YAML> module be installed to create it.
-If the C<YAML> module is not installed, an internal module supplied
+It is recommended that the C<YAML::Tiny> module be installed to create it.
+If the C<YAML::Tiny> module is not installed, an internal module supplied
 with Module::Build will be used to write the META.yml file, and this
 will most likely be fine.
 
@@ -445,6 +445,24 @@ This can be a good idea, as it helps prevent multiple versions of a
 module from being present on your system, which can be a confusing
 situation indeed.
 
+=item installdeps
+
+[version 0.36]
+
+This action will use the C<cpan_client> parameter as a command to install
+missing prerequisites.  You will be prompted whether to install
+optional dependencies.
+
+The C<cpan_client> option defaults to 'cpan' but can be set as an option or in
+F<.modulebuildrc>.  It must be a shell command that takes a list of modules to
+install as arguments (e.g. 'cpanp -i' for CPANPLUS).  If the program part is a
+relative path (e.g. 'cpan' or 'cpanp'), it will be located relative to the perl
+program that executed Build.PL.
+
+  /opt/perl/5.8.9/bin/perl Build.PL
+  ./Build installdeps --cpan_client 'cpanp -i'
+  # installs to 5.8.9
+
 =item manifest
 
 [version 0.05]
@@ -541,7 +559,7 @@ for a bug report.
 [version 0.28]
 
 This action is identical to the C<install> action.  In the future,
-though, when C<install> starts writing to the file 
+though, when C<install> starts writing to the file
 F<$(INSTALLARCHLIB)/perllocal.pod>, C<pure_install> won't, and that
 will be the only difference between them.
 
@@ -666,7 +684,7 @@ argument.
 
 [version 0.25]
 
-This checks all the files described in the C<docs> action and 
+This checks all the files described in the C<docs> action and
 produces C<Test::Harness>-style output.  If you are a module author,
 this is useful to run before creating a new release.
 
@@ -674,7 +692,7 @@ this is useful to run before creating a new release.
 
 [version 0.28]
 
-This checks the pod coverage of the distribution and 
+This checks the pod coverage of the distribution and
 produces C<Test::Harness>-style output. If you are a module author,
 this is useful to run before creating a new release.
 
@@ -731,15 +749,20 @@ C<no> or C<no-> (e.g. C<--noverbose> or C<--no-verbose>).
 
 Suppress informative messages on output.
 
+=item verbose
+
+Display extra information about the Build on output.
+
+=item cpan_client
+
+Sets the C<cpan_client> command for use with the C<installdeps> action.
+See C<installdeps> for more details.
+
 =item use_rcfile
 
 Load the F<~/.modulebuildrc> option file.  This option can be set to
 false to prevent the custom resource file from being loaded.
 
-=item verbose
-
-Display extra information about the Build on output.
-
 =item allow_mb_mismatch
 
 Suppresses the check upon startup that the version of Module::Build
@@ -754,7 +777,6 @@ executed build actions.
 
 =back
 
-
 =head2 Default Options File (F<.modulebuildrc>)
 
 [version 0.28]
@@ -782,15 +804,35 @@ key C<*> (asterisk) denotes any global options that should be applied
 to all actions, and the key 'Build_PL' specifies options to be applied
 when you invoke C<perl Build.PL>.
 
-  *        verbose=1   # global options
-  diff     flags=-u
-  install  --install_base /home/ken
-           --install_path html=/home/ken/docs/html
+  *           verbose=1   # global options
+  diff        flags=-u
+  install     --install_base /home/ken
+              --install_path html=/home/ken/docs/html
+  installdeps --cpan_client 'cpanp -i'
 
 If you wish to locate your resource file in a different location, you
 can set the environment variable C<MODULEBUILDRC> to the complete
 absolute path of the file containing your options.
 
+=head2 Environment variables
+
+=over
+
+=item MODULEBUILDRC
+
+[version 0.28]
+
+Specifies an alternate location for a default options file as described above.
+
+=item PERL_MB_OPT
+
+[version 0.36]
+
+Command line options that are applied to Build.PL or any Build action.  The
+string is split as the shell would (e.g. whitespace) and the result is
+prepended to any actual command-line arguments.
+
+=back
 
 =head1 INSTALL PATHS
 
@@ -1091,7 +1133,7 @@ modify it under the same terms as Perl itself.
 =head1 SEE ALSO
 
 perl(1), L<Module::Build::Cookbook>, L<Module::Build::Authoring>,
-L<Module::Build::API>, L<ExtUtils::MakeMaker>, L<YAML>
+L<Module::Build::API>, L<ExtUtils::MakeMaker>, L<YAML::Tiny>
 
 F<META.yml> Specification:
 L<http://module-build.sourceforge.net/META-spec-current.html>
index f4e4cea..1f5d51f 100644 (file)
@@ -454,8 +454,13 @@ Specifies the licensing terms of your distribution.  Valid options include:
 
 =item apache
 
-The distribution is licensed under the Apache Software License
-(L<http://opensource.org/licenses/apachepl.php>).
+The distribution is licensed under the Apache License, Version 2.0
+(L<http://apache.org/licenses/LICENSE-2.0>).
+
+=item apache_1_1
+
+The distribution is licensed under the Apache Software License, Version 1.1
+(L<http://apache.org/licenses/LICENSE-1.1>).
 
 =item artistic
 
@@ -580,6 +585,18 @@ used to set C<dist_version>.
 Setting C<module_name> won't override a C<dist_*> parameter you
 specify explicitly.
 
+=item needs_compiler
+
+[version 0.36]
+
+The C<needs_compiler> parameter indicates whether a compiler is required to
+build the distsribution.  The default is false, unless XS files are found or
+the C<c_source> parameter is set, in which case it is true.  If true,
+L<ExtUtils::CBuilder> is automatically added to C<build_requires> if needed.
+
+For a distribution where a compiler is I<optional>, e.g. a dual XS/pure-Perl
+distribution, C<needs_compiler> should explicitly be set to a false value.
+
 =item PL_files
 
 [version 0.06]
@@ -737,6 +754,35 @@ For backward compatibility, you may use the parameter C<scripts>
 instead of C<script_files>.  Please consider this usage deprecated,
 though it will continue to exist for several version releases.
 
+=item share_dir
+
+[version 0.36]
+
+An optional parameter specifying directories of static data files to
+be installed as read-only files for use with L<File::ShareDir>.  The
+C<share_dir> property supports both distribution-level and
+module-level share files.
+
+The default when C<share_dir> is not set is for any files in a F<share>
+directory at the top level of the distribution to be installed in
+distribution-level share directory.  Alternatively, C<share_dir> can be set to
+a directory name or an arrayref of directory names containing files to be
+installed in the distribution-level share directory.
+
+If C<share_dir> is a hashref, it may have C<dist> or C<module> keys
+providing full flexibility in defining share directories to install.
+
+  share_dir => {
+    dist => [ 'examples', 'more_examples' ],
+    module => {
+      Foo::Templates => ['share/html', 'share/text'],
+      Foo::Config    => 'share/config',
+    }
+  }
+
+If C<share_dir> is set (manually or automatically), then File::ShareDir
+will automatically be added to the C<requires> hash.
+
 =item sign
 
 [version 0.16]
@@ -802,25 +848,23 @@ files in your distribution.
 
 [version 0.28]
 
-When called from a directory containing a F<Build.PL> script and a
-F<META.yml> file (in other words, the base directory of a
-distribution), this method will run the F<Build.PL> and return the
-resulting C<Module::Build> object to the caller.  Any key-value
-arguments given to C<new_from_context()> are essentially like
-command line arguments given to the F<Build.PL> script, so for example
-you could pass C<< verbose => 1 >> to this method to turn on
-verbosity.
+When called from a directory containing a F<Build.PL> script (in other words,
+the base directory of a distribution), this method will run the F<Build.PL> and
+call C<resume()> to return the resulting C<Module::Build> object to the caller.
+Any key-value arguments given to C<new_from_context()> are essentially like
+command line arguments given to the F<Build.PL> script, so for example you
+could pass C<< verbose => 1 >> to this method to turn on verbosity.
 
 =item resume()
 
 [version 0.03]
 
-You'll probably never call this method directly, it's only called from
-the auto-generated C<Build> script.  The C<new()> method is only
-called once, when the user runs C<perl Build.PL>.  Thereafter, when
-the user runs C<Build test> or another action, the C<Module::Build>
-object is created using the C<resume()> method to re-instantiate with
-the settings given earlier to C<new()>.
+You'll probably never call this method directly, it's only called from the
+auto-generated C<Build> script (and the C<new_from_context> method).  The
+C<new()> method is only called once, when the user runs C<perl Build.PL>.
+Thereafter, when the user runs C<Build test> or another action, the
+C<Module::Build> object is created using the C<resume()> method to
+re-instantiate with the settings given earlier to C<new()>.
 
 =item subclass()
 
@@ -1527,22 +1571,25 @@ Assigning the value C<undef> to an element causes it to be removed.
 
 =item prepare_metadata()
 
-[version 0.28]
+[version 0.36]
 
-This method is provided for authors to override to customize the
-fields of F<META.yml>.  It is passed a YAML::Node node object which can
-be modified as desired and then returned.  E.g.
+This method returns a hash reference of metadata that can be used to create a
+YAML datastream. It is provided for authors to override or customize the fields
+of F<META.yml>.   E.g.
 
   package My::Builder;
   use base 'Module::Build';
 
   sub prepare_metadata {
     my $self = shift;
-    my $node = $self->SUPER::prepare_metadata( shift );
-    $node->{custom_field} = 'foo';
-    return $node;
+    my $data = $self->SUPER::prepare_metadata();
+    $data->{custom_field} = 'foo';
+    return $data;
   }
 
+Prior to version 0.36, this method took a YAML::Node as an argument to hold
+assembled metadata.
+
 =item prereq_failures()
 
 [version 0.11]
@@ -1782,6 +1829,10 @@ accessor methods for the following properties:
 
 =item build_script()
 
+=item bundle_inc()
+
+=item bundle_inc_preload()
+
 =item c_source()
 
 =item config_dir()
@@ -1790,6 +1841,8 @@ accessor methods for the following properties:
 
 =item conflicts()
 
+=item cpan_client()
+
 =item create_license()
 
 =item create_makefile_pl()
@@ -1830,6 +1883,10 @@ accessor methods for the following properties:
 
 =item module_name()
 
+=item mymetafile()
+
+=item needs_compiler()
+
 =item orig_dir()
 
 =item perl()
@@ -1920,7 +1977,7 @@ modify it under the same terms as Perl itself.
 =head1 SEE ALSO
 
 perl(1), L<Module::Build>(3), L<Module::Build::Authoring>(3),
-L<Module::Build::Cookbook>(3), L<ExtUtils::MakeMaker>(3), L<YAML>(3)
+L<Module::Build::Cookbook>(3), L<ExtUtils::MakeMaker>(3), L<YAML::Tiny>(3)
 
 F<META.yml> Specification:
 L<http://module-build.sourceforge.net/META-spec-current.html>
index 531c354..abeea2e 100644 (file)
@@ -4,7 +4,7 @@ package Module::Build::Base;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 BEGIN { require 5.00503 }
 
@@ -23,6 +23,7 @@ use Text::ParseWords ();
 use Module::Build::ModuleInfo;
 use Module::Build::Notes;
 use Module::Build::Config;
+use Module::Build::Version;
 
 
 #################### Constructors ###########################
@@ -31,16 +32,37 @@ sub new {
 
   $self->{invoked_action} = $self->{action} ||= 'Build_PL';
   $self->cull_args(@ARGV);
-  
+
   die "Too early to specify a build action '$self->{action}'.  Do 'Build $self->{action}' instead.\n"
     if $self->{action} && $self->{action} ne 'Build_PL';
 
   $self->check_manifest;
-  $self->check_prereq;
-  $self->check_autofeatures;
+  $self->auto_require;
+  if ( $self->check_prereq + $self->check_autofeatures != 2) {
+    $self->log_warn(<<EOF);
+
+ERRORS/WARNINGS FOUND IN PREREQUISITES.  You may wish to install the versions
+of the modules indicated above before proceeding with this installation
+
+EOF
+    unless (
+      $self->dist_name eq 'Module-Build' ||
+      $ENV{PERL5_CPANPLUS_IS_RUNNING} || $ENV{PERL5_CPAN_IS_RUNNING}
+    ) {
+      $self->log_warn(
+        "Run 'Build installdeps' to install missing prerequisites.\n\n"
+      );
+    }
+  }
+
+  # record for later use in resume;
+  $self->{properties}{_added_to_INC} = [ $self->_added_to_INC ];
+
+  $self->set_bundle_inc;
 
   $self->dist_name;
   $self->dist_version;
+  $self->_guess_module_name unless $self->module_name;
 
   $self->_find_nested_builds;
 
@@ -52,6 +74,8 @@ sub resume {
   my $self = $package->_construct(@_);
   $self->read_config;
 
+  unshift @INC, @{ $self->{properties}{_added_to_INC} || [] };
+
   # If someone called Module::Build->current() or
   # Module::Build->new_from_context() and the correct class to use is
   # actually a *subclass* of Module::Build, we may need to load that
@@ -72,7 +96,7 @@ sub resume {
     $self->log_warn(" * WARNING: Configuration was initially created with '$self->{properties}{perl}',\n".
                    "   but we are now using '$perl'.\n");
   }
-  
+
   $self->cull_args(@ARGV);
 
   unless ($self->allow_mb_mismatch) {
@@ -82,7 +106,7 @@ sub resume {
        "   or use --allow_mb_mismatch 1 to skip this version check.\n")
     if $mb_version ne $self->{properties}{mb_version};
   }
-  
+
   $self->{invoked_action} = $self->{action} ||= 'build';
 
   return $self;
@@ -90,18 +114,8 @@ sub resume {
 
 sub new_from_context {
   my ($package, %args) = @_;
-  
-  # XXX Read the META.yml and see whether we need to run the Build.PL?
-  
-  # Run the Build.PL.  We use do() rather than run_perl_script() so
-  # that it runs in this process rather than a subprocess, because we
-  # need to make sure that the environment is the same during Build.PL
-  # as it is during resume() (and thereafter).
-  {
-    local @ARGV = $package->unparse_args(\%args);
-    do './Build.PL';
-    die $@ if $@;
-  }
+
+  $package->run_perl_script('Build.PL',[],[$package->unparse_args(\%args)]);
   return $package->resume;
 }
 
@@ -497,6 +511,28 @@ sub _discover_perl_interpreter {
       "in (@paths)\n";
 }
 
+# Adapted from IPC::Cmd::can_run()
+sub find_command {
+    my ($self, $command) = @_;
+
+    if( File::Spec->file_name_is_absolute($command) ) {
+        return $self->_maybe_command($command);
+
+    } else {
+        for my $dir ( File::Spec->path ) {
+            my $abs = File::Spec->catfile($dir, $command);
+            return $abs if $abs = $self->_maybe_command($abs);
+        }
+    }
+}
+
+# Copied from ExtUtils::MM_Unix::maybe_command
+sub _maybe_command {
+    my($self,$file) = @_;
+    return $file if -x $file && ! -d $file;
+    return;
+}
+
 sub _is_interactive {
   return -t STDIN && (-t STDOUT || !(-f STDOUT || -c STDOUT)) ;   # Pipe?
 }
@@ -588,10 +624,18 @@ sub features     {
     }
 
     if (my $info = $ph->{auto_features}->access($key)) {
-      my $failures = $self->prereq_failures($info);
-      my $disabled = grep( /^(?:\w+_)?(?:requires|conflicts)$/,
-                          keys %$failures ) ? 1 : 0;
-      return !$disabled;
+      my $disabled;
+      for my $type ( @{$self->prereq_action_types} ) {
+        next if $type eq 'description' || $type eq 'recommends' || ! exists $info->{$type};
+        my $prereqs = $info->{$type};
+        for my $modname ( sort keys %$prereqs ) {
+          my $spec = $prereqs->{$modname};
+          my $status = $self->check_installed_status($modname, $spec);
+          if ((!$status->{ok}) xor ($type =~ /conflicts$/)) { return 0; }
+          if ( ! eval "require $modname; 1" ) { return 0; }
+        }
+      }
+      return 1;
     }
 
     return $ph->{features}->access($key, @_);
@@ -614,7 +658,7 @@ BEGIN { *feature = \&features } # Alias
 
 sub _mb_feature {
   my $self = shift;
-  
+
   if (($self->module_name || '') eq 'Module::Build') {
     # We're building Module::Build itself, so ...::ConfigData isn't
     # valid, but $self->features() should be.
@@ -625,6 +669,15 @@ sub _mb_feature {
   }
 }
 
+sub _warn_mb_feature_deps {
+  my $self = shift;
+  my $name = shift;
+  $self->log_warn(
+    "The '$name' feature is not available.  Please install missing\n" .
+    "feature dependencies and try again.\n".
+    $self->_feature_deps_msg($name) . "\n"
+  );
+}
 
 sub add_build_element {
     my ($self, $elem) = @_;
@@ -635,7 +688,7 @@ sub add_build_element {
 sub ACTION_config_data {
   my $self = shift;
   return unless $self->has_config_data;
-  
+
   my $module_name = $self->module_name
     or die "The config_data feature requires that 'module_name' be set";
   my $notes_name = $module_name . '::ConfigData'; # TODO: Customize name ???
@@ -646,7 +699,7 @@ sub ACTION_config_data {
                               $self->config_file('features')
                              ], $notes_pm);
 
-  $self->log_info("Writing config notes to $notes_pm\n");
+  $self->log_verbose("Writing config notes to $notes_pm\n");
   File::Path::mkpath(File::Basename::dirname($notes_pm));
 
   Module::Build::Notes->write_config_data
@@ -661,7 +714,7 @@ sub ACTION_config_data {
 }
 
 ########################################################################
-{ # enclosing these lexicals -- TODO 
+{ # enclosing these lexicals -- TODO
   my %valid_properties = ( __PACKAGE__,  {} );
   my %additive_properties;
 
@@ -681,10 +734,10 @@ sub ACTION_config_data {
 
   sub valid_properties_defaults {
     my %out;
-    for (reverse shift->_mb_classes) {
-      @out{ keys %{ $valid_properties{$_} } } = map {
+    for my $class (reverse shift->_mb_classes) {
+      @out{ keys %{ $valid_properties{$class} } } = map {
         $_->()
-      } values %{ $valid_properties{$_} };
+      } values %{ $valid_properties{$class} };
     }
     return \%out;
   }
@@ -710,9 +763,11 @@ sub ACTION_config_data {
     my %p = @_ == 1 ? ( default => shift ) : @_;
 
     my $type = ref $p{default};
-    $valid_properties{$class}{$property} = $type eq 'CODE'
-      ? $p{default}
-      : sub { $p{default} };
+    $valid_properties{$class}{$property} =
+      $type eq 'CODE' ? $p{default}                           :
+      $type eq 'HASH' ? sub { return { %{ $p{default} } }   } :
+      $type eq 'ARRAY'? sub { return [ @{ $p{default} } ]   } :
+                        sub { return $p{default}            } ;
 
     push @{$additive_properties{$class}->{$type}}, $property
       if $type;
@@ -831,12 +886,16 @@ sub _make_accessor {
 __PACKAGE__->add_property(auto_configure_requires => 1);
 __PACKAGE__->add_property(blib => 'blib');
 __PACKAGE__->add_property(build_class => 'Module::Build');
-__PACKAGE__->add_property(build_elements => [qw(PL support pm xs pod script)]);
+__PACKAGE__->add_property(build_elements => [qw(PL support pm xs share_dir pod script)]);
 __PACKAGE__->add_property(build_script => 'Build');
 __PACKAGE__->add_property(build_bat => 0);
+__PACKAGE__->add_property(bundle_inc => []);
+__PACKAGE__->add_property(bundle_inc_preload => []);
 __PACKAGE__->add_property(config_dir => '_build');
 __PACKAGE__->add_property(include_dirs => []);
+__PACKAGE__->add_property(license => 'unknown');
 __PACKAGE__->add_property(metafile => 'META.yml');
+__PACKAGE__->add_property(mymetafile => 'MYMETA.yml');
 __PACKAGE__->add_property(recurse_into => []);
 __PACKAGE__->add_property(use_rcfile => 1);
 __PACKAGE__->add_property(create_packlist => 1);
@@ -844,6 +903,7 @@ __PACKAGE__->add_property(allow_mb_mismatch => 0);
 __PACKAGE__->add_property(config => undef);
 __PACKAGE__->add_property(test_file_exts => ['.t']);
 __PACKAGE__->add_property(use_tap_harness => 0);
+__PACKAGE__->add_property(cpan_client => 'cpan');
 __PACKAGE__->add_property(tap_harness_args => {});
 __PACKAGE__->add_property(
   'installdirs',
@@ -906,10 +966,10 @@ __PACKAGE__->add_property($_) for qw(
   has_config_data
   install_base
   libdoc_dirs
-  license
   magic_number
   mb_version
   module_name
+  needs_compiler
   orig_dir
   perl
   pm_files
@@ -921,6 +981,7 @@ __PACKAGE__->add_property($_) for qw(
   recursive_test_files
   script_files
   scripts
+  share_dir
   sign
   test_files
   verbose
@@ -993,14 +1054,14 @@ sub subclass {
 
   $opts{code}  ||= '';
   $opts{class} ||= 'MyModuleBuilder';
-  
+
   my $filename = File::Spec->catfile($build_dir, 'lib', split '::', $opts{class}) . '.pm';
   my $filedir  = File::Basename::dirname($filename);
-  $pack->log_info("Creating custom builder $filename in $filedir\n");
-  
+  $pack->log_verbose("Creating custom builder $filename in $filedir\n");
+
   File::Path::mkpath($filedir);
   die "Can't create directory $filedir: $!" unless -d $filedir;
-  
+
   my $fh = IO::File->new("> $filename") or die "Can't create $filename: $!";
   print $fh <<EOF;
 package $opts{class};
@@ -1010,7 +1071,7 @@ $opts{code}
 1;
 EOF
   close $fh;
-  
+
   unshift @INC, File::Spec->catdir(File::Spec->rel2abs($build_dir), 'lib');
   eval "use $opts{class}";
   die $@ if $@;
@@ -1018,16 +1079,43 @@ EOF
   return $opts{class};
 }
 
+sub _guess_module_name {
+  my $self = shift;
+  my $p = $self->{properties};
+  return if $p->{module_name};
+  if ( $p->{dist_version_from} && -e $p->{dist_version_from} ) {
+    my $mi = Module::Build::ModuleInfo->new_from_file($self->dist_version_from);
+    $p->{module_name} = $mi->name;
+  }
+  else {
+    my $mod_path = my $mod_name = File::Basename::basename($self->base_dir);
+    $mod_name =~ s{-}{::}g;
+    $mod_path =~ s{-}{/}g;
+    $mod_path .= ".pm";
+    if ( -e $mod_path || -e File::Spec->catfile('lib', $mod_path) ) {
+      $p->{module_name} = $mod_name;
+    }
+    else {
+      $self->log_warn( << 'END_WARN' );
+No 'module_name' was provided and it could not be inferred
+from other properties.  This will prevent a packlist from
+being written for this file.  Please set either 'module_name'
+or 'dist_version_from' in Build.PL.
+END_WARN
+    }
+  }
+}
+
 sub dist_name {
   my $self = shift;
   my $p = $self->{properties};
   return $p->{dist_name} if defined $p->{dist_name};
-  
+
   die "Can't determine distribution name, must supply either 'dist_name' or 'module_name' parameter"
     unless $self->module_name;
-  
+
   ($p->{dist_name} = $self->module_name) =~ s/::/-/g;
-  
+
   return $p->{dist_name};
 }
 
@@ -1069,12 +1157,12 @@ sub _pod_parse {
   my $p = $self->{properties};
   my $member = "dist_$part";
   return $p->{$member} if defined $p->{$member};
-  
+
   my $docfile = $self->_main_docfile
     or return;
   my $fh = IO::File->new($docfile)
     or return;
-  
+
   require Module::Build::PodParser;
   my $parser = Module::Build::PodParser->new(fh => $fh);
   my $method = "get_$part";
@@ -1109,7 +1197,7 @@ sub config_file {
 
 sub read_config {
   my ($self) = @_;
-  
+
   my $file = $self->config_file('build_params')
     or die "Can't find 'build_params' in " . $self->config_dir;
   my $fh = IO::File->new($file) or die "Can't read '$file': $!";
@@ -1128,7 +1216,7 @@ sub has_config_data {
 
 sub _write_data {
   my ($self, $filename, $data) = @_;
-  
+
   my $file = $self->config_file($filename);
   my $fh = IO::File->new("> $file") or die "Can't create '$file': $!";
   unless (ref($data)) {  # e.g. magicnum
@@ -1141,10 +1229,10 @@ sub _write_data {
 
 sub write_config {
   my ($self) = @_;
-  
+
   File::Path::mkpath($self->{properties}{config_dir});
   -d $self->{properties}{config_dir} or die "Can't mkdir $self->{properties}{config_dir}: $!";
-  
+
   my @items = @{ $self->prereq_action_types };
   $self->_write_data('prereqs', { map { $_, $self->$_() } @items });
   $self->_write_data('build_params', [$self->{args}, $self->{config}->values_set, $self->{properties}]);
@@ -1155,13 +1243,74 @@ sub write_config {
   $self->{phash}{$_}->write() foreach qw(notes cleanup features auto_features config_data runtime_params);
 }
 
+{
+  # packfile map -- keys are guts of regular expressions;  If they match,
+  # values are module names corresponding to the packlist
+  my %packlist_map = (
+    '^File::Spec'         => 'Cwd',
+    '^Devel::AssertOS'    => 'Devel::CheckOS',
+  );
+
+  sub _find_packlist {
+    my ($self, $inst, $mod) = @_;
+    my $lookup = $mod;
+    my $packlist = eval { $inst->packlist($lookup) };
+    if ( ! $packlist ) {
+      # try from packlist_map
+      while ( my ($re, $new_mod) = each %packlist_map ) {
+        if ( $mod =~ qr/$re/ ) {
+          $lookup = $new_mod;
+          $packlist = eval { $inst->packlist($lookup) };
+          last;
+        }
+      }
+    }
+    return $packlist ? $lookup : undef;
+  }
+
+  sub set_bundle_inc {
+    my $self = shift;
+
+    my $bundle_inc = $self->{properties}{bundle_inc};
+    my $bundle_inc_preload = $self->{properties}{bundle_inc_preload};
+    # We're in author mode if inc::latest is loaded, but not from cwd
+    return unless inc::latest->can('loaded_modules');
+    require ExtUtils::Installed;
+    # ExtUtils::Installed is buggy about finding additions to default @INC
+    my $inst = ExtUtils::Installed->new(extra_libs => [@INC]);
+    my @bundle_list = map { [ $_, 0 ] } inc::latest->loaded_modules;
+
+    # XXX TODO: Need to get ordering of prerequisites correct so they are
+    # are loaded in the right order. Use an actual tree?!
+
+    while( @bundle_list ) {
+      my ($mod, $prereq) = @{ shift @bundle_list };
+
+      # XXX TODO: Append prereqs to list
+      # skip if core or already in bundle or preload lists
+      # push @bundle_list, [$_, 1] for prereqs()
+
+      # Locate packlist for bundling
+      my $lookup = $self->_find_packlist($inst,$mod);
+      if ( ! $lookup ) {
+        # XXX Really needs a more helpful error message here
+        die << "NO_PACKLIST";
+Could not find a packlist for '$mod'.  If it's a core module, try
+force installing it from CPAN.
+NO_PACKLIST
+      }
+      else {
+        push @{ $prereq ? $bundle_inc_preload : $bundle_inc }, $lookup;
+      }
+    }
+  } # sub check_bundling
+}
+
 sub check_autofeatures {
   my ($self) = @_;
   my $features = $self->auto_features;
-  
-  return unless %$features;
 
-  $self->log_info("Checking features:\n");
+  return 1 unless %$features;
 
   # TODO refactor into ::Util
   my $longest = sub {
@@ -1177,30 +1326,117 @@ sub check_autofeatures {
   };
   my $max_name_len = length($longest->(keys %$features));
 
-  while (my ($name, $info) = each %$features) {
-    $self->log_info("  $name" . '.' x ($max_name_len - length($name) + 4));
+  my ($num_disabled, $log_text) = (0, "\nChecking optional features...\n");
+  for my $name ( sort keys %$features ) {
+    $log_text .= $self->_feature_deps_msg($name, $max_name_len);
+  }
+
+  $num_disabled = () = $log_text =~ /disabled/g;
+
+  # warn user if features disabled
+  if ( $num_disabled ) {
+    $self->log_warn( $log_text );
+    return 0;
+  }
+  else {
+    $self->log_verbose( $log_text );
+    return 1;
+  }
+}
+
+sub _feature_deps_msg {
+  my ($self, $name, $max_name_len) = @_;
+    $max_name_len ||= length $name;
+    my $features = $self->auto_features;
+    my $info = $features->{$name};
+    my $feature_text = "$name" . '.' x ($max_name_len - length($name) + 4);
 
+    my ($log_text, $disabled) = ('','');
     if ( my $failures = $self->prereq_failures($info) ) {
-      my $disabled = grep( /^(?:\w+_)?(?:requires|conflicts)$/,
-                          keys %$failures ) ? 1 : 0;
-      $self->log_info( $disabled ? "disabled\n" : "enabled\n" );
-
-      my $log_text;
-      while (my ($type, $prereqs) = each %$failures) {
-       while (my ($module, $status) = each %$prereqs) {
-         my $required =
-           ($type =~ /^(?:\w+_)?(?:requires|conflicts)$/) ? 1 : 0;
-         my $prefix = ($required) ? '-' : '*';
-         $log_text .= "    $prefix $status->{message}\n";
-       }
+      $disabled = grep( /^(?:\w+_)?(?:requires|conflicts)$/,
+                  keys %$failures ) ? 1 : 0;
+      $feature_text .= $disabled ? "disabled\n" : "enabled\n";
+
+      for my $type ( @{ $self->prereq_action_types } ) {
+        next unless exists $failures->{$type};
+        $feature_text .= "  $type:\n";
+        my $prereqs = $failures->{$type};
+        for my $module ( sort keys %$prereqs ) {
+          my $status = $prereqs->{$module};
+          my $required =
+            ($type =~ /^(?:\w+_)?(?:requires|conflicts)$/) ? 1 : 0;
+          my $prefix = ($required) ? '!' : '*';
+          $feature_text .= "    $prefix $status->{message}\n";
+        }
       }
-      $self->log_warn("$log_text") unless $self->quiet;
     } else {
-      $self->log_info("enabled\n");
+      $feature_text .= "enabled\n";
+    }
+    $log_text .= $feature_text if $disabled || $self->verbose;
+    return $log_text;
+}
+
+# Automatically detect and add prerequisites based on configuration
+sub auto_require {
+  my ($self) = @_;
+  my $p = $self->{properties};
+
+  # add current Module::Build to configure_requires if there
+  # isn't one already specified (but not ourself, so we're not circular)
+  if ( $self->dist_name ne 'Module-Build'
+    && $self->auto_configure_requires
+    && ! exists $p->{configure_requires}{'Module::Build'}
+  ) {
+    (my $ver = $VERSION) =~ s/^(\d+\.\d\d).*$/$1/; # last major release only
+    $self->_add_prereq('configure_requires', 'Module::Build', $ver);
+  }
+
+  # if we're in author mode, add inc::latest modules to
+  # configure_requires if not already set.  If we're not in author mode
+  # then configure_requires will have been satisfied, or we'll just
+  # live with what we've bundled
+  if ( inc::latest->can('loaded_module') ) {
+    for my $mod ( inc::latest->loaded_modules ) {
+      next if exists $p->{configure_requires}{$mod};
+      $self->_add_prereq('configure_requires', $mod, $mod->VERSION);
     }
   }
 
-  $self->log_warn("\n") unless $self->quiet;
+  # If needs_compiler is not explictly set, automatically set it
+  # If set, we need ExtUtils::CBuilder (and a compiler)
+  my $xs_files = $self->find_xs_files;
+  if ( ! defined $p->{needs_compiler} ) {
+    $self->needs_compiler( keys %$xs_files || defined $self->c_source );
+  }
+  if ($self->needs_compiler) {
+    $self->_add_prereq('build_requires', 'ExtUtils::CBuilder', 0);
+    if ( ! $self->have_c_compiler ) {
+      $self->log_warn(<<'EOM');
+Warning: ExtUtils::CBuilder not installed or no compiler detected
+Proceeding with configuration, but compilation may fail during Build
+
+EOM
+    }
+  }
+
+  # If using share_dir, require File::ShareDir
+  if ( $self->share_dir ) {
+    $self->_add_prereq( 'requires', 'File::ShareDir', '1.00' );
+  }
+
+  return;
+}
+
+sub _add_prereq {
+  my ($self, $type, $module, $version) = @_;
+  my $p = $self->{properties};
+  $version = 0 unless defined $version;
+  if ( exists $p->{$type}{$module} ) {
+    return if $self->compare_versions( $version, '<=', $p->{$type}{$module} );
+  }
+  $self->log_verbose("Adding to $type\: $module => $version\n");
+  $p->{$type}{$module} = $version;
+  return 1;
 }
 
 sub prereq_failures {
@@ -1213,7 +1449,8 @@ sub prereq_failures {
 
   foreach my $type (@types) {
     my $prereqs = $info->{$type};
-    while ( my ($modname, $spec) = each %$prereqs ) {
+    for my $modname ( keys %$prereqs ) {
+      my $spec = $prereqs->{$modname};
       my $status = $self->check_installed_status($modname, $spec);
 
       if ($type =~ /^(?:\w+_)?conflicts$/) {
@@ -1224,7 +1461,7 @@ sub prereq_failures {
       } elsif ($type =~ /^(?:\w+_)?recommends$/) {
        next if $status->{ok};
        $status->{message} = (!ref($status->{have}) && $status->{have} eq '<none>'
-                             ? "Optional prerequisite $modname is not installed"
+                             ? "$modname is not installed"
                              : "$modname ($status->{have}) is installed, but we prefer to have $spec");
       } else {
        next if $status->{ok};
@@ -1253,44 +1490,29 @@ sub _enum_prereqs {
 sub check_prereq {
   my $self = shift;
 
-  # If we have XS files, make sure we can process them.
-  my $xs_files = $self->find_xs_files;
-  if (keys %$xs_files && !$self->_mb_feature('C_support')) {
-    $self->log_warn("Warning: this distribution contains XS files, ".
-                   "but Module::Build is not configured with C_support.  ".
-                   "Please install ExtUtils::CBuilder to enable C_support.\n");
-  }
-
   # Check to see if there are any prereqs to check
   my $info = $self->_enum_prereqs;
   return 1 unless $info;
 
-  $self->log_info("Checking prerequisites...\n");
+  my $log_text = "Checking prerequisites...\n";
 
   my $failures = $self->prereq_failures($info);
 
   if ( $failures ) {
-
-    while (my ($type, $prereqs) = each %$failures) {
-      while (my ($module, $status) = each %$prereqs) {
-       my $prefix = ($type =~ /^(?:\w+_)?recommends$/) ? '*' : '- ERROR:';
-       $self->log_warn(" $prefix $status->{message}\n");
+    $self->log_warn($log_text);
+    for my $type ( @{ $self->prereq_action_types } ) {
+      my $prereqs = $failures->{$type};
+      $self->log_warn("  ${type}:\n") if keys %$prereqs;
+      for my $module ( sort keys %$prereqs ) {
+        my $status = $prereqs->{$module};
+        my $prefix = ($type =~ /^(?:\w+_)?recommends$/) ? "* " : "! ";
+        $self->log_warn("    $prefix $status->{message}\n");
       }
     }
-
-    $self->log_warn(<<EOF);
-
-ERRORS/WARNINGS FOUND IN PREREQUISITES.  You may wish to install the versions
-of the modules indicated above before proceeding with this installation
-
-EOF
     return 0;
-
   } else {
-
-    $self->log_info("Looks good\n\n");
+    $self->log_verbose($log_text . "Looks good\n\n");
     return 1;
-
   }
 }
 
@@ -1323,44 +1545,44 @@ sub _parse_conditions {
 sub check_installed_status {
   my ($self, $modname, $spec) = @_;
   my %status = (need => $spec);
-  
+
   if ($modname eq 'perl') {
     $status{have} = $self->perl_version;
-  
+
   } elsif (eval { no strict; $status{have} = ${"${modname}::VERSION"} }) {
     # Don't try to load if it's already loaded
-    
+
   } else {
     my $pm_info = Module::Build::ModuleInfo->new_from_module( $modname );
     unless (defined( $pm_info )) {
       @status{ qw(have message) } = ('<none>', "$modname is not installed");
       return \%status;
     }
-    
+
     $status{have} = $pm_info->version();
     if ($spec and !defined($status{have})) {
       @status{ qw(have message) } = (undef, "Couldn't find a \$VERSION in prerequisite $modname");
       return \%status;
     }
   }
-  
+
   my @conditions = $self->_parse_conditions($spec);
-  
+
   foreach (@conditions) {
     my ($op, $version) = /^\s*  (<=?|>=?|==|!=)  \s*  ([\w.]+)  \s*$/x
       or die "Invalid prerequisite condition '$_' for $modname";
-    
+
     $version = $self->perl_version_to_float($version)
       if $modname eq 'perl';
-    
+
     next if $op eq '>=' and !$version;  # Module doesn't have to actually define a $VERSION
-    
+
     unless ($self->compare_versions( $status{have}, $op, $version )) {
       $status{message} = "$modname ($status{have}) is installed, but we need version $op $version";
       return \%status;
     }
   }
-  
+
   $status{ok} = 1;
   return \%status;
 }
@@ -1368,7 +1590,7 @@ sub check_installed_status {
 sub compare_versions {
   my $self = shift;
   my ($v1, $op, $v2) = @_;
-  $v1 = Module::Build::Version->new($v1) 
+  $v1 = Module::Build::Version->new($v1)
     unless UNIVERSAL::isa($v1,'Module::Build::Version');
 
   my $eval_str = "\$v1 $op \$v2";
@@ -1381,14 +1603,14 @@ sub compare_versions {
 # I wish I could set $! to a string, but I can't, so I use $@
 sub check_installed_version {
   my ($self, $modname, $spec) = @_;
-  
+
   my $status = $self->check_installed_status($modname, $spec);
-  
+
   if ($status->{ok}) {
     return $status->{have} if $status->{have} and "$status->{have}" ne '<none>';
     return '0 but true';
   }
-  
+
   $@ = $status->{message};
   return 0;
 }
@@ -1430,23 +1652,23 @@ sub _added_to_INC {
   sub _default_INC {
     my $self = shift;
     return @default_inc if @default_inc;
-    
+
     local $ENV{PERL5LIB};  # this is not considered part of the default.
-    
+
     my $perl = ref($self) ? $self->perl : $self->find_perl_interpreter;
-    
+
     my @inc = $self->_backticks($perl, '-le', 'print for @INC');
     chomp @inc;
-    
+
     return @default_inc = @inc;
   }
 }
 
 sub print_build_script {
   my ($self, $fh) = @_;
-  
+
   my $build_package = $self->build_class;
-  
+
   my $closedata="";
 
   my %q = map {$_, $self->$_()} qw(config_dir base_dir);
@@ -1532,20 +1754,29 @@ EOF
 sub create_build_script {
   my ($self) = @_;
   $self->write_config;
-  
+
+  # Create MYMETA.yml
+  my $mymetafile = $self->mymetafile;
+  if ( $self->delete_filetree($mymetafile) ) {
+    $self->log_verbose("Removed previous '$mymetafile'\n");
+  }
+  $self->log_info("Creating new '$mymetafile' with configuration results\n");
+  $self->write_metafile( $mymetafile, $self->prepare_metadata( fatal => 0 ) );
+
+  # Create Build
   my ($build_script, $dist_name, $dist_version)
     = map $self->$_(), qw(build_script dist_name dist_version);
-  
+
   if ( $self->delete_filetree($build_script) ) {
-    $self->log_info("Removed previous script '$build_script'\n\n");
+    $self->log_verbose("Removed previous script '$build_script'\n");
   }
 
   $self->log_info("Creating new '$build_script' script for ",
-                 "'$dist_name' version '$dist_version'\n");
+                  "'$dist_name' version '$dist_version'\n");
   my $fh = IO::File->new(">$build_script") or die "Can't create '$build_script': $!";
   $self->print_build_script($fh);
   close $fh;
-  
+
   $self->make_executable($build_script);
 
   return 1;
@@ -1554,20 +1785,20 @@ sub create_build_script {
 sub check_manifest {
   my $self = shift;
   return unless -e 'MANIFEST';
-  
+
   # Stolen nearly verbatim from MakeMaker.  But ExtUtils::Manifest
   # could easily be re-written into a modern Perl dialect.
 
   require ExtUtils::Manifest;  # ExtUtils::Manifest is not warnings clean.
   local ($^W, $ExtUtils::Manifest::Quiet) = (0,1);
-  
-  $self->log_info("Checking whether your kit is complete...\n");
+
+  $self->log_verbose("Checking whether your kit is complete...\n");
   if (my @missed = ExtUtils::Manifest::manicheck()) {
     $self->log_warn("WARNING: the following files are missing in your kit:\n",
                    "\t", join("\n\t", @missed), "\n",
                    "Please inform the author.\n\n");
   } else {
-    $self->log_info("Looks good\n\n");
+    $self->log_verbose("Looks good\n\n");
   }
 }
 
@@ -1692,6 +1923,7 @@ sub _translate_option {
     use_rcfile
     use_tap_harness
     tap_harness_args
+    cpan_client
   ); # normalize only selected option names
 
   return $opt;
@@ -1824,7 +2056,7 @@ sub read_args {
     require Module::Build::Compat;
     %args = (%args, Module::Build::Compat->makefile_to_build_macros);
   }
-  
+
   return \%args, $action;
 }
 
@@ -1977,7 +2209,10 @@ sub merge_args {
 
 sub cull_args {
   my $self = shift;
-  my ($args, $action) = $self->read_args(@_);
+  my @arg_list = @_;
+  unshift @arg_list, $self->split_like_shell($ENV{PERL_MB_OPT})
+    if $ENV{PERL_MB_OPT};
+  my ($args, $action) = $self->read_args(@arg_list);
   $self->merge_args($action, %$args);
   $self->merge_modulebuildrc( $action, %$args );
 }
@@ -1986,7 +2221,7 @@ sub super_classes {
   my ($self, $class, $seen) = @_;
   $class ||= ref($self) || $self;
   $seen  ||= {};
-  
+
   no strict 'refs';
   my @super = grep {not $seen->{$_}++} $class, @{ $class . '::ISA' };
   return @super, map {$self->super_classes($_,$seen)} @super;
@@ -1997,7 +2232,7 @@ sub known_actions {
 
   my %actions;
   no strict 'refs';
-  
+
   foreach my $class ($self->super_classes) {
     foreach ( keys %{ $class . '::' } ) {
       $actions{$1}++ if /^ACTION_(\w+)/;
@@ -2073,7 +2308,7 @@ sub get_action_docs {
     $@ = "Couldn't find any docs for action '$action'";
     return;
   }
-  
+
   return join '', @docs;
 }
 
@@ -2147,7 +2382,7 @@ sub prereq_report {
 sub ACTION_help {
   my ($self) = @_;
   my $actions = $self->known_actions;
-  
+
   if (@{$self->{args}{ARGV}}) {
     my $msg = eval {$self->get_action_docs($self->{args}{ARGV}[0], $actions)};
     print $@ ? "$@\n" : $msg;
@@ -2158,10 +2393,10 @@ sub ACTION_help {
 
  Usage: $0 <action> arg1=value arg2=value ...
  Example: $0 test verbose=1
+
  Actions defined:
 EOF
-  
+
   print $self->_action_listing($actions);
 
   print "\nRun `Build help <action>` for details on an individual action.\n";
@@ -2174,7 +2409,7 @@ sub _action_listing {
   # Flow down columns, not across rows
   my @actions = sort keys %$actions;
   @actions = map $actions[($_ + ($_ % 2) * @actions) / 2],  0..$#actions;
-  
+
   my $out = '';
   while (my ($one, $two) = splice @actions, 0, 2) {
     $out .= sprintf("  %-12s                   %-12s\n", $one, $two||'');
@@ -2184,7 +2419,7 @@ sub _action_listing {
 
 sub ACTION_retest {
   my ($self) = @_;
-  
+
   # Protect others against our @INC changes
   local @INC = @INC;
 
@@ -2232,7 +2467,7 @@ sub generic_test {
   my $p = $self->{properties};
 
   my @types = (
-    (exists($args{type})  ? $args{type} : ()), 
+    (exists($args{type})  ? $args{type} : ()),
     (exists($args{types}) ? @{$args{types}} : ()),
   );
   @types or croak "need some types of tests to check";
@@ -2265,6 +2500,8 @@ sub generic_test {
   $self->do_tests;
 }
 
+# Test::Harness dies on failure but TAP::Harness does not, so we must
+# die if running under TAP::Harness
 sub do_tests {
   my $self = shift;
 
@@ -2273,7 +2510,10 @@ sub do_tests {
   if(@$tests) {
     my $args = $self->tap_harness_args;
     if($self->use_tap_harness or ($args and %$args)) {
-      $self->run_tap_harness($tests);
+      my $aggregate = $self->run_tap_harness($tests);
+      if ( $aggregate->has_errors ) {
+        die "Errors in testing.  Cannot continue.\n";
+      }
     }
     else {
       $self->run_test_harness($tests);
@@ -2293,12 +2533,14 @@ sub run_tap_harness {
 
   # TODO allow the test @INC to be set via our API?
 
-  TAP::Harness->new({
+  my $aggregate = TAP::Harness->new({
     lib => [@INC],
     verbosity => $self->{properties}{verbose},
     switches  => [ $self->harness_switches ],
     %{ $self->tap_harness_args },
   })->runtests(@$tests);
+
+  return $aggregate;
 }
 
 sub run_test_harness {
@@ -2382,14 +2624,14 @@ sub ACTION_testcover {
     my $pm_files = $self->rscan_dir
         (File::Spec->catdir($self->blib, 'lib'), file_qr('\.pm$') );
     my $cover_files = $self->rscan_dir('cover_db', sub {-f $_ and not /\.html$/});
-    
+
     $self->do_system(qw(cover -delete))
       unless $self->up_to_date($pm_files,         $cover_files)
          && $self->up_to_date($self->test_files, $cover_files);
   }
 
-  local $Test::Harness::switches    = 
-  local $Test::Harness::Switches    = 
+  local $Test::Harness::switches    =
+  local $Test::Harness::Switches    =
   local $ENV{HARNESS_PERL_SWITCHES} = "-MDevel::Cover";
 
   $self->depends_on('test');
@@ -2398,17 +2640,17 @@ sub ACTION_testcover {
 
 sub ACTION_code {
   my ($self) = @_;
-  
+
   # All installable stuff gets created in blib/ .
   # Create blib/arch to keep blib.pm happy
   my $blib = $self->blib;
   $self->add_to_cleanup($blib);
   File::Path::mkpath( File::Spec->catdir($blib, 'arch') );
-  
+
   if (my $split = $self->autosplit) {
     $self->autosplit_file($_, $blib) for ref($split) ? @$split : ($split);
   }
-  
+
   foreach my $element (@{$self->build_elements}) {
     my $method = "process_${element}_files";
     $method = "process_files_by_extension" unless $self->can($method);
@@ -2420,16 +2662,17 @@ sub ACTION_code {
 
 sub ACTION_build {
   my $self = shift;
+  $self->log_info("Building " . $self->dist_name . "\n");
   $self->depends_on('code');
   $self->depends_on('docs');
 }
 
 sub process_files_by_extension {
   my ($self, $ext) = @_;
-  
+
   my $method = "find_${ext}_files";
   my $files = $self->can($method) ? $self->$method() : $self->_find_file_by_type($ext,  'lib');
-  
+
   while (my ($file, $dest) = each %$files) {
     $self->copy_if_modified(from => $file, to => File::Spec->catfile($self->blib, $dest) );
   }
@@ -2439,19 +2682,70 @@ sub process_support_files {
   my $self = shift;
   my $p = $self->{properties};
   return unless $p->{c_source};
-  
+
   push @{$p->{include_dirs}}, $p->{c_source};
-  
-  my $files = $self->rscan_dir($p->{c_source}, file_qr('\.c(pp)?$'));
+
+  my $files = $self->rscan_dir($p->{c_source}, file_qr('\.c(c|p|pp|xx|\+\+)?$'));
   foreach my $file (@$files) {
     push @{$p->{objects}}, $self->compile_c($file);
   }
 }
 
+sub process_share_dir_files {
+  my $self = shift;
+  my $files = $self->_find_share_dir_files;
+  return unless $files;
+
+  # root for all File::ShareDir paths
+  my $share_prefix = File::Spec->catdir($self->blib, qw/lib auto share/);
+
+  # copy all share files to blib
+  while (my ($file, $dest) = each %$files) {
+    $self->copy_if_modified(
+      from => $file, to => File::Spec->catfile( $share_prefix, $dest )
+    );
+  }
+}
+
+sub _find_share_dir_files {
+  my $self = shift;
+  my $share_dir = $self->share_dir;
+  return unless $share_dir;
+
+  my @file_map;
+  if ( $share_dir->{dist} ) {
+    my $prefix = File::Spec->catdir( "dist", $self->dist_name );
+    push @file_map, $self->_share_dir_map( $prefix, $share_dir->{dist} );
+  }
+
+  if ( $share_dir->{module} ) {
+    for my $mod ( keys %{ $share_dir->{module} } ) {
+      (my $altmod = $mod) =~ s{::}{-}g;
+      my $prefix = File::Spec->catdir("module", $altmod);
+      push @file_map, $self->_share_dir_map($prefix, $share_dir->{module}{$mod});
+    }
+  }
+
+  return { @file_map };
+}
+
+sub _share_dir_map {
+  my ($self, $prefix, $list) = @_;
+  my %files;
+  for my $dir ( @$list ) {
+    for my $f ( @{ $self->rscan_dir( $dir, sub {-f} )} ) {
+      $files{File::Spec->canonpath($f)} = File::Spec->catfile(
+        $prefix, File::Spec->abs2rel( $f, $dir )
+      );
+    }
+  }
+  return %files;
+}
+
 sub process_PL_files {
   my ($self) = @_;
   my $files = $self->find_PL_files;
-  
+
   while (my ($file, $to) = each %$files) {
     unless ($self->up_to_date( $file, $to )) {
       $self->run_perl_script($file, [], [@$to]) or die "$file failed";
@@ -2482,7 +2776,7 @@ sub process_script_files {
 
   my $script_dir = File::Spec->catdir($self->blib, 'script');
   File::Path::mkpath( $script_dir );
-  
+
   foreach my $file (keys %$files) {
     my $result = $self->copy_if_modified($file, $script_dir, 'flatten') or next;
     $self->fix_shebang_line($result) unless $self->is_vmsish;
@@ -2494,7 +2788,7 @@ sub find_PL_files {
   my $self = shift;
   if (my $files = $self->{properties}{PL_files}) {
     # 'PL_files' is given as a Unix file spec, so we localize_file_path().
-    
+
     if (UNIVERSAL::isa($files, 'ARRAY')) {
       return { map {$_, [/^(.*)\.PL$/]}
               map $self->localize_file_path($_),
@@ -2512,7 +2806,7 @@ sub find_PL_files {
       die "'PL_files' must be a hash reference or array reference";
     }
   }
-  
+
   return unless -d 'lib';
   return { map {$_, [/^(.*)\.PL$/i ]} @{ $self->rscan_dir('lib',
                                                           file_qr('\.PL$')) } };
@@ -2529,7 +2823,7 @@ sub find_script_files {
     # meaningless, but we preserve if present.
     return { map {$self->localize_file_path($_), $files->{$_}} keys %$files };
   }
-  
+
   # No default location for script files
   return {};
 }
@@ -2543,10 +2837,10 @@ sub find_test_files {
     $files = [map { -d $_ ? $self->expand_test_dir($_) : $_ }
              map glob,
              $self->split_like_shell($files)];
-    
+
     # Always given as a Unix file spec.
     return [ map $self->localize_file_path($_), @$files ];
-    
+
   } else {
     # Find all possible tests in t/ or test.pl
     my @tests;
@@ -2558,12 +2852,12 @@ sub find_test_files {
 
 sub _find_file_by_type {
   my ($self, $type, $dir) = @_;
-  
+
   if (my $files = $self->{properties}{"${type}_files"}) {
     # Always given as a Unix file spec
     return { map $self->localize_file_path($_), %$files };
   }
-  
+
   return {} unless -d $dir;
   return { map {$_, $_}
           map $self->localize_file_path($_),
@@ -2584,48 +2878,48 @@ sub localize_dir_path {
 sub fix_shebang_line { # Adapted from fixin() in ExtUtils::MM_Unix 1.35
   my ($self, @files) = @_;
   my $c = ref($self) ? $self->{config} : 'Module::Build::Config';
-  
+
   my ($does_shbang) = $c->get('sharpbang') =~ /^\s*\#\!/;
   for my $file (@files) {
     my $FIXIN = IO::File->new($file) or die "Can't process '$file': $!";
     local $/ = "\n";
     chomp(my $line = <$FIXIN>);
     next unless $line =~ s/^\s*\#!\s*//;     # Not a shbang file.
-    
+
     my ($cmd, $arg) = (split(' ', $line, 2), '');
     next unless $cmd =~ /perl/i;
     my $interpreter = $self->{properties}{perl};
-    
+
     $self->log_verbose("Changing sharpbang in $file to $interpreter");
     my $shb = '';
     $shb .= $c->get('sharpbang')."$interpreter $arg\n" if $does_shbang;
-    
+
     # I'm not smart enough to know the ramifications of changing the
     # embedded newlines here to \n, so I leave 'em in.
     $shb .= qq{
 eval 'exec $interpreter $arg -S \$0 \${1+"\$\@"}'
     if 0; # not running under some shell
 } unless $self->is_windowsish; # this won't work on win32, so don't
-    
+
     my $FIXOUT = IO::File->new(">$file.new")
       or die "Can't create new $file: $!\n";
-    
+
     # Print out the new #! line (or equivalent).
     local $\;
     undef $/; # Was localized above
     print $FIXOUT $shb, <$FIXIN>;
     close $FIXIN;
     close $FIXOUT;
-    
+
     rename($file, "$file.bak")
       or die "Can't rename $file to $file.bak: $!";
-    
+
     rename("$file.new", $file)
       or die "Can't rename $file.new to $file: $!";
-    
+
     $self->delete_filetree("$file.bak")
       or $self->log_warn("Couldn't clean up $file.bak, leaving it there");
-    
+
     $self->do_system($c->get('eunicefix'), $file) if $c->get('eunicefix') ne ':';
   }
 }
@@ -2634,7 +2928,7 @@ eval 'exec $interpreter $arg -S \$0 \${1+"\$\@"}'
 sub ACTION_testpod {
   my $self = shift;
   $self->depends_on('docs');
-  
+
   eval q{use Test::Pod 0.95; 1}
     or die "The 'testpod' action requires Test::Pod version 0.95";
 
@@ -2655,7 +2949,7 @@ sub ACTION_testpodcoverage {
   my $self = shift;
 
   $self->depends_on('docs');
-  
+
   eval q{use Test::Pod::Coverage 1.00; 1}
     or die "The 'testpodcoverage' action requires ",
            "Test::Pod::Coverage version 1.00";
@@ -2738,9 +3032,9 @@ sub manify_bin_pods {
                  $self->config( 'man1ext' );
     my $outfile = File::Spec->catfile($mandir, $manpage);
     next if $self->up_to_date( $file, $outfile );
-    $self->log_info("Manifying $file -> $outfile\n");
+    $self->log_verbose("Manifying $file -> $outfile\n");
     eval { $parser->parse_from_file( $file, $outfile ); 1 }
-      or $self->log_warn("Error creating '$outfile': $@\n"); 
+      or $self->log_warn("Error creating '$outfile': $@\n");
     $files->{$file} = $outfile;
   }
 }
@@ -2763,9 +3057,9 @@ sub manify_lib_pods {
                  $self->config( 'man3ext' );
     my $outfile = File::Spec->catfile( $mandir, $manpage);
     next if $self->up_to_date( $file, $outfile );
-    $self->log_info("Manifying $file -> $outfile\n");
+    $self->log_verbose("Manifying $file -> $outfile\n");
     eval { $parser->parse_from_file( $file, $outfile ); 1 }
-      or $self->log_warn("Error creating '$outfile': $@\n"); 
+      or $self->log_warn("Error creating '$outfile': $@\n");
     $files->{$file} = $outfile;
   }
 }
@@ -2790,12 +3084,12 @@ sub _find_pods {
 sub contains_pod {
   my ($self, $file) = @_;
   return '' unless -T $file;  # Only look at text files
-  
+
   my $fh = IO::File->new( $file ) or die "Can't open $file: $!";
   while (my $line = <$fh>) {
     return 1 if $line =~ /^\=(?:head|pod|item)/;
   }
-  
+
   return '';
 }
 
@@ -2808,7 +3102,7 @@ sub ACTION_html {
 
   foreach my $type ( qw(bin lib) ) {
     my $files = $self->_find_pods( $self->{properties}{"${type}doc_dirs"},
-                                  exclude => 
+                                  exclude =>
                                         [ file_qr('\.(?:bat|com|html)$') ] );
     next unless %$files;
 
@@ -2897,9 +3191,9 @@ sub htmlify_pods {
       push( @opts, "--css=$path2root/" . $self->html_css) if $self->html_css;
     }
 
-    $self->log_info("HTMLifying $infile -> $outfile\n");
+    $self->log_verbose("HTMLifying $infile -> $outfile\n");
     $self->log_verbose("pod2html @opts\n");
-    eval { Pod::Html::pod2html(@opts); 1 } 
+    eval { Pod::Html::pod2html(@opts); 1 }
       or $self->log_warn("pod2html @opts failed: $@");
   }
 
@@ -2919,10 +3213,10 @@ sub man3page_name {
   my $self = shift;
   my ($vol, $dirs, $file) = File::Spec->splitpath( shift );
   my @dirs = File::Spec->splitdir( File::Spec->canonpath($dirs) );
-  
+
   # Remove known exts from the base name
   $file =~ s/\.p(?:od|m|l)\z//i;
-  
+
   return join( $self->manpage_separator, @dirs, $file );
 }
 
@@ -2942,7 +3236,7 @@ sub ACTION_diff {
 
   my @flags = @{$self->{args}{ARGV}};
   @flags = $self->split_like_shell($self->{args}{flags} || '') unless @flags;
-  
+
   my $installmap = $self->install_map;
   delete $installmap->{read};
   delete $installmap->{write};
@@ -2952,22 +3246,22 @@ sub ACTION_diff {
   while (my $localdir = each %$installmap) {
     my @localparts = File::Spec->splitdir($localdir);
     my $files = $self->rscan_dir($localdir, sub {-f});
-    
+
     foreach my $file (@$files) {
       my @parts = File::Spec->splitdir($file);
       @parts = @parts[@localparts .. $#parts]; # Get rid of blib/lib or similar
-      
+
       my $installed = Module::Build::ModuleInfo->find_module_by_name(
                         join('::', @parts), \@myINC );
       if (not $installed) {
        print "Only in lib: $file\n";
        next;
       }
-      
+
       my $status = File::Compare::compare($installed, $file);
       next if $status == 0;  # Files are the same
       die "Can't compare $installed and $file: $!" if $status == -1;
-      
+
       if ($file =~ $text_suffix) {
        $self->do_system('diff', @flags, $installed, $file);
       } else {
@@ -2985,7 +3279,7 @@ sub ACTION_install {
   my ($self) = @_;
   require ExtUtils::Install;
   $self->depends_on('build');
-  ExtUtils::Install::install($self->install_map, !$self->quiet, 0, $self->{args}{uninst}||0);
+  ExtUtils::Install::install($self->install_map, $self->verbose, 0, $self->{args}{uninst}||0);
 }
 
 sub ACTION_fakeinstall {
@@ -3005,19 +3299,74 @@ sub ACTION_fakeinstall {
 
 sub ACTION_versioninstall {
   my ($self) = @_;
-  
+
   die "You must have only.pm 0.25 or greater installed for this operation: $@\n"
     unless eval { require only; 'only'->VERSION(0.25); 1 };
-  
+
   $self->depends_on('build');
-  
+
   my %onlyargs = map {exists($self->{args}{$_}) ? ($_ => $self->{args}{$_}) : ()}
     qw(version versionlib);
   only::install::install(%onlyargs);
 }
 
+sub ACTION_installdeps {
+  my ($self) = @_;
+
+  # XXX include feature prerequisites as optional prereqs?
+
+  my $info = $self->_enum_prereqs;
+  if (! $info ) {
+    $self->log_info( "No prerequisites detected\n" );
+    return;
+  }
+
+  my $failures = $self->prereq_failures($info);
+  if ( ! $failures ) {
+    $self->log_info( "All prerequisites satisfied\n" );
+    return;
+  }
+
+  my @install;
+  while (my ($type, $prereqs) = each %$failures) {
+    if($type =~ m/^(?:\w+_)?requires$/) {
+      push(@install, keys %$prereqs);
+      next;
+    }
+    $self->log_info("Checking optional dependencies:\n");
+    while (my ($module, $status) = each %$prereqs) {
+      push(@install, $module) if($self->y_n("Install $module?", 'y'));
+    }
+  }
+
+  return unless @install;
+
+  my ($command, @opts) = $self->split_like_shell($self->cpan_client);
+
+  # relative command should be relative to our active Perl
+  # so we need to locate that command
+  if ( ! File::Spec->file_name_is_absolute( $command ) ) {
+    my @bindirs = File::Basename::dirname($self->perl);
+    push @bindirs, map {$self->config->{"install${_}bin"}} '','site','vendor';
+    for my $d ( @bindirs ) {
+      my $abs_cmd = $self->find_command(File::Spec->catfile( $d, $command ));
+      if ( defined $abs_cmd ) {
+        $command = $abs_cmd;
+        last;
+      }
+    }
+  }
+
+  if ( ! -x $command ) {
+    die "cpan_client '$command' is not executable\n";
+  }
+
+  $self->do_system($command, @opts, @install);
+}
+
 sub ACTION_clean {
   my ($self) = @_;
+  $self->log_info("Cleaning up build files\n");
   foreach my $item (map glob($_), $self->cleanup) {
     $self->delete_filetree($item);
   }
@@ -3026,11 +3375,15 @@ sub ACTION_clean {
 sub ACTION_realclean {
   my ($self) = @_;
   $self->depends_on('clean');
-  $self->delete_filetree($self->config_dir, $self->build_script);
+  $self->log_info("Cleaning up configuration files\n");
+  $self->delete_filetree(
+    $self->config_dir, $self->mymetafile, $self->build_script
+  );
 }
 
 sub ACTION_ppd {
   my ($self) = @_;
+
   require Module::Build::PPMMaker;
   my $ppd = Module::Build::PPMMaker->new();
   my $file = $ppd->make_ppd(%{$self->{args}}, build => $self);
@@ -3104,7 +3457,7 @@ sub ACTION_pardist {
     );
     return();
   }
-  
+
   $self->depends_on( 'build' );
 
   return PAR::Dist::blib_to_par(
@@ -3115,11 +3468,11 @@ sub ACTION_pardist {
 
 sub ACTION_dist {
   my ($self) = @_;
-  
+
   $self->depends_on('distdir');
-  
+
   my $dist_dir = $self->dist_dir;
-  
+
   $self->make_tarball($dist_dir);
   $self->delete_filetree($dist_dir);
 }
@@ -3127,6 +3480,8 @@ sub ACTION_dist {
 sub ACTION_distcheck {
   my ($self) = @_;
 
+  $self->_check_manifest_skip;
+
   require ExtUtils::Manifest;
   local $^W; # ExtUtils::Manifest is not warnings clean.
   my ($missing, $extra) = ExtUtils::Manifest::fullcheck();
@@ -3141,6 +3496,25 @@ sub ACTION_distcheck {
   }
 }
 
+sub _check_mymeta_skip {
+  my $self = shift;
+  my $maniskip = shift || 'MANIFEST.SKIP';
+
+  require ExtUtils::Manifest;
+  local $^W; # ExtUtils::Manifest is not warnings clean.
+
+  # older ExtUtils::Manifest had a private _maniskip
+  my $skip_factory = ExtUtils::Manifest->can('maniskip')
+                  || ExtUtils::Manifest->can('_maniskip');
+
+  my $mymetafile = $self->mymetafile;
+  # we can't check it, just add it anyway to be safe
+  unless ( $skip_factory && $skip_factory->($maniskip)->($mymetafile) ) {
+    $self->log_warn("File '$maniskip' does not include '$mymetafile'. Adding it now.\n");
+    $self->_append_maniskip("^$mymetafile\$", $maniskip);
+  }
+}
+
 sub _add_to_manifest {
   my ($self, $manifest, $lines) = @_;
   $lines = [$lines] unless ref $lines;
@@ -3153,7 +3527,7 @@ sub _add_to_manifest {
 
   my $mode = (stat $manifest)[2];
   chmod($mode | oct(222), $manifest) or die "Can't make $manifest writable: $!";
-  
+
   my $fh = IO::File->new("< $manifest") or die "Can't read $manifest: $!";
   my $last_line = (<$fh>)[-1] || "\n";
   my $has_newline = $last_line =~ /\n$/;
@@ -3165,7 +3539,7 @@ sub _add_to_manifest {
   close $fh;
   chmod($mode, $manifest);
 
-  $self->log_info(map "Added to $manifest: $_\n", @$lines);
+  $self->log_verbose(map "Added to $manifest: $_\n", @$lines);
 }
 
 sub _sign_dir {
@@ -3175,16 +3549,16 @@ sub _sign_dir {
     $self->log_warn("Couldn't load Module::Signature for 'distsign' action:\n $@\n");
     return;
   }
-  
+
   # Add SIGNATURE to the MANIFEST
   {
     my $manifest = File::Spec->catfile($dir, 'MANIFEST');
     die "Signing a distribution requires a MANIFEST file" unless -e $manifest;
     $self->_add_to_manifest($manifest, "SIGNATURE    Added here by Module::Build");
   }
-  
+
   # Would be nice if Module::Signature took a directory argument.
-  
+
   $self->_do_in_dir($dir, sub {local $Module::Signature::Quiet = 1; Module::Signature::sign()});
 }
 
@@ -3210,7 +3584,7 @@ sub ACTION_distsign {
 
 sub ACTION_skipcheck {
   my ($self) = @_;
-  
+
   require ExtUtils::Manifest;
   local $^W; # ExtUtils::Manifest is not warnings clean.
   ExtUtils::Manifest::skipcheck();
@@ -3218,7 +3592,7 @@ sub ACTION_skipcheck {
 
 sub ACTION_distclean {
   my ($self) = @_;
-  
+
   $self->depends_on('realclean');
   $self->depends_on('distcheck');
 }
@@ -3235,6 +3609,11 @@ sub do_create_license {
   my $self = shift;
   $self->log_info("Creating LICENSE file\n");
 
+  if (  ! $self->_mb_feature('license_creation') ) {
+    $self->_warn_mb_feature_deps('license_creation');
+    die "Aborting.\n";
+  }
+
   my $l = $self->license
     or die "No license specified";
 
@@ -3243,7 +3622,7 @@ sub do_create_license {
   my $class = "Software::License::$key";
 
   eval "use $class; 1"
-    or die "Can't load Software::License to create LICENSE file: $@";
+    or die "Can't load Software::License::$key to create LICENSE file: $@";
 
   $self->delete_filetree('LICENSE');
 
@@ -3270,7 +3649,9 @@ EOF
     return;
   }
 
-  if ( eval {require Pod::Readme; 1} ) {
+  # work around some odd Pod::Readme->new() failures in test reports by
+  # confirming that new() is available
+  if ( eval {require Pod::Readme; Pod::Readme->can('new') } ) {
     $self->log_info("Creating README using Pod::Readme\n");
 
     my $parser = Pod::Readme->new;
@@ -3326,29 +3707,48 @@ sub _main_docfile {
   }
 }
 
+sub do_create_bundle_inc {
+  my $self = shift;
+  my $dist_inc = File::Spec->catdir( $self->dist_dir, 'inc' );
+  require inc::latest;
+  inc::latest->write($dist_inc, @{$self->bundle_inc_preload});
+  inc::latest->bundle_module($_, $dist_inc) for @{$self->bundle_inc};
+  return 1;
+}
+
 sub ACTION_distdir {
   my ($self) = @_;
 
+  if ( @{$self->bundle_inc} && ! $self->_mb_feature('inc_bundling_support') ) {
+    $self->_warn_mb_feature_deps('inc_bundling_support');
+    die "Aborting.\n";
+  }
+
   $self->depends_on('distmeta');
 
+  # Must not include MYMETA
+  $self->_check_mymeta_skip('MANIFEST.SKIP');
+
   my $dist_files = $self->_read_manifest('MANIFEST')
-    or die "Can't create distdir without a MANIFEST file - run 'manifest' action first";
+    or die "Can't create distdir without a MANIFEST file - run 'manifest' action first.\n";
   delete $dist_files->{SIGNATURE};  # Don't copy, create a fresh one
   die "No files found in MANIFEST - try running 'manifest' action?\n"
     unless ($dist_files and keys %$dist_files);
   my $metafile = $self->metafile;
   $self->log_warn("*** Did you forget to add $metafile to the MANIFEST?\n")
     unless exists $dist_files->{$metafile};
-  
+
   my $dist_dir = $self->dist_dir;
   $self->delete_filetree($dist_dir);
   $self->log_info("Creating $dist_dir\n");
   $self->add_to_cleanup($dist_dir);
-  
+
   foreach my $file (keys %$dist_files) {
     my $new = $self->copy_if_modified(from => $file, to_dir => $dist_dir, verbose => 0);
   }
-  
+
+  $self->do_create_bundle_inc if @{$self->bundle_inc};
+
   $self->_sign_dir($dist_dir) if $self->{properties}{sign};
 }
 
@@ -3388,8 +3788,7 @@ sub _eumanifest_has_include {
     my $self = shift;
 
     require ExtUtils::Manifest;
-    return ExtUtils::Manifest->VERSION >= 1.50 ? 1 : 0;
-    return 0;
+    return eval { ExtUtils::Manifest->VERSION(1.50); 1 };
 }
 
 
@@ -3436,6 +3835,19 @@ sub _slurp {
 }
 
 
+
+sub _append_maniskip {
+  my $self = shift;
+  my $skip = shift;
+  my $file = shift || 'MANIFEST.SKIP';
+  return unless defined $skip && length $skip;
+  my $fh = IO::File->new(">> $file")
+    or die "Can't open $file: $!";
+
+  print $fh "$skip\n";
+  $fh->close();
+}
+
 sub _write_default_maniskip {
   my $self = shift;
   my $file = shift || 'MANIFEST.SKIP';
@@ -3446,6 +3858,8 @@ sub _write_default_maniskip {
                                                : $self->_slurp( $self->_default_maniskip );
 
   $content .= <<'EOF';
+# Avoid configuration metadata file
+^MYMETA\.$
 
 # Avoid Module::Build generated and utility files.
 \bBuild$
@@ -3466,14 +3880,27 @@ EOF
   return;
 }
 
-sub ACTION_manifest {
+sub _check_manifest_skip {
   my ($self) = @_;
 
   my $maniskip = 'MANIFEST.SKIP';
-  unless ( -e 'MANIFEST' || -e $maniskip ) {
+
+  if ( ! -e $maniskip ) {
     $self->log_warn("File '$maniskip' does not exist: Creating a default '$maniskip'\n");
     $self->_write_default_maniskip($maniskip);
   }
+  else {
+    # MYMETA must not be added to MANIFEST, so always confirm the skip
+    $self->_check_mymeta_skip( $maniskip );
+  }
+
+  return;
+}
+
+sub ACTION_manifest {
+  my ($self) = @_;
+
+  $self->_check_manifest_skip;
 
   require ExtUtils::Manifest;  # ExtUtils::Manifest is not warnings clean.
   local ($^W, $ExtUtils::Manifest::Quiet) = (0,1);
@@ -3511,6 +3938,63 @@ sub _files_in {
   return @files;
 }
 
+sub share_dir {
+  my $self = shift;
+  my $p = $self->{properties};
+
+  $p->{share_dir} = shift if @_;
+
+  # Always coerce to proper hash form
+  if    ( ! defined $p->{share_dir} ) {
+    # not set -- use default 'share' dir if exists
+    $p->{share_dir} = { dist => [ 'share' ] } if -d 'share';
+  }
+  elsif ( ! ref $p->{share_dir}  ) {
+    # scalar -- treat as a single 'dist' directory
+    $p->{share_dir} = { dist => [ $p->{share_dir} ] };
+  }
+  elsif ( ref $p->{share_dir} eq 'ARRAY' ) {
+    # array -- treat as a list of 'dist' directories
+    $p->{share_dir} = { dist => $p->{share_dir} };
+  }
+  elsif ( ref $p->{share_dir} eq 'HASH' ) {
+    # hash -- check structure
+    my $share_dir = $p->{share_dir};
+    # check dist key
+    if ( defined $share_dir->{dist} ) {
+      if ( ! ref $share_dir->{dist} ) {
+        # scalar, so upgrade to arrayref
+        $share_dir->{dist} = [ $share_dir->{dist} ];
+      }
+      elsif ( ref $share_dir->{dist} ne 'ARRAY' ) {
+        die "'dist' key in 'share_dir' must be scalar or arrayref";
+      }
+    }
+    # check module key
+    if ( defined $share_dir->{module} ) {
+      my $mod_hash = $share_dir->{module};
+      if ( ref $mod_hash eq 'HASH' ) {
+        for my $k ( keys %$mod_hash ) {
+          if ( ! ref $mod_hash->{$k} ) {
+            $mod_hash->{$k} = [ $mod_hash->{$k} ];
+          }
+          elsif( ref $mod_hash->{$k} ne 'ARRAY' ) {
+            die "modules in 'module' key of 'share_dir' must be scalar or arrayref";
+          }
+        }
+      }
+      else {
+          die "'module' key in 'share_dir' must be hashref";
+      }
+    }
+  }
+  else {
+    die "'share_dir' must be hashref, arrayref or string";
+  }
+
+  return $p->{share_dir};
+}
+
 sub script_files {
   my $self = shift;
 
@@ -3529,13 +4013,13 @@ sub script_files {
   }
 
   my %pl_files = map {
-    File::Spec->canonpath( File::Spec->case_tolerant ? uc $_ : $_ ) => 1 
+    File::Spec->canonpath( File::Spec->case_tolerant ? uc $_ : $_ ) => 1
   } keys %{ $self->PL_files || {} };
 
   my @bin_files = $self->_files_in('bin');
 
   my %bin_map = map {
-    $_ => File::Spec->canonpath( File::Spec->case_tolerant ? uc $_ : $_ ) 
+    $_ => File::Spec->canonpath( File::Spec->case_tolerant ? uc $_ : $_ )
   } @bin_files;
 
   return $_ = { map {$_ => 1} grep !$pl_files{$bin_map{$_}}, @bin_files };
@@ -3546,6 +4030,7 @@ BEGIN { *scripts = \&script_files; }
   my %licenses = (
     perl         => 'Perl_5',
     apache       => 'Apache_2_0',
+    apache_1_1   => 'Apache_1_1',
     artistic     => 'Artistic_1_0',
     artistic_2   => 'Artistic_2_0',
     lgpl         => 'LGPL_2_1',
@@ -3568,6 +4053,7 @@ BEGIN { *scripts = \&script_files; }
   my %license_urls = (
     perl         => 'http://dev.perl.org/licenses/',
     apache       => 'http://apache.org/licenses/LICENSE-2.0',
+    apache_1_1   => 'http://apache.org/licenses/LICENSE-1.1',
     artistic     => 'http://opensource.org/licenses/artistic-license.php',
     artistic_2   => 'http://opensource.org/licenses/artistic-license-2.0.php',
     lgpl         => 'http://opensource.org/licenses/lgpl-license.php',
@@ -3615,10 +4101,10 @@ sub ACTION_distmeta {
 sub do_create_metafile {
   my $self = shift;
   return if $self->{wrote_metadata};
-  
+
   my $p = $self->{properties};
   my $metafile = $self->metafile;
-  
+
   unless ($p->{license}) {
     $self->log_warn("No license specified, setting license = 'unknown'\n");
     $p->{license} = 'unknown';
@@ -3639,7 +4125,7 @@ sub do_create_metafile {
     push @INC, File::Spec->catdir($self->blib, 'lib');
   }
 
-  if ( $self->write_metafile( $self->metafile, $self->generate_metadata ) ) {
+  if ( $self->write_metafile( $self->metafile, $self->prepare_metadata( fatal => 1 ) ) ) {
     $self->{wrote_metadata} = 1;
     $self->_add_to_manifest('MANIFEST', $metafile);
   }
@@ -3647,42 +4133,22 @@ sub do_create_metafile {
   return 1;
 }
 
-sub generate_metadata {
-  my $self = shift;
-  my $node = {};
-
-  if ($self->_mb_feature('YAML_support')) {
-    require YAML;
-    require YAML::Node;
-    # We use YAML::Node to get the order nice in the YAML file.
-    $self->prepare_metadata( $node = YAML::Node->new({}) );
-  } else {
-    require Module::Build::YAML;
-    my @order_keys;
-    $self->prepare_metadata($node, \@order_keys);
-    $node->{_order} = \@order_keys;
-  }
-  return $node;
-}
-
 sub write_metafile {
   my $self = shift;
   my ($metafile, $node) = @_;
+  my $yaml;
 
   if ($self->_mb_feature('YAML_support')) {
     # XXX this is probably redundant, but stick with it
-    require YAML;
-    require YAML::Node;
-    delete $node->{_order}; # XXX also probably redundant, but for safety
-    # YAML API changed after version 0.30
-    my $yaml_sub = $YAML::VERSION le '0.30' ? \&YAML::StoreFile : \&YAML::DumpFile;
-    $yaml_sub->( $metafile, $node );
+    require YAML::Tiny;
+    $yaml = YAML::Tiny->new($node);
   } else {
-    # XXX probably redundant
     require Module::Build::YAML;
-    &Module::Build::YAML::DumpFile($metafile, $node);
+    $yaml = Module::Build::YAML->new($node);
   }
-  return 1;
+  my $result = $yaml->write($metafile)
+    or $self->log_warn( "Error writing '$metafile': " . $yaml->errstr . "\n");
+  return $result;
 }
 
 sub normalize_version {
@@ -3690,7 +4156,7 @@ sub normalize_version {
   if ( $version =~ /[=<>!,]/ ) { # logic, not just version
     # take as is without modification
   }
-  elsif ( ref $version eq 'version' || 
+  elsif ( ref $version eq 'version' ||
           ref $version eq 'Module::Build::Version' ) { # version objects
     $version = $version->is_qv ? $version->normal : $version->stringify;
   }
@@ -3705,31 +4171,46 @@ sub normalize_version {
 }
 
 sub prepare_metadata {
-  my ($self, $node, $keys) = @_;
+  my ($self, %args) = @_;
+  my $fatal = $args{fatal} || 0;
   my $p = $self->{properties};
+  my $node = {};
 
   # A little helper sub
   my $add_node = sub {
     my ($name, $val) = @_;
     $node->{$name} = $val;
-    push @$keys, $name if $keys;
   };
 
   foreach (qw(dist_name dist_version dist_author dist_abstract license)) {
     (my $name = $_) =~ s/^dist_//;
     $add_node->($name, $self->$_());
-    die "ERROR: Missing required field '$_' for META.yml\n"
-      unless defined($node->{$name}) && length($node->{$name});
+    unless ( defined($node->{$name}) && length($node->{$name}) ) {
+      my $err = "ERROR: Missing required field '$_' for metafile\n";
+      if ( $fatal ) {
+        die $err;
+      }
+      else {
+        $self->log_warn($err);
+      }
+    }
   }
-  $node->{version} = $self->normalize_version($node->{version}); 
+  $node->{version} = $self->normalize_version($node->{version});
 
   if (defined( my $l = $self->license )) {
-    die "Unknown license string '$l'"
-      unless exists $self->valid_licenses->{ $l };
+    unless ( exists $self->valid_licenses->{ $l } ) {
+      my $err = "Unknown license string '$l'";
+      if ( $fatal ) {
+        die $err;
+      }
+      else {
+        $self->log_warn($err);
+      }
+    }
 
     if (my $key = $self->valid_licenses->{ $l }) {
       my $class = "Software::License::$key";
-      if (eval "use $class; 1") {
+      if (eval "require Software::License; require $class; 1") {
         # S::L requires a 'holder' key
         $node->{resources}{license} = $class->new({holder=>"nobody"})->url;
       }
@@ -3743,24 +4224,14 @@ sub prepare_metadata {
   # copy prereq data structures so we can modify them before writing to META
   my %prereq_types;
   for my $type ( 'configure_requires', @{$self->prereq_action_types} ) {
-    if (exists $p->{$type}) {  
+    if (exists $p->{$type}) {
       for my $mod ( keys %{ $p->{$type} } ) {
-        $prereq_types{$type}{$mod} = 
+        $prereq_types{$type}{$mod} =
           $self->normalize_version($p->{$type}{$mod});
       }
     }
   }
 
-  # add current Module::Build to configure_requires if there 
-  # isn't one already specified (but not ourself, so we're not circular)
-  if ( $self->dist_name ne 'Module-Build' 
-    && $self->auto_configure_requires
-    && ! exists $prereq_types{'configure_requires'}{'Module::Build'}
-  ) {
-    (my $ver = $VERSION) =~ s/^(\d+\.\d\d).*$/$1/; # last major release only
-    $prereq_types{configure_requires}{'Module::Build'} = $ver;
-  }
-
   for my $t ( keys %prereq_types ) {
       $add_node->($t, $prereq_types{$t});
   }
@@ -3771,7 +4242,7 @@ sub prepare_metadata {
   my $pkgs = eval { $self->find_dist_packages };
   if ($@) {
     $self->log_warn("$@\nWARNING: Possible missing or corrupt 'MANIFEST' file.\n" .
-                   "Nothing to enter for 'provides' field in META.yml\n");
+                   "Nothing to enter for 'provides' field in metafile.\n");
   } else {
     $node->{provides} = $pkgs if %$pkgs;
   }
@@ -3782,7 +4253,7 @@ sub prepare_metadata {
 
   $add_node->('generated_by', "Module::Build version $Module::Build::VERSION");
 
-  $add_node->('meta-spec', 
+  $add_node->('meta-spec',
              {version => '1.4',
               url     => 'http://module-build.sourceforge.net/META-spec-v1.4.html',
              });
@@ -3815,21 +4286,28 @@ sub find_dist_packages {
   # private stock.
 
   my $manifest = $self->_read_manifest('MANIFEST')
-    or die "Can't find dist packages without a MANIFEST file - run 'manifest' action first";
+    or die "Can't find dist packages without a MANIFEST file\nRun 'Build manifest' to generate one\n";
 
   # Localize
   my %dist_files = map { $self->localize_file_path($_) => $_ }
                        keys %$manifest;
 
-  my @pm_files = grep {exists $dist_files{$_}} keys %{ $self->find_pm_files };
+  my @pm_files = grep { $_ !~ m{^t} } # skip things in t/
+                   grep {exists $dist_files{$_}}
+                     keys %{ $self->find_pm_files };
+
+  return $self->find_packages_in_files(\@pm_files, \%dist_files);
+}
+
+sub find_packages_in_files {
+  my ($self, $file_list, $filename_map) = @_;
 
   # First, we enumerate all packages & versions,
   # separating into primary & alternative candidates
   my( %prime, %alt );
-  foreach my $file (@pm_files) {
-    next if $dist_files{$file} =~ m{^t/};  # Skip things in t/
-
-    my @path = split( /\//, $dist_files{$file} );
+  foreach my $file (@{$file_list}) {
+    my $mapped_filename = $filename_map->{$file};
+    my @path = split( /\//, $mapped_filename );
     (my $prime_package = join( '::', @path[1..$#path] )) =~ s/\.pm$//;
 
     my $pm_info = Module::Build::ModuleInfo->new_from_file( $file );
@@ -3841,18 +4319,18 @@ sub find_dist_packages {
       my $version = $pm_info->version( $package );
 
       if ( $package eq $prime_package ) {
-       if ( exists( $prime{$package} ) ) {
-         # M::B::ModuleInfo will handle this conflict
-         die "Unexpected conflict in '$package'; multiple versions found.\n";
-       } else {
-         $prime{$package}{file} = $dist_files{$file};
+        if ( exists( $prime{$package} ) ) {
+          # M::B::ModuleInfo will handle this conflict
+          die "Unexpected conflict in '$package'; multiple versions found.\n";
+        } else {
+          $prime{$package}{file} = $mapped_filename;
           $prime{$package}{version} = $version if defined( $version );
         }
       } else {
-       push( @{$alt{$package}}, {
-                                 file    => $dist_files{$file},
-                                 version => $version,
-                                } );
+        push( @{$alt{$package}}, {
+                                  file    => $mapped_filename,
+                                  version => $version,
+                                 } );
       }
     }
   }
@@ -3972,24 +4450,29 @@ sub _resolve_module_versions {
 sub make_tarball {
   my ($self, $dir, $file) = @_;
   $file ||= $dir;
-  
+
   $self->log_info("Creating $file.tar.gz\n");
-  
+
   if ($self->{args}{tar}) {
     my $tar_flags = $self->verbose ? 'cvf' : 'cf';
     $self->do_system($self->split_like_shell($self->{args}{tar}), $tar_flags, "$file.tar", $dir);
     $self->do_system($self->split_like_shell($self->{args}{gzip}), "$file.tar") if $self->{args}{gzip};
   } else {
-    eval { require Archive::Tar && Archive::Tar->VERSION(1.08); 1 }
-      or die "You must install Archive::Tar to make a distribution tarball\n".
+    eval { require Archive::Tar && Archive::Tar->VERSION(1.09); 1 }
+      or die "You must install Archive::Tar 1.09+ to make a distribution tarball\n".
              "or specify a binary tar program with the '--tar' option.\n".
              "See the documentation for the 'dist' action.\n";
 
+    my $files = $self->rscan_dir($dir);
+
     # Archive::Tar versions >= 1.09 use the following to enable a compatibility
     # hack so that the resulting archive is compatible with older clients.
-    $Archive::Tar::DO_NOT_USE_PREFIX = 0;
+    # If no file path is 100 chars or longer, we disable the prefix field
+    # for maximum compatibility.  If there are any long file paths then we
+    # need the prefix field after all.
+    $Archive::Tar::DO_NOT_USE_PREFIX =
+      (grep { length($_) >= 100 } @$files) ? 0 : 1;
 
-    my $files = $self->rscan_dir($dir);
     my $tar   = Archive::Tar->new;
     $tar->add_files(@$files);
     for my $f ($tar->get_files) {
@@ -4055,7 +4538,7 @@ sub original_prefix {
   #   or original_prefix('lib' => $value);
   my ($self, $key, $value) = @_;
   # update property before merging with defaults
-  if ( @_ == 3 && defined $key) { 
+  if ( @_ == 3 && defined $key) {
     # $value can be undef; will mask default
     $self->{properties}{original_prefix}{$key} = $value;
   }
@@ -4263,7 +4746,7 @@ sub install_map {
       }
     }
   }
-  
+
   $map{read} = '';  # To keep ExtUtils::Install quiet
 
   return \%map;
@@ -4284,7 +4767,7 @@ sub rscan_dir {
              !ref($pattern) || (ref $pattern eq 'Regexp') ? sub {push @result, $File::Find::name if /$pattern/} :
             ref($pattern) eq 'CODE' ? sub {push @result, $File::Find::name if $pattern->()} :
             die "Unknown pattern type";
-  
+
   File::Find::find({wanted => $subr, no_chdir => 1}, $dir);
   return \@result;
 }
@@ -4294,7 +4777,7 @@ sub delete_filetree {
   my $deleted = 0;
   foreach (@_) {
     next unless -e $_;
-    $self->log_info("Deleting $_\n");
+    $self->log_verbose("Deleting $_\n");
     File::Path::rmtree($_, 0, 0);
     die "Couldn't remove '$_': $!\n" if -e $_;
     $deleted++;
@@ -4327,21 +4810,25 @@ sub cbuilder {
 
 sub have_c_compiler {
   my ($self) = @_;
-  
+
   my $p = $self->{properties};
-  return $p->{have_compiler} if defined $p->{have_compiler};
-  
+  return $p->{_have_c_compiler} if defined $p->{_have_c_compiler};
+
   $self->log_verbose("Checking if compiler tools configured... ");
   my $b = eval { $self->cbuilder };
-  my $have = $b && $b->have_compiler;
+  my $have = $b && eval { $b->have_compiler };
   $self->log_verbose($have ? "ok.\n" : "failed.\n");
-  return $p->{have_compiler} = $have;
+  return $p->{_have_c_compiler} = $have;
 }
 
 sub compile_c {
   my ($self, $file, %args) = @_;
-  my $b = $self->cbuilder;
 
+  if ( ! $self->have_c_compiler ) {
+    die "Error: no compiler detected to compile '$file'.  Aborting\n";
+  }
+
+  my $b = $self->cbuilder;
   my $obj_file = $b->object_file($file);
   $self->add_to_cleanup($obj_file);
   return $obj_file if $self->up_to_date($file, $obj_file);
@@ -4381,11 +4868,11 @@ sub link_c {
 
 sub compile_xs {
   my ($self, $file, %args) = @_;
-  
-  $self->log_info("$file -> $args{outfile}\n");
+
+  $self->log_verbose("$file -> $args{outfile}\n");
 
   if (eval {require ExtUtils::ParseXS; 1}) {
-    
+
     ExtUtils::ParseXS::process_file(
                                    filename => $file,
                                    prototypes => 0,
@@ -4393,26 +4880,26 @@ sub compile_xs {
                                   );
   } else {
     # Ok, I give up.  Just use backticks.
-    
+
     my $xsubpp = Module::Build::ModuleInfo->find_module_by_name('ExtUtils::xsubpp')
       or die "Can't find ExtUtils::xsubpp in INC (@INC)";
-    
+
     my @typemaps;
     push @typemaps, Module::Build::ModuleInfo->find_module_by_name(
         'ExtUtils::typemap', \@INC
     );
     my $lib_typemap = Module::Build::ModuleInfo->find_module_by_name(
-        'typemap', [File::Basename::dirname($file)]
+        'typemap', [File::Basename::dirname($file), File::Spec->rel2abs('.')]
     );
     push @typemaps, $lib_typemap if $lib_typemap;
     @typemaps = map {+'-typemap', $_} @typemaps;
 
     my $cf = $self->{config};
     my $perl = $self->{properties}{perl};
-    
+
     my @command = ($perl, "-I".$cf->get('installarchlib'), "-I".$cf->get('installprivlib'), $xsubpp, '-noprototypes',
                   @typemaps, $file);
-    
+
     $self->log_info("@command\n");
     my $fh = IO::File->new("> $args{outfile}") or die "Couldn't write $args{outfile}: $!";
     print {$fh} $self->_backticks(@command);
@@ -4422,12 +4909,12 @@ sub compile_xs {
 
 sub split_like_shell {
   my ($self, $string) = @_;
-  
+
   return () unless defined($string);
   return @$string if UNIVERSAL::isa($string, 'ARRAY');
   $string =~ s/^\s+|\s+$//g;
   return () unless length($string);
-  
+
   return Text::ParseWords::shellwords($string);
 }
 
@@ -4553,12 +5040,12 @@ sub process_xs {
 
 sub do_system {
   my ($self, @cmd) = @_;
-  $self->log_info("@cmd\n");
+  $self->log_verbose("@cmd\n");
 
   # Some systems proliferate huge PERL5LIBs, try to ameliorate:
   my %seen;
   my $sep = $self->config('path_sep');
-  local $ENV{PERL5LIB} = 
+  local $ENV{PERL5LIB} =
     ( !exists($ENV{PERL5LIB}) ? '' :
       length($ENV{PERL5LIB}) < 500
       ? $ENV{PERL5LIB}
@@ -4587,8 +5074,8 @@ sub copy_if_modified {
   unless (defined $file and length $file) {
     die "No 'from' parameter given to copy_if_modified";
   }
-  # makes no sense to replicate an absolute path, so assume flatten 
+
+  # makes no sense to replicate an absolute path, so assume flatten
   $args{flatten} = 1 if File::Spec->file_name_is_absolute( $file );
 
   my $to_path;
@@ -4601,7 +5088,7 @@ sub copy_if_modified {
   } else {
     die "No 'to' or 'to_dir' parameter given to copy_if_modified";
   }
-  
+
   return if $self->up_to_date($file, $to_path); # Already fresh
 
   {
@@ -4611,9 +5098,9 @@ sub copy_if_modified {
 
   # Create parent directories
   File::Path::mkpath(File::Basename::dirname($to_path), 0, oct(777));
-  
-  $self->log_info("Copying $file -> $to_path\n") if $args{verbose};
-  
+
+  $self->log_verbose("Copying $file -> $to_path\n");
+
   if ($^O eq 'os2') {# copy will not overwrite; 0x1 = overwrite
     chmod 0666, $to_path;
     File::Copy::syscopy($file, $to_path, 0x1) or die "Can't copy('$file', '$to_path'): $!";
@@ -4644,7 +5131,7 @@ sub up_to_date {
     }
     $most_recent_source = -M _ if -M _ < $most_recent_source;
   }
-  
+
   foreach my $derived (@$derived) {
     return 0 if -M $derived > $most_recent_source;
   }
@@ -4655,21 +5142,21 @@ sub dir_contains {
   my ($self, $first, $second) = @_;
   # File::Spec doesn't have an easy way to check whether one directory
   # is inside another, unfortunately.
-  
+
   ($first, $second) = map File::Spec->canonpath($_), ($first, $second);
   my @first_dirs = File::Spec->splitdir($first);
   my @second_dirs = File::Spec->splitdir($second);
 
   return 0 if @second_dirs < @first_dirs;
-  
+
   my $is_same = ( File::Spec->case_tolerant
                  ? sub {lc(shift()) eq lc(shift())}
                  : sub {shift() eq shift()} );
-  
+
   while (@first_dirs) {
     return 0 unless $is_same->(shift @first_dirs, shift @second_dirs);
   }
-  
+
   return 1;
 }
 
diff --git a/cpan/Module-Build/lib/Module/Build/Bundling.pod b/cpan/Module-Build/lib/Module/Build/Bundling.pod
new file mode 100644 (file)
index 0000000..0a60d8f
--- /dev/null
@@ -0,0 +1,154 @@
+=head1 NAME
+
+Module::Build::Bundling - How to bundle Module::Build with a distribution
+
+=head1 SYNOPSIS
+
+  # Build.PL
+  use lib '.';
+  use inc::latest 'Module::Build';
+
+  Module::Build->new(
+    module_name => 'Foo::Bar',
+    license => 'perl',
+  )->create_build_script;
+
+=head1 DESCRIPTION
+
+B<WARNING -- THIS IS AN EXPERIMENTAL FEATURE>
+
+In order to install a distribution using Module::Build, users must
+have Module::Build available on their systems.  There are two ways
+to do this.  The first way is to include Module::Build in the
+C<configure_requires> metadata field.  This field is supported by
+recent versions L<CPAN> and L<CPANPLUS> and is a standard feature
+in the Perl core as of Perl 5.10.1.  Module::Build now adds itself
+to C<configure_requires> by default.
+
+The second way supports older Perls that have not upgraded CPAN or
+CPANPLUS and involves bundling an entire copy of Module::Build
+into the distribution's C<inc/> directory.  This is the same approach
+used by L<Module::Install>, a modern wrapper around ExtUtils::MakeMaker
+for Makefile.PL based distributions.
+
+The "trick" to making this work for Module::Build is making sure the
+highest version Module::Build is used, whether this is in C<inc/> or
+already installed on the user's system.  This ensures that all necessary
+features are available as well as any new bug fixes.  This is done using
+the new L<inc::latest> module.
+
+A "normal" Build.PL looks like this (with only the minimum required
+fields):
+
+  use Module::Build;
+
+  Module::Build->new(
+    module_name => 'Foo::Bar',
+    license     => 'perl',
+  )->create_build_script;
+
+A "bundling" Build.PL replaces the initial "use" line with a nearly
+transparent replacement:
+
+  use lib '.';
+  use inc::latest 'Module::Build';
+
+  Module::Build->new(
+    module_name => 'Foo::Bar',
+    license => 'perl',
+  )->create_build_script;
+
+The inital C<lib> line ensures that the top-level distribution directory is
+added to C<@INC> so that C<inc::latest> loads from C<./inc/latest.pm>.  You
+SHOULD NOT add 'inc' to C<@INC> (unless you have other special reasons for
+doing so) -- that's not how C<inc::latest> works.
+
+For I<authors>, when "Build dist" is run, Module::Build will be
+automatically bundled into C<inc> according to the rules for
+L<inc::latest>.
+
+For I<users>, inc::latest will load the latest Module::Build, whether
+installed or bundled in C<inc/>.
+
+=head1 BUNDLING OTHER CONFIGURATION DEPENDENCIES
+
+The same approach works for other configuration dependencies -- modules
+that I<must> be available for Build.PL to run.  All other dependencies can
+be specified as usual in the Build.PL and CPAN or CPANPLUS will install
+them after Build.PL finishes.
+
+For example, to bundle the L<Devel::AssertOS::Unix> module (which ensures a
+"Unix-like" operating system), one could do this:
+
+  use inc::latest 'Devel::AssertOS::Unix';
+  use inc::latest 'Module::Build';
+
+  Module::Build->new(
+    module_name => 'Foo::Bar',
+    license => 'perl',
+  )->create_build_script;
+
+The C<inc::latest> module creates bundled directories based on the packlist
+file of an installed distribution.  Even though C<inc::latest> takes module
+name arguments, it is better to think of it as bundling and making
+available entire I<distributions>.  When a module is loaded through
+C<inc::latest>, it looks in all bundled distributions in C<inc/> for a
+newer module than can be found in the existing C<@INC> array.
+
+Thus, the module-name provided should usually be the "top-level" module
+name of a distribution, though this is not strictly required.  For example,
+L<Module::Build> has a number of heuristics to map module names to
+packlists, allowing users to do things like this:
+
+  use inc::latest 'Devel::AssertOS::Unix';
+
+even though Devel::AssertOS::Unix is contained within the Devel-CheckOS
+distribution.
+
+At the current time, packlists are required.  Thus, bundling dual-core
+modules, I<including Module::Build>, may require a 'forced install' over
+versions in the latest version of perl in order to create the necessary
+packlist for bundling.  This limitation will hopefully be addressed in a
+future version of Module::Build.
+
+=head2 WARNING -- How to Manage Dependency Chains
+
+Before bundling a distribution you must ensure that all prerequisites are
+also bundled and load in the correct order.  For Module::Build itself, this
+should not be necessary, but it is necessary for any other distribution.
+(A future release of Module::Build will hopefully address this deficiency.)
+
+For example, if you need C<Wibble>, but C<Wibble> depends on C<Wobble>,
+your Build.PL might look like this:
+
+  use inc::latest 'Wobble';
+  use inc::latest 'Wibble';
+  use inc::latest 'Module::Build';
+
+  Module::Build->new(
+    module_name => 'Foo::Bar',
+    license => 'perl',
+  )->create_build_script;
+
+Authors are strongly suggested to limit the bundling of additional
+dependencies if at all possible and to carefully test their distribution
+tarballs on older versions of Perl before uploading to CPAN.
+
+=head1 AUTHOR
+
+David Golden <dagolden@cpan.org>
+
+Development questions, bug reports, and patches should be sent to the
+Module-Build mailing list at <module-build@perl.org>.
+
+Bug reports are also welcome at
+<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Module-Build>.
+
+=head1 SEE ALSO
+
+perl(1), L<inc::latest>, L<Module::Build>(3), L<Module::Build::API>(3),
+L<Module::Build::Cookbook>(3),
+
+=cut
+
+# vim: tw=75
index dfe75d5..ebe1b12 100644 (file)
@@ -2,7 +2,7 @@ package Module::Build::Compat;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 
 use File::Basename ();
 use File::Spec;
@@ -18,7 +18,7 @@ my %convert_installdirs = (
     VENDOR      => 'vendor',
 );
 
-my %makefile_to_build = 
+my %makefile_to_build =
   (
    TEST_VERBOSE => 'verbose',
    VERBINST     => 'verbose',
@@ -64,13 +64,50 @@ my %macro_to_build = %makefile_to_build;
 # "LIB=foo make" is not the same as "perl Makefile.PL LIB=foo"
 delete $macro_to_build{LIB};
 
+sub _simple_prereq {
+  return $_[0] =~ /^[0-9_]+\.?[0-9_]*$/; # crudly, a decimal literal
+}
+
+sub _merge_prereq {
+  my ($req, $breq) = @_;
+  $req ||= {};
+  $breq ||= {};
+
+  # validate formats
+  for my $p ( $req, $breq ) {
+    for my $k (keys %$p) {
+      die "Prereq '$p->{$k}' for '$k' is not supported by Module::Build::Compat\n"
+        unless _simple_prereq($p->{$k});
+    }
+  }
+  # merge
+  my $merge = { %$req };
+  for my $k ( keys %$breq ) {
+    my $v1 = $merge->{$k} || 0;
+    my $v2 = $breq->{$k};
+    $merge->{$k} = $v1 > $v2 ? $v1 : $v2;
+  }
+  return %$merge;
+}
+
 
 sub create_makefile_pl {
   my ($package, $type, $build, %args) = @_;
-  
+
   die "Don't know how to build Makefile.PL of type '$type'"
     unless $type =~ /^(small|passthrough|traditional)$/;
 
+  if ($type eq 'passthrough') {
+    $build->log_warn(<<"HERE");
+
+IMPORTANT NOTE: The '$type' style of Makefile.PL is deprecated and
+may be removed in a future version of Module::Build in favor of the
+'configure_requires' property.  See Module::Build::Compat
+documentation for details.
+
+HERE
+  }
+
   my $fh;
   if ($args{fh}) {
     $fh = $args{fh};
@@ -83,7 +120,7 @@ sub create_makefile_pl {
 
   print {$fh} "# Note: this file was auto-generated by ", __PACKAGE__, " version $VERSION\n";
 
-  # Minimum perl version should be specified as "require 5.XXXXXX" in 
+  # Minimum perl version should be specified as "require 5.XXXXXX" in
   # Makefile.PL
   my $requires = $build->requires;
   if ( my $minimum_perl = $requires->{perl} ) {
@@ -123,41 +160,41 @@ EOF
 
   } elsif ($type eq 'passthrough') {
     printf {$fh} <<'EOF', $subclass_load, ref($build), ref($build);
-    
+
     unless (eval "use Module::Build::Compat 0.02; 1" ) {
       print "This module requires Module::Build to install itself.\n";
-      
+
       require ExtUtils::MakeMaker;
       my $yn = ExtUtils::MakeMaker::prompt
        ('  Install Module::Build now from CPAN?', 'y');
-      
+
       unless ($yn =~ /^y/i) {
        die " *** Cannot install without Module::Build.  Exiting ...\n";
       }
-      
+
       require Cwd;
       require File::Spec;
       require CPAN;
-      
+
       # Save this 'cause CPAN will chdir all over the place.
       my $cwd = Cwd::cwd();
-      
+
       CPAN::Shell->install('Module::Build::Compat');
       CPAN::Shell->expand("Module", "Module::Build::Compat")->uptodate
        or die "Couldn't install Module::Build, giving up.\n";
-      
+
       chdir $cwd or die "Cannot chdir() back to $cwd: $!";
     }
     eval "use Module::Build::Compat 0.02; 1" or die $@;
     %s
     Module::Build::Compat->run_build_pl(args => \@ARGV);
-    my $build_script = 'Build';  
+    my $build_script = 'Build';
     $build_script .= '.com' if $^O eq 'VMS';
     exit(0) unless(-e $build_script); # cpantesters convention
     require %s;
     Module::Build::Compat->write_makefile(build_class => '%s');
 EOF
-    
+
   } elsif ($type eq 'traditional') {
 
     my (%MM_Args, %prereq);
@@ -165,37 +202,37 @@ EOF
       tie %MM_Args, 'Tie::IxHash'; # Don't care if it fails here
       tie %prereq,  'Tie::IxHash'; # Don't care if it fails here
     }
-    
+
     my %name = ($build->module_name
                ? (NAME => $build->module_name)
                : (DISTNAME => $build->dist_name));
-    
+
     my %version = ($build->dist_version_from
                   ? (VERSION_FROM => $build->dist_version_from)
                   : (VERSION      => $build->dist_version)
                  );
     %MM_Args = (%name, %version);
-    
-    %prereq = ( %{$build->requires}, %{$build->build_requires} );
+
+    %prereq = _merge_prereq( $build->requires, $build->build_requires );
     %prereq = map {$_, $prereq{$_}} sort keys %prereq;
-    
+
      delete $prereq{perl};
     $MM_Args{PREREQ_PM} = \%prereq;
-    
+
     $MM_Args{INSTALLDIRS} = $build->installdirs eq 'core' ? 'perl' : $build->installdirs;
-    
+
     $MM_Args{EXE_FILES} = [ sort keys %{$build->script_files} ] if $build->script_files;
-    
+
     $MM_Args{PL_FILES} = $build->PL_files || {};
 
     if ($build->recursive_test_files) {
-        $MM_Args{TESTS} = join q{ }, $package->_test_globs($build);
+        $MM_Args{test} = { TESTS => join q{ }, $package->_test_globs($build) };
     }
 
     local $Data::Dumper::Terse = 1;
     my $args = Data::Dumper::Dumper(\%MM_Args);
     $args =~ s/\{(.*)\}/($1)/s;
-    
+
     print $fh <<"EOF";
 use ExtUtils::MakeMaker;
 WriteMakefile
@@ -213,7 +250,7 @@ sub _test_globs {
 
 sub subclass_dir {
   my ($self, $build) = @_;
-  
+
   return (Module::Build::ModuleInfo->find_module_dir_by_name(ref $build)
          || File::Spec->catdir($build->config_dir, 'lib'));
 }
@@ -228,7 +265,7 @@ sub makefile_to_build_args {
   my @out;
   foreach my $arg (@_) {
     next if $arg eq '';
-    
+
     my ($key, $val) = ($arg =~ /^(\w+)=(.+)/ ? ($1, $2) :
                       die "Malformed argument '$arg'");
 
@@ -283,7 +320,7 @@ sub makefile_to_build_macros {
       }
     }
   }
-  push @out, (config => \%config) if %config; 
+  push @out, (config => \%config) if %config;
   return @out;
 }
 
@@ -342,19 +379,19 @@ $action : force_do_it
        $perl $Build $action
 EOF
   }
-  
+
   if ($self->_is_vms_mms) {
     # Roll our own .EXPORT as MMS/MMK don't honor that directive.
-    $maketext .= "\n.FIRST\n\t\@ $noop\n"; 
+    $maketext .= "\n.FIRST\n\t\@ $noop\n";
     for my $macro (keys %macro_to_build) {
       $maketext .= ".IFDEF $macro\n\tDEFINE $macro \"\$($macro)\"\n.ENDIF\n";
     }
-    $maketext .= "\n"; 
+    $maketext .= "\n";
   }
   else {
     $maketext .= "\n.EXPORT : " . join(' ', keys %macro_to_build) . "\n\n";
   }
-  
+
   return $maketext;
 }
 
@@ -363,15 +400,13 @@ sub fake_prereqs {
   my $fh = IO::File->new("< $file") or die "Can't read $file: $!";
   my $prereqs = eval do {local $/; <$fh>};
   close $fh;
-  
+
+  my %merged = _merge_prereq( $prereqs->{requires}, $prereqs->{build_requires} );
   my @prereq;
-  foreach my $section (qw/build_requires requires/) {
-    foreach (keys %{$prereqs->{$section}}) {
-      next if $_ eq 'perl';
-      push @prereq, "$_=>q[$prereqs->{$section}{$_}]";
-    }
+  foreach (sort keys %merged) {
+    next if $_ eq 'perl';
+    push @prereq, "$_=>q[$merged{$_}]";
   }
-
   return unless @prereq;
   return "#     PREREQ_PM => { " . join(", ", @prereq) . " }\n\n";
 }
@@ -414,7 +449,7 @@ Module::Build::Compat - Compatibility with ExtUtils::MakeMaker
   my $build = Module::Build->new
     ( module_name => 'Foo::Bar',
       license     => 'perl',
-      create_makefile_pl => 'passthrough' );
+      create_makefile_pl => 'traditional' );
   ...
 
 
@@ -448,6 +483,18 @@ The currently supported styles are:
 
 =over 4
 
+=item traditional
+
+A F<Makefile.PL> will be created in the "traditional" style, i.e. it will
+use C<ExtUtils::MakeMaker> and won't rely on C<Module::Build> at all.
+In order to create the F<Makefile.PL>, we'll include the C<requires> and
+C<build_requires> dependencies as the C<PREREQ_PM> parameter.
+
+You don't want to use this style if during the C<perl Build.PL> stage
+you ask the user questions, or do some auto-sensing about the user's
+environment, or if you subclass C<Module::Build> to do some
+customization, because the vanilla F<Makefile.PL> won't do any of that.
+
 =item small
 
 A small F<Makefile.PL> will be created that passes all functionality
@@ -455,24 +502,22 @@ through to the F<Build.PL> script in the same directory.  The user must
 already have C<Module::Build> installed in order to use this, or else
 they'll get a module-not-found error.
 
-=item passthrough
+=item passthrough (DEPRECATED)
 
 This is just like the C<small> option above, but if C<Module::Build> is
 not already installed on the user's system, the script will offer to
 use C<CPAN.pm> to download it and install it before continuing with
 the build.
 
-=item traditional
-
-A F<Makefile.PL> will be created in the "traditional" style, i.e. it will
-use C<ExtUtils::MakeMaker> and won't rely on C<Module::Build> at all.
-In order to create the F<Makefile.PL>, we'll include the C<requires> and
-C<build_requires> dependencies as the C<PREREQ_PM> parameter.
+This option has been deprecated and may be removed in a future version
+of Module::Build.  Modern CPAN.pm and CPANPLUS will recognize the
+C<configure_requires> metadata property and install Module::Build before
+running Build.PL if Module::Build is listed and Module::Build now
+adds itself to configure_requires by default.
 
-You don't want to use this style if during the C<perl Build.PL> stage
-you ask the user questions, or do some auto-sensing about the user's
-environment, or if you subclass C<Module::Build> to do some
-customization, because the vanilla F<Makefile.PL> won't do any of that.
+Perl 5.10.1 includes C<configure_requires> support.  In the future, when
+C<configure_requires> support is deemed sufficiently widespread, the
+C<passthrough> style will be removed.
 
 =back
 
index de8b44d..b833e2b 100644 (file)
@@ -2,7 +2,7 @@ package Module::Build::Config;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 use Config;
 
index 82c8e01..42054d1 100644 (file)
@@ -1,7 +1,7 @@
 package Module::Build::Cookbook;
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 
 
 =head1 NAME
@@ -487,7 +487,7 @@ Next, add this to the top of your F<Build.PL>.
 
     # Find out what version of Module::Build is installed or fail quietly.
     # This should be cross-platform.
-    my $Installed_MB = 
+    my $Installed_MB =
         `$^X -e "eval q{require Module::Build; print Module::Build->VERSION} or exit 1";
 
     # some operating systems put a newline at the end of every print.
index 1cd8cd0..6f8ff7a 100644 (file)
@@ -1,7 +1,7 @@
 package Module::Build::Dumper;
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 
 # This is just a split-out of a wrapper function to do Data::Dumper
 # stuff "the right way".  See:
index 4de09b4..12ffa1d 100644 (file)
@@ -8,13 +8,14 @@ package Module::Build::ModuleInfo;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 
 use File::Spec;
 use IO::File;
 use Module::Build::Version;
 
+my $V_NUM_REGEXP = qr{v?[0-9._]+};  # crudely, a v-string or decimal
 
 my $PKG_REGEXP  = qr{   # match a package declaration
   ^[\s\{;]*             # intro chars on a line
@@ -22,6 +23,8 @@ my $PKG_REGEXP  = qr{   # match a package declaration
   \s+                   # whitespace
   ([\w:]+)              # a package name
   \s*                   # optional whitespace
+  ($V_NUM_REGEXP)?        # optional version number
+  \s*                   # optional whitesapce
   ;                     # semicolon line terminator
 }x;
 
@@ -221,10 +224,10 @@ sub _parse_fh {
          $self->_parse_version_expression( $line );
 
       if ( $line =~ $PKG_REGEXP ) {
-       $pkg = $1;
-       push( @pkgs, $pkg ) unless grep( $pkg eq $_, @pkgs );
-       $vers{$pkg} = undef unless exists( $vers{$pkg} );
-       $need_vers = 1;
+        $pkg = $1;
+        push( @pkgs, $pkg ) unless grep( $pkg eq $_, @pkgs );
+        $vers{$pkg} = (defined $2 ? $2 : undef)  unless exists( $vers{$pkg} );
+        $need_vers = defined $2 ? 0 : 1;
 
       # VERSION defined with full package spec, i.e. $Module::VERSION
       } elsif ( $vers_fullname && $vers_pkg ) {
@@ -232,7 +235,7 @@ sub _parse_fh {
        $need_vers = 0 if $vers_pkg eq $pkg;
 
        unless ( defined $vers{$vers_pkg} && length $vers{$vers_pkg} ) {
-         $vers{$vers_pkg} = 
+         $vers{$vers_pkg} =
            $self->_evaluate_version_line( $vers_sig, $vers_fullname, $line );
        } else {
          # Warn unless the user is using the "$VERSION = eval
@@ -323,11 +326,22 @@ sub _evaluate_version_line {
   (ref($vsub) eq 'CODE') or
     die "failed to build version sub for $self->{filename}";
   my $result = eval { $vsub->() };
+  die "Could not get version from $self->{filename} by executing:\n$eval\n\nThe fatal error was: $@\n"
+    if $@;
 
-  die "Could not get version from $self->{filename} by executing:\n$eval\n\nThe fatal error was: $@\n" if $@;
+  # Activestate apparently creates custom versions like '1.23_45_01', which
+  # cause M::B::Version to think it's an invalid alpha.  So check for that
+  # and strip them
+  my $num_dots = () = $result =~ m{\.}g;
+  my $num_unders = () = $result =~ m{_}g;
+  if ( substr($result,0,1) ne 'v' && $num_dots < 2 && $num_unders > 1 ) {
+    $result =~ s{_}{}g;
+  }
 
   # Bless it into our own version class
-  $result = Module::Build::Version->new($result);
+  eval { $result = Module::Build::Version->new($result) };
+  die "Version '$result' from $self->{filename} does not appear to be valid:\n$eval\n\nThe fatal error was: $@\n"
+    if $@;
 
   return $result;
 }
index fe98419..a0506c6 100644 (file)
@@ -4,7 +4,7 @@ package Module::Build::Notes;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 use Data::Dumper;
 use IO::File;
@@ -33,10 +33,10 @@ sub restore {
 sub access {
   my $self = shift;
   return $self->read() unless @_;
-  
+
   my $key = shift;
   return $self->read($key) unless @_;
-  
+
   my $value = shift;
   $self->write({ $key => $value });
   return $self->read($key);
@@ -61,7 +61,7 @@ sub read {
     return $self->{new}{$key} if exists $self->{new}{$key};
     return $self->{disk}{$key};
   }
-   
+
   # Return all data
   my $out = (keys %{$self->{new}}
             ? {%{$self->{disk}}, %{$self->{new}}}
@@ -79,7 +79,7 @@ sub _same {
 sub write {
   my ($self, $href) = @_;
   $href ||= {};
-  
+
   @{$self->{new}}{ keys %$href } = values %$href;  # Merge
 
   # Do some optimization to avoid unnecessary writes
@@ -88,17 +88,17 @@ sub write {
     next if ref $self->{disk}{$key} or !exists $self->{disk}{$key};
     delete $self->{new}{$key} if $self->_same($self->{new}{$key}, $self->{disk}{$key});
   }
-  
+
   if (my $file = $self->{file}) {
     my ($vol, $dir, $base) = File::Spec->splitpath($file);
     $dir = File::Spec->catpath($vol, $dir, '');
     return unless -e $dir && -d $dir;  # The user needs to arrange for this
 
     return if -e $file and !keys %{ $self->{new} };  # Nothing to do
-    
-    @{$self->{disk}}{ keys %{$self->{new}} } = values %{$self->{new}};  # Merge 
+
+    @{$self->{disk}}{ keys %{$self->{new}} } = values %{$self->{new}};  # Merge
     $self->_dump($file, $self->{disk});
-   
+
     $self->{new} = {};
   }
   return $self->read;
@@ -106,18 +106,66 @@ sub write {
 
 sub _dump {
   my ($self, $file, $data) = @_;
-  
+
   my $fh = IO::File->new("> $file") or die "Can't create '$file': $!";
   print {$fh} Module::Build::Dumper->_data_dump($data);
 }
 
+my $orig_template = do { local $/; <DATA> };
+close DATA;
+
 sub write_config_data {
   my ($self, %args) = @_;
 
+  my $template = $orig_template;
+  $template =~ s/NOTES_NAME/$args{config_module}/g;
+  $template =~ s/MODULE_NAME/$args{module}/g;
+  $template =~ s/=begin private\n//;
+  $template =~ s/=end private/=cut/;
+
+  # strip out private POD markers we use to keep pod from being
+  # recognized for *this* source file
+  $template =~ s{$_\n}{} for '=begin private', '=end private';
+
   my $fh = IO::File->new("> $args{file}") or die "Can't create '$args{file}': $!";
+  print {$fh} $template;
+  print {$fh} "\n__DATA__\n";
+  print {$fh} Module::Build::Dumper->_data_dump([$args{config_data}, $args{feature}, $args{auto_features}]);
+
+}
+
+1;
+
+
+=head1 NAME
+
+Module::Build::Notes - Create persistent distribution configuration modules
+
+=head1 DESCRIPTION
+
+This module is used internally by Module::Build to create persistent
+configuration files that can be installed with a distribution.  See
+L<Module::Build::ConfigData> for an example.
+
+=head1 AUTHOR
 
-  printf $fh <<'EOF', $args{config_module};
-package %s;
+Ken Williams <kwilliams@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2001-2006 Ken Williams.  All rights reserved.
+
+This library is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+perl(1), L<Module::Build>(3)
+
+=cut
+
+__DATA__
+package NOTES_NAME;
 use strict;
 my $arrayref = eval do {local $/; <DATA>}
   or die "Couldn't load ConfigData data: $@";
@@ -129,14 +177,14 @@ sub config { $config->{$_[1]} }
 sub set_config { $config->{$_[1]} = $_[2] }
 sub set_feature { $features->{$_[1]} = 0+!!$_[2] }  # Constrain to 1 or 0
 
-sub auto_feature_names { grep !exists $features->{$_}, keys %%$auto_features }
+sub auto_feature_names { grep !exists $features->{$_}, keys %$auto_features }
 
 sub feature_names {
-  my @features = (keys %%$features, auto_feature_names());
+  my @features = (keys %$features, auto_feature_names());
   @features;
 }
 
-sub config_names  { keys %%$config }
+sub config_names  { keys %$config }
 
 sub write {
   my $me = __FILE__;
@@ -170,20 +218,20 @@ sub write {
 sub feature {
   my ($package, $key) = @_;
   return $features->{$key} if exists $features->{$key};
-  
+
   my $info = $auto_features->{$key} or return 0;
-  
-  # Under perl 5.005, each(%%$foo) isn't working correctly when $foo
+
+  # Under perl 5.005, each(%$foo) isn't working correctly when $foo
   # was reanimated with Data::Dumper and eval().  Not sure why, but
   # copying to a new hash seems to solve it.
-  my %%info = %%$info;
-  
+  my %info = %$info;
+
   require Module::Build;  # XXX should get rid of this
-  while (my ($type, $prereqs) = each %%info) {
+  while (my ($type, $prereqs) = each %info) {
     next if $type eq 'description' || $type eq 'recommends';
-    
-    my %%p = %%$prereqs;  # Ditto here.
-    while (my ($modname, $spec) = each %%p) {
+
+    my %p = %$prereqs;  # Ditto here.
+    while (my ($modname, $spec) = each %p) {
       my $status = Module::Build->check_installed_status($modname, $spec);
       if ((!$status->{ok}) xor ($type =~ /conflicts$/)) { return 0; }
       if ( ! eval "require $modname; 1" ) { return 0; }
@@ -192,36 +240,32 @@ sub feature {
   return 1;
 }
 
-EOF
-
-  my ($module_name, $notes_name) = ($args{module}, $args{config_module});
-  printf $fh <<"EOF", $notes_name, $module_name;
+=begin private
 
 =head1 NAME
 
-$notes_name - Configuration for $module_name
-
+NOTES_NAME - Configuration for MODULE_NAME
 
 =head1 SYNOPSIS
 
-  use $notes_name;
-  \$value = $notes_name->config('foo');
-  \$value = $notes_name->feature('bar');
-  
-  \@names = $notes_name->config_names;
-  \@names = $notes_name->feature_names;
-  
-  $notes_name->set_config(foo => \$new_value);
-  $notes_name->set_feature(bar => \$new_value);
-  $notes_name->write;  # Save changes
+  use NOTES_NAME;
+  $value = NOTES_NAME->config('foo');
+  $value = NOTES_NAME->feature('bar');
+
+  @names = NOTES_NAME->config_names;
+  @names = NOTES_NAME->feature_names;
+
+  NOTES_NAME->set_config(foo => $new_value);
+  NOTES_NAME->set_feature(bar => $new_value);
+  NOTES_NAME->write;  # Save changes
 
 
 =head1 DESCRIPTION
 
-This module holds the configuration data for the C<$module_name>
+This module holds the configuration data for the C<MODULE_NAME>
 module.  It also provides a programmatic interface for getting or
 setting that configuration data.  Note that in order to actually make
-changes, you'll have to have write access to the C<$notes_name>
+changes, you'll have to have write access to the C<NOTES_NAME>
 module, and you should attempt to understand the repercussions of your
 actions.
 
@@ -230,17 +274,17 @@ actions.
 
 =over 4
 
-=item config(\$name)
+=item config($name)
 
 Given a string argument, returns the value of the configuration item
 by that name, or C<undef> if no such item exists.
 
-=item feature(\$name)
+=item feature($name)
 
 Given a string argument, returns the value of the feature by that
 name, or C<undef> if no such feature exists.
 
-=item set_config(\$name, \$value)
+=item set_config($name, $value)
 
 Sets the configuration item with the given name to the given value.
 The value may be any Perl scalar that will serialize correctly using
@@ -248,7 +292,7 @@ C<Data::Dumper>.  This includes references, objects (usually), and
 complex data structures.  It probably does not include transient
 things like filehandles or sockets.
 
-=item set_feature(\$name, \$value)
+=item set_feature($name, $value)
 
 Sets the feature with the given name to the given boolean value.  The
 value will be converted to 0 or 1 automatically.
@@ -256,12 +300,12 @@ value will be converted to 0 or 1 automatically.
 =item config_names()
 
 Returns a list of all the names of config items currently defined in
-C<$notes_name>, or in scalar context the number of items.
+C<NOTES_NAME>, or in scalar context the number of items.
 
 =item feature_names()
 
 Returns a list of all the names of features currently defined in
-C<$notes_name>, or in scalar context the number of features.
+C<NOTES_NAME>, or in scalar context the number of features.
 
 =item auto_feature_names()
 
@@ -273,24 +317,16 @@ a fixed value.
 =item write()
 
 Commits any changes from C<set_config()> and C<set_feature()> to disk.
-Requires write access to the C<$notes_name> module.
+Requires write access to the C<NOTES_NAME> module.
 
 =back
 
 
 =head1 AUTHOR
 
-C<$notes_name> was automatically created using C<Module::Build>.
+C<NOTES_NAME> was automatically created using C<Module::Build>.
 C<Module::Build> was written by Ken Williams, but he holds no
-authorship claim or copyright claim to the contents of C<$notes_name>.
-
-=cut
+authorship claim or copyright claim to the contents of C<NOTES_NAME>.
 
-__DATA__
-
-EOF
-
-  print {$fh} Module::Build::Dumper->_data_dump([$args{config_data}, $args{feature}, $args{auto_features}]);
-}
+=end private
 
-1;
index 35b5a75..74a5a73 100644 (file)
@@ -1,8 +1,9 @@
 package Module::Build::PPMMaker;
 
 use strict;
+use Config;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 
 # This code is mostly borrowed from ExtUtils::MM_Unix 6.10_03, with a
@@ -34,7 +35,6 @@ sub make_ppd {
     my $method = "dist_$info";
     $dist{$info} = $build->$method() or die "Can't determine distribution's $info\n";
   }
-  $dist{version} = $self->_ppd_version($dist{version});
 
   $self->_simple_xml_escape($_) foreach $dist{abstract}, @{$dist{author}};
 
@@ -42,21 +42,17 @@ sub make_ppd {
   # various licenses
   my $ppd = <<"PPD";
 <SOFTPKG NAME=\"$dist{name}\" VERSION=\"$dist{version}\">
-    <TITLE>$dist{name}</TITLE>
     <ABSTRACT>$dist{abstract}</ABSTRACT>
 @{[ join "\n", map "    <AUTHOR>$_</AUTHOR>", @{$dist{author}} ]}
     <IMPLEMENTATION>
 PPD
 
-  # TODO: We could set <IMPLTYPE VALUE="PERL" /> or maybe
-  # <IMPLTYPE VALUE="PERL/XS" /> ???
-
   # We don't include recommended dependencies because PPD has no way
   # to distinguish them from normal dependencies.  We don't include
   # build_requires dependencies because the PPM installer doesn't
   # build or test before installing.  And obviously we don't include
   # conflicts either.
-  
+
   foreach my $type (qw(requires)) {
     my $prereq = $build->$type();
     while (my ($modname, $spec) = each %$prereq) {
@@ -73,27 +69,18 @@ PPD
         }
       }
 
-      # Another hack - dependencies are on modules, but PPD expects
-      # them to be on distributions (I think).
-      $modname =~ s/::/-/g;
-
-      $ppd .= sprintf(<<'EOF', $modname, $self->_ppd_version($min_version));
-        <DEPENDENCY NAME="%s" VERSION="%s" />
-EOF
+      # PPM4 spec requires a '::' for top level modules
+      $modname .= '::' unless $modname =~ /::/;
 
+      $ppd .= qq!        <REQUIRE NAME="$modname" VERSION="$min_version" />\n!;
     }
   }
 
   # We only include these tags if this module involves XS, on the
-  # assumption that pure Perl modules will work on any OS.  PERLCORE,
-  # unfortunately, seems to indicate that a module works with _only_
-  # that version of Perl, and so is only appropriate when a module
-  # uses XS.
+  # assumption that pure Perl modules will work on any OS.
   if (keys %{$build->find_xs_files}) {
     my $perl_version = $self->_ppd_version($build->perl_version);
-    $ppd .= sprintf(<<'EOF', $perl_version, $^O, $self->_varchname($build->config) );
-        <PERLCORE VERSION="%s" />
-        <OS NAME="%s" />
+    $ppd .= sprintf(<<'EOF', $self->_varchname($build->config) );
         <ARCHITECTURE NAME="%s" />
 EOF
   }
@@ -113,7 +100,9 @@ EOF
   my $ppd_file = "$dist{name}.ppd";
   my $fh = IO::File->new(">$ppd_file")
     or die "Cannot write to $ppd_file: $!";
-  $fh->binmode(":utf8") if $fh->can("binmode");
+
+  $fh->binmode(":utf8")
+    if $fh->can('binmode') && $] >= 5.008 && $Config{useperlio};
   print $fh $ppd;
   close $fh;
 
@@ -148,7 +137,7 @@ sub _varchname {  # Copied from PPM.pm
                 '<' => '&lt;',
                );
   my $rx = join '|', keys %escapes;
-  
+
   sub _simple_xml_escape {
     $_[1] =~ s/($rx)/$escapes{$1}/go;
   }
index 5ce8cf5..b31a963 100644 (file)
@@ -2,7 +2,7 @@ package Module::Build::Platform::Amiga;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 use Module::Build::Base;
 
index df29af5..b0e83a3 100644 (file)
@@ -2,7 +2,7 @@ package Module::Build::Platform::Default;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 use Module::Build::Base;
 
index d68836c..4365b12 100644 (file)
@@ -2,7 +2,7 @@ package Module::Build::Platform::EBCDIC;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 use Module::Build::Base;
 
index a835c30..c735378 100644 (file)
@@ -2,7 +2,7 @@ package Module::Build::Platform::MPEiX;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 use Module::Build::Base;
 
index 9c9281a..2c74942 100644 (file)
@@ -2,7 +2,7 @@ package Module::Build::Platform::MacOS;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 use Module::Build::Base;
 use vars qw(@ISA);
@@ -15,17 +15,17 @@ sub have_forkpipe { 0 }
 sub new {
   my $class = shift;
   my $self = $class->SUPER::new(@_);
-  
+
   # $Config{sitelib} and $Config{sitearch} are, unfortunately, missing.
   foreach ('sitelib', 'sitearch') {
     $self->config($_ => $self->config("install$_"))
       unless $self->config($_);
   }
-  
+
   # For some reason $Config{startperl} is filled with a bunch of crap.
   (my $sp = $self->config('startperl')) =~ s/.*Exit \{Status\}\s//;
   $self->config(startperl => $sp);
-  
+
   return $self;
 }
 
@@ -42,7 +42,7 @@ sub dispatch {
 
   if( !@_ and !@ARGV ) {
     require MacPerl;
-      
+
     # What comes first in the action list.
     my @action_list = qw(build test install);
     my %actions = map {+($_, 1)} $self->known_actions;
@@ -53,17 +53,17 @@ sub dispatch {
     foreach (@action_list) {
       $_ .= ' *' if $toolserver{$_};
     }
-    
+
     my $cmd = MacPerl::Pick("What build command? ('*' requires ToolServer)", @action_list);
     return unless defined $cmd;
     $cmd =~ s/ \*$//;
     $ARGV[0] = ($cmd);
-    
+
     my $args = MacPerl::Ask('Any extra arguments?  (ie. verbose=1)', '');
     return unless defined $args;
     push @ARGV, $self->split_like_shell($args);
   }
-  
+
   $self->SUPER::dispatch(@_);
 }
 
@@ -82,10 +82,10 @@ sub ACTION_realclean {
 
 sub ACTION_install {
   my $self = shift;
-  
+
   return $self->SUPER::ACTION_install(@_)
     if eval {ExtUtils::Install->VERSION('1.30'); 1};
-    
+
   local $^W = 0; # Avoid a 'redefine' warning
   local *ExtUtils::Install::find = sub {
     my ($code, @dirs) = @_;
@@ -94,7 +94,7 @@ sub ACTION_install {
 
     return File::Find::find($code, @dirs);
   };
-  
+
   return $self->SUPER::ACTION_install(@_);
 }
 
index c240750..9deb097 100644 (file)
@@ -2,7 +2,7 @@ package Module::Build::Platform::RiscOS;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 use Module::Build::Base;
 
index 879ca3a..43f585f 100644 (file)
@@ -2,7 +2,7 @@ package Module::Build::Platform::Unix;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 use Module::Build::Base;
 
index 3305154..13d350d 100644 (file)
@@ -2,7 +2,7 @@ package Module::Build::Platform::VMS;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 use Module::Build::Base;
 
@@ -131,22 +131,22 @@ sub _quote_args {
   # or if we get a single arg that is an array reference, quote the
   # elements of it and return the reference.
   my ($self, @args) = @_;
-  my $got_arrayref = (scalar(@args) == 1 
-                      && UNIVERSAL::isa($args[0], 'ARRAY')) 
-                   ? 1 
+  my $got_arrayref = (scalar(@args) == 1
+                      && UNIVERSAL::isa($args[0], 'ARRAY'))
+                   ? 1
                    : 0;
 
   # Do not quote qualifiers that begin with '/'.
-  map { if (!/^\//) { 
+  map { if (!/^\//) {
           $_ =~ s/\"/""/g;     # escape C<"> by doubling
           $_ = q(").$_.q(");
         }
   }
-    ($got_arrayref ? @{$args[0]} 
+    ($got_arrayref ? @{$args[0]}
                    : @args
     );
 
-  return $got_arrayref ? $args[0] 
+  return $got_arrayref ? $args[0]
                        : join(' ', @args);
 }
 
@@ -173,6 +173,62 @@ sub _backticks {
   return `$cmd $args`;
 }
 
+=item find_command
+
+Local an executable program
+
+=cut
+
+sub find_command {
+    my ($self, $command) = @_;
+
+    # a lot of VMS executables have a symbol defined
+    # check those first
+    if ( $^O eq 'VMS' ) {
+        require VMS::DCLsym;
+        my $syms = VMS::DCLsym->new;
+        return $command if scalar $syms->getsym( uc $command );
+    }
+
+    $self->SUPER::find_command($command);
+}
+
+# _maybe_command copied from ExtUtils::MM_VMS::maybe_command
+
+=item _maybe_command (override)
+
+Follows VMS naming conventions for executable files.
+If the name passed in doesn't exactly match an executable file,
+appends F<.Exe> (or equivalent) to check for executable image, and F<.Com>
+to check for DCL procedure.  If this fails, checks directories in DCL$PATH
+and finally F<Sys$System:> for an executable file having the name specified,
+with or without the F<.Exe>-equivalent suffix.
+
+=cut
+
+sub _maybe_command {
+    my($self,$file) = @_;
+    return $file if -x $file && ! -d _;
+    my(@dirs) = ('');
+    my(@exts) = ('',$Config{'exe_ext'},'.exe','.com');
+
+    if ($file !~ m![/:>\]]!) {
+        for (my $i = 0; defined $ENV{"DCL\$PATH;$i"}; $i++) {
+            my $dir = $ENV{"DCL\$PATH;$i"};
+            $dir .= ':' unless $dir =~ m%[\]:]$%;
+            push(@dirs,$dir);
+        }
+        push(@dirs,'Sys$System:');
+        foreach my $dir (@dirs) {
+            my $sysfile = "$dir$file";
+            foreach my $ext (@exts) {
+                return $file if -x "$sysfile$ext" && ! -d _;
+            }
+        }
+    }
+    return;
+}
+
 =item do_system
 
 Override to ensure that we quote the arguments but not the command.
@@ -182,7 +238,7 @@ Override to ensure that we quote the arguments but not the command.
 sub do_system {
   # The command must not be quoted but the arguments to it must be.
   my ($self, @cmd) = @_;
-  $self->log_info("@cmd\n");
+  $self->log_verbose("@cmd\n");
   my $cmd = shift @cmd;
   my $args = $self->_quote_args(@cmd);
   return !system("$cmd $args");
@@ -205,7 +261,7 @@ sub oneliner {
 
 =item _infer_xs_spec
 
-Inherit the standard version but tweak the library file name to be 
+Inherit the standard version but tweak the library file name to be
 something Dynaloader can find.
 
 =cut
@@ -250,7 +306,7 @@ sub rscan_dir {
 
 =item dist_dir
 
-Inherit the standard version but replace embedded dots with underscores because 
+Inherit the standard version but replace embedded dots with underscores because
 a dot is the directory delimiter on VMS.
 
 =cut
@@ -265,7 +321,7 @@ sub dist_dir {
 
 =item man3page_name
 
-Inherit the standard version but chop the extra manpage delimiter off the front if 
+Inherit the standard version but chop the extra manpage delimiter off the front if
 there is one.  The VMS version of splitdir('[.foo]') returns '', 'foo'.
 
 =cut
@@ -367,7 +423,7 @@ sub _detildefy {
             $newdirs = File::Spec::Unix->catdir(@hdirs, @backup, @dirs);
 
         }
-        
+
         # Now put the two cases back together
         $arg = File::Spec::Unix->catpath($hvol, $newdirs, $file);
 
@@ -446,7 +502,7 @@ sub _unix_rpt {
         $unix_rpt = VMS::Feature::current("filename_unix_report");
     } else {
         my $env_unix_rpt = $ENV{'DECC$FILENAME_UNIX_REPORT'} || '';
-        $unix_rpt = $env_unix_rpt =~ /^[ET1]/i; 
+        $unix_rpt = $env_unix_rpt =~ /^[ET1]/i;
     }
     return $unix_rpt;
 }
@@ -459,7 +515,7 @@ sub _efs {
         $efs = VMS::Feature::current("efs_charset");
     } else {
         my $env_efs = $ENV{'DECC$EFS_CHARSET'} || '';
-        $efs = $env_efs =~ /^[ET1]/i; 
+        $efs = $env_efs =~ /^[ET1]/i;
     }
     return $efs;
 }
index be46a80..2061b2c 100644 (file)
@@ -2,7 +2,7 @@ package Module::Build::Platform::VOS;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 use Module::Build::Base;
 
index 6cf9da9..fcaef5a 100644 (file)
@@ -2,7 +2,7 @@ package Module::Build::Platform::Windows;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 
 use Config;
@@ -39,7 +39,7 @@ sub ACTION_realclean {
 
   if ( lc $basename eq lc $self->build_script ) {
     if ( $self->build_bat ) {
-      $self->log_info("Deleting $basename.bat\n");
+      $self->log_verbose("Deleting $basename.bat\n");
       my $full_progname = $0;
       $full_progname =~ s/(?:\.bat)?$/.bat/i;
 
@@ -207,22 +207,22 @@ sub split_like_shell {
   # into words.  The algorithm below was bashed out by Randy and Ken
   # (mostly Randy), and there are a lot of regression tests, so we
   # should feel free to adjust if desired.
-  
+
   (my $self, local $_) = @_;
-  
+
   return @$_ if defined() && UNIVERSAL::isa($_, 'ARRAY');
-  
+
   my @argv;
   return @argv unless defined() && length();
-  
+
   my $arg = '';
   my( $i, $quote_mode ) = ( 0, 0 );
-  
+
   while ( $i < length() ) {
-    
+
     my $ch      = substr( $_, $i  , 1 );
     my $next_ch = substr( $_, $i+1, 1 );
-    
+
     if ( $ch eq '\\' && $next_ch eq '"' ) {
       $arg .= '"';
       $i++;
@@ -249,10 +249,10 @@ sub split_like_shell {
     } else {
       $arg .= $ch;
     }
-    
+
     $i++;
   }
-  
+
   push( @argv, $arg ) if defined( $arg ) && length( $arg );
   return @argv;
 }
@@ -273,6 +273,27 @@ sub do_system {
   return !$status;
 }
 
+# Copied from ExtUtils::MM_Win32
+sub _maybe_command {
+    my($self,$file) = @_;
+    my @e = exists($ENV{'PATHEXT'})
+          ? split(/;/, $ENV{PATHEXT})
+         : qw(.com .exe .bat .cmd);
+    my $e = '';
+    for (@e) { $e .= "\Q$_\E|" }
+    chop $e;
+    # see if file ends in one of the known extensions
+    if ($file =~ /($e)$/i) {
+       return $file if -e $file;
+    }
+    else {
+       for (@e) {
+           return "$file$_" if -e "$file$_";
+       }
+    }
+    return;
+}
+
 
 1;
 
index 45feb3c..7ba3c32 100644 (file)
@@ -2,7 +2,7 @@ package Module::Build::Platform::aix;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 use Module::Build::Platform::Unix;
 
index 62a6461..8b882ed 100644 (file)
@@ -2,7 +2,7 @@ package Module::Build::Platform::cygwin;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 use Module::Build::Platform::Unix;
 
@@ -13,6 +13,22 @@ sub manpage_separator {
    '.'
 }
 
+# Copied from ExtUtils::MM_Cygwin::maybe_command()
+# If our path begins with F</cygdrive/> then we use C<ExtUtils::MM_Win32>
+# to determine if it may be a command.  Otherwise we use the tests
+# from C<ExtUtils::MM_Unix>.
+
+sub _maybe_command {
+    my ($self, $file) = @_;
+
+    if ($file =~ m{^/cygdrive/}i) {
+        require Module::Build::Platform::Win32;
+        return Module::Build::Platform::Win32->_maybe_command($file);
+    }
+
+    return $self->SUPER::_maybe_command($file);
+}
+
 1;
 __END__
 
index 39e9e36..145933d 100644 (file)
@@ -2,7 +2,7 @@ package Module::Build::Platform::darwin;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 use Module::Build::Platform::Unix;
 
index ace01a3..b6615c8 100644 (file)
@@ -2,7 +2,7 @@ package Module::Build::Platform::os2;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 use Module::Build::Platform::Unix;
 
@@ -13,6 +13,16 @@ sub manpage_separator { '.' }
 
 sub have_forkpipe { 0 }
 
+# Copied from ExtUtils::MM_OS2::maybe_command
+sub _maybe_command {
+    my($self,$file) = @_;
+    $file =~ s,[/\\]+,/,g;
+    return $file if -x $file && ! -d _;
+    return "$file.exe" if -x "$file.exe" && ! -d _;
+    return "$file.cmd" if -x "$file.cmd" && ! -d _;
+    return;
+}
+
 1;
 __END__
 
index b17b80b..7a94e77 100644 (file)
@@ -2,7 +2,7 @@ package Module::Build::PodParser;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.35';
+$VERSION = '0.35_08';
 $VERSION = eval $VERSION;
 use vars qw(@ISA);
 
@@ -33,31 +33,31 @@ sub new {
 
 sub _myparse_from_filehandle {
   my ($self, $fh) = @_;
-  
+
   local $_;
   while (<$fh>) {
     next unless /^=(?!cut)/ .. /^=cut/;  # in POD
     last if ($self->{abstract}) = /^  (?:  [a-z:]+  \s+ - \s+  )  (.*\S)  /ix;
   }
-  
+
   my @author;
   while (<$fh>) {
-    next unless /^=head1\s+AUTHORS?/ ... /^=/;
+    next unless /^=head1\s+AUTHORS?/i ... /^=/;
     next if /^=/;
     push @author, $_ if /\@/;
   }
   return unless @author;
   s/^\s+|\s+$//g foreach @author;
-  
+
   $self->{author} = \@author;
-  
+
   return;
 }
 
 sub get_abstract {
   my $self = shift;
   return $self->{abstract} if defined $self->{abstract};
-  
+
   $self->parse_from_filehandle($self->{fh});
 
   return $self->{abstract};
@@ -66,7 +66,7 @@ sub get_abstract {
 sub get_author {
   my $self = shift;
   return $self->{author} if defined $self->{author};
-  
+
   $self->parse_from_filehandle($self->{fh});
 
   return $self->{author} || [];
@@ -92,10 +92,10 @@ sub textblock {
   my ($self, $text) = @_;
   $text =~ s/^\s+//;
   $text =~ s/\s+$//;
-  if ($self->{_head} eq 'NAME') {
+  if (uc $self->{_head} eq 'NAME') {
     my ($name, $abstract) = split( /\s+-\s+/, $text, 2 );
     $self->{abstract} = $abstract;
-  } elsif ($self->{_head} =~ /^AUTHORS?$/) {
+  } elsif ($self->{_head} =~ /^AUTHORS?$/i) {
     push @{$self->{author}}, $text if $text =~ /\@/;
   }
 }
index 0664d43..4a1b961 100644 (file)
@@ -81,7 +81,7 @@ sub import {
        map { $args{$_} = 1 } @_
     }
     else { # no parameters at all on use line
-       %args = 
+    args =
        (
            qv => 1,
            'UNIVERSAL::VERSION' => 1,
@@ -89,9 +89,9 @@ sub import {
     }
 
     my $callpkg = caller();
-    
+
     if (exists($args{declare})) {
-       *{$callpkg."::declare"} = 
+       *{$callpkg."::declare"} =
            sub {return $class->declare(shift) }
          unless defined(&{$callpkg.'::declare'});
     }
@@ -155,7 +155,7 @@ sub new
 {
        my ($class, $value) = @_;
        my $self = bless ({}, ref ($class) || $class);
-       
+
        if ( ref($value) && eval('$value->isa("version")') ) {
            # Can copy the elements directly
            $self->{version} = [ @{$value->{version} } ];
@@ -193,7 +193,7 @@ sub new
            $value = sprintf("%.9f",$value);
            $value =~ s/(0+)$//; # trim trailing zeros
        }
-       
+
        # This is not very efficient, but it is morally equivalent
        # to the XS code (as that is the reference implementation).
        # See vutil/vutil.c for details
@@ -215,7 +215,7 @@ sub new
        }
 
        $start = $last = $pos = $s;
-               
+
        # pre-scan the input string to check for decimals/underbars
        while ( substr($value,$pos,1) =~ /[._\d,]/ ) {
            if ( substr($value,$pos,1) eq '.' ) {
@@ -300,7 +300,7 @@ sub new
                            $orev = $rev;
                            $rev += substr($value,$s,1) * $mult;
                            $mult /= 10;
-                           if (   abs($orev) > abs($rev) 
+                           if (   abs($orev) > abs($rev)
                                || abs($rev) > abs($VERSION_MAX) ) {
                                if ( warnings::enabled("overflow") ) {
                                    require Carp;
@@ -320,7 +320,7 @@ sub new
                            $orev = $rev;
                            $rev += substr($value,$end,1) * $mult;
                            $mult *= 10;
-                           if (   abs($orev) > abs($rev) 
+                           if (   abs($orev) > abs($rev)
                                || abs($rev) > abs($VERSION_MAX) ) {
                                if ( warnings::enabled("overflow") ) {
                                    require Carp;
@@ -335,15 +335,15 @@ sub new
 
                # Append revision
                push @{$self->{version}}, $rev;
-               if ( substr($value,$pos,1) eq '.' 
+               if ( substr($value,$pos,1) eq '.'
                    && substr($value,$pos+1,1) =~ /\d/ ) {
                    $s = ++$pos;
                }
-               elsif ( substr($value,$pos,1) eq '_' 
+               elsif ( substr($value,$pos,1) eq '_'
                    && substr($value,$pos+1,1) =~ /\d/ ) {
                    $s = ++$pos;
                }
-               elsif ( substr($value,$pos,1) eq ',' 
+               elsif ( substr($value,$pos,1) eq ','
                    && substr($value,$pos+1,1) =~ /\d/ ) {
                    $s = ++$pos;
                }
@@ -400,7 +400,7 @@ sub new
 
 *parse = \&new;
 
-sub numify 
+sub numify
 {
     my ($self) = @_;
     unless (_verify($self)) {
@@ -441,7 +441,7 @@ sub numify
     return $string;
 }
 
-sub normal 
+sub normal
 {
     my ($self) = @_;
     unless (_verify($self)) {
@@ -484,9 +484,9 @@ sub stringify
        require Carp;
        Carp::croak("Invalid version object");
     }
-    return exists $self->{original} 
-       ? $self->{original} 
-       : exists $self->{qv} 
+    return exists $self->{original}
+        ? $self->{original}
+       : exists $self->{qv}
            ? $self->normal
            : $self->numify;
 }
@@ -524,8 +524,8 @@ sub vcmp
     }
 
     # tiebreaker for alpha with identical terms
-    if ( $retval == 0 
-       && $l == $r 
+    if ( $retval == 0
+       && $l == $r
        && $left->{version}[$m] == $right->{version}[$m]
        && ( $lalpha || $ralpha ) ) {
 
@@ -557,7 +557,7 @@ sub vcmp
        }
     }
 
-    return $retval;  
+    return $retval;
 }
 
 sub vbool {
@@ -565,8 +565,8 @@ sub vbool {
     return vcmp($self,$self->new("0"),1);
 }
 
-sub vnoop { 
-    require Carp; 
+sub vnoop {
+    require Carp;
     Carp::croak("operation not supported with version object");
 }
 
@@ -644,7 +644,7 @@ sub _VERSION {
     if ( defined $req ) {
        unless ( defined $version ) {
            require Carp;
-           my $msg =  $] < 5.006 
+           my $msg =  $] < 5.006
            ? "$class version $req required--this is only version "
            : "$class does not define \$$class\::VERSION"
              ."--version check failed";
@@ -662,14 +662,14 @@ sub _VERSION {
        if ( $req > $version ) {
            require Carp;
            if ( $req->is_qv ) {
-               Carp::croak( 
+               Carp::croak(
                    sprintf ("%s version %s required--".
                        "this is only version %s", $class,
                        $req->normal, $version->normal)
                );
            }
            else {
-               Carp::croak( 
+               Carp::croak(
                    sprintf ("%s version %s required--".
                        "this is only version %s", $class,
                        $req->stringify, $version->stringify)
index 4a181ad..2da91f2 100644 (file)
+# Adapted from YAML::Tiny 1.40
 package Module::Build::YAML;
 
 use strict;
-use vars qw($VERSION @EXPORT @EXPORT_OK);
-$VERSION = "0.50";
-@EXPORT = ();
-@EXPORT_OK = qw(Dump Load DumpFile LoadFile);
+use Carp 'croak';
 
+# UTF Support?
+sub HAVE_UTF8 () { $] >= 5.007003 }
+BEGIN {
+       if ( HAVE_UTF8 ) {
+               # The string eval helps hide this from Test::MinimumVersion
+               eval "require utf8;";
+               die "Failed to load UTF-8 support" if $@;
+       }
+
+       # Class structure
+       require 5.004;
+
+       $Module::Build::YAML::VERSION   = '1.40';
+
+       # Error storage
+       $Module::Build::YAML::errstr    = '';
+}
+
+# The character class of all characters we need to escape
+# NOTE: Inlined, since it's only used once
+# my $RE_ESCAPE   = '[\\x00-\\x08\\x0b-\\x0d\\x0e-\\x1f\"\n]';
+
+# Printed form of the unprintable characters in the lowest range
+# of ASCII characters, listed by ASCII ordinal position.
+my @UNPRINTABLE = qw(
+       z    x01  x02  x03  x04  x05  x06  a
+       x08  t    n    v    f    r    x0e  x0f
+       x10  x11  x12  x13  x14  x15  x16  x17
+       x18  x19  x1a  e    x1c  x1d  x1e  x1f
+);
+
+# Printable characters for escapes
+my %UNESCAPES = (
+       z => "\x00", a => "\x07", t    => "\x09",
+       n => "\x0a", v => "\x0b", f    => "\x0c",
+       r => "\x0d", e => "\x1b", '\\' => '\\',
+);
+
+# Special magic boolean words
+my %QUOTE = map { $_ => 1 } qw{
+       null Null NULL
+       y Y yes Yes YES n N no No NO
+       true True TRUE false False FALSE
+       on On ON off Off OFF
+};
+
+#####################################################################
+# Implementation
+
+# Create an empty Module::Build::YAML object
 sub new {
-    my $this = shift;
-    my $class = ref($this) || $this;
-    my $self = {};
-    bless $self, $class;
-    return($self);
+       my $class = shift;
+       bless [ @_ ], $class;
 }
 
-sub Dump {
-    shift if ($_[0] eq __PACKAGE__ || ref($_[0]) eq __PACKAGE__);
-    my $yaml = "";
-    foreach my $item (@_) {
-        $yaml .= "---\n";
-        $yaml .= &_yaml_chunk("", $item);
-    }
-    return $yaml;
+# Create an object from a file
+sub read {
+       my $class = ref $_[0] ? ref shift : shift;
+
+       # Check the file
+       my $file = shift or return $class->_error( 'You did not specify a file name' );
+       return $class->_error( "File '$file' does not exist" )              unless -e $file;
+       return $class->_error( "'$file' is a directory, not a file" )       unless -f _;
+       return $class->_error( "Insufficient permissions to read '$file'" ) unless -r _;
+
+       # Slurp in the file
+       local $/ = undef;
+       local *CFG;
+       unless ( open(CFG, $file) ) {
+               return $class->_error("Failed to open file '$file': $!");
+       }
+       my $contents = <CFG>;
+       unless ( close(CFG) ) {
+               return $class->_error("Failed to close file '$file': $!");
+       }
+
+       $class->read_string( $contents );
 }
 
-sub Load {
-    shift if ($_[0] eq __PACKAGE__ || ref($_[0]) eq __PACKAGE__);
-    die "not yet implemented";
+# Create an object from a string
+sub read_string {
+       my $class  = ref $_[0] ? ref shift : shift;
+       my $self   = bless [], $class;
+       my $string = $_[0];
+       unless ( defined $string ) {
+               return $self->_error("Did not provide a string to load");
+       }
+
+       # Byte order marks
+       # NOTE: Keeping this here to educate maintainers
+       # my %BOM = (
+       #     "\357\273\277" => 'UTF-8',
+       #     "\376\377"     => 'UTF-16BE',
+       #     "\377\376"     => 'UTF-16LE',
+       #     "\377\376\0\0" => 'UTF-32LE'
+       #     "\0\0\376\377" => 'UTF-32BE',
+       # );
+       if ( $string =~ /^(?:\376\377|\377\376|\377\376\0\0|\0\0\376\377)/ ) {
+               return $self->_error("Stream has a non UTF-8 BOM");
+       } else {
+               # Strip UTF-8 bom if found, we'll just ignore it
+               $string =~ s/^\357\273\277//;
+       }
+
+       # Try to decode as utf8
+       utf8::decode($string) if HAVE_UTF8;
+
+       # Check for some special cases
+       return $self unless length $string;
+       unless ( $string =~ /[\012\015]+\z/ ) {
+               return $self->_error("Stream does not end with newline character");
+       }
+
+       # Split the file into lines
+       my @lines = grep { ! /^\s*(?:\#.*)?\z/ }
+                   split /(?:\015{1,2}\012|\015|\012)/, $string;
+
+       # Strip the initial YAML header
+       @lines and $lines[0] =~ /^\%YAML[: ][\d\.]+.*\z/ and shift @lines;
+
+       # A nibbling parser
+       while ( @lines ) {
+               # Do we have a document header?
+               if ( $lines[0] =~ /^---\s*(?:(.+)\s*)?\z/ ) {
+                       # Handle scalar documents
+                       shift @lines;
+                       if ( defined $1 and $1 !~ /^(?:\#.+|\%YAML[: ][\d\.]+)\z/ ) {
+                               push @$self, $self->_read_scalar( "$1", [ undef ], \@lines );
+                               next;
+                       }
+               }
+
+               if ( ! @lines or $lines[0] =~ /^(?:---|\.\.\.)/ ) {
+                       # A naked document
+                       push @$self, undef;
+                       while ( @lines and $lines[0] !~ /^---/ ) {
+                               shift @lines;
+                       }
+
+               } elsif ( $lines[0] =~ /^\s*\-/ ) {
+                       # An array at the root
+                       my $document = [ ];
+                       push @$self, $document;
+                       $self->_read_array( $document, [ 0 ], \@lines );
+
+               } elsif ( $lines[0] =~ /^(\s*)\S/ ) {
+                       # A hash at the root
+                       my $document = { };
+                       push @$self, $document;
+                       $self->_read_hash( $document, [ length($1) ], \@lines );
+
+               } else {
+                       croak("Module::Build::YAML failed to classify the line '$lines[0]'");
+               }
+       }
+
+       $self;
 }
 
-# This is basically copied out of YAML.pm and simplified a little.
-sub DumpFile {
-    shift if ($_[0] eq __PACKAGE__ || ref($_[0]) eq __PACKAGE__);
-    my $filename = shift;
-    local $/ = "\n"; # reset special to "sane"
-    my $mode = '>';
-    if ($filename =~ /^\s*(>{1,2})\s*(.*)$/) {
-        ($mode, $filename) = ($1, $2);
-    }
-    open my $OUT, "$mode $filename"
-      or die "Can't open $filename for writing: $!";
-    binmode($OUT, ':utf8') if $] >= 5.008;
-    print $OUT Dump(@_);
-    close $OUT;
-}
-
-# This is basically copied out of YAML.pm and simplified a little.
-sub LoadFile {
-    shift if ($_[0] eq __PACKAGE__ || ref($_[0]) eq __PACKAGE__);
-    my $filename = shift;
-    open my $IN, $filename
-      or die "Can't open $filename for reading: $!";
-    binmode($IN, ':utf8') if $] >= 5.008;
-    return Load(do { local $/; <$IN> });
-    close $IN;
-}
-
-sub _yaml_chunk {
-  my ($indent, $values) = @_;
-  my $yaml_chunk = "";
-  my $ref = ref($values);
-  my ($value, @allkeys, %keyseen);
-  if (!$ref) {  # a scalar
-    $yaml_chunk .= &_yaml_value($values) . "\n";
-  }
-  elsif ($ref eq "ARRAY") {
-    foreach $value (@$values) {
-      $yaml_chunk .= "$indent-";
-      $ref = ref($value);
-      if (!$ref) {
-        $yaml_chunk .= " " . &_yaml_value($value) . "\n";
-      }
-      else {
-        $yaml_chunk .= "\n";
-        $yaml_chunk .= &_yaml_chunk("$indent  ", $value);
-      }
-    }
-  }
-  else { # assume "HASH"
-    if ($values->{_order} && ref($values->{_order}) eq "ARRAY") {
-        @allkeys = @{$values->{_order}};
-        $values = { %$values };
-        delete $values->{_order};
-    }
-    push(@allkeys, sort keys %$values);
-    foreach my $key (@allkeys) {
-      next if (!defined $key || $key eq "" || $keyseen{$key});
-      $keyseen{$key} = 1;
-      $yaml_chunk .= "$indent$key:";
-      $value = $values->{$key};
-      $ref = ref($value);
-      if (!$ref) {
-        $yaml_chunk .= " " . &_yaml_value($value) . "\n";
-      }
-      else {
-        $yaml_chunk .= "\n";
-        $yaml_chunk .= &_yaml_chunk("$indent  ", $value);
-      }
-    }
-  }
-  return($yaml_chunk);
-}
-
-sub _yaml_value {
-  my ($value) = @_;
-  # undefs become ~
-  return '~' if not defined $value;
-
-  # empty strings will become empty strings
-  return '""' if $value eq '';
-
-  # allow simple scalars (without embedded quote chars) to be unquoted
-  # (includes $%_+=-\;:,./)
-  return $value if $value !~ /["'`~\n!\@\#^\&\*\(\)\{\}\[\]\|<>\?]/;
-
-  # quote and escape strings with special values
-  return "'$value'"
-    if $value !~ /['`~\n!\#^\&\*\(\)\{\}\[\]\|\?]/;  # nothing but " or @ or < or > (email addresses)
-
-  $value =~ s/\n/\\n/g;    # handle embedded newlines
-  $value =~ s/"/\\"/g;     # handle embedded quotes
-  return qq{"$value"};
+# Deparse a scalar string to the actual scalar
+sub _read_scalar {
+       my ($self, $string, $indent, $lines) = @_;
+
+       # Trim trailing whitespace
+       $string =~ s/\s*\z//;
+
+       # Explitic null/undef
+       return undef if $string eq '~';
+
+       # Quotes
+       if ( $string =~ /^\'(.*?)\'\z/ ) {
+               return '' unless defined $1;
+               $string = $1;
+               $string =~ s/\'\'/\'/g;
+               return $string;
+       }
+       if ( $string =~ /^\"((?:\\.|[^\"])*)\"\z/ ) {
+               # Reusing the variable is a little ugly,
+               # but avoids a new variable and a string copy.
+               $string = $1;
+               $string =~ s/\\"/"/g;
+               $string =~ s/\\([never\\fartz]|x([0-9a-fA-F]{2}))/(length($1)>1)?pack("H2",$2):$UNESCAPES{$1}/gex;
+               return $string;
+       }
+
+       # Special cases
+       if ( $string =~ /^[\'\"!&]/ ) {
+               croak("Module::Build::YAML does not support a feature in line '$lines->[0]'");
+       }
+       return {} if $string eq '{}';
+       return [] if $string eq '[]';
+
+       # Regular unquoted string
+       return $string unless $string =~ /^[>|]/;
+
+       # Error
+       croak("Module::Build::YAML failed to find multi-line scalar content") unless @$lines;
+
+       # Check the indent depth
+       $lines->[0]   =~ /^(\s*)/;
+       $indent->[-1] = length("$1");
+       if ( defined $indent->[-2] and $indent->[-1] <= $indent->[-2] ) {
+               croak("Module::Build::YAML found bad indenting in line '$lines->[0]'");
+       }
+
+       # Pull the lines
+       my @multiline = ();
+       while ( @$lines ) {
+               $lines->[0] =~ /^(\s*)/;
+               last unless length($1) >= $indent->[-1];
+               push @multiline, substr(shift(@$lines), length($1));
+       }
+
+       my $j = (substr($string, 0, 1) eq '>') ? ' ' : "\n";
+       my $t = (substr($string, 1, 1) eq '-') ? ''  : "\n";
+       return join( $j, @multiline ) . $t;
 }
 
-1;
+# Parse an array
+sub _read_array {
+       my ($self, $array, $indent, $lines) = @_;
 
-__END__
+       while ( @$lines ) {
+               # Check for a new document
+               if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) {
+                       while ( @$lines and $lines->[0] !~ /^---/ ) {
+                               shift @$lines;
+                       }
+                       return 1;
+               }
+
+               # Check the indent level
+               $lines->[0] =~ /^(\s*)/;
+               if ( length($1) < $indent->[-1] ) {
+                       return 1;
+               } elsif ( length($1) > $indent->[-1] ) {
+                       croak("Module::Build::YAML found bad indenting in line '$lines->[0]'");
+               }
+
+               if ( $lines->[0] =~ /^(\s*\-\s+)[^\'\"]\S*\s*:(?:\s+|$)/ ) {
+                       # Inline nested hash
+                       my $indent2 = length("$1");
+                       $lines->[0] =~ s/-/ /;
+                       push @$array, { };
+                       $self->_read_hash( $array->[-1], [ @$indent, $indent2 ], $lines );
+
+               } elsif ( $lines->[0] =~ /^\s*\-(\s*)(.+?)\s*\z/ ) {
+                       # Array entry with a value
+                       shift @$lines;
+                       push @$array, $self->_read_scalar( "$2", [ @$indent, undef ], $lines );
 
-=head1 NAME
+               } elsif ( $lines->[0] =~ /^\s*\-\s*\z/ ) {
+                       shift @$lines;
+                       unless ( @$lines ) {
+                               push @$array, undef;
+                               return 1;
+                       }
+                       if ( $lines->[0] =~ /^(\s*)\-/ ) {
+                               my $indent2 = length("$1");
+                               if ( $indent->[-1] == $indent2 ) {
+                                       # Null array entry
+                                       push @$array, undef;
+                               } else {
+                                       # Naked indenter
+                                       push @$array, [ ];
+                                       $self->_read_array( $array->[-1], [ @$indent, $indent2 ], $lines );
+                               }
 
-Module::Build::YAML - Provides just enough YAML support so that Module::Build works even if YAML.pm is not installed
+                       } elsif ( $lines->[0] =~ /^(\s*)\S/ ) {
+                               push @$array, { };
+                               $self->_read_hash( $array->[-1], [ @$indent, length("$1") ], $lines );
 
-=head1 SYNOPSIS
+                       } else {
+                               croak("Module::Build::YAML failed to classify line '$lines->[0]'");
+                       }
 
-    use Module::Build::YAML;
+               } elsif ( defined $indent->[-2] and $indent->[-1] == $indent->[-2] ) {
+                       # This is probably a structure like the following...
+                       # ---
+                       # foo:
+                       # - list
+                       # bar: value
+                       #
+                       # ... so lets return and let the hash parser handle it
+                       return 1;
 
-    ...
+               } else {
+                       croak("Module::Build::YAML failed to classify line '$lines->[0]'");
+               }
+       }
 
-=head1 DESCRIPTION
+       return 1;
+}
+
+# Parse an array
+sub _read_hash {
+       my ($self, $hash, $indent, $lines) = @_;
+
+       while ( @$lines ) {
+               # Check for a new document
+               if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) {
+                       while ( @$lines and $lines->[0] !~ /^---/ ) {
+                               shift @$lines;
+                       }
+                       return 1;
+               }
 
-Provides just enough YAML support so that Module::Build works even if YAML.pm is not installed.
+               # Check the indent level
+               $lines->[0] =~ /^(\s*)/;
+               if ( length($1) < $indent->[-1] ) {
+                       return 1;
+               } elsif ( length($1) > $indent->[-1] ) {
+                       croak("Module::Build::YAML found bad indenting in line '$lines->[0]'");
+               }
 
-Currently, this amounts to the ability to write META.yml files when C<perl Build distmeta>
-is executed via the Dump() and DumpFile() functions/methods.
+               # Get the key
+               unless ( $lines->[0] =~ s/^\s*([^\'\" ][^\n]*?)\s*:(\s+|$)// ) {
+                       if ( $lines->[0] =~ /^\s*[?\'\"]/ ) {
+                               croak("Module::Build::YAML does not support a feature in line '$lines->[0]'");
+                       }
+                       croak("Module::Build::YAML failed to classify line '$lines->[0]'");
+               }
+               my $key = $1;
 
-=head1 AUTHOR
+               # Do we have a value?
+               if ( length $lines->[0] ) {
+                       # Yes
+                       $hash->{$key} = $self->_read_scalar( shift(@$lines), [ @$indent, undef ], $lines );
+               } else {
+                       # An indent
+                       shift @$lines;
+                       unless ( @$lines ) {
+                               $hash->{$key} = undef;
+                               return 1;
+                       }
+                       if ( $lines->[0] =~ /^(\s*)-/ ) {
+                               $hash->{$key} = [];
+                               $self->_read_array( $hash->{$key}, [ @$indent, length($1) ], $lines );
+                       } elsif ( $lines->[0] =~ /^(\s*)./ ) {
+                               my $indent2 = length("$1");
+                               if ( $indent->[-1] >= $indent2 ) {
+                                       # Null hash entry
+                                       $hash->{$key} = undef;
+                               } else {
+                                       $hash->{$key} = {};
+                                       $self->_read_hash( $hash->{$key}, [ @$indent, length($1) ], $lines );
+                               }
+                       }
+               }
+       }
 
-Stephen Adkins <spadkins@gmail.com>
+       return 1;
+}
+
+# Save an object to a file
+sub write {
+       my $self = shift;
+       my $file = shift or return $self->_error('No file name provided');
 
-=head1 COPYRIGHT
+       # Write it to the file
+       open( CFG, '>' . $file ) or return $self->_error(
+               "Failed to open file '$file' for writing: $!"
+               );
+       print CFG $self->write_string;
+       close CFG;
 
-Copyright (c) 2006. Stephen Adkins. All rights reserved.
+       return 1;
+}
 
-This program is free software; you can redistribute it and/or modify it
-under the same terms as Perl itself.
+# Save an object to a string
+sub write_string {
+       my $self = shift;
+       return '' unless @$self;
 
-See L<http://www.perl.com/perl/misc/Artistic.html>
+       # Iterate over the documents
+       my $indent = 0;
+       my @lines  = ();
+       foreach my $cursor ( @$self ) {
+               push @lines, '---';
 
-=cut
+               # An empty document
+               if ( ! defined $cursor ) {
+                       # Do nothing
+
+               # A scalar document
+               } elsif ( ! ref $cursor ) {
+                       $lines[-1] .= ' ' . $self->_write_scalar( $cursor, $indent );
+
+               # A list at the root
+               } elsif ( ref $cursor eq 'ARRAY' ) {
+                       unless ( @$cursor ) {
+                               $lines[-1] .= ' []';
+                               next;
+                       }
+                       push @lines, $self->_write_array( $cursor, $indent, {} );
+
+               # A hash at the root
+               } elsif ( ref $cursor eq 'HASH' ) {
+                       unless ( %$cursor ) {
+                               $lines[-1] .= ' {}';
+                               next;
+                       }
+                       push @lines, $self->_write_hash( $cursor, $indent, {} );
+
+               } else {
+                       croak("Cannot serialize " . ref($cursor));
+               }
+       }
+
+       join '', map { "$_\n" } @lines;
+}
+
+sub _write_scalar {
+       my $string = $_[1];
+       return '~'  unless defined $string;
+       return "''" unless length  $string;
+       if ( $string =~ /[\x00-\x08\x0b-\x0d\x0e-\x1f\"\'\n]/ ) {
+               $string =~ s/\\/\\\\/g;
+               $string =~ s/"/\\"/g;
+               $string =~ s/\n/\\n/g;
+               $string =~ s/([\x00-\x1f])/\\$UNPRINTABLE[ord($1)]/g;
+               return qq|"$string"|;
+       }
+       if ( $string =~ /(?:^\W|\s)/ or $QUOTE{$string} ) {
+               return "'$string'";
+       }
+       return $string;
+}
+
+sub _write_array {
+       my ($self, $array, $indent, $seen) = @_;
+       if ( $seen->{refaddr($array)}++ ) {
+               die "Module::Build::YAML does not support circular references";
+       }
+       my @lines  = ();
+       foreach my $el ( @$array ) {
+               my $line = ('  ' x $indent) . '-';
+               my $type = ref $el;
+               if ( ! $type ) {
+                       $line .= ' ' . $self->_write_scalar( $el, $indent + 1 );
+                       push @lines, $line;
+
+               } elsif ( $type eq 'ARRAY' ) {
+                       if ( @$el ) {
+                               push @lines, $line;
+                               push @lines, $self->_write_array( $el, $indent + 1, $seen );
+                       } else {
+                               $line .= ' []';
+                               push @lines, $line;
+                       }
+
+               } elsif ( $type eq 'HASH' ) {
+                       if ( keys %$el ) {
+                               push @lines, $line;
+                               push @lines, $self->_write_hash( $el, $indent + 1, $seen );
+                       } else {
+                               $line .= ' {}';
+                               push @lines, $line;
+                       }
+
+               } else {
+                       die "Module::Build::YAML does not support $type references";
+               }
+       }
+
+       @lines;
+}
+
+sub _write_hash {
+       my ($self, $hash, $indent, $seen) = @_;
+       if ( $seen->{refaddr($hash)}++ ) {
+               die "Module::Build::YAML does not support circular references";
+       }
+       my @lines  = ();
+       foreach my $name ( sort keys %$hash ) {
+               my $el   = $hash->{$name};
+               my $line = ('  ' x $indent) . "$name:";
+               my $type = ref $el;
+               if ( ! $type ) {
+                       $line .= ' ' . $self->_write_scalar( $el, $indent + 1 );
+                       push @lines, $line;
+
+               } elsif ( $type eq 'ARRAY' ) {
+                       if ( @$el ) {
+                               push @lines, $line;
+                               push @lines, $self->_write_array( $el, $indent + 1, $seen );
+                       } else {
+                               $line .= ' []';
+                               push @lines, $line;
+                       }
+
+               } elsif ( $type eq 'HASH' ) {
+                       if ( keys %$el ) {
+                               push @lines, $line;
+                               push @lines, $self->_write_hash( $el, $indent + 1, $seen );
+                       } else {
+                               $line .= ' {}';
+                               push @lines, $line;
+                       }
+
+               } else {
+                       die "Module::Build::YAML does not support $type references";
+               }
+       }
+
+       @lines;
+}
+
+# Set error
+sub _error {
+       $Module::Build::YAML::errstr = $_[1];
+       undef;
+}
+
+# Retrieve error
+sub errstr {
+       $Module::Build::YAML::errstr;
+}
+
+#####################################################################
+# YAML Compatibility
+
+sub Dump {
+       Module::Build::YAML->new(@_)->write_string;
+}
+
+sub Load {
+       my $self = Module::Build::YAML->read_string(@_);
+       unless ( $self ) {
+               croak("Failed to load YAML document from string");
+       }
+       if ( wantarray ) {
+               return @$self;
+       } else {
+               # To match YAML.pm, return the last document
+               return $self->[-1];
+       }
+}
+
+BEGIN {
+       *freeze = *Dump;
+       *thaw   = *Load;
+}
+
+sub DumpFile {
+       my $file = shift;
+       Module::Build::YAML->new(@_)->write($file);
+}
+
+sub LoadFile {
+       my $self = Module::Build::YAML->read($_[0]);
+       unless ( $self ) {
+               croak("Failed to load YAML document from '" . ($_[0] || '') . "'");
+       }
+       if ( wantarray ) {
+               return @$self;
+       } else {
+               # Return only the last document to match YAML.pm,
+               return $self->[-1];
+       }
+}
+
+#####################################################################
+# Use Scalar::Util if possible, otherwise emulate it
+
+BEGIN {
+       eval {
+               require Scalar::Util;
+       };
+       if ( $@ ) {
+               # Failed to load Scalar::Util
+               eval <<'END_PERL';
+sub refaddr {
+       my $pkg = ref($_[0]) or return undef;
+       if (!!UNIVERSAL::can($_[0], 'can')) {
+               bless $_[0], 'Scalar::Util::Fake';
+       } else {
+               $pkg = undef;
+       }
+       "$_[0]" =~ /0x(\w+)/;
+       my $i = do { local $^W; hex $1 };
+       bless $_[0], $pkg if defined $pkg;
+       $i;
+}
+END_PERL
+       } else {
+               Scalar::Util->import('refaddr');
+       }
+}
+
+1;
+
+__END__
 
diff --git a/cpan/Module-Build/lib/inc/latest.pm b/cpan/Module-Build/lib/inc/latest.pm
new file mode 100644 (file)
index 0000000..9d4a380
--- /dev/null
@@ -0,0 +1,250 @@
+package inc::latest;
+use strict;
+use vars qw($VERSION);
+$VERSION = '0.35_08';
+$VERSION = eval $VERSION;
+
+use Carp;
+use File::Basename  ();
+use File::Spec      ();
+use File::Path      ();
+use IO::File        ();
+use File::Copy      ();
+
+# track and return modules loaded by inc::latest
+my @loaded_modules;
+sub loaded_modules {@loaded_modules}
+
+# must ultimately "goto" the import routine of the module to be loaded
+# so that the calling package is correct when $mod->import() runs.
+sub import {
+  my ($package, $mod, @args) = @_;
+  return unless(defined $mod);
+
+  my $inc_path = './inc/latest.pm';
+  my $private_path = './inc/latest/private.pm';
+  if(-e $inc_path) {
+    # delete our methods
+    delete $inc::latest::{$_} for(keys %inc::latest::);
+    # load the bundled module
+    require $inc_path;
+    require $private_path;
+    my $import = inc::latest->can('import');
+    goto $import;
+  }
+
+  # author mode - just record and load the modules
+  push(@loaded_modules, $mod);
+  require inc::latest::private;
+  goto \&inc::latest::private::_load_module;
+}
+
+sub write {
+  my $package = shift;
+  my ($where, @preload) = @_;
+
+  warn "should really be writing in inc/" unless $where =~ /inc$/;
+
+  # write inc/latest.pm
+  File::Path::mkpath( $where );
+  my $fh = IO::File->new( File::Spec->catfile($where,'latest.pm'), "w" );
+  print {$fh} "# This stub created by inc::latest $VERSION\n";
+  print {$fh} <<'HERE';
+package inc::latest;
+use strict;
+use vars '@ISA';
+require inc::latest::private;
+@ISA = qw/inc::latest::private/;
+HERE
+  if (@preload) {
+    print {$fh} "\npackage inc::latest::preload;\n";
+    for my $mod (@preload) {
+      print {$fh} "inc::latest->import('$mod');\n";
+    }
+  }
+  print {$fh} "\n1;\n";
+  close $fh;
+
+  # write inc/latest/private;
+  require inc::latest::private;
+  File::Path::mkpath( File::Spec->catdir( $where, 'latest' ) );
+  my $from = $INC{'inc/latest/private.pm'};
+  my $to = File::Spec->catfile($where,'latest','private.pm');
+  File::Copy::copy( $from, $to ) or die "Couldn't copy '$from' to '$to': $!";
+
+  return 1;
+}
+
+sub bundle_module {
+  my ($package, $module, $where) = @_;
+
+  # create inc/inc_$foo
+  (my $dist = $module) =~ s{::}{-}g;
+  my $inc_lib = File::Spec->catdir($where,"inc_$dist");
+  File::Path::mkpath $inc_lib;
+
+  # get list of files to copy
+  require ExtUtils::Installed;
+  # workaround buggy EU::Installed check of @INC
+  my $inst = ExtUtils::Installed->new(extra_libs => [@INC]);
+  my $packlist = $inst->packlist( $module ) or die "Couldn't find packlist";
+  my @files = grep { /\.pm$/ } keys %$packlist;
+
+
+  # figure out prefix
+  my $mod_path = quotemeta $package->_mod2path( $module );
+  my ($prefix) = grep { /$mod_path$/ } @files;
+  $prefix =~ s{$mod_path$}{};
+
+  # copy files
+  for my $from ( @files ) {
+    next unless $from =~ /\.pm$/;
+    (my $mod_path = $from) =~ s{^\Q$prefix\E}{};
+    my $to = File::Spec->catfile( $inc_lib, $mod_path );
+    File::Path::mkpath(File::Basename::dirname($to));
+    File::Copy::copy( $from, $to ) or die "Couldn't copy '$from' to '$to': $!";
+  }
+  return 1;
+}
+
+# Translate a module name into a directory/file.pm to search for in @INC
+sub _mod2path {
+  my ($self, $mod) = @_;
+  my @parts = split /::/, $mod;
+  $parts[-1] .= '.pm';
+  return $parts[0] if @parts == 1;
+  return File::Spec->catfile(@parts);
+}
+
+1;
+
+
+=head1 NAME
+
+inc::latest - use modules bundled in inc/ if they are newer than installed ones
+
+=head1 SYNOPSIS
+
+  # in Build.PL
+  use inc::latest 'Module::Build';
+
+=head1 DESCRIPTION
+
+The C<inc::latest> module helps bootstrap configure-time dependencies for CPAN
+distributions.  These dependencies get bundled into the C<inc> directory within
+a distribution and are used by Build.PL (or Makefile.PL).
+
+Arguments to C<inc::latest> are module names that are checked against both the
+current C<@INC> array and against specially-named directories in C<inc>.  If
+the bundled verison is newer than the installed one (or the module isn't
+installed, then, the bundled directory is added to the start of <@INC> and the
+module is loaded from there.
+
+There are actually two variations of C<inc::latest> -- one for authors and one
+for the C<inc> directory.  For distribution authors, the C<inc::latest>
+installed in the system will record modules loaded via C<inc::latest> and can
+be used to create the bundled files in C<inc>, including writing the second
+variation as C<inc/latest.pm>.
+
+This second C<inc::latest> is the one that is loaded in a distribution being
+installed (e.g. from Build.PL).  This bundled C<inc::latest> is the one
+that determines which module to load.
+
+=head2 Special notes on bundling
+
+The C<inc::latest> module creates bundled directories based on the packlist
+file of an installed distribution.  Even though C<inc::latest> takes module
+name arguments, it is better to think of it as bundling and making available
+entire I<distributions>.  When a module is loaded through C<inc::latest>,
+it looks in all bundled distributions in C<inc/> for a newer module than
+can be found in the existing C<@INC> array.
+
+Thus, the module-name provided should usually be the "top-level" module name of
+a distribution, though this is not strictly required.  For example,
+L<Module::Build> has a number of heuristics to map module names to packlists,
+allowing users to do things like this:
+
+  use inc::latest 'Devel::AssertOS::Unix';
+
+even though Devel::AssertOS::Unix is contained within the Devel-CheckOS
+distribution.
+
+At the current time, packlists are required.  Thus, bundling dual-core modules
+may require a 'forced install' over versions in the latest version of perl
+in order to create the necessary packlist for bundling.
+
+=head1 USAGE
+
+When calling C<use>, the bundled C<inc::latest> takes a single module name and
+optional arguments to pass to that module's own import method.
+
+  use 'inc::latest' 'Foo::Bar' qw/foo bar baz/;
+
+=head2 Author-mode
+
+You are in author-mode inc::latest if any of the Author-mode methods are
+available.  For example:
+
+  if ( inc::latest->can('write') ) {
+    inc::latest->write('inc');
+  }
+
+=over 4
+
+=item loaded_modules()
+
+  my @list = inc::latest->loaded_modules;
+
+This takes no arguments and always returns a list of module names requested for
+loading via "use inc::latest 'MODULE'", regardless of wether the load was
+successful or not.
+
+=item write()
+
+  inc::latest->write( 'inc' );
+
+This writes the bundled version of inc::latest to the directory name given as an
+argument.  It almost all cases, it should be 'C<inc>'.
+
+=item bundle_module()
+
+  for my $mod ( inc::latest->loaded_modules ) {
+    inc::latest->bundle_module($mod, $dir);
+  }
+
+If $mod corresponds to a packlist, then this function creates a specially-named
+directory in $dir and copies all .pm files from the modlist to the new
+directory (which almost always should just be 'inc').  For example, if Foo::Bar
+is the name of the module, and $dir is 'inc', then the directory would be
+'inc/inc_Foo-Bar' and contain files like this:
+
+  inc/inc_Foo-Bar/Foo/Bar.pm
+
+Currently, $mod B<must> have a packlist.  If this is not the case (e.g. for a
+dual-core module), then the bundling will fail.  You may be able to create a
+packlist by forced installing the module on top of the version that came with
+core Perl.
+
+=back
+
+=head2 As bundled in inc/
+
+All methods are private.  Only the C<import> method is public.
+
+=head1 AUTHOR
+
+Eric Wilhelm <ewilhelm@cpan.org>, David Golden <dagolden@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2009 by Eric Wilhelm and David Golden
+
+This library is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<Module::Build>
+
+=cut
+
diff --git a/cpan/Module-Build/lib/inc/latest/private.pm b/cpan/Module-Build/lib/inc/latest/private.pm
new file mode 100644 (file)
index 0000000..285514b
--- /dev/null
@@ -0,0 +1,101 @@
+package inc::latest::private;
+use strict;
+use vars qw($VERSION);
+$VERSION = '0.35_08';
+$VERSION = eval $VERSION;
+
+use File::Spec;
+use IO::File;
+
+# must ultimately "goto" the import routine of the module to be loaded
+# so that the calling package is correct when $mod->import() runs.
+sub import {
+  my ($package, $mod, @args) = @_;
+  my $file = $package->_mod2path($mod);
+
+  if ($INC{$file}) {
+    # Already loaded, but let _load_module handle import args
+    goto \&_load_module;
+  }
+
+  # A bundled copy must be present
+  my ($bundled, $bundled_dir) = $package->_search_bundled($file)
+    or die "No bundled copy of $mod found";
+
+  my $from_inc = $package->_search_INC($file);
+  unless ($from_inc) {
+    # Only bundled is available
+    unshift(@INC, $bundled_dir);
+    goto \&_load_module;
+  }
+
+  if (_version($from_inc) >= _version($bundled)) {
+    # Ignore the bundled copy
+    goto \&_load_module;
+  }
+
+  # Load the bundled copy
+  unshift(@INC, $bundled_dir);
+  goto \&_load_module;
+}
+
+sub _version {
+  require ExtUtils::MakeMaker;
+  return ExtUtils::MM->parse_version(shift);
+}
+
+# use "goto" for import to preserve caller
+sub _load_module {
+  my $package = shift; # remaining @_ is ready for goto
+  my ($mod, @args) = @_;
+  eval "require $mod; 1" or die $@;
+  if ( my $import = $mod->can('import') ) {
+    goto $import;
+  }
+  return 1;
+}
+
+sub _search_bundled {
+  my ($self, $file) = @_;
+
+  my $mypath = 'inc';
+
+  local *DH;   # Maintain 5.005 compatibility
+  opendir DH, $mypath or die "Can't open directory $mypath: $!";
+
+  while (defined(my $e = readdir DH)) {
+    next unless $e =~ /^inc_/;
+    my $try = File::Spec->catfile($mypath, $e, $file);
+
+    return($try, File::Spec->catdir($mypath, $e)) if -e $try;
+  }
+  return;
+}
+
+# Look for the given path in @INC.
+sub _search_INC {
+  # TODO: doesn't handle coderefs or arrayrefs or objects in @INC, but
+  # it probably should
+  my ($self, $file) = @_;
+
+  foreach my $dir (@INC) {
+    next if ref $dir;
+    my $try = File::Spec->catfile($dir, $file);
+    return $try if -e $try;
+  }
+
+  return;
+}
+
+# Translate a module name into a directory/file.pm to search for in @INC
+sub _mod2path {
+  my ($self, $mod) = @_;
+  my @parts = split /::/, $mod;
+  $parts[-1] .= '.pm';
+  return $parts[0] if @parts == 1;
+  return File::Spec->catfile(@parts);
+}
+
+1;
+
+
index a221714..68614c8 100644 (file)
@@ -4,7 +4,7 @@ use strict;
 use lib 't/lib';
 use MBTest tests => 8;
 use DistGen;
-use Module::Build;
+blib_load('Module::Build');
 
 my $dist;
 
diff --git a/cpan/Module-Build/t/README.pod b/cpan/Module-Build/t/README.pod
new file mode 100644 (file)
index 0000000..b2d0579
--- /dev/null
@@ -0,0 +1,94 @@
+=head1 A GUIDE TO WRITING TESTS FOR MODULE::BUILD
+
+This document provides tips on writing new tests for Module::Build.  Please
+note that many existing tests were written prior to these guidelines and
+have many different styles.  Please don't copy/paste old tests by rote without
+considering better ways to test. See C<sample.t> for a starter test file.
+
+=head1 TEST FILE PREAMBLE
+
+Every Module::Build test should begin with the same preamble to ensure that the
+test library is set properly and that the correct version of Module::Build is
+being tested.
+
+  use strict;
+  use lib 't/lib';
+  use MBTest tests => 2; # or 'no_plan'
+
+  blib_load('Module::Build');
+
+The C<MBTest> module is in C<t/lib/> and subclasses Test::More.  When loaded
+it cleans up several environment variables that could cause problems,
+tweaks C<@INC> and exports several helper functions.  See that module for
+details.
+
+=head1 CREATING A TEST DISTRIBUTION
+
+The C<DistGen> module in C<t/lib/> should be used to create sample
+distributions for testing.  It provides numerous helpful methods to
+create a skeleton distribution, add files, change files, and so on.
+Run C<perldoc> on C<t/lib/DistGen.pm> to see the documentation.
+
+  # CREATE A TEST DISTRIBUTION
+
+  use DistGen;
+
+  # create dist object in a temp directory
+  my $dist = DistGen->new;
+
+  # enter the test distribution directory before further testing
+  $dist->chdir_in;
+
+  # generate the skeleton files
+  $dist->regen;
+
+
+=head1 GETTING A MODULE::BUILD OBJECT
+
+From inside the test distribution, you can get the Module::Build object
+configured in Build.PL using the C<new_from_context> method on the
+dist object.  This is just like Module::Build's C<new_from_context> except
+it passes C<< quiet => 1 >> to avoid sending output to the terminal.
+Use the Module::Build object to test the programmatic API.
+
+  my $mb = $dist->new_from_context( quiet => 1 );
+  isa_ok( $mb, "Module::Build" );
+  is( $mb->dist_name, "Simple", "dist_name is 'Simple'" );
+
+=head1 TESTING THE COMMAND LINE API
+
+The command line API is tested by running subprocesses, not via a Module::Build
+object.  The C<DistGen> object has helper methods for running C<Build.PL> and
+C<Build> and passing arguments on the command line.
+
+  $dist->run_build_pl( '--quiet' );
+  $dist->run_build( 'test' );
+
+=head1 TYPICAL TESTING CYCLE
+
+The typical testing cycle is to generate or modify a test distribution, either
+through the C<DistGen> object or directly in the filesystem, then regenerate
+the distribution and test it (or run command line tests and observe the
+result.)
+
+  # Modify the distribution
+
+  $dist->change_build_pl(
+    {
+      module_name   => $dist->name,
+      license       => 'artistic',
+    }
+  );
+  $dist->regen;
+
+  # Get a new build object and test it
+
+  $mb = $dist->new_from_context;
+  is( $mb->license, "artistic", "saw 'artistic' license" );
+
+
+=head1 COPYRIGHT
+
+This documentation is Copyright (C) 2009 by David Golden.  You can redistribute
+it and/or modify it under the same terms as Perl 5.10.0.
+
diff --git a/cpan/Module-Build/t/actions/installdeps.t b/cpan/Module-Build/t/actions/installdeps.t
new file mode 100644 (file)
index 0000000..95e221d
--- /dev/null
@@ -0,0 +1,48 @@
+use strict;
+use lib 't/lib';
+use MBTest;
+use DistGen;
+
+plan tests => 7;
+
+# Ensure any Module::Build modules are loaded from correct directory
+blib_load('Module::Build');
+
+# create dist object in a temp directory
+# enter the directory and generate the skeleton files
+my $dist = DistGen->new->chdir_in;
+
+$dist->change_build_pl(
+  module_name => $dist->name,
+  requires => {
+    'File::Spec' => 9999,
+  },
+  build_requires => {
+    'Getopt::Long' => 9998,
+  },
+  cpan_client => $^X . ' -le print($_)for($^X,@ARGV)',
+)->regen;
+
+# get a Module::Build object and test with it
+my $mb;
+stdout_stderr_of( sub { $mb = $dist->new_from_context('verbose' => 1) } );
+isa_ok( $mb, "Module::Build" );
+like( $mb->cpan_client, qr/^\Q$^X\E/, "cpan_client is mocked with perl" );
+
+my $out = stdout_of( sub {
+    $dist->run_build('installdeps')
+});
+ok( length($out), "ran mocked Build installdeps");
+my $expected = quotemeta(Module::Build->find_command($^X));
+like( $out, qr/$expected/i, "relative cpan_client resolved relative to \$^X" );
+like( $out, qr/File::Spec/, "saw File::Spec prereq" );
+like( $out, qr/Getopt::Long/, "saw Getopt::Long prereq" );
+
+$out = stdout_stderr_of( sub {
+    $dist->run_build('installdeps', '--cpan_client', 'ADLKASJDFLASDJ')
+});
+like( $out, qr/cpan_client .* is not executable/,
+  "Build installdeps with bad cpan_client dies"
+);
+
+# vim:ts=2:sw=2:et:sta:sts=2
index 6032b09..e0b25ae 100644 (file)
@@ -2,12 +2,11 @@
 
 use strict;
 use lib 't/lib';
-use MBTest tests => 29;
+use MBTest tests => 27;
 #use MBTest 'no_plan';
 use DistGen;
 
-BEGIN { use_ok 'Module::Build' or die; }
-ensure_blib 'Module::Build';
+blib_load 'Module::Build';
 
 my $tmp = MBTest->tmpdir;
 my $dist = DistGen->new( dir => $tmp );
index f46be0a..74c50b6 100644 (file)
@@ -2,10 +2,9 @@
 
 use strict;
 use lib 't/lib';
-use MBTest tests => 60;
+use MBTest tests => 58;
 
-use_ok 'Module::Build';
-ensure_blib('Module::Build');
+blib_load('Module::Build');
 
 my $tmp = MBTest->tmpdir;
 
@@ -28,7 +27,7 @@ $dist->chdir_in;
 
   $mb = Module::Build->new( dist_name => $dist->name, dist_version => 7 );
   ok $mb;
-  ok ! $mb->module_name;  # Make sure it's defined
+  ok $mb->module_name;  # Set via heuristics
   is $mb->dist_name, $dist->name;
 }
 
@@ -163,10 +162,7 @@ $dist->chdir_in;
   is $args{foo}, 1;
 
   # revert test distribution to pristine state because we modified a file
-  $dist->remove;
-  $dist = DistGen->new( dir => $tmp );
-  $dist->regen;
-  $dist->chdir_in;
+  $dist->regen( clean => 1 );
 }
 
 # Test author stuff
@@ -236,5 +232,3 @@ $dist->chdir_in;
   is_deeply $mb->include_dirs, ['/foo'], 'Should have single include dir';
 }
 
-# cleanup
-$dist->remove;
diff --git a/cpan/Module-Build/t/bundle_inc.t b/cpan/Module-Build/t/bundle_inc.t
new file mode 100644 (file)
index 0000000..edb1aa9
--- /dev/null
@@ -0,0 +1,194 @@
+# sample.t -- a sample test file for Module::Build
+
+use strict;
+use lib 't/lib';
+use MBTest; # or 'no_plan'
+use DistGen;
+use Config;
+use IO::File;
+use File::Spec;
+use ExtUtils::Packlist;
+use File::Path;
+
+# Ensure any Module::Build modules are loaded from correct directory
+blib_load('Module::Build');
+blib_load('Module::Build::ConfigData');
+
+if ( Module::Build::ConfigData->feature('inc_bundling_support') ) {
+  plan tests => 18;
+} else {
+  plan skip_all => 'inc_bundling_support feature is not enabled';
+}
+
+# need to do a temp install of M::B being tested to ensure a packlist
+# is available for bundling
+
+my $current_mb = Module::Build->resume();
+my $temp_install = MBTest->tmpdir();
+my $arch = $Config{archname};
+my $lib_path = File::Spec->catdir($temp_install,qw/lib perl5/);
+my $arch_path = File::Spec->catdir( $lib_path, $arch );
+mkpath ( $arch_path );
+ok( -d $arch_path, "created temporary M::B pseudo-install directory");
+
+unshift @INC, $lib_path, $arch_path;
+local $ENV{PERL5LIB} = join( $Config{path_sep},
+  $lib_path, $arch_path, ($ENV{PERL5LIB} ? $ENV{PERL5LIB} : () )
+);
+
+stdout_of( sub { $current_mb->dispatch('install', install_base => $temp_install) } );
+
+# create dist object in a temp directory
+# enter the directory and generate the skeleton files
+my $dist = DistGen->new( inc => 1 )->chdir_in->regen;
+
+# get a Module::Build object and test with it
+my $mb = $dist->new_from_context(); # quiet by default
+isa_ok( $mb, "Module::Build" );
+is( $mb->dist_name, "Simple", "dist_name is 'Simple'" );
+is_deeply( $mb->bundle_inc, [ 'Module::Build' ],
+  "Module::Build is flagged for bundling"
+);
+
+# see what gets bundled
+stdout_stderr_of( sub { $mb->dispatch('distdir') } );
+
+my $dist_inc = File::Spec->catdir($mb->dist_dir, 'inc');
+ok( -e File::Spec->catfile( $dist_inc, 'latest.pm' ),
+  "./inc/latest.pm created"
+);
+
+ok( -d File::Spec->catdir( $dist_inc, 'inc_Module-Build' ),
+  "dist_dir/inc/inc_Module_Build created"
+);
+
+my $mb_file =
+  File::Spec->catfile( $dist_inc, qw/inc_Module-Build Module Build.pm/ );
+
+ok( -e $mb_file,
+  "dist_dir/inc/inc_Module_Build/Module/Build.pm created"
+);
+
+ok( -e File::Spec->catfile( $dist_inc, qw/inc_Module-Build Module Build Base.pm/ ),
+  "dist_dir/inc/inc_Module_Build/Module/Build/Base.pm created"
+);
+
+# Force bundled M::B to a higher version so it gets loaded
+
+my $fh = IO::File->new($mb_file, "+<") or die "Could not open $mb_file: $!";
+my $mb_code = do { local $/; <$fh> };
+$mb_code =~ s{\$VERSION\s+=\s+\S+}{\$VERSION = 9999;};
+$fh->seek(0,0);
+print {$fh} $mb_code;
+$fh->close;
+
+# test the bundling in dist_dir
+chdir $mb->dist_dir;
+
+stdout_of( sub { Module::Build->run_perl_script('Build.PL',[],[]) } );
+
+my $meta = IO::File->new('MYMETA.yml');
+ok( $meta, "found MYMETA.yml" );
+ok( scalar( grep { /generated_by:.*9999/ } <$meta> ),
+  "dist_dir Build.PL loaded bundled Module::Build"
+);
+
+#--------------------------------------------------------------------------#
+# test identification of dependencies
+#--------------------------------------------------------------------------#
+
+$dist->chdir_in;
+
+$dist->add_file( 'mylib/Foo.pm', << 'HERE' );
+package Foo;
+our $VERSION = 1;
+1;
+HERE
+
+$dist->add_file( 'mylib/Bar.pm', << 'HERE' );
+package Bar;
+use Foo;
+our $VERSION = 42;
+1;
+HERE
+
+$dist->change_file( 'Build.PL', << "HERE" );
+use inc::latest 'Module::Build';
+use inc::latest 'Foo';
+
+Module::Build->new(
+  module_name => '$dist->{name}',
+  license => 'perl',
+)->create_build_script;
+HERE
+
+$dist->regen( clean => 1 );
+
+make_packlist($_,'mylib') for qw/Foo Bar/;
+
+# get a Module::Build object and test with it
+my $abs_mylib = File::Spec->rel2abs('mylib');
+
+
+unshift @INC, $abs_mylib;
+$mb = $dist->new_from_context(); # quiet by default
+isa_ok( $mb, "Module::Build" );
+is_deeply( [sort @{$mb->bundle_inc}], [ 'Foo', 'Module::Build' ],
+  "Module::Build and Foo are flagged for bundling"
+);
+
+my $output = stdout_stderr_of( sub { $mb->dispatch('distdir') } );
+
+ok( -e File::Spec->catfile( $dist_inc, 'latest.pm' ),
+  "./inc/latest.pm created"
+);
+
+ok( -d File::Spec->catdir( $dist_inc, 'inc_Foo' ),
+  "dist_dir/inc/inc_Foo created"
+);
+
+$dist->change_file( 'Build.PL', << "HERE" );
+use inc::latest 'Module::Build';
+use inc::latest 'Bar';
+
+Module::Build->new(
+  module_name => '$dist->{name}',
+  license => 'perl',
+)->create_build_script;
+HERE
+
+$dist->regen( clean => 1 );
+make_packlist($_,'mylib') for qw/Foo Bar/;
+
+$mb = $dist->new_from_context(); # quiet by default
+isa_ok( $mb, "Module::Build" );
+is_deeply( [sort @{$mb->bundle_inc}], [ 'Bar', 'Module::Build' ],
+  "Module::Build and Bar are flagged for bundling"
+);
+
+$output = stdout_stderr_of( sub { $mb->dispatch('distdir') } );
+
+ok( -e File::Spec->catfile( $dist_inc, 'latest.pm' ),
+  "./inc/latest.pm created"
+);
+
+ok( -d File::Spec->catdir( $dist_inc, 'inc_Bar' ),
+  "dist_dir/inc/inc_Bar created"
+);
+
+
+
+sub make_packlist {
+  my ($mod, $lib) = @_;
+  my $arch = $Config{archname};
+  (my $mod_path = $mod) =~ s{::}{/}g;
+  my $mod_file = File::Spec->catfile( $lib, "$mod_path\.pm" );
+  my $abs = File::Spec->rel2abs($mod_file);
+  my $packlist_path = File::Spec->catdir($lib, $arch, 'auto', $mod_path);
+  mkpath $packlist_path;
+  my $packlist = ExtUtils::Packlist->new;
+  $packlist->{$abs}++;
+  $packlist->write( File::Spec->catfile( $packlist_path, '.packlist' ));
+}
+
+# vim:ts=2:sw=2:et:sta:sts=2
index 88e5953..f84b79b 100644 (file)
@@ -25,8 +25,8 @@ if ( $Config{make} && $^O ne 'VMS' ? find_in_path($Config{make}) : 1 ) {
 
 my $is_vms_mms = ($^O eq 'VMS') && ($Config{make} =~ /MM[SK]/i);
 
-use_ok 'Module::Build';
-ensure_blib('Module::Build');
+blib_load('Module::Build');
+blib_load('Module::Build::Version');
 
 
 #########################
@@ -43,8 +43,8 @@ $dist->chdir_in;
 
 #########################
 
-use Module::Build;
-use Module::Build::Compat;
+blib_load('Module::Build');
+blib_load('Module::Build::Compat');
 
 use Carp;  $SIG{__WARN__} = \&Carp::cluck;
 
@@ -72,10 +72,11 @@ $dist->change_build_pl({
   license             => 'perl',
   requires            => {
     'perl'        => $],
-    'File::Spec'  => 0,
+    'File::Spec'  => 0.2,
   },
-  build_requires      => {
-    'Test::More'  => 0,
+  build_requires => {
+      'Test::More' => 0,
+      'File::Spec' => 0,
   },
   PL_files            => { 'foo.PL' => 'foo' },
 });
@@ -90,8 +91,11 @@ $dist->regen;
 test_makefile_types(
     requires => {
         'perl' => $],
-        'File::Spec' => 0,
+        'File::Spec' => 0.2,
+    },
+    build_requires => {
         'Test::More' => 0,
+        'File::Spec' => 0,
     },
     PL_files => {
         'foo.PL' => 'foo',
@@ -108,7 +112,7 @@ $dist->regen;
 
 # Create M::B instance but don't pollute STDOUT
 my $mb;
-stdout_of( sub {
+stdout_stderr_of( sub {
     $mb = Module::Build->new_from_context;
 });
 ok $mb, "Module::Build->new_from_context";
@@ -131,7 +135,7 @@ ok $mb, "Module::Build->new_from_context";
   # Makefile.PL - make sure it fails in the right way here.
   local @Foo::Builder::ISA = qw(Module::Build);
   my $foo_builder;
-  stdout_of( sub {
+  stdout_stderr_of( sub {
     $foo_builder = Foo::Builder->new_from_context;
   });
   foreach my $style ('passthrough', 'small') {
@@ -148,13 +152,13 @@ ok $mb, "Module::Build->new_from_context";
   
   # Now make sure it can actually work.
   my $bar_builder;
-  stdout_of( sub {
+  stdout_stderr_of( sub {
     $bar_builder = Module::Build->subclass( class => 'Bar::Builder' )->new_from_context;
   });
   foreach my $style ('passthrough', 'small') {
     create_makefile_pl($style, $bar_builder);
     my $result;
-    stdout_of( sub {
+    stdout_stderr_of( sub {
       $result = $mb->run_perl_script('Makefile.PL');
     });
     ok $result, "Makefile.PL ran without error";
@@ -167,7 +171,7 @@ ok $mb, "Module::Build->new_from_context";
 
   my $libdir = File::Spec->catdir( $tmp, 'libdir' );
   my $result;
-  stdout_of( sub {
+  stdout_stderr_of( sub {
     $result = $mb->run_perl_script('Makefile.PL', [],
       [
       "LIB=$libdir",
@@ -188,7 +192,7 @@ ok $mb, "Module::Build->new_from_context";
 
   # Make sure those switches actually had an effect
   my ($ran_ok, $output);
-  $output = stdout_of( sub { $ran_ok = $new_build->do_system(@make, 'test') } );
+  $output = stdout_stderr_of( sub { $ran_ok = $new_build->do_system(@make, 'test') } );
   ok $ran_ok, "make test ran without error";
   $output =~ s/^/# /gm;  # Don't confuse our own test output
   like $output, qr/(?:# ok \d+\s+)+/, 'Should be verbose';
@@ -201,7 +205,7 @@ ok $mb, "Module::Build->new_from_context";
     $make_macro = '/macro=("' . $make_macro . '")';
   }
 
-  $output = stdout_of( sub {
+  $output = stdout_stderr_of( sub {
     local $ENV{HARNESS_TIMER}; # RT#39635 - timer messes with output
     $ran_ok = $mb->do_system(@make, 'test', $make_macro)
   } );
@@ -258,7 +262,7 @@ ok $mb, "Module::Build->new_from_context";
     }
   }
 
-  stdout_of( sub { $mb->do_system(@make, 'realclean'); } );
+  stdout_stderr_of( sub { $mb->do_system(@make, 'realclean'); } );
   ok ! -e $makefile, "$makefile shouldn't exist";
 
   1 while unlink 'Makefile.PL';
@@ -274,14 +278,14 @@ ok $mb, "Module::Build->new_from_context";
 
   create_makefile_pl('passthrough', $mb);
 
-  stdout_of( sub {
+  stdout_stderr_of( sub {
     $mb->run_perl_script('Makefile.PL', [], ['INSTALL_BASE=~/foo']);
   });
   my $b2 = Module::Build->current;
   ok $b2->install_base, "install_base set";
   unlike $b2->install_base, qr/^~/, "Tildes should be expanded";
   
-  stdout_of( sub { $mb->do_system(@make, 'realclean'); } );
+  stdout_stderr_of( sub { $mb->do_system(@make, 'realclean'); } );
   ok ! -e $makefile, "$makefile shouldn't exist";
 
   1 while unlink 'Makefile.PL';
@@ -293,34 +297,53 @@ ok $mb, "Module::Build->new_from_context";
   $dist->regen;
 
   my $mb;
-  stdout_of( sub {
+  stdout_stderr_of( sub {
       $mb = Module::Build->new_from_context( recursive_test_files => 1 );
   });
 
   create_makefile_pl('traditional', $mb);
   my $args = extract_writemakefile_args() || {};
-  is $args->{TESTS}, 
-    join( q{ }, 
-      File::Spec->catfile(qw(t *.t)),
-      File::Spec->catfile(qw(t deep *.t))
-    ),
-    'Makefile.PL has correct TESTS line for recursive test files';
-}
 
-# cleanup
-$dist->remove;
+  if ( exists $args->{test}->{TESTS} ) {
+    is $args->{test}->{TESTS},
+      join( q{ },
+        File::Spec->catfile(qw(t *.t)),
+        File::Spec->catfile(qw(t deep *.t))
+      ),
+      'Makefile.PL has correct TESTS line for recursive test files';
+  } else {
+    ok( ! exists $args->{TESTS}, 'Not using incorrect recursive tests key' );
+  }
+
+}
 
 #########################################################
 
+sub _merge_prereqs {
+  my ($first, $second) = @_;
+  my $new = { %$first };
+  for my $k (keys %$second) {
+    if ( exists $new->{$k} ) {
+      my ($v1,$v2) = ($new->{$k},$second->{$k});
+      $new->{$k} = ($v1 > $v2 ? $v1 : $v2);
+    }
+    else {
+      $new->{$k} = $second->{$k};
+    }
+  }
+  return $new;
+}
+
 sub test_makefile_types {
   my %opts = @_;
   $opts{requires} ||= {};
+  $opts{build_requires} ||= {};
   $opts{PL_files} ||= {};
 
   foreach my $type (@makefile_types) {
     # Create M::B instance 
     my $mb;
-    stdout_of( sub {
+    stdout_stderr_of( sub {
         $mb = Module::Build->new_from_context;
     });
     ok $mb, "Module::Build->new_from_context";
@@ -330,12 +353,12 @@ sub test_makefile_types {
 
     test_makefile_pl_requires_perl( $opts{requires}{perl} );
     test_makefile_creation($mb);
-    test_makefile_prereq_pm( $opts{requires} );
+    test_makefile_prereq_pm( _merge_prereqs($opts{requires}, $opts{build_requires}) );
     test_makefile_pl_files( $opts{PL_files} ) if $type eq 'traditional';
       
     my ($output,$success);
     # Capture output to keep our STDOUT clean
-    $output = stdout_of( sub {
+    $output = stdout_stderr_of( sub {
       $success = $mb->do_system(@make);
     });
     ok $success, "make ran without error";
@@ -345,13 +368,13 @@ sub test_makefile_types {
     }
 
     # Can't let 'test' STDOUT go to our STDOUT, or it'll confuse Test::Harness.
-    $output = stdout_of( sub {
+    $output = stdout_stderr_of( sub {
       $success = $mb->do_system(@make, 'test');
     });
     ok $success, "make test ran without error";
     like uc $output, qr{DONE\.|SUCCESS}, "make test output indicated success";
     
-    $output = stdout_of( sub {
+    $output = stdout_stderr_of( sub {
       $success = $mb->do_system(@make, 'realclean');
     });
     ok $success, "make realclean ran without error";
@@ -372,7 +395,7 @@ sub test_makefile_creation {
   
   my ($output, $result);
   # capture output to avoid polluting our test output
-  $output = stdout_of( sub {
+  $output = stdout_stderr_of( sub {
       $result = $build->run_perl_script('Makefile.PL', $preargs, $postargs);
   });
   my $label = "Makefile.PL ran without error";
@@ -472,7 +495,8 @@ sub extract_writemakefile_args {
 }
 
 sub create_makefile_pl {
-    Module::Build::Compat->create_makefile_pl(@_);
+    my @args = @_;
+    stdout_stderr_of( sub { Module::Build::Compat->create_makefile_pl(@args) } );
     my $ok = ok -e 'Makefile.PL', "$_[0] Makefile.PL created";
 
     # Some really conservative make's, like HP/UX, assume files with the same
old mode 100644 (file)
new mode 100755 (executable)
index 78269a9..3672c93
@@ -3,10 +3,9 @@
 use strict;
 
 use lib 't/lib';
-use MBTest tests => 5;
+use MBTest tests => 3;
 
-use_ok 'Module::Build';
-ensure_blib('Module::Build');
+blib_load('Module::Build');
 
 #########################
 
@@ -24,11 +23,13 @@ $dist->chdir_in;
 
 my $mb; stdout_of(sub{ $mb = Module::Build->new_from_context});
 
-use Module::Build::Compat;
+blib_load('Module::Build::Compat');
 
 $dist->regen;
 
-Module::Build::Compat->create_makefile_pl('passthrough', $mb);
+stdout_stderr_of(
+  sub{ Module::Build::Compat->create_makefile_pl('passthrough', $mb); }
+);
 
 # as silly as all of this exit(0) business is, that is what the cpan
 # testers have instructed everybody to do so...
index c9b4fa5..e0b8f60 100644 (file)
@@ -2,18 +2,15 @@
 
 use strict;
 use lib 't/lib';
-use MBTest tests => 3;
+use MBTest tests => 1;
 
-require_ok('Module::Build');
-ensure_blib('Module::Build');
+blib_load('Module::Build');
 
 my $tmp = MBTest->tmpdir;
 
 use DistGen;
 my $dist = DistGen->new( dir => $tmp );
 $dist->regen;
-END{ $dist->remove }
-
 $dist->chdir_in;
 
 #########################
@@ -28,6 +25,3 @@ $dist->chdir_in;
   );
 }
 
-#########################
-
-# cleanup
index 4af99d0..07247a3 100644 (file)
@@ -2,10 +2,9 @@
 
 use strict;
 use lib 't/lib';
-use MBTest tests => 115;
+use MBTest tests => 113;
 
-use_ok 'Module::Build';
-ensure_blib('Module::Build');
+blib_load('Module::Build');
 
 my $tmp = MBTest->tmpdir;
 
@@ -248,7 +247,8 @@ $mb->prefix(undef);
     }
 
     # Poke at the innards of MB to change the default install locations.
-    my $old =  $mb->install_sets->{site} = \%test_config;
+    my $old =  $mb->install_sets->{site};
+    $mb->install_sets->{site} = \%test_config;
     $mb->config(siteprefixexp => catdir(File::Spec->rootdir, 
                                        'wierd', 'prefix'));
 
@@ -321,5 +321,3 @@ sub test_install_destinations {
     }
 }
 
-
-$dist->remove;
index 8045761..6101bcc 100644 (file)
@@ -4,8 +4,6 @@ use strict;
 use lib 't/lib';
 use MBTest;
 
-use Module::Build;
-
 my @unix_splits = 
   (
    { q{one t'wo th'ree f"o\"ur " "five" } => [ 'one', 'two three', 'fo"ur ', 'five' ] },
@@ -58,9 +56,11 @@ my @win_splits =
    { 'a " b " c'            => [ 'a', ' b ', 'c' ] },
 );
 
-plan tests => 10 + 4*@unix_splits + 4*@win_splits;
+plan tests => 9 + 4*@unix_splits + 4*@win_splits;
 
-ensure_blib('Module::Build');
+blib_load('Module::Build');
+blib_load('Module::Build::Platform::Unix');
+blib_load('Module::Build::Platform::Windows');
 
 #########################
 
@@ -74,7 +74,6 @@ foreach my $platform ('', '::Platform::Unix', '::Platform::Windows') {
 
 # I think 3.24 isn't actually the majik version, my 3.23 seems to pass...
 my $low_TPW_version = Text::ParseWords->VERSION < 3.24;
-use Module::Build::Platform::Unix;
 foreach my $test (@unix_splits) {
   # Text::ParseWords bug:
   local $TODO = $low_TPW_version && ((keys %$test)[0] =~ m{\\\n});
@@ -82,7 +81,6 @@ foreach my $test (@unix_splits) {
   do_split_tests('Module::Build::Platform::Unix', $test);
 }
 
-use Module::Build::Platform::Windows;
 foreach my $test (@win_splits) {
   do_split_tests('Module::Build::Platform::Windows', $test);
 }
index db99eec..36ff4b6 100644 (file)
@@ -2,10 +2,9 @@
 
 use strict;
 use lib 't/lib';
-use MBTest tests => 66;
+use MBTest tests => 64;
 
-use_ok 'Module::Build';
-ensure_blib('Module::Build');
+blib_load('Module::Build');
 
 my $tmp = MBTest->tmpdir;
 
@@ -79,7 +78,7 @@ print "Hello, World!\n";
 
   $mb->add_build_element('foo');
   $mb->add_build_element('foo');
-  is_deeply $mb->build_elements, [qw(PL support pm xs pod script foo)],
+  is_deeply $mb->build_elements, [qw(PL support pm xs share_dir pod script foo)],
       'The foo element should be in build_elements only once';
 
   $mb->dispatch('build');
@@ -187,21 +186,20 @@ print "Hello, World!\n";
                                  meta_add => {foo => 'bar'},
                                  conflicts => {'Foo::Barxx' => 0},
                                );
-  my %data;
-  $mb->prepare_metadata( \%data );
-  is $data{foo}, 'bar';
+  my $data = $mb->prepare_metadata;
+  is $data->{foo}, 'bar';
 
   $mb->meta_merge(foo => 'baz');
-  $mb->prepare_metadata( \%data );
-  is $data{foo}, 'baz';
+  $data = $mb->prepare_metadata;
+  is $data->{foo}, 'baz';
 
   $mb->meta_merge(conflicts => {'Foo::Fooxx' => 0});
-  $mb->prepare_metadata( \%data );
-  is_deeply $data{conflicts}, {'Foo::Barxx' => 0, 'Foo::Fooxx' => 0};
+  $data = $mb->prepare_metadata;
+  is_deeply $data->{conflicts}, {'Foo::Barxx' => 0, 'Foo::Fooxx' => 0};
 
   $mb->meta_add(conflicts => {'Foo::Bazxx' => 0});
-  $mb->prepare_metadata( \%data );
-  is_deeply $data{conflicts}, {'Foo::Bazxx' => 0, 'Foo::Fooxx' => 0};
+  $data = $mb->prepare_metadata;
+  is_deeply $data->{conflicts}, {'Foo::Bazxx' => 0, 'Foo::Fooxx' => 0};
 }
 
 {
@@ -275,5 +273,3 @@ print "Hello, World!\n";
 
 }
 
-# cleanup
-$dist->remove;
index 87b192e..cf822fb 100644 (file)
@@ -2,10 +2,9 @@
 
 use strict;
 use lib 't/lib';
-use MBTest tests => 6;
+use MBTest tests => 4;
 
-use_ok 'Module::Build';
-ensure_blib('Module::Build');
+blib_load('Module::Build');
 
 use IO::File;
 my $tmp = MBTest->tmpdir;
@@ -46,5 +45,3 @@ my $mb = Module::Build->new_from_context;
   ok( Module::Build->dir_contains($first, $second) );
 }
 
-# cleanup
-$dist->remove;
index 8408315..2bf34c8 100644 (file)
@@ -2,38 +2,23 @@
 
 use strict;
 use lib 't/lib';
-use MBTest tests => 25;
+use MBTest tests => 23;
 
-use_ok 'Module::Build';
-ensure_blib('Module::Build');
-
-use Cwd ();
-use File::Path ();
-
-my $cwd = Cwd::cwd();
-my $tmp = MBTest->tmpdir;
+blib_load('Module::Build');
 
 use DistGen;
 
-my $dist = DistGen->new(dir => $tmp);
-
-
+my $dist = DistGen->new;
 $dist->regen;
+$dist->chdir_in;
 
 my $restart = sub {
-  $dist->clean();
-  DistGen::chdir_all( $cwd );
-  File::Path::rmtree( $tmp );
   # we're redefining the same package as we go, so...
   delete($::{'MyModuleBuilder::'});
   delete($INC{'MyModuleBuilder.pm'});
-  $dist->regen;
-  chdir($dist->dirname) or
-    die "Can't chdir to '@{[$dist->dirname]}': $!";
+  $dist->regen( clean => 1 );
 };
 
-chdir($dist->dirname) or die "Can't chdir to '@{[$dist->dirname]}': $!";
-
 ########################################################################
 { # check the =item style
 my $mb = Module::Build->subclass(
@@ -274,7 +259,5 @@ is($mb->get_action_docs('batz'), undef, 'nothing after uplevel');
 
 # cleanup
 $dist->clean();
-DistGen::chdir_all($cwd);
-File::Path::rmtree( $tmp );
 
 # vim:ts=2:sw=2:et:sta
index 2cadaa3..66cdd5c 100644 (file)
@@ -2,10 +2,9 @@
 
 use strict;
 use lib 't/lib';
-use MBTest tests => 36;
+use MBTest tests => 34;
 
-use_ok 'Module::Build';
-ensure_blib('Module::Build');
+blib_load('Module::Build');
 
 use Config;
 use Cwd ();
@@ -225,10 +224,7 @@ Simple Man <simple@example.com>
   is keys %$pms, 0;
 
   # revert to pristine state
-  $dist->remove;
-  $dist = DistGen->new( dir => $tmp );
-  $dist->regen;
-  $dist->chdir_in;
+  $dist->regen( clean => 1 );
 }
 
 sub strip_volume {
@@ -243,6 +239,3 @@ sub file_exists {
   ok -e $file or diag("Expected $file to exist, but it doesn't");
 }
 
-
-# cleanup
-$dist->remove;
index c717ce5..21d0c27 100644 (file)
@@ -3,10 +3,9 @@
 
 use strict;
 use lib 't/lib';
-use MBTest tests => 8;
+use MBTest tests => 6;
 
-require_ok 'Module::Build';
-ensure_blib('Module::Build');
+blib_load('Module::Build');
 
 use File::Spec::Functions qw( catdir );
 
@@ -46,11 +45,11 @@ sub process_etc_files
 }
 
 #Copy share files to blib
-sub process_share_files
+sub process_shared_files
 {
        my $self = shift;
 
-       $self->copy_files("share");
+       $self->copy_files("shared");
 }
 
 1;
@@ -62,23 +61,23 @@ my $build = $subclass->new(
 );
 
 $build->add_build_element('etc');
-$build->add_build_element('share');
+$build->add_build_element('shared');
 
 my $distdir = lc $build->dist_name();
 
 foreach my $id ('core', 'site', 'vendor') {
        #Where to install these build types when using prefix symantics
-       $build->prefix_relpaths($id, 'share' => "share/$distdir");
+       $build->prefix_relpaths($id, 'shared' => "shared/$distdir");
        $build->prefix_relpaths($id, 'etc' => "etc/$distdir");
 
        #Where to install these build types when using default symantics
        my $set = $build->install_sets($id);
-       $set->{'share'} = '/usr/'.($id eq 'site' ? 'local/':'')."share/$distdir";
+       $set->{'shared'} = '/usr/'.($id eq 'site' ? 'local/':'')."shared/$distdir";
        $set->{'etc'} = ($id eq 'site' ? '/usr/local/etc/':'/etc/').$distdir;
 }
 
 #Where to install these types when using install_base symantics
-$build->install_base_relpaths('share' => "share/$distdir");
+$build->install_base_relpaths('shared' => "shared/$distdir");
 $build->install_base_relpaths('etc' => "etc/$distdir");
 
 $build->create_build_script();
@@ -97,12 +96,12 @@ stardate = 1234344
 
 ===EOF===
 
-$dist->add_file("share/data", <<'===EOF===');
+$dist->add_file("shared/data", <<'===EOF===');
 7 * 9 = 42?
 
 ===EOF===
 
-$dist->add_file("share/html/index.html", <<'===EOF===');
+$dist->add_file("shared/html/index.html", <<'===EOF===');
 <HTML>
   <BODY>
     <H1>Hello World!</H1>
@@ -122,16 +121,15 @@ $output .= stdout_of sub { $dist->run_build };
 
 my $error;
 $error++ unless ok(-e "blib/etc/config", "Built etc/config");
-$error++ unless ok(-e "blib/share/data", "Built share/data");
-$error++ unless ok(-e "blib/share/html/index.html", "Built share/html");
+$error++ unless ok(-e "blib/shared/data", "Built shared/data");
+$error++ unless ok(-e "blib/shared/html/index.html", "Built shared/html");
 diag "OUTPUT:\n$output" if $error;
 
 $output = stdout_of sub { $dist->run_build('install') };
 
 $error = 0;
 $error++ unless ok(-e "$installdest/etc/simple/config", "installed etc/config");
-$error++ unless ok(-e "$installdest/share/simple/data", "installed share/data");
-$error++ unless ok(-e "$installdest/share/simple/html/index.html", "installed share/html");
+$error++ unless ok(-e "$installdest/shared/simple/data", "installed shared/data");
+$error++ unless ok(-e "$installdest/shared/simple/html/index.html", "installed shared/html");
 diag "OUTPUT:\n$output" if $error;
 
-$dist->remove();
index 86ee794..d1fb260 100644 (file)
@@ -7,9 +7,9 @@ use vars qw( $VERSION $VERBOSE @EXPORT_OK);
 $VERSION = '0.01';
 $VERBOSE = 0;
 
-
 use Carp;
 
+use MBTest ();
 use Cwd ();
 use File::Basename ();
 use File::Find ();
@@ -38,7 +38,7 @@ BEGIN {
         $vms_efs_case = VMS::Feature::current("efs_case_preserve");
     } else {
         my $env_unix_rpt = $ENV{'DECC$FILENAME_UNIX_REPORT'} || '';
-        $unix_rpt = $env_unix_rpt =~ /^[ET1]/i; 
+        $unix_rpt = $env_unix_rpt =~ /^[ET1]/i;
         my $efs_case = $ENV{'DECC$EFS_CASE_PRESERVE'} || '';
         $vms_efs_case = $efs_case =~ /^[ET1]/i;
     }
@@ -64,44 +64,76 @@ sub undent {
 }
 
 sub chdir_all ($) {
-  # OS/2 has "current directory per disk", undeletable; 
+  # OS/2 has "current directory per disk", undeletable;
   # doing chdir() to another disk won't change cur-dir of initial disk...
   chdir('/') if $^O eq 'os2';
   chdir shift;
 }
+
 ########################################################################
 
+END { chdir_all(MBTest->original_cwd); }
+
 sub new {
-  my $package = shift;
+  my $self = bless {}, shift;
+  $self->reset(@_);
+}
+
+sub reset {
+  my $self = shift;
   my %options = @_;
 
   $options{name} ||= 'Simple';
-  $options{dir}  ||= Cwd::cwd();
+  $options{dir} = File::Spec->rel2abs(
+    defined $options{dir} ? $options{dir} : MBTest->tmpdir
+  );
 
   my %data = (
     no_manifest   => 0,
     xs            => 0,
+    inc           => 0,
     %options,
   );
-  my $self = bless( \%data, $package );
-
-  # So we can clean up later even if the caller chdir()s
-  $self->{dir} = File::Spec->rel2abs($self->{dir});
+  %$self = %data;
 
   tie %{$self->{filedata}}, 'Tie::CPHash';
 
   tie %{$self->{pending}{change}}, 'Tie::CPHash';
 
+  # start with a fresh, empty directory
   if ( -d $self->dirname ) {
     warn "Warning: Removing existing directory '@{[$self->dirname]}'\n";
-    $self->remove;
+    File::Path::rmtree( $self->dirname );
   }
+  File::Path::mkpath( $self->dirname );
 
   $self->_gen_default_filedata();
 
   return $self;
 }
 
+sub remove {
+  my $self = shift;
+  $self->chdir_original if($self->did_chdir);
+  File::Path::rmtree( $self->dirname );
+  return $self;
+}
+
+sub revert {
+  my ($self, $file) = @_;
+  if ( defined $file ) {
+    delete $self->{filedata}{$file};
+    delete $self->{pending}{$_}{$file} for qw/change remove/;
+  }
+  else {
+    delete $self->{filedata}{$_} for keys %{ $self->{filedata} };
+    for my $pend ( qw/change remove/ ) {
+      delete $self->{pending}{$pend}{$_} for keys %{ $self->{pending}{$pend} };
+    }
+  }
+  $self->_gen_default_filedata;
+}
+
 sub _gen_default_filedata {
   my $self = shift;
 
@@ -112,17 +144,32 @@ sub _gen_default_filedata {
     $self->add_file($member, $data) unless($self->{filedata}{$member});
   };
 
-  $self->$add_unless('Build.PL', undent(<<"    ---"));
-    use strict;
-    use Module::Build;
+  if ( ! $self->{inc} ) {
+    $self->$add_unless('Build.PL', undent(<<"      ---"));
+      use strict;
+      use Module::Build;
 
-    my \$builder = Module::Build->new(
-        module_name         => '$self->{name}',
-        license             => 'perl',
-    );
+      my \$builder = Module::Build->new(
+          module_name         => '$self->{name}',
+          license             => 'perl',
+      );
 
-    \$builder->create_build_script();
-    ---
+      \$builder->create_build_script();
+      ---
+  }
+  else {
+    $self->$add_unless('Build.PL', undent(<<"      ---"));
+      use strict;
+      use inc::latest 'Module::Build';
+
+      my \$builder = Module::Build->new(
+          module_name         => '$self->{name}',
+          license             => 'perl',
+      );
+
+      \$builder->create_build_script();
+      ---
+  }
 
   my $module_filename =
     join( '/', ('lib', split(/::/, $self->{name})) ) . '.pm';
@@ -229,7 +276,7 @@ sub _gen_default_filedata {
 
   # 5.6 is missing const char * in its typemap
   $self->$add_unless('typemap', undent(<<"      ---"));
-      const char *              T_PV
+      const char *\tT_PV
       ---
 
   $self->$add_unless('t/basic.t', undent(<<"    ---"));
@@ -249,7 +296,6 @@ sub _gen_manifest {
   my $manifest = shift;
 
   my $fh = IO::File->new( ">$manifest" ) or do {
-    $self->remove();
     die "Can't write '$manifest'\n";
   };
 
@@ -312,7 +358,6 @@ sub regen {
       my $dirname = File::Basename::dirname( $fullname );
       unless ( -d $dirname ) {
         File::Path::mkpath( $dirname ) or do {
-          $self->remove();
           die "Can't create '$dirname'\n";
         };
       }
@@ -322,7 +367,6 @@ sub regen {
       }
 
       my $fh = IO::File->new(">$fullname") or do {
-        $self->remove();
         die "Can't write '$fullname'\n";
       };
       print $fh $self->{filedata}{$file};
@@ -339,6 +383,7 @@ sub regen {
     }
     $self->_gen_manifest( $manifest );
   }
+  return $self;
 }
 
 sub clean {
@@ -396,20 +441,7 @@ sub clean {
   }, ($^O eq 'VMS' ? './' : File::Spec->curdir) );
 
   chdir_all( $here );
-}
-
-sub remove {
-  my $self = shift;
-  croak("invalid usage -- remove()") if(@_);
-  $self->chdir_original if($self->did_chdir);
-  File::Path::rmtree( $self->dirname );
-  # might as well check
-  croak("\nthis test should have used chdir_in()") unless(Cwd::getcwd);
-}
-
-sub revert {
-  my $self = shift;
-  die "Unimplemented.\n";
+  return $self;
 }
 
 sub add_file {
@@ -425,10 +457,13 @@ sub remove_file {
   }
   delete( $self->{filedata}{$file} );
   $self->{pending}{remove}{$file} = 1;
+  return $self;
 }
 
 sub change_build_pl {
-  my ($self, $opts) = @_;
+  my ($self, @opts) = @_;
+
+  my $opts = ref $opts[0] eq 'HASH' ? $opts[0] : { @opts };
 
   local $Data::Dumper::Terse = 1;
   (my $args = Dumper($opts)) =~ s/^\s*\{|\}\s*$//g;
@@ -437,16 +472,17 @@ sub change_build_pl {
     use strict;
     use Module::Build;
     my \$b = Module::Build->new(
-    # Some CPANPLUS::Dist::Build versions need to allow mismatches 
+    # Some CPANPLUS::Dist::Build versions need to allow mismatches
     # On logic: thanks to Module::Install, CPAN.pm must set both keys, but
     # CPANPLUS sets only the one
-    allow_mb_mismatch => ( 
+    allow_mb_mismatch => (
       \$ENV{PERL5_CPANPLUS_IS_RUNNING} && ! \$ENV{PERL5_CPAN_IS_RUNNING} ? 1 : 0
     ),
     $args
     );
     \$b->create_build_script();
     ---
+  return $self;
 }
 
 sub change_file {
@@ -455,6 +491,7 @@ sub change_file {
   my $data = shift;
   $self->{filedata}{$file} = $data;
   $self->{pending}{change}{$file} = 1;
+  return $self;
 }
 
 sub get_file {
@@ -466,40 +503,43 @@ sub get_file {
 
 sub chdir_in {
   my $self = shift;
-
-  $self->{original_dir} ||= Cwd::cwd; # only once
+  $self->{original_dir} ||= Cwd::cwd; # only once!
   my $dir = $self->dirname;
   chdir($dir) or die "Can't chdir to '$dir': $!";
+  return $self;
 }
 ########################################################################
 
-sub did_chdir {
-  my $self = shift;
+sub did_chdir { exists shift()->{original_dir} }
 
-  return exists($self->{original_dir});
-}
 ########################################################################
 
 sub chdir_original {
   my $self = shift;
 
-  croak("never called chdir_in()") unless($self->{original_dir});
-  my $dir = $self->{original_dir};
+  my $dir = delete $self->{original_dir};
   chdir_all($dir) or die "Can't chdir to '$dir': $!";
+  return $self;
 }
 ########################################################################
 
+sub new_from_context {
+  my ($self, @args) = @_;
+  require Module::Build;
+  return Module::Build->new_from_context( quiet => 1, @args );
+}
+
 sub run_build_pl {
   my ($self, @args) = @_;
   require Module::Build;
-  Module::Build->run_perl_script('Build.PL', [], [@args])
+  return Module::Build->run_perl_script('Build.PL', [], [@args])
 }
 
 sub run_build {
   my ($self, @args) = @_;
   require Module::Build;
   my $build_script = $^O eq 'VMS' ? 'Build.com' : 'Build';
-  Module::Build->run_perl_script($build_script, [], [@args])
+  return Module::Build->run_perl_script($build_script, [], [@args])
 }
 
 1;
@@ -516,8 +556,7 @@ DistGen - Creates simple distributions for testing.
   use DistGen;
 
   # create distribution and prepare to test
-  my $dist = DistGen->new(name => 'Foo::Bar', dir => $tmp);
-  $dist->regen;
+  my $dist = DistGen->new(name => 'Foo::Bar');
   $dist->chdir_in;
 
   # change distribution files
@@ -526,42 +565,48 @@ DistGen - Creates simple distributions for testing.
   $dist->remove_file('t/some_test.t');
   $dist->regen;
 
-  # clean up extraneous files
+  # undo changes and clean up extraneous files
+  $dist->revert;
   $dist->clean;
 
   # exercise the command-line interface
   $dist->run_build_pl();
   $dist->run_build('test');
 
-  # finish testing and clean up
-  $dist->chdir_original;
-  $dist->remove;
+  # start over as a new distribution
+  $dist->reset( name => 'Foo::Bar', xs => 1 );
+  $dist->chdir_in;
 
 =head1 USAGE
 
 A DistGen object manages a set of files in a distribution directory.
 
-The constructor and some methods only define the target state of the
-distribution.  They do B<not> make any changes to the filesystem:
+The C<new()> constructor initializes the object and creates an empty
+directory for the distribution. It does not create files or chdir into
+the directory.  The C<reset()> method re-initializes the object in a
+new directory with new parameters.  It also does not create files or change
+the current directory.
+
+Some methods only define the target state of the distribution.  They do B<not>
+make any changes to the filesystem:
 
-  new
   add_file
   change_file
   change_build_pl
   remove_file
+  revert
 
 Other methods then change the filesystem to match the target state of
-the distribution (or to remove it entirely):
+the distribution:
 
-  regen
   clean
+  regen
   remove
 
 Other methods are provided for a convenience during testing. The
-most important are ones that manage the current directory:
+most important is the one to enter the distribution directory:
 
   chdir_in
-  chdir_original
 
 Additional methods portably encapsulate running Build.PL and Build:
 
@@ -570,16 +615,19 @@ Additional methods portably encapsulate running Build.PL and Build:
 
 =head1 API
 
-=head2 Constructor
+=head2 Constructors
 
 =head3 new()
 
-Create a new object.  Does not write its contents (see L</regen()>.)
+Create a new object and an empty directory to hold the distribution's files.
+If no C<dir> option is provided, it defaults to MBTest->tmpdir, which sets
+a different temp directory for Perl core testing and CPAN testing.
+
+The C<new> method does not write any files -- see L</regen()> below.
 
-  my $tmp = MBTest->tmpdir;
   my $dist = DistGen->new(
     name        => 'Foo::Bar',
-    dir         => $tmp,
+    dir         => MBTest->tmpdir,
     xs          => 1,
     no_manifest => 0,
   );
@@ -596,9 +644,14 @@ dist name.
 
 =item dir
 
-The (parent) directory in which to create the distribution directory.
-The default is File::Spec->curdir.  The distribution will be created
-under this according to the "dist" form of C<name> (e.g. "Foo-Bar".)
+The (parent) directory in which to create the distribution directory.  The
+distribution will be created under this according to the "dist" form of C<name>
+(e.g. "Foo-Bar".)  Defaults to a temporary directory.
+
+  $dist = DistGen->new( dir => '/tmp/MB-test' );
+  $dist->regen;
+
+  # distribution files have been created in /tmp/MB-test/Simple
 
 =item xs
 
@@ -622,6 +675,13 @@ the following files are also added:
   typemap
   lib/Simple.xs # based on name parameter
 
+=head3 reset()
+
+The C<reset> method re-initializes the object as if it were generated
+from a fresh call to C<new>.  It takes the same optional parameters as C<new>.
+
+  $dist->reset( name => 'Foo::Bar', xs => 0 );
+
 =head2 Adding and editing files
 
 Note that C<$filename> should always be specified with unix-style paths,
@@ -669,6 +729,14 @@ Removes C<$filename> from the distribution.
 
   $dist->remove_file( $filename );
 
+=head3 revert()
+
+Returns the object to its initial state, or given a $filename it returns that
+file to its initial state if it is one of the built-in files.
+
+  $dist->revert;
+  $dist->revert($filename);
+
 =head2 Changing the distribution directory
 
 These methods immediately affect the filesystem.
@@ -680,8 +748,10 @@ flagged for removal with remove_file().
 
   $dist->regen(clean => 1);
 
-If the optional C<clean> argument is given, it also removes any
-extraneous files that do not belong to the distribution.
+If the optional C<clean> argument is given, it also calls C<clean>.  These
+can also be chained like this, instead:
+
+  $dist->clean->regen;
 
 =head3 clean()
 
@@ -689,22 +759,19 @@ Removes any files that are not part of the distribution.
 
   $dist->clean;
 
-=begin TODO
-
-=head3 revert()
-
-[Unimplemented] Returns the object to its initial state, or given a
-$filename it returns that file to it's initial state if it is one of
-the built-in files.
+=head3 remove()
 
-  $dist->revert;
-  $dist->revert($filename);
+Changes back to the original directory and removes the distribution
+directory (but not the temporary directory set during C<new()>).
 
-=end TODO
+  $dist = DistGen->new->chdir->regen;
+  # ... do some testing ...
 
-=head3 remove()
+  $dist->remove->chdir_in->regen;
+  # ... do more testing ...
 
-Removes the entire distribution directory.
+This is like a more aggressive form of C<clean>.  Generally, calling C<clean>
+and C<regen> should be sufficient.
 
 =head2 Changing directories
 
index dc2410b..8a5acd2 100644 (file)
@@ -13,6 +13,7 @@ BEGIN {
     my @delete_env_keys = qw(
         DEVEL_COVER_OPTIONS
         MODULEBUILDRC
+        PERL_MB_OPT
         HARNESS_TIMER
         HARNESS_OPTIONS
         HARNESS_VERBOSE
@@ -49,7 +50,15 @@ BEGIN {
 
   # In case the test wants to use our other bundled
   # modules, make sure they can be loaded.
-  push @INC, File::Spec->catdir('t', 'bundled');
+  my $t_lib = File::Spec->catdir('t', 'bundled');
+  push @INC, $t_lib; # Let user's installed version override
+
+  if ($ENV{PERL_CORE}) {
+    # We change directories, so expand @INC and $^X to absolute paths
+    # Also add .
+    @INC = (map(File::Spec->rel2abs($_), @INC), ".");
+    $^X = File::Spec->rel2abs($^X);
+  }
 }
 
 use Exporter;
@@ -74,7 +83,7 @@ my @extra_exports = qw(
   find_in_path
   check_compiler
   have_module
-  ensure_blib
+  blib_load
 );
 push @EXPORT, @extra_exports;
 __PACKAGE__->export(scalar caller, @extra_exports);
@@ -85,7 +94,9 @@ __PACKAGE__->export(scalar caller, @extra_exports);
 
 # always return to the current directory
 { 
-  my $cwd = Cwd::cwd;
+  my $cwd = File::Spec->rel2abs(Cwd::cwd);
+
+  sub original_cwd { return $cwd }
 
   END {
     # Go back to where you came from!
@@ -103,13 +114,11 @@ __PACKAGE__->export(scalar caller, @extra_exports);
 }
 ########################################################################
 
-# Setup a temp directory 
-sub tmpdir { 
-  my ($self, $usr_tmp) = @_;
-  return File::Temp::tempdir( 'MB-XXXXXXXX', 
-    CLEANUP => 1, DIR => $ENV{PERL_CORE} ? Cwd::cwd : 
-                         $usr_tmp        ? $usr_tmp : File::Spec->tmpdir 
-  );
+# Setup a temp directory
+sub tmpdir {
+  my ($self, @args) = @_;
+  my $dir = $ENV{PERL_CORE} ? MBTest->original_cwd : File::Spec->tmpdir;
+  return File::Temp::tempdir('MB-XXXXXXXX', CLEANUP => 1, DIR => $dir, @args);
 }
 
 sub save_handle {
@@ -137,7 +146,7 @@ sub stdout_stderr_of {
   $stdout = stdout_of ( sub {
       $stderr = stderr_of( $subr )
   });
-  return ($stdout, $stderr);
+  return wantarray ? ($stdout, $stderr) : $stdout . $stderr;
 }
 
 sub slurp {
@@ -160,13 +169,20 @@ sub exe_exts {
 
 sub find_in_path {
   my $thing = shift;
-  
-  my @path = split $Config{path_sep}, $ENV{PATH};
+
   my @exe_ext = exe_exts();
-  foreach (@path) {
-    my $fullpath = File::Spec->catfile($_, $thing);
+  if ( File::Spec->file_name_is_absolute( $thing ) ) {
     foreach my $ext ( '', @exe_ext ) {
-      return "$fullpath$ext" if -e "$fullpath$ext";
+      return "$thing$ext" if -e "$thing$ext";
+    }
+  }
+  else {
+    my @path = split $Config{path_sep}, $ENV{PATH};
+    foreach (@path) {
+      my $fullpath = File::Spec->catfile($_, $thing);
+      foreach my $ext ( '', @exe_ext ) {
+        return "$fullpath$ext" if -e "$fullpath$ext";
+      }
     }
   }
   return;
@@ -178,6 +194,7 @@ sub check_compiler {
 
   local $SIG{__WARN__} = sub {};
 
+  blib_load('Module::Build');
   my $mb = Module::Build->current;
   $mb->verbose( 0 );
 
@@ -202,21 +219,23 @@ sub check_compiler {
 
 sub have_module {
   my $module = shift;
-  return eval "use $module; 1";
+  return eval "require $module; 1";
 }
 
-sub ensure_blib {
-  # Make sure the given module was loaded from blib/, not the larger system
+sub blib_load {
+  # Load the given module and ensure it came from blib/, not the larger system
   my $mod = shift;
+  have_module($mod) or die "Error loading $mod\: $@\n";
+
   (my $path = $mod) =~ s{::}{/}g;
-  local $Test::Builder::Level = $Test::Builder::Level + 1; 
SKIP: {
-    skip "no blib in core", 1 if $ENV{PERL_CORE};
-    like $INC{"$path.pm"}, qr/\bblib\b/, "Make sure $mod was loaded from blib/"
-      or diag "PERL5LIB: " . ($ENV{PERL5LIB} || '') . "\n" .
-              "PERL5OPT: " . ($ENV{PERL5OPT} || '') . "\n" .
-              "\@INC contains:\n  " . join("\n  ", @INC) . "\n"; 
+  $path .= ".pm";
+  my ($pkg, $file, $line) = caller;
 unless($ENV{PERL_CORE}) {
+    unless($INC{$path} =~ m/\bblib\b/) {
+      (my $load_from = $INC{$path}) =~ s{$path$}{};
+      die "$mod loaded from '$load_from'\nIt should have been loaded from blib.  \@INC contains:\n  ",
+      join("\n  ", @INC) . "\nFatal error occured in blib_load() at $file, line $line.\n";
+    }
   }
 }
 
index 31c9e8e..5947646 100644 (file)
@@ -3,15 +3,14 @@
 use strict;
 use lib 't/lib';
 use MBTest;
-use Module::Build;
-use Module::Build::ConfigData;
+blib_load('Module::Build');
+blib_load('Module::Build::ConfigData');
 
 if ( Module::Build::ConfigData->feature('manpage_support') ) {
-  plan tests => 22;
+  plan tests => 21;
 } else {
   plan skip_all => 'manpage_support feature is not enabled';
 }
-ensure_blib('Module::Build');
 
 
 #########################
@@ -139,11 +138,7 @@ $mb->dispatch('realclean');
 
 
 # revert to a pristine state
-$dist->remove;
-$dist = DistGen->new( dir => $tmp );
-$dist->regen;
-$dist->chdir_in;
-
+$dist->regen( clean => 1 );
 
 my $mb2 = Module::Build->new(
   module_name => $dist->name,
@@ -163,6 +158,3 @@ foreach ('testcover', 'disttest') {
   unlike $docs, qr/\n=/, $docs;
 }
 
-
-# cleanup
-$dist->remove;
diff --git a/cpan/Module-Build/t/mbyaml.t b/cpan/Module-Build/t/mbyaml.t
deleted file mode 100644 (file)
index d2cb0d5..0000000
+++ /dev/null
@@ -1,262 +0,0 @@
-#!/usr/local/bin/perl -w
-
-use strict;
-use lib 't/lib';
-use MBTest 'no_plan';
-
-use_ok 'Module::Build::YAML';
-ensure_blib('Module::Build::YAML');
-
-my ($dir);
-$dir = ".";
-$dir = "t" if (-d "t");
-
-{
-    my ($expected, $got, $var);
-    ##########################################################
-    # Test a typical-looking Module::Build structure (alphabetized)
-    ##########################################################
-    $var = {
-          'resources' => {
-                           'license' => 'http://opensource.org/licenses/artistic-license.php'
-                         },
-          'meta-spec' => {
-                           'version' => '1.2',
-                           'url' => 'http://module-build.sourceforge.net/META-spec-v1.2.html'
-                         },
-          'generated_by' => 'Module::Build version 0.2709',
-          'version' => '0.13',
-          'name' => 'js-app',
-          'dynamic_config' => '1',
-          'author' => [
-                        '"Stephen Adkins" <spadkins@gmail.com>'
-                      ],
-          'license' => 'lgpl',
-          'build_requires' => {
-                                'App::Build' => '0',
-                                'File::Spec' => '0',
-                                'Module::Build' => '0'
-                              },
-          'provides' => {
-                          'JavaScript::App' => {
-                                                 'version' => '0',
-                                                 'file' => 'lib/JavaScript/App.pm'
-                                               }
-                        },
-          'requires' => {
-                          'App::Options' => '0'
-                        },
-          'abstract' => 'A framework for building dynamic widgets or full applications in Javascript'
-        };
-    $expected = <<'EOF';
----
-abstract: A framework for building dynamic widgets or full applications in Javascript
-author:
-  - '"Stephen Adkins" <spadkins@gmail.com>'
-build_requires:
-  App::Build: 0
-  File::Spec: 0
-  Module::Build: 0
-dynamic_config: 1
-generated_by: Module::Build version 0.2709
-license: lgpl
-meta-spec:
-  url: http://module-build.sourceforge.net/META-spec-v1.2.html
-  version: 1.2
-name: js-app
-provides:
-  JavaScript::App:
-    file: lib/JavaScript/App.pm
-    version: 0
-requires:
-  App::Options: 0
-resources:
-  license: http://opensource.org/licenses/artistic-license.php
-version: 0.13
-EOF
-    $got = &Module::Build::YAML::Dump($var);
-    is($got, $expected, "Dump(): single deep hash");
-
-    ##########################################################
-    # Test a typical-looking Module::Build structure (ordered)
-    ##########################################################
-    $expected = <<'EOF';
----
-name: js-app
-version: 0.13
-author:
-  - '"Stephen Adkins" <spadkins@gmail.com>'
-abstract: A framework for building dynamic widgets or full applications in Javascript
-license: lgpl
-resources:
-  license: http://opensource.org/licenses/artistic-license.php
-requires:
-  App::Options: 0
-build_requires:
-  App::Build: 0
-  File::Spec: 0
-  Module::Build: 0
-dynamic_config: 1
-provides:
-  JavaScript::App:
-    file: lib/JavaScript/App.pm
-    version: 0
-generated_by: Module::Build version 0.2709
-meta-spec:
-  url: http://module-build.sourceforge.net/META-spec-v1.2.html
-  version: 1.2
-EOF
-    $var->{_order} = [qw(name version author abstract license resources requires build_requires dynamic_config provides)];
-    $got = &Module::Build::YAML::Dump($var);
-    is($got, $expected, "Dump(): single deep hash, ordered");
-
-    ##########################################################
-    # Test that an array turns into multiple documents
-    ##########################################################
-    $var = [
-        "e",
-        2.71828,
-        [ "pi", "is", 3.1416 ],
-        { fun => "under_sun", 6 => undef, "more", undef },
-    ];
-    $expected = <<'EOF';
----
-e
----
-2.71828
----
-- pi
-- is
-- 3.1416
----
-6: ~
-fun: under_sun
-more: ~
-EOF
-    $got = &Module::Build::YAML::Dump(@$var);
-    is($got, $expected, "Dump(): multiple, various");
-
-    ##########################################################
-    # Test that a single array ref turns into one document
-    ##########################################################
-    $expected = <<'EOF';
----
-- e
-- 2.71828
--
-  - pi
-  - is
-  - 3.1416
--
-  6: ~
-  fun: under_sun
-  more: ~
-EOF
-    $got = &Module::Build::YAML::Dump($var);
-    is($got, $expected, "Dump(): single array of various");
-
-    ##########################################################
-    # Test Object-Oriented Flavor of the API
-    ##########################################################
-    my $y = Module::Build::YAML->new();
-    $got = $y->Dump($var);
-    is($got, $expected, "Dump(): single array of various (OO)");
-
-    ##########################################################
-    # Test Quoting Conditions (newlines, quotes, tildas, undefs)
-    ##########################################################
-    $var = {
-        'foo01' => '`~!@#$%^&*()_+-={}|[]\\;\':",./?<>
-<nl>',
-        'foo02' => '~!@#$%^&*()_+-={}|[]\\;:,./<>?',
-        'foo03' => undef,
-        'foo04' => '~',
-    };
-    $expected = <<'EOF';
----
-foo01: "`~!@#$%^&*()_+-={}|[]\;':\",./?<>\n<nl>"
-foo02: "~!@#$%^&*()_+-={}|[]\;:,./<>?"
-foo03: ~
-foo04: "~"
-EOF
-    $got = &Module::Build::YAML::Dump($var);
-    is($got, $expected, "Dump(): tricky embedded characters");
-
-    $var = {
-        'foo10' => undef,
-        'foo40' => '!',
-        'foo41' => '@',
-        'foo42' => '#',
-        'foo43' => '$',
-        'foo44' => '%',
-        'foo45' => '^',
-        'foo47' => '&',
-        'foo48' => '*',
-        'foo49' => '(',
-        'foo50' => ')',
-        'foo51' => '_',
-        'foo52' => '+',
-        'foo53' => '-',
-        'foo54' => '=',
-        'foo55' => '{',
-        'foo56' => '}',
-        'foo57' => '|',
-        'foo58' => '[',
-        'foo59' => ']',
-        'foo60' => '\\',
-        'foo61' => ';',
-        'foo62' => ':',
-        'foo63' => ',',
-        'foo64' => '.',
-        'foo65' => '/',
-        'foo66' => '<',
-        'foo67' => '>',
-        'foo68' => '?',
-        'foo69' => '\'',
-        'foo70' => '"',
-        'foo71' => '`',
-        'foo72' => '
-',
-    };
-    $expected = <<'EOF';
----
-foo10: ~
-foo40: "!"
-foo41: '@'
-foo42: "#"
-foo43: $
-foo44: %
-foo45: "^"
-foo47: "&"
-foo48: "*"
-foo49: "("
-foo50: ")"
-foo51: _
-foo52: +
-foo53: -
-foo54: =
-foo55: "{"
-foo56: "}"
-foo57: "|"
-foo58: "["
-foo59: "]"
-foo60: \
-foo61: ;
-foo62: :
-foo63: ,
-foo64: .
-foo65: /
-foo66: '<'
-foo67: '>'
-foo68: "?"
-foo69: "'"
-foo70: '"'
-foo71: "`"
-foo72: "\n"
-EOF
-    $got = &Module::Build::YAML::Dump($var);
-    is($got, $expected, "Dump(): tricky embedded characters (singles)");
-
-}
-
-
index 6f53c1d..2850bea 100644 (file)
@@ -2,15 +2,13 @@
 
 use strict;
 use lib 't/lib';
-use MBTest tests => 53;
+use MBTest tests => 51;
 
-use_ok 'Module::Build';
-ensure_blib('Module::Build');
+blib_load('Module::Build');
+blib_load('Module::Build::ConfigData');
 
 my $tmp = MBTest->tmpdir;
 
-use Module::Build::ConfigData;
-
 my %metadata = 
   (
    module_name   => 'Simple',
@@ -56,7 +54,6 @@ my $simple2_file = 'lib/Simple2.pm';
 
 $dist->chdir_in;
 
-use Module::Build;
 my $mb = Module::Build->new_from_context;
 
 ##################################################
@@ -68,7 +65,7 @@ my $mb = Module::Build->new_from_context;
   my $mb_config_req = { 
     'Module::Build' => int($Module::Build::VERSION * 100)/100 
   };
-  my $node = $mb->prepare_metadata( {} );
+  my $node = $mb->prepare_metadata( );
 
   # exists() doesn't seem to work here
   is $node->{name}, $metadata{module_name};
@@ -89,7 +86,7 @@ my $mb = Module::Build->new_from_context;
 {
   my $mb_prereq = { 'Module::Build' => 0 };
   $mb->configure_requires( $mb_prereq );
-  my $node = $mb->prepare_metadata( {} );
+  my $node = $mb->prepare_metadata( );
 
 
   # exists() doesn't seem to work here
@@ -366,7 +363,7 @@ package Simple;
 $VERSION = '2.34';
 ---
 $dist->regen( clean => 1 );
-$mb = new_build();
+stderr_of( sub { $mb = new_build(); } );
 $err = stderr_of( sub { $provides = $mb->find_dist_packages } );
 is_deeply($provides,
          {'Simple' => { file => $simple_file,
@@ -470,7 +467,7 @@ package Foo;
 $VERSION = '2.34';
 ---
 $dist->regen( clean => 1 );
-$mb = new_build();
+stderr_of( sub { $mb = new_build(); } );
 $err = stderr_of( sub { $provides = $mb->find_dist_packages } );
 # XXX Should 'Foo' exist ??? Can't predict values for file & version
 ok( exists( $provides->{Foo} ) );
@@ -604,6 +601,3 @@ $dist->regen( clean => 1 );
 $mb = new_build();
 is_deeply($mb->find_dist_packages, {});
 
-############################################################
-# cleanup
-$dist->remove;
index a5af034..954b658 100644 (file)
@@ -2,14 +2,11 @@
 
 use strict;
 use lib 't/lib';
-use MBTest tests => 20;
+use MBTest tests => 18;
 
-use_ok 'Module::Build';
-ensure_blib('Module::Build');
+blib_load('Module::Build');
+blib_load('Module::Build::ConfigData');
 
-my $tmp = MBTest->tmpdir;
-
-use Module::Build::ConfigData;
 use DistGen;
 
 
@@ -19,14 +16,12 @@ SKIP: {
   skip( 'YAML_support feature is not enabled', 4 )
       unless Module::Build::ConfigData->feature('YAML_support');
 
-  my $dist = DistGen->new( dir => $tmp, no_manifest => 1 );
-  $dist->regen;
-
-  $dist->chdir_in;
+  my $dist = DistGen->new( no_manifest => 1 )->chdir_in->regen;
 
   ok ! -e 'MANIFEST';
 
-  my $mb = Module::Build->new_from_context;
+  my $mb;
+  stderr_of( sub { $mb = Module::Build->new_from_context } );
 
   my $out;
   $out = eval { stderr_of(sub{$mb->dispatch('distmeta')}) };
@@ -36,7 +31,6 @@ SKIP: {
 
   ok -e 'META.yml';
 
-  $dist->remove;
 }
 
 
@@ -62,7 +56,7 @@ Simple Simon <simon@simple.sim>
 =cut
 ---
 
-my $dist = DistGen->new( dir => $tmp );
+my $dist = DistGen->new->chdir_in;
 
 $dist->change_build_pl
 ({
@@ -71,10 +65,6 @@ $dist->change_build_pl
     license             => 'perl',
     create_readme       => 1,
 });
-$dist->regen;
-
-$dist->chdir_in;
-
 
 # .pm File with pod
 #
@@ -139,7 +129,3 @@ is( $mb->dist_author->[0], 'Simple Simon <simon@simple.sim>',
 is( $mb->dist_abstract, "A simple module",
     "Extracting abstract from .pod over .pm");
 
-
-############################################################
-# cleanup
-$dist->remove;
index ca7eb04..e28726d 100644 (file)
@@ -4,99 +4,58 @@
 
 use strict;
 use lib 't/lib';
-use MBTest tests => 82;
-
-use_ok 'Module::Build::ModuleInfo';
-ensure_blib('Module::Build::ModuleInfo');
-
-my $tmp = MBTest->tmpdir;
-
-use DistGen;
-my $dist = DistGen->new( dir => $tmp );
-$dist->regen;
-
-$dist->chdir_in;
-
-#########################
-
-# class method C<find_module_by_name>
-my $module = Module::Build::ModuleInfo->find_module_by_name(
-               'Module::Build::ModuleInfo' );
-ok( -e $module, 'find_module_by_name() succeeds' );
-
-
-# fail on invalid module name
-my $pm_info = Module::Build::ModuleInfo->new_from_module(
-               'Foo::Bar', inc => [] );
-ok( !defined( $pm_info ), 'fail if can\'t find module by module name' );
-
-
-# fail on invalid filename
-my $file = File::Spec->catfile( 'Foo', 'Bar.pm' );
-$pm_info = Module::Build::ModuleInfo->new_from_file( $file, inc => [] );
-ok( !defined( $pm_info ), 'fail if can\'t find module by file name' );
-
-
-# construct from module filename
-$file = File::Spec->catfile( 'lib', split( /::/, $dist->name ) ) . '.pm';
-$pm_info = Module::Build::ModuleInfo->new_from_file( $file );
-ok( defined( $pm_info ), 'new_from_file() succeeds' );
-
-