develooper Front page | perl.perl5.porters | Postings from January 2009

[PATCH] Update Module::Build from trunk (rev 12308)

From:
David Golden
Date:
January 7, 2009 08:04
Subject:
[PATCH] Update Module::Build from trunk (rev 12308)
Message ID:
1231344354-24704-1-git-send-email-dagolden@cpan.org
My third attempt, merges M::B upstream repo (now with blead backports)
and also avoids unrelated MANIFEST sorting

Changes since 0.30:

 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.  THIS ALSO STILL NEEDS DOCS.
 - Added lgpl2/lgpl3 entries to the supported licenses (RT#40532).
 - Support for validating properties with a check subref. [David
   Wheeler]

 Bug Fixes
 - make Software::License dependency "softer".
 - 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]

 Test Fixes
 - Defend against more stray environment variables interfering
   with the tests.

 Deprecations
 - Use of attributes as class methods is deprecated (this was never a
   documented feature and appears to only have worked accidentally.)

 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]

 Other
 - Updated our embedded version.pm to 0.76, enhanced documentation on
   dist_version_from.  [John Peacock]
 - Added 'haiku' as a Unix-type OS
---
 MANIFEST                                 |    5 +
 installperl                              |    2 +-
 lib/Module/Build.pm                      |    2 +-
 lib/Module/Build/API.pod                 |   99 ++++++++-
 lib/Module/Build/Base.pm                 |  364 +++++++++++++++++++++---------
 lib/Module/Build/Compat.pm               |    4 +-
 lib/Module/Build/Config.pm               |    2 +-
 lib/Module/Build/Cookbook.pm             |   84 +++++++-
 lib/Module/Build/Dumper.pm               |    2 +-
 lib/Module/Build/ModuleInfo.pm           |    2 +-
 lib/Module/Build/Notes.pm                |    2 +-
 lib/Module/Build/PPMMaker.pm             |    2 +-
 lib/Module/Build/Platform/Amiga.pm       |    2 +-
 lib/Module/Build/Platform/Default.pm     |    2 +-
 lib/Module/Build/Platform/EBCDIC.pm      |    2 +-
 lib/Module/Build/Platform/MPEiX.pm       |    2 +-
 lib/Module/Build/Platform/MacOS.pm       |    2 +-
 lib/Module/Build/Platform/RiscOS.pm      |    2 +-
 lib/Module/Build/Platform/Unix.pm        |    4 +-
 lib/Module/Build/Platform/VMS.pm         |    2 +-
 lib/Module/Build/Platform/VOS.pm         |    2 +-
 lib/Module/Build/Platform/Windows.pm     |    2 +-
 lib/Module/Build/Platform/aix.pm         |    2 +-
 lib/Module/Build/Platform/cygwin.pm      |    2 +-
 lib/Module/Build/Platform/darwin.pm      |    2 +-
 lib/Module/Build/Platform/os2.pm         |    2 +-
 lib/Module/Build/PodParser.pm            |    2 +-
 lib/Module/Build/Version.pm              |   11 +-
 lib/Module/Build/scripts/bundle.pl       |   53 +++++
 lib/Module/Build/t/add_property.t        |   93 ++++++++
 lib/Module/Build/t/bundled/Tie/CPHash.pm |    2 +-
 lib/Module/Build/t/compat.t              |   74 ++++--
 lib/Module/Build/t/ext.t                 |    8 +-
 lib/Module/Build/t/lib/MBTest.pm         |   46 ++++-
 lib/Module/Build/t/par.t                 |   84 +++++++
 lib/Module/Build/t/ppm.t                 |    2 -
 lib/Module/Build/t/signature.t           |  103 +++++++++
 lib/Module/Build/t/test_type.t           |    7 -
 lib/Module/Build/t/tilde.t               |    9 +-
 lib/Module/Build/t/xs.t                  |    2 -
 utils.lst                                |    1 +
 utils/Makefile.SH                        |    8 +-
 utils/bundle.pl.PL                       |   51 ++++
 win32/Makefile                           |    3 +-
 win32/makefile.mk                        |    3 +-
 45 files changed, 969 insertions(+), 193 deletions(-)
 mode change 100644 => 100755 MANIFEST
 create mode 100755 lib/Module/Build/scripts/bundle.pl
 create mode 100644 lib/Module/Build/t/add_property.t
 create mode 100644 lib/Module/Build/t/par.t
 create mode 100644 lib/Module/Build/t/signature.t
 create mode 100644 utils/bundle.pl.PL

diff --git a/MANIFEST b/MANIFEST
old mode 100644
new mode 100755
index 075532c..425fd92
--- a/MANIFEST
+++ b/MANIFEST
@@ -2406,7 +2406,9 @@ lib/Module/Build/Platform/Windows.pm	Module::Build
 lib/Module/Build.pm		Module::Build
 lib/Module/Build/PodParser.pm	Module::Build
 lib/Module/Build/PPMMaker.pm	Module::Build
+lib/Module/Build/scripts/bundle.pl	the bundle.pl utility
 lib/Module/Build/scripts/config_data	Module::Build
+lib/Module/Build/t/add_property.t	Module::Build tests
 lib/Module/Build/t/basic.t	Module::Build
 lib/Module/Build/t/bundled/Tie/CPHash.pm	Module::Build.pm
 lib/Module/Build/t/compat.t	Module::Build
@@ -2426,10 +2428,12 @@ lib/Module/Build/t/moduleinfo.t	Module::Build
 lib/Module/Build/t/new_from_context.t	Module::Build
 lib/Module/Build/t/notes.t	Module::Build
 lib/Module/Build/t/parents.t	Module::Build
+lib/Module/Build/t/par.t	Module::Build tests
 lib/Module/Build/t/pod_parser.t	Module::Build
 lib/Module/Build/t/ppm.t	Module::Build
 lib/Module/Build/t/runthrough.t	Module::Build
 lib/Module/Build/t/script_dist.t	Module::Build
+lib/Module/Build/t/signature.t	Module::Build tests
 lib/Module/Build/t/test_file_exts.t	Module::Build
 lib/Module/Build/t/test_types.t	Module::Build
 lib/Module/Build/t/test_type.t	Module::Build
@@ -4253,6 +4257,7 @@ utf8.h				Unicode header
 utfebcdic.h			Unicode on EBCDIC (UTF-EBCDIC, tr16) header
 util.c				Utility routines
 util.h				Dummy header
+utils/bundle.pl.PL	the bundle.pl utility
 utils/c2ph.PL			program to translate dbx stabs to perl
 utils/config_data.PL		Module::Build tool
 utils/corelist.PL		Module::CoreList
diff --git a/installperl b/installperl
index d8d36be..b219b2f 100755
--- a/installperl
+++ b/installperl
@@ -728,7 +728,7 @@ sub installlib {
     # the corelist script from lib/Module/CoreList/bin and ptar* in
     # lib/Archive/Tar/bin, the config_data script in lib/Module/Build/scripts
     # (they're installed later with other utils)
-    return if $name =~ /^(?:cpan|instmodsh|prove|corelist|ptar|cpan2dist|cpanp|cpanp-run-perl|ptardiff|config_data)\z/;
+    return if $name =~ /^(?:cpan|instmodsh|prove|corelist|ptar|cpan2dist|cpanp|cpanp-run-perl|bundle.pl|ptardiff|config_data)\z/;
     # ignore the Makefiles
     return if $name =~ /^makefile$/i;
     # ignore the test extensions
diff --git a/lib/Module/Build.pm b/lib/Module/Build.pm
index 4bba600..7b6d4a6 100644
--- a/lib/Module/Build.pm
+++ b/lib/Module/Build.pm
@@ -15,7 +15,7 @@ use Module::Build::Base;
 
 use vars qw($VERSION @ISA);
 @ISA = qw(Module::Build::Base);
-$VERSION = '0.30_01';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 
 # Okay, this is the brute-force method of finding out what kind of
diff --git a/lib/Module/Build/API.pod b/lib/Module/Build/API.pod
index 6c5e24c..dee3de5 100644
--- a/lib/Module/Build/API.pod
+++ b/lib/Module/Build/API.pod
@@ -211,12 +211,12 @@ generated F<README>.
 
 [version 0.20]
 
-This should be a short description of the distribution.  This is used
-when generating metadata for F<META.yml> and PPD files.  If it is not
-given then C<Module::Build> looks in the POD of the module from which
-it gets the distribution's version.  It looks for the first line
-matching C<$package\s-\s(.+)>, and uses the captured text as the
-abstract.
+This should be a short description of the distribution.  This is used when
+generating metadata for F<META.yml> and PPD files.  If it is not given
+then C<Module::Build> looks in the POD of the module from which it gets
+the distribution's version.  If it finds a POD section marked "=head1
+NAME", then it looks for the first line matching C<\s+-\s+(.+)>,
+and uses the captured text as the abstract.
 
 =item dist_author
 
@@ -268,6 +268,10 @@ variable.  Quite ugly, really, but all the modules on CPAN depend on
 this process, so there's no real opportunity to change to something
 better.
 
+If the target file of L</dist_version_from> contains more than one package
+declaration, the version returned will be the one matching the configured
+L</module_name>.
+
 =item dynamic_config
 
 [version 0.07]
@@ -791,6 +795,86 @@ C<class> parameter indicates the name to use for the new subclass, and
 defaults to C<MyModuleBuilder>.  The C<code> parameter specifies Perl
 code to use as the body of the subclass.
 
+=item add_property
+
+[version 0.31]
+
+  package 'My::Build';
+  use base 'Module::Build';
+  __PACKAGE__->add_property( 'pedantic' );
+  __PACKAGE__->add_property( answer => 42 );
+  __PACKAGE__->add_property(
+     'epoch',
+      default => sub { time },
+      check   => sub {
+          return 1 if /^\d+$/;
+          shift->property_error( "'$_' is not an epoch time" );
+          return 0;
+      },
+  );
+
+Adds a property to a Module::Build class. Properties are those attributes of a
+Module::Build object which can be passed to the constructor and which have
+accessors to get and set them. All of the core properties, such as
+C<module_name> and C<license>, are defined using this class method.
+
+The first argument to C<add_property()> is always the name of the property.
+The second argument can be either a default value for the property, or a list
+of key/value pairs. The supported keys are:
+
+=over
+
+=item C<default>
+
+The default value. May optionally be specified as a code reference, in which
+case the return value from the execution of the code reference will be used.
+If you need the default to be a code reference, just use a code reference to
+return it, e.g.:
+
+      default => sub { sub { ... } },
+
+=item C<check>
+
+A code reference that checks that a value specified for the property is valid.
+During the execution of the code reference, the new value will be included in
+the C<$_> variable. If the value is correct, the C<check> code reference
+should return true. If the value is not correct, it sends an error message to
+C<property_error()> and returns false.
+
+=back
+
+When this method is called, a new property will be installed in the
+Module::Build class, and an accessor will be built to allow the property to be
+get or set on the build object.
+
+  print $build->pedantic, $/;
+  $build->pedantic(0);
+
+If the default value is a hash reference, this generetes a special-case
+accessor method, wherein individual key/value pairs may be set or fetched:
+
+  print "stuff{foo} is: ", $build->stuff( 'foo' ), $/;
+  $build->stuff( foo => 'bar' );
+  print $build->stuff( 'foo' ), $/; # Outputs "bar"
+
+Of course, you can still set the entire hash reference at once, as well:
+
+  $build->stuff( { foo => 'bar', baz => 'yo' } );
+
+In either case, if a C<check> has been specified for the property, it will be
+applied to the entire hash. So the check code reference should look something
+like:
+
+      check => sub {
+            return 1 if defined $_ && exists $_->{foo};
+            shift->property_error(qq{Property "stuff" needs "foo"});
+            return 0;
+      },
+
+=item property_error
+
+[version 0.31]
+
 =back
 
 
@@ -883,7 +967,6 @@ Returns the internal ExtUtils::CBuilder object that can be used for
 compiling & linking C code.  If no such object is available (e.g. if
 the system has no compiler installed) an exception will be thrown.
 
-
 =item check_installed_status($module, $version)
 
 [version 0.11]
@@ -1648,6 +1731,8 @@ accessor methods for the following properties:
 
 =item conflicts()
 
+=item create_license()
+
 =item create_makefile_pl()
 
 =item create_packlist()
diff --git a/lib/Module/Build/Base.pm b/lib/Module/Build/Base.pm
index d844e4f..9403a71 100644
--- a/lib/Module/Build/Base.pm
+++ b/lib/Module/Build/Base.pm
@@ -4,7 +4,7 @@ package Module::Build::Base;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 BEGIN { require 5.00503 }
 
@@ -177,8 +177,14 @@ sub _construct {
 
 ################## End constructors #########################
 
-sub log_info { print @_ unless shift()->quiet }
-sub log_verbose { shift()->log_info(@_) if $_[0]->verbose }
+sub log_info {
+  my $self = shift;
+  print @_ unless(ref($self) and $self->quiet);
+}
+sub log_verbose {
+  my $self = shift;
+  $self->log_info(@_) if(ref($self) and $self->verbose);
+}
 sub log_warn {
   # Try to make our call stack invisible
   shift;
@@ -644,125 +650,172 @@ sub ACTION_config_data {
       );
 }
 
-{
-    my %valid_properties = ( __PACKAGE__,  {} );
-    my %additive_properties;
+########################################################################
+{ # enclosing these lexicals -- TODO 
+  my %valid_properties = ( __PACKAGE__,  {} );
+  my %additive_properties;
 
-    sub _mb_classes {
-      my $class = ref($_[0]) || $_[0];
-      return ($class, $class->mb_parents);
-    }
+  sub _mb_classes {
+    my $class = ref($_[0]) || $_[0];
+    return ($class, $class->mb_parents);
+  }
+
+  sub valid_property {
+    my ($class, $prop) = @_;
+    return grep exists( $valid_properties{$_}{$prop} ), $class->_mb_classes;
+  }
+
+  sub valid_properties {
+    return keys %{ shift->valid_properties_defaults() };
+  }
 
-    sub valid_property {
-      my ($class, $prop) = @_;
-      return grep exists( $valid_properties{$_}{$prop} ), $class->_mb_classes;
+  sub valid_properties_defaults {
+    my %out;
+    for (reverse shift->_mb_classes) {
+      @out{ keys %{ $valid_properties{$_} } } = map {
+        $_->()
+      } values %{ $valid_properties{$_} };
     }
+    return \%out;
+  }
 
-    sub valid_properties {
-      return keys %{ shift->valid_properties_defaults() };
+  sub array_properties {
+    for (shift->_mb_classes) {
+      return @{$additive_properties{$_}->{ARRAY}}
+        if exists $additive_properties{$_}->{ARRAY};
     }
+  }
 
-    sub valid_properties_defaults {
-      my %out;
-      for (reverse shift->_mb_classes) {
-	@out{ keys %{ $valid_properties{$_} } } = values %{ $valid_properties{$_} };
-      }
-      return \%out;
+  sub hash_properties {
+    for (shift->_mb_classes) {
+      return @{$additive_properties{$_}->{'HASH'}}
+        if exists $additive_properties{$_}->{'HASH'};
     }
+  }
 
-    sub array_properties {
-      for (shift->_mb_classes) {
-        return @{$additive_properties{$_}->{ARRAY}}
-	  if exists $additive_properties{$_}->{ARRAY};
-      }
+  sub add_property {
+    my ($class, $property) = (shift, shift);
+    die "Property '$property' already exists"
+      if $class->valid_property($property);
+    my %p = @_ == 1 ? ( default => shift ) : @_;
+
+    my $type = ref $p{default};
+    $valid_properties{$class}{$property} = $type eq 'CODE'
+      ? $p{default}
+      : sub { $p{default} };
+
+    push @{$additive_properties{$class}->{$type}}, $property
+      if $type;
+
+    unless ($class->can($property)) {
+      # TODO probably should put these in a util package
+      my $sub = $type eq 'HASH'
+        ? _make_hash_accessor($property, \%p)
+        : _make_accessor($property, \%p);
+      no strict 'refs';
+      *{"$class\::$property"} = $sub;
     }
 
-    sub hash_properties {
-      for (shift->_mb_classes) {
-        return @{$additive_properties{$_}->{'HASH'}}
-	  if exists $additive_properties{$_}->{'HASH'};
-      }
+    return $class;
+  }
+
+    sub property_error {
+      my $self = shift;
+      die 'ERROR: ', @_;
     }
 
-    sub add_property {
-      my ($class, $property, $default) = @_;
-      die "Property '$property' already exists" if $class->valid_property($property);
+  sub _set_defaults {
+    my $self = shift;
 
-      $valid_properties{$class}{$property} = $default;
+    # Set the build class.
+    $self->{properties}{build_class} ||= ref $self;
 
-      my $type = ref $default;
-      if ($type) {
-	push @{$additive_properties{$class}->{$type}}, $property;
-      }
+    # If there was no orig_dir, set to the same as base_dir
+    $self->{properties}{orig_dir} ||= $self->{properties}{base_dir};
 
-      unless ($class->can($property)) {
-        no strict 'refs';
-	if ( $type eq 'HASH' ) {
-          *{"$class\::$property"} = sub {
-            # XXX this needs 'use strict' again
-	    my $self = shift;
-	    my $x = $self->{properties};
-	    return $x->{$property} unless @_;
-
-	    if ( defined($_[0]) && !ref($_[0]) ) {
-	      if ( @_ == 1 ) {
-		return exists( $x->{$property}{$_[0]} ) ?
-		         $x->{$property}{$_[0]} : undef;
-              } elsif ( @_ % 2 == 0 ) {
-	        my %args = @_;
-	        while ( my($k, $v) = each %args ) {
-	          $x->{$property}{$k} = $v;
-	        }
-	      } else {
-		die "Unexpected arguments for property '$property'\n";
-	      }
-	    } else {
-	      $x->{$property} = $_[0];
-	    }
-	  };
-
-        } else {
-          *{"$class\::$property"} = sub {
-            # XXX this needs 'use strict' again
-	    my $self = shift;
-	    $self->{properties}{$property} = shift if @_;
-	    return $self->{properties}{$property};
-	  }
-        }
+    my $defaults = $self->valid_properties_defaults;
 
-      }
-      return $class;
+    foreach my $prop (keys %$defaults) {
+      $self->{properties}{$prop} = $defaults->{$prop}
+        unless exists $self->{properties}{$prop};
     }
 
-    sub _set_defaults {
-      my $self = shift;
+    # Copy defaults for arrays any arrays.
+    for my $prop ($self->array_properties) {
+      $self->{properties}{$prop} = [@{$defaults->{$prop}}]
+        unless exists $self->{properties}{$prop};
+    }
+    # Copy defaults for arrays any hashes.
+    for my $prop ($self->hash_properties) {
+      $self->{properties}{$prop} = {%{$defaults->{$prop}}}
+        unless exists $self->{properties}{$prop};
+    }
+  }
 
-      # Set the build class.
-      $self->{properties}{build_class} ||= ref $self;
+} # end closure
+########################################################################
+sub _make_hash_accessor {
+  my ($property, $p) = @_;
+  my $check = $p->{check} || sub { 1 };
 
-      # If there was no orig_dir, set to the same as base_dir
-      $self->{properties}{orig_dir} ||= $self->{properties}{base_dir};
+  return sub {
+    my $self = shift;
 
-      my $defaults = $self->valid_properties_defaults;
-      
-      foreach my $prop (keys %$defaults) {
-	$self->{properties}{$prop} = $defaults->{$prop}
-	  unless exists $self->{properties}{$prop};
-      }
-      
-      # Copy defaults for arrays any arrays.
-      for my $prop ($self->array_properties) {
-	$self->{properties}{$prop} = [@{$defaults->{$prop}}]
-	  unless exists $self->{properties}{$prop};
-      }
-      # Copy defaults for arrays any hashes.
-      for my $prop ($self->hash_properties) {
-	$self->{properties}{$prop} = {%{$defaults->{$prop}}}
-	  unless exists $self->{properties}{$prop};
+    # This is only here to deprecate the historic accident of calling
+    # properties as class methods - I suspect it only happens in our
+    # test suite.
+    unless(ref($self)) {
+      carp("\n$property not a class method (@_)");
+      return;
+    }
+
+    my $x = $self->{properties};
+    return $x->{$property} unless @_;
+
+    my $prop = $x->{$property};
+    if ( defined $_[0] && !ref $_[0] ) {
+      if ( @_ == 1 ) {
+        return exists $prop->{$_[0]} ? $prop->{$_[0]} : undef;
+      } elsif ( @_ % 2 == 0 ) {
+        my %new = (%{ $prop }, @_);
+        local $_ = \%new;
+        $x->{$property} = \%new if $check->($self);
+        return $x->{$property};
+      } else {
+        die "Unexpected arguments for property '$property'\n";
       }
+    } else {
+      die "Unexpected arguments for property '$property'\n"
+          if defined $_[0] && ref $_[0] ne 'HASH';
+      local $_ = $_[0];
+      $x->{$property} = shift if $check->($self);
     }
+  };
+}
+########################################################################
+sub _make_accessor {
+  my ($property, $p) = @_;
+  my $check = $p->{check} || sub { 1 };
+
+  return sub {
+    my $self = shift;
 
+    # This is only here to deprecate the historic accident of calling
+    # properties as class methods - I suspect it only happens in our
+    # test suite.
+    unless(ref($self)) {
+      carp("\n$property not a class method (@_)");
+      return;
+    }
+
+    my $x = $self->{properties};
+    return $x->{$property} unless @_;
+    local $_ = $_[0];
+    $x->{$property} = shift if $check->($self);
+    return $x->{$property};
+  };
 }
+########################################################################
 
 # Add the default properties.
 __PACKAGE__->add_property(blib => 'blib');
@@ -772,7 +825,6 @@ __PACKAGE__->add_property(build_script => 'Build');
 __PACKAGE__->add_property(build_bat => 0);
 __PACKAGE__->add_property(config_dir => '_build');
 __PACKAGE__->add_property(include_dirs => []);
-__PACKAGE__->add_property(installdirs => 'site');
 __PACKAGE__->add_property(metafile => 'META.yml');
 __PACKAGE__->add_property(recurse_into => []);
 __PACKAGE__->add_property(use_rcfile => 1);
@@ -782,6 +834,20 @@ __PACKAGE__->add_property(config => undef);
 __PACKAGE__->add_property(test_file_exts => ['.t']);
 __PACKAGE__->add_property(use_tap_harness => 0);
 __PACKAGE__->add_property(tap_harness_args => {});
+__PACKAGE__->add_property(
+  'installdirs',
+  default => 'site',
+  check   => sub {
+    return 1 if /^(core|site|vendor)$/;
+    return shift->property_error(
+      $_ eq 'perl'
+      ? 'Perhaps you meant installdirs to be "core" rather than "perl"?'
+      : 'installdirs must be one of "core", "site", or "vendor"'
+    );
+    return shift->property_error("Perhaps you meant 'core'?") if $_ eq 'perl';
+    return 0;
+  },
+);
 
 {
   my $Is_ActivePerl = eval {require ActivePerl::DocTools};
@@ -814,6 +880,7 @@ __PACKAGE__->add_property($_) for qw(
   base_dir
   bindoc_dirs
   c_source
+  create_license
   create_makefile_pl
   create_readme
   debugger
@@ -1084,10 +1151,19 @@ sub check_autofeatures {
 
   $self->log_info("Checking features:\n");
 
-  my $max_name_len = 0;
-  $max_name_len = ( length($_) > $max_name_len ) ?
-                    length($_) : $max_name_len
-    for keys %$features;
+  # TODO refactor into ::Util
+  my $longest = sub {
+    my @str = @_ or croak("no strings given");
+
+    my @len = map({length($_)} @str);
+    my $max = 0;
+    my $longest;
+    for my $i (0..$#len) {
+      ($max, $longest) = ($len[$i], $str[$i]) if($len[$i] > $max);
+    }
+    return($longest);
+  };
+  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));
@@ -1518,6 +1594,9 @@ sub cull_options {
     my $self = shift;
     my (@argv) = @_;
 
+    # XXX is it even valid to call this as a class method?
+    return({}, @argv) unless(ref($self)); # no object
+
     my $specs = $self->get_options;
     return({}, @argv) unless($specs and %$specs); # no user options
 
@@ -1579,6 +1658,7 @@ sub _translate_option {
   (my $tr_opt = $opt) =~ tr/-/_/;
 
   return $tr_opt if grep $tr_opt =~ /^(?:no_?)?$_$/, qw(
+    create_license
     create_makefile_pl
     create_readme
     extra_compiler_flags
@@ -1620,6 +1700,7 @@ sub _optional_arg {
 
   my @bool_opts = qw(
     build_bat
+    create_license
     create_readme
     pollute
     quiet
@@ -3100,6 +3181,32 @@ sub do_create_makefile_pl {
   $self->_add_to_manifest('MANIFEST', 'Makefile.PL');
 }
 
+sub do_create_license {
+  my $self = shift;
+  $self->log_info("Creating LICENSE file");
+
+  my $l = $self->license
+    or die "No license specified";
+
+  my $key = $self->valid_licenses->{$l}
+    or die "'$l' isn't a license key we know about";
+  my $class = "Software::License::$key";
+
+  eval "use $class; 1"
+    or die "Can't load Software::License to create LICENSE file: $@";
+
+  $self->delete_filetree('LICENSE');
+
+  my $author = join " & ", @{ $self->dist_author };
+  my $license = $class->new({holder => $author});
+  my $fh = IO::File->new('> LICENSE')
+    or die "Can't write LICENSE file: $!";
+  print $fh $license->fulltext;
+  close $fh;
+
+  $self->_add_to_manifest('MANIFEST', 'LICENSE');
+}
+
 sub do_create_readme {
   my $self = shift;
   $self->delete_filetree('README');
@@ -3346,11 +3453,35 @@ BEGIN { *scripts = \&script_files; }
 
 {
   my %licenses = (
+    perl         => 'Perl_5',
+    apache       => 'Apache_2_0',
+    artistic     => 'Artistic_1_0',
+    artistic_2   => 'Artistic_2_0',
+    lgpl         => 'LGPL_2_1',
+    lgpl2        => 'LGPL_2_1',
+    lgpl3        => 'LGPL_3_0',
+    bsd          => 'BSD',
+    gpl          => 'GPL_1',
+    gpl2         => 'GPL_2',
+    gpl3         => 'GPL_3',
+    mit          => 'MIT',
+    mozilla      => 'Mozilla_1_1',
+    open_source  => undef,
+    unrestricted => undef,
+    restrictive  => undef,
+    unknown      => undef,
+  );
+
+  # TODO - would be nice to not have these here, since they're more
+  # properly stored only in Software::License
+  my %license_urls = (
     perl         => 'http://dev.perl.org/licenses/',
     apache       => 'http://apache.org/licenses/LICENSE-2.0',
     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',
+    lgpl2        => 'http://opensource.org/licenses/lgpl-2.1.php',
+    lgpl3        => 'http://opensource.org/licenses/lgpl-3.0.html',
     bsd          => 'http://opensource.org/licenses/bsd-license.php',
     gpl          => 'http://opensource.org/licenses/gpl-license.php',
     gpl2         => 'http://opensource.org/licenses/gpl-2.0.php',
@@ -3365,6 +3496,9 @@ BEGIN { *scripts = \&script_files; }
   sub valid_licenses {
     return \%licenses;
   }
+  sub _license_url {
+    return $license_urls{$_[1]};
+  }
 }
 
 sub _hash_merge {
@@ -3383,6 +3517,7 @@ sub ACTION_distmeta {
 
   $self->do_create_makefile_pl if $self->create_makefile_pl;
   $self->do_create_readme if $self->create_readme;
+  $self->do_create_license if $self->create_license;
   $self->do_create_metafile;
 }
 
@@ -3462,9 +3597,19 @@ sub prepare_metadata {
   }
   $node->{version} = '' . $node->{version}; # Stringify version objects
 
-  if (defined( $self->license ) &&
-      defined( my $url = $self->valid_licenses->{ $self->license } )) {
-    $node->{resources}{license} = $url;
+  if (defined( my $l = $self->license )) {
+    die "Unknown license string '$l'"
+      unless exists $self->valid_licenses->{ $self->license };
+
+    if (my $key = $self->valid_licenses->{ $self->license }) {
+      my $class = "Software::License::$key";
+      if (eval "use $class; 1") {
+        # S::L requires a 'holder' key
+        $node->{resources}{license} = $class->new({holder=>"nobody"})->url;
+      } else {
+        $node->{resources}{license} = $self->_license_url($key);
+      }
+    }
   }
 
   if (exists $p->{configure_requires}) {
@@ -3697,11 +3842,18 @@ sub make_tarball {
     $self->do_system($self->split_like_shell($self->{args}{gzip}), "$file.tar") if $self->{args}{gzip};
   } else {
     require Archive::Tar;
+
     # 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;
+
     my $files = $self->rscan_dir($dir);
-    Archive::Tar->create_archive("$file.tar.gz", 1, @$files);
+    my $tar   = Archive::Tar->new;
+    $tar->add_files(@$files);
+    for my $f ($tar->get_files) {
+      $f->mode($f->mode & ~022); # chmod go-w
+    }
+    $tar->write("$file.tar.gz", 1);
   }
 }
 
diff --git a/lib/Module/Build/Compat.pm b/lib/Module/Build/Compat.pm
index 92c2b5e..a2e1664 100644
--- a/lib/Module/Build/Compat.pm
+++ b/lib/Module/Build/Compat.pm
@@ -2,7 +2,7 @@ package Module::Build::Compat;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 
 use File::Spec;
 use IO::File;
@@ -175,7 +175,7 @@ EOF
     
     $MM_Args{EXE_FILES} = [ sort keys %{$build->script_files} ] if $build->script_files;
     
-    $MM_Args{PL_FILES} = {};
+    $MM_Args{PL_FILES} = $build->PL_files if $build->PL_files;
     
     local $Data::Dumper::Terse = 1;
     my $args = Data::Dumper::Dumper(\%MM_Args);
diff --git a/lib/Module/Build/Config.pm b/lib/Module/Build/Config.pm
index e8004aa..8b645c8 100644
--- a/lib/Module/Build/Config.pm
+++ b/lib/Module/Build/Config.pm
@@ -2,7 +2,7 @@ package Module::Build::Config;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 use Config;
 
diff --git a/lib/Module/Build/Cookbook.pm b/lib/Module/Build/Cookbook.pm
index 7e963b0..0e95664 100644
--- a/lib/Module/Build/Cookbook.pm
+++ b/lib/Module/Build/Cookbook.pm
@@ -1,7 +1,7 @@
 package Module::Build::Cookbook;
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 
 
 =head1 NAME
@@ -395,7 +395,7 @@ testing, do I generate a test file.
 I'm sure I could not have handled this complexity with EU::MM, but it
 was very easy to do with M::B.
 
-=back 4
+=back
 
 
 =head2 Modifying an action
@@ -431,6 +431,84 @@ the C<install> action:
   )->create_build_script;
 
 
+=head2 Adding an action
+
+You can add a new C<./Build> action simply by writing the method for
+it in your subclass.  Use C<depends_on> to declare that another action
+must have been run before your action.
+
+For example, let's say you wanted to be able to write C<./Build
+commit> to test your code and commit it to Subversion.
+
+  # Build.PL
+  use Module::Build;
+  my $class = Module::Build->subclass(
+      class => "Module::Build::Custom",
+      code => <<'SUBCLASS' );
+
+  sub ACTION_commit {
+      my $self = shift;
+
+      $self->depends_on("test");
+      $self->do_system(qw(svn commit));
+  }
+  SUBCLASS
+
+
+=head2 Bundling Module::Build
+
+Note: This section probably needs an update as the technology improves
+(see scripts/bundle.pl in the distribution).
+
+Suppose you want to use some new-ish features of Module::Build,
+e.g. newer than the version of Module::Build your users are likely to
+already have installed on their systems.  The first thing you should
+do is set C<configure_requires> to your minimum version of
+Module::Build.  See L<Module::Build::Authoring>.
+
+But not every build system honors C<configure_requires> yet.  Here's
+how you can ship a copy of Module::Build, but still use a newer
+installed version to take advantage of any bug fixes and upgrades.
+
+First, install Module::Build into F<Your-Project/inc/Module-Build>.
+CPAN will not index anything in the F<inc> directory so this copy will
+not show up in CPAN searches.
+
+    cd Module-Build
+    perl Build.PL --install_base /path/to/Your-Project/inc/Module-Build
+    ./Build test
+    ./Build install
+
+You should now have all the Module::Build .pm files in
+F<Your-Project/inc/Module-Build/lib/perl5>.
+
+Next, add this to the top of your F<Build.PL>.
+
+    my $Bundled_MB = 0.30;  # or whatever version it was.
+
+    # Find out what version of Module::Build is installed or fail quietly.
+    # This should be cross-platform.
+    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.
+    chomp $Installed_MB;
+
+    $Installed_MB = 0 if $?;
+
+    # Use our bundled copy of Module::Build if it's newer than the installed.
+    unshift @INC, "inc/Module-Build/lib/perl5" if $Bundled_MB > $Installed_MB;
+
+    require Module::Build;
+
+And write the rest of your F<Build.PL> normally.  Module::Build will
+remember your change to C<@INC> and use it when you run F<./Build>.
+
+In the future, we hope to provide a more automated solution for this
+scenario; see C<inc/latest.pm> in the Module::Build distribution for
+one indication of the direction we're moving.
+
+
 =head1 AUTHOR
 
 Ken Williams <kwilliams@cpan.org>
@@ -438,7 +516,7 @@ Ken Williams <kwilliams@cpan.org>
 
 =head1 COPYRIGHT
 
-Copyright (c) 2001-2006 Ken Williams.  All rights reserved.
+Copyright (c) 2001-2008 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.
diff --git a/lib/Module/Build/Dumper.pm b/lib/Module/Build/Dumper.pm
index 2c2ca59..aa5e85f 100644
--- a/lib/Module/Build/Dumper.pm
+++ b/lib/Module/Build/Dumper.pm
@@ -1,7 +1,7 @@
 package Module::Build::Dumper;
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 
 # This is just a split-out of a wrapper function to do Data::Dumper
 # stuff "the right way".  See:
diff --git a/lib/Module/Build/ModuleInfo.pm b/lib/Module/Build/ModuleInfo.pm
index d78efed..cfcd4cb 100644
--- a/lib/Module/Build/ModuleInfo.pm
+++ b/lib/Module/Build/ModuleInfo.pm
@@ -8,7 +8,7 @@ package Module::Build::ModuleInfo;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 
 use File::Spec;
diff --git a/lib/Module/Build/Notes.pm b/lib/Module/Build/Notes.pm
index 056ac4d..9c44f65 100644
--- a/lib/Module/Build/Notes.pm
+++ b/lib/Module/Build/Notes.pm
@@ -4,7 +4,7 @@ package Module::Build::Notes;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 use Data::Dumper;
 use IO::File;
diff --git a/lib/Module/Build/PPMMaker.pm b/lib/Module/Build/PPMMaker.pm
index bf6715c..a23d2a3 100644
--- a/lib/Module/Build/PPMMaker.pm
+++ b/lib/Module/Build/PPMMaker.pm
@@ -2,7 +2,7 @@ package Module::Build::PPMMaker;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 
 # This code is mostly borrowed from ExtUtils::MM_Unix 6.10_03, with a
diff --git a/lib/Module/Build/Platform/Amiga.pm b/lib/Module/Build/Platform/Amiga.pm
index a74c173..b4989b4 100644
--- a/lib/Module/Build/Platform/Amiga.pm
+++ b/lib/Module/Build/Platform/Amiga.pm
@@ -2,7 +2,7 @@ package Module::Build::Platform::Amiga;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 use Module::Build::Base;
 
diff --git a/lib/Module/Build/Platform/Default.pm b/lib/Module/Build/Platform/Default.pm
index a8e9dce..ea0a02c 100644
--- a/lib/Module/Build/Platform/Default.pm
+++ b/lib/Module/Build/Platform/Default.pm
@@ -2,7 +2,7 @@ package Module::Build::Platform::Default;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 use Module::Build::Base;
 
diff --git a/lib/Module/Build/Platform/EBCDIC.pm b/lib/Module/Build/Platform/EBCDIC.pm
index 63b9bfd..f30939f 100644
--- a/lib/Module/Build/Platform/EBCDIC.pm
+++ b/lib/Module/Build/Platform/EBCDIC.pm
@@ -2,7 +2,7 @@ package Module::Build::Platform::EBCDIC;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 use Module::Build::Base;
 
diff --git a/lib/Module/Build/Platform/MPEiX.pm b/lib/Module/Build/Platform/MPEiX.pm
index b548e06..ce08efe 100644
--- a/lib/Module/Build/Platform/MPEiX.pm
+++ b/lib/Module/Build/Platform/MPEiX.pm
@@ -2,7 +2,7 @@ package Module::Build::Platform::MPEiX;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 use Module::Build::Base;
 
diff --git a/lib/Module/Build/Platform/MacOS.pm b/lib/Module/Build/Platform/MacOS.pm
index 6ad7be3..e703a23 100644
--- a/lib/Module/Build/Platform/MacOS.pm
+++ b/lib/Module/Build/Platform/MacOS.pm
@@ -2,7 +2,7 @@ package Module::Build::Platform::MacOS;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 use Module::Build::Base;
 use vars qw(@ISA);
diff --git a/lib/Module/Build/Platform/RiscOS.pm b/lib/Module/Build/Platform/RiscOS.pm
index faeac89..e1641e3 100644
--- a/lib/Module/Build/Platform/RiscOS.pm
+++ b/lib/Module/Build/Platform/RiscOS.pm
@@ -2,7 +2,7 @@ package Module::Build::Platform::RiscOS;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 use Module::Build::Base;
 
diff --git a/lib/Module/Build/Platform/Unix.pm b/lib/Module/Build/Platform/Unix.pm
index 5e67436..a5be5fe 100644
--- a/lib/Module/Build/Platform/Unix.pm
+++ b/lib/Module/Build/Platform/Unix.pm
@@ -2,7 +2,7 @@ package Module::Build::Platform::Unix;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 use Module::Build::Base;
 
@@ -47,7 +47,7 @@ sub _detildefy {
   $value =~ s[^~(\w[-\w]*)?(?=/|$)]   # tilde with optional username
     [$1 ?
      ((getpwnam $1)[7] || "~$1") :
-     (getpwuid $>)[7]
+     ($ENV{HOME} || (getpwuid $>)[7])
     ]ex;
   return $value;
 }
diff --git a/lib/Module/Build/Platform/VMS.pm b/lib/Module/Build/Platform/VMS.pm
index 85320e7..8786d59 100644
--- a/lib/Module/Build/Platform/VMS.pm
+++ b/lib/Module/Build/Platform/VMS.pm
@@ -2,7 +2,7 @@ package Module::Build::Platform::VMS;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 use Module::Build::Base;
 
diff --git a/lib/Module/Build/Platform/VOS.pm b/lib/Module/Build/Platform/VOS.pm
index befec9d..6e42459 100644
--- a/lib/Module/Build/Platform/VOS.pm
+++ b/lib/Module/Build/Platform/VOS.pm
@@ -2,7 +2,7 @@ package Module::Build::Platform::VOS;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 use Module::Build::Base;
 
diff --git a/lib/Module/Build/Platform/Windows.pm b/lib/Module/Build/Platform/Windows.pm
index 7cdb560..b15d49d 100644
--- a/lib/Module/Build/Platform/Windows.pm
+++ b/lib/Module/Build/Platform/Windows.pm
@@ -2,7 +2,7 @@ package Module::Build::Platform::Windows;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 
 use Config;
diff --git a/lib/Module/Build/Platform/aix.pm b/lib/Module/Build/Platform/aix.pm
index b521a65..c06640c 100644
--- a/lib/Module/Build/Platform/aix.pm
+++ b/lib/Module/Build/Platform/aix.pm
@@ -2,7 +2,7 @@ package Module::Build::Platform::aix;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 use Module::Build::Platform::Unix;
 
diff --git a/lib/Module/Build/Platform/cygwin.pm b/lib/Module/Build/Platform/cygwin.pm
index 56b600f..375f8ae 100644
--- a/lib/Module/Build/Platform/cygwin.pm
+++ b/lib/Module/Build/Platform/cygwin.pm
@@ -2,7 +2,7 @@ package Module::Build::Platform::cygwin;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 use Module::Build::Platform::Unix;
 
diff --git a/lib/Module/Build/Platform/darwin.pm b/lib/Module/Build/Platform/darwin.pm
index aee1773..8ee5d44 100644
--- a/lib/Module/Build/Platform/darwin.pm
+++ b/lib/Module/Build/Platform/darwin.pm
@@ -2,7 +2,7 @@ package Module::Build::Platform::darwin;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 use Module::Build::Platform::Unix;
 
diff --git a/lib/Module/Build/Platform/os2.pm b/lib/Module/Build/Platform/os2.pm
index 035cc9a..d92dfb2 100644
--- a/lib/Module/Build/Platform/os2.pm
+++ b/lib/Module/Build/Platform/os2.pm
@@ -2,7 +2,7 @@ package Module::Build::Platform::os2;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 use Module::Build::Platform::Unix;
 
diff --git a/lib/Module/Build/PodParser.pm b/lib/Module/Build/PodParser.pm
index 58301d7..ebc6711 100644
--- a/lib/Module/Build/PodParser.pm
+++ b/lib/Module/Build/PodParser.pm
@@ -2,7 +2,7 @@ package Module::Build::PodParser;
 
 use strict;
 use vars qw($VERSION);
-$VERSION = '0.30';
+$VERSION = '0.3101';
 $VERSION = eval $VERSION;
 use vars qw(@ISA);
 
diff --git a/lib/Module/Build/Version.pm b/lib/Module/Build/Version.pm
index f85d0d9..8f4d78b 100644
--- a/lib/Module/Build/Version.pm
+++ b/lib/Module/Build/Version.pm
@@ -74,7 +74,7 @@ use strict;
 
 use locale;
 use vars qw ($VERSION @ISA @REGEXS);
-$VERSION = 0.74;
+$VERSION = 0.76;
 
 push @REGEXS, qr/
 	^v?	# optional leading 'v'
@@ -426,7 +426,11 @@ sub stringify
 	require Carp;
 	Carp::croak("Invalid version object");
     }
-    return $self->{original};
+    return exists $self->{original} 
+    	? $self->{original} 
+	: exists $self->{qv} 
+	    ? $self->normal
+	    : $self->numify;
 }
 
 sub vcmp
@@ -557,7 +561,8 @@ sub _un_vstring {
 # Thanks to Yitzchak Scott-Thoennes for this mode of operation
 {
     local $^W;
-    *UNIVERSAL::VERSION = sub {
+    *UNIVERSAL::VERSION # Module::Build::ModuleInfo doesn't see this now
+      = sub {
 	my ($obj, $req) = @_;
 	my $class = ref($obj) || $obj;
 
diff --git a/lib/Module/Build/scripts/bundle.pl b/lib/Module/Build/scripts/bundle.pl
new file mode 100755
index 0000000..78de143
--- /dev/null
+++ b/lib/Module/Build/scripts/bundle.pl
@@ -0,0 +1,53 @@
+#!/usr/bin/perl
+
+# this is just a first crack and it uses File::Fu because I'm lazy.
+
+=head1 using
+
+This installs from a fresh Module::Build to your inc/inc_Module-Build
+directory.  Use it from within your dist:
+
+  perl /path/to/Module-Build/scripts/bundle.pl
+
+You still need to manually add the following to your Build.PL
+
+  use lib 'inc';
+  use latest 'Module::Build';
+
+You also need to regen your manifest.
+
+  perl Build.PL
+  ./Build distmeta; >MANIFEST; ./Build manifest; svn diff MANIFEST
+
+=cut
+
+use warnings;
+use strict;
+
+use File::Fu;
+use File::Copy ();
+
+my $inc_dir = shift(@ARGV);
+$inc_dir = File::Fu->dir($inc_dir || 'inc/inc_Module-Build');
+$inc_dir->create unless($inc_dir->e);
+$inc_dir = $inc_dir->absolutely;
+
+
+my $mb_dir = File::Fu->program_dir->dirname;
+
+$mb_dir->chdir_for(sub {
+  my $temp = File::Fu->temp_dir('mb_bundle');
+  local @INC = @INC;
+  unshift(@INC, 'lib', 'inc');
+  require Module::Build;
+  my $builder = Module::Build->new_from_context;
+  $builder->dispatch(install =>
+    install_base => $temp,
+    install_path => {lib => $inc_dir},
+  );
+});
+
+my $latest = $mb_dir/'inc'+'latest.pm';
+File::Copy::copy($latest, 'inc');
+
+# vim:ts=2:sw=2:et:sta
diff --git a/lib/Module/Build/t/add_property.t b/lib/Module/Build/t/add_property.t
new file mode 100644
index 0000000..ed18eb9
--- /dev/null
+++ b/lib/Module/Build/t/add_property.t
@@ -0,0 +1,93 @@
+#!/usr/bin/perl -w
+
+use strict;
+use lib $ENV{PERL_CORE} ? '../lib/Module/Build/t/lib' : 't/lib';
+use MBTest tests => 29;
+#use MBTest 'no_plan';
+use DistGen;
+
+BEGIN { use_ok 'Module::Build' or die; }
+ensure_blib 'Module::Build';
+
+my $tmp = MBTest->tmpdir;
+my $dist = DistGen->new( dir => $tmp );
+$dist->regen;
+$dist->chdir_in;
+
+ADDPROP: {
+  package My::Build::Prop;
+  use base 'Module::Build';
+  __PACKAGE__->add_property( 'foo' );
+  __PACKAGE__->add_property( 'bar', 'howdy' );
+  __PACKAGE__->add_property( 'baz', default => 'howdy' );
+  __PACKAGE__->add_property( 'code', default => sub { 'yay' } );
+  __PACKAGE__->add_property(
+    'check',
+    default => sub { 'howdy' },
+    check   => sub {
+      return 1 if $_ eq 'howdy';
+      shift->property_error(qq{"$_" is invalid});
+      return 0;
+    },
+  );
+  __PACKAGE__->add_property(
+    'hash',
+    default => { foo => 1 },
+    check   => sub {
+      return 1 if !defined $_ or exists $_->{foo};
+      shift->property_error(qq{hash is invalid});
+      return 0;
+    },
+  );
+}
+
+ok my $build = My::Build::Prop->new(
+  'module_name' => 'Simple',
+  quiet => 1,
+), 'Create new build object';
+
+is $build->foo, undef, 'Property "foo" should be undef';
+ok $build->foo(42), 'Set "foo"';
+is $build->foo, 42, 'Now "foo" should have new value';
+
+is $build->bar, 'howdy', 'Property "bar" should be its default';
+ok $build->bar('yo'), 'Set "bar"';
+is $build->bar, 'yo', 'Now "bar" should have new value';
+
+is $build->check, 'howdy', 'Property "check" should be its default';
+
+eval { $build->check('yo') };
+ok my $err = $@, 'Should get an error for an invalid value';
+like $err, qr/^ERROR: "yo" is invalid/, 'It should be the correct error';
+
+is $build->code, 'yay', 'Property "code" should have its code value';
+
+is_deeply $build->hash, { foo => 1 }, 'Property "hash" should be default';
+is $build->hash('foo'), 1, 'Should be able to get key in hash';
+ok $build->hash( bar => 3 ), 'Add a key to the hash prop';
+is_deeply $build->hash, { foo => 1, bar => 3 }, 'New key should be in hash';
+
+eval { $build->hash({ bar => 3 }) };
+ok $err = $@, 'Should get exception for assigning invalid hash';
+like $err, qr/^ERROR: hash is invalid/, 'It should be the correct error';
+
+eval { $build->hash( []) };
+ok $err = $@, 'Should get exception for assigning an array for a hash';
+like $err, qr/^Unexpected arguments for property 'hash'/,
+  'It should be the proper error';
+is $build->hash(undef), undef, 'Should be able to set hash to undef';
+
+# Check core properties.
+is $build->installdirs, 'site', 'Property "installdirs" should be default';
+ok $build->installdirs('core'), 'Set "installdirst" to "core"';
+is $build->installdirs, 'core', 'Now "installdirs" should be "core"';
+
+eval { $build->installdirs('perl') };
+ok $err = $@, 'Should have caught exception setting "installdirs" to "perl"';
+like $err, qr/^ERROR: Perhaps you meant installdirs to be "core" rather than "perl"\?/,
+  'And it should suggest "core" in the error message';
+
+eval { $build->installdirs('foo') };
+ok $err = $@, 'Should catch exception for invalid "installdirs" value';
+like $err, qr/ERROR: installdirs must be one of "core", "site", or "vendor"/,
+  'And it should suggest the proper values in the error message';
diff --git a/lib/Module/Build/t/bundled/Tie/CPHash.pm b/lib/Module/Build/t/bundled/Tie/CPHash.pm
index 4276a9d..376f8a0 100644
--- a/lib/Module/Build/t/bundled/Tie/CPHash.pm
+++ b/lib/Module/Build/t/bundled/Tie/CPHash.pm
@@ -5,7 +5,7 @@ package Tie::CPHash;
 #
 # Author: Christopher J. Madsen <cjm@pobox.com>
 # Created: 08 Nov 1997
-# $Revision: 5841 $  $Date: 2006-03-21 07:27:29 -0600 (Tue, 21 Mar 2006) $
+# $Revision: 11234 $  $Date: 2006-03-21T13:27:29.000000Z $
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the same terms as Perl itself.
diff --git a/lib/Module/Build/t/compat.t b/lib/Module/Build/t/compat.t
index 9a8ccbf..d12898b 100644
--- a/lib/Module/Build/t/compat.t
+++ b/lib/Module/Build/t/compat.t
@@ -18,7 +18,7 @@ my $tests_per_type = 15;
 #find_in_path does not understand VMS.
 
 if ( $Config{make} && $^O ne 'VMS' ? find_in_path($Config{make}) : 1 ) {
-    plan tests => 34 + @makefile_types*$tests_per_type*2;
+    plan 'no_plan';
 } else {
     plan skip_all => "Don't know how to invoke 'make'";
 }
@@ -64,7 +64,7 @@ if ($is_vms_mms) {
 
 test_makefile_types();
 
-# Test with requires
+# Test with requires and PL_files
 
 my $distname = $dist->name;
 $dist->change_build_pl({ 
@@ -77,15 +77,26 @@ $dist->change_build_pl({
   build_requires      => {
     'Test::More'  => 0,
   },
+  PL_files            => { 'foo.PL' => 'foo' },
 });
 
+$dist->add_file("foo.PL", <<'END');
+open my $fh, ">$ARGV[0]" or die $!;
+print $fh "foo\n";
+END
+
 $dist->regen;
 
-test_makefile_types( requires => {
-    'perl' => $],
-    'File::Spec' => 0,
-    'Test::More' => 0,
-});
+test_makefile_types(
+    requires => {
+        'perl' => $],
+        'File::Spec' => 0,
+        'Test::More' => 0,
+    },
+    PL_files => {
+        'foo.PL' => 'foo',
+    },
+);
 
 ######################
 
@@ -260,6 +271,7 @@ $dist->remove;
 sub test_makefile_types {
   my %opts = @_;
   $opts{requires} ||= {};
+  $opts{PL_files} ||= {};
 
   foreach my $type (@makefile_types) {
     # Create M::B instance 
@@ -275,6 +287,7 @@ sub test_makefile_types {
     test_makefile_pl_requires_perl( $opts{requires}{perl} );
     test_makefile_creation($mb);
     test_makefile_prereq_pm( $opts{requires} );
+    test_makefile_pl_files( $opts{PL_files} ) if $type eq 'traditional';
       
     my ($output,$success);
     # Capture output to keep our STDOUT clean
@@ -283,6 +296,10 @@ sub test_makefile_types {
     });
     ok $success, "make ran without error";
 
+    for my $file (values %{ $opts{PL_files} }) {
+        ok -e $file, "PL_files generated - $file";
+    }
+
     # Can't let 'test' STDOUT go to our STDOUT, or it'll confuse Test::Harness.
     $output = stdout_of( sub {
       $success = $mb->do_system(@make, 'test');
@@ -334,12 +351,23 @@ sub test_makefile_prereq_pm {
   delete $requires{perl}; # until EU::MM supports this
   SKIP: {
     skip "$makefile not found", 1 unless -e $makefile;
-    my $prereq_pm = find_makefile_prereq_pm();
+    my $prereq_pm = find_params_in_makefile()->{PREREQ_PM} || {};
     is_deeply $prereq_pm, \%requires,
       "$makefile has correct PREREQ_PM line";
   }
 }
 
+sub test_makefile_pl_files {
+  my $expected = shift;
+
+  SKIP: {
+    skip "$makefile not found", 1 unless -e $makefile;
+    my $pl_files = find_params_in_makefile()->{PL_FILES} || {};
+    is_deeply $pl_files, $expected,
+      "$makefile has correct PL_FILES line";
+  }
+}
+
 sub test_makefile_pl_requires_perl {
   my $perl_version = shift || q{};
   SKIP: {
@@ -356,30 +384,28 @@ sub test_makefile_pl_requires_perl {
   }
 }
 
-# Following subroutine adapted from code in CPAN.pm 
-# by Andreas Koenig and A. Speer.
-sub find_makefile_prereq_pm {
+sub find_params_in_makefile {
   my $fh = IO::File->new( $makefile, 'r' ) 
     or die "Can't read $makefile: $!";
-  my $req = {};
   local($/) = "\n";
+
+  my %params;
   while (<$fh>) {
-    # locate PREREQ_PM
-    last if /MakeMaker post_initialize section/;
-    my($p) = m{^[\#]
-      \s+PREREQ_PM\s+=>\s+(.+)
-    }x;
-    next unless $p;
-
-    # extract modules
-    while ( $p =~ m/(?:\s)([\w\:]+)=>(q\[.*?\]|undef),?/g ){
+    # Blank line after params.
+    last if keys %params and !/\S+/;
+
+    next unless m{^\# \s+ ( [A-Z_]+ ) \s+ => \s+ ( .* )$}x;
+
+    my($key, $val) = ($1, $2);
+    # extract keys and values
+    while ( $val =~ m/(?:\s)(\S+)=>(q\[.*?\]|undef),?/g ) {
       my($m,$n) = ($1,$2);
       if ($n =~ /^q\[(.*?)\]$/) {
         $n = $1;
       }
-      $req->{$m} = $n;
+      $params{$key}{$m} = $n;
     }
-    last;
   }
-  return $req;
+
+  return \%params;
 }
diff --git a/lib/Module/Build/t/ext.t b/lib/Module/Build/t/ext.t
index faa392b..3730ef0 100644
--- a/lib/Module/Build/t/ext.t
+++ b/lib/Module/Build/t/ext.t
@@ -106,8 +106,8 @@ foreach my $test (@win_splits) {
   # Make sure data can make a round-trip through an external perl
   # process, which can involve the shell command line
 
-  # Holy crap, I can't believe this works:
-  local $Module::Build{properties}{quiet} = 1;
+  # silence the printing for easier matching
+  local *Module::Build::log_info = sub {};
 
   my @data = map values(%$_), @unix_splits, @win_splits;
   for my $d (@data) {
@@ -124,7 +124,9 @@ foreach my $test (@win_splits) {
   # Make sure data can make a round-trip through an external backtick
   # process, which can involve the shell command line
 
-  local $Module::Build{properties}{quiet} = 1;
+  # silence the printing for easier matching
+  local *Module::Build::log_info = sub {};
+
   my @data = map values(%$_), @unix_splits, @win_splits;
   for my $d (@data) {
     chomp(my $out = Module::Build->_backticks('perl', '-le', 'print join " ", map "{$_}", @ARGV', @$d));
diff --git a/lib/Module/Build/t/lib/MBTest.pm b/lib/Module/Build/t/lib/MBTest.pm
index 34f262a..b7f5429 100644
--- a/lib/Module/Build/t/lib/MBTest.pm
+++ b/lib/Module/Build/t/lib/MBTest.pm
@@ -5,9 +5,46 @@ use strict;
 use File::Spec;
 use File::Path ();
 
+
+# Setup the code to clean out %ENV
+BEGIN {
+    # Environment variables which might effect our testing
+    my @delete_env_keys = qw(
+        DEVEL_COVER_OPTIONS
+        MODULEBUILDRC
+        HARNESS_TIMER
+        HARNESS_OPTIONS
+        HARNESS_VERBOSE
+        PREFIX
+        INSTALL_BASE
+        INSTALLDIRS
+    );
+
+    # Remember the ENV values because on VMS %ENV is global
+    # to the user, not the process.
+    my %restore_env_keys;
+
+    sub clean_env {
+        for my $key (@delete_env_keys) {
+            if( exists $ENV{$key} ) {
+                $restore_env_keys{$key} = delete $ENV{$key};
+            }
+            else {
+                delete $ENV{$key};
+            }
+        }
+    }
+
+    END {
+        while( my($key, $val) = each %restore_env_keys ) {
+            $ENV{$key} = $val;
+        }
+    }
+}
+
+
 BEGIN {
-  # Make sure none of our tests load the users ~/.modulebuildrc file
-  $ENV{MODULEBUILDRC} = 'NONE';
+  clean_env();
 
   # In case the test wants to use our other bundled
   # modules, make sure they can be loaded.
@@ -16,10 +53,9 @@ BEGIN {
   unless ($ENV{PERL_CORE}) {
     push @INC, $t_lib; # Let user's installed version override
   } else {
-    # We change directories, so expand @INC and $^X to absolute paths
+    # We change directories, so expand @INC to absolute paths
     # Also add .
     @INC = (map(File::Spec->rel2abs($_), @INC), ".");
-    $^X = File::Spec->rel2abs($^X);
 
     # we are in 't', go up a level so we don't create t/t/_tmp
     chdir '..' or die "Couldn't chdir to ..";
@@ -59,6 +95,8 @@ my @extra_exports = qw(
 push @EXPORT, @extra_exports;
 __PACKAGE__->export(scalar caller, @extra_exports);
 # XXX ^-- that should really happen in import()
+
+
 ########################################################################
 
 { # Setup a temp directory if it doesn't exist
diff --git a/lib/Module/Build/t/par.t b/lib/Module/Build/t/par.t
new file mode 100644
index 0000000..d845548
--- /dev/null
+++ b/lib/Module/Build/t/par.t
@@ -0,0 +1,84 @@
+#!/usr/bin/perl -w
+
+use strict;
+use lib $ENV{PERL_CORE} ? '../lib/Module/Build/t/lib' : 't/lib';
+use MBTest;
+use Module::Build;
+use Module::Build::ConfigData;
+
+{
+  my ($have_c_compiler, $C_support_feature) = check_compiler();
+  if (! $C_support_feature) {
+    plan skip_all => 'C_support not enabled';
+  } elsif ( ! $have_c_compiler ) {
+    plan skip_all => 'C_support enabled, but no compiler found';
+  } elsif ( ! eval {require PAR::Dist; PAR::Dist->VERSION(0.17)} ) {
+    plan skip_all => "PAR::Dist 0.17 or up not installed to check .par's.";
+  } elsif ( ! eval {require Archive::Zip} ) {
+    plan skip_all => "Archive::Zip required.";
+  } else {
+    plan tests => 4;
+  }
+}
+ensure_blib('Module::Build');
+
+
+my $tmp = MBTest->tmpdir;
+
+
+use DistGen;
+my $dist = DistGen->new( dir => $tmp, xs => 1 );
+$dist->add_file( 'hello', <<'---' );
+#!perl -w
+print "Hello, World!\n";
+__END__
+
+=pod
+
+=head1 NAME
+
+hello
+
+=head1 DESCRIPTION
+
+Says "Hello"
+
+=cut
+---
+$dist->change_build_pl
+({
+  module_name => $dist->name,
+  version => '0.01',
+  license     => 'perl',
+  scripts     => [ 'hello' ],
+});
+$dist->regen;
+
+$dist->chdir_in;
+
+use File::Spec::Functions qw(catdir);
+
+use Module::Build;
+my @installstyle = qw(lib perl5);
+my $mb = Module::Build->new_from_context(
+  verbose => 0,
+  quiet   => 1,
+
+  installdirs => 'site',
+);
+
+my $filename = $mb->dispatch('pardist');
+
+ok( -f $filename, '.par distributions exists' );
+my $distname = $dist->name;
+ok( $filename =~ /^\Q$distname\E/, 'Distribution name seems correct' );
+
+my $meta;
+eval { $meta = PAR::Dist::get_meta($filename) };
+
+ok(
+  (not $@ and defined $meta and not $meta eq ''),
+  'Distribution contains META.yml'
+);
+
+$dist->remove;
diff --git a/lib/Module/Build/t/ppm.t b/lib/Module/Build/t/ppm.t
index d4c3dbf..af492e1 100644
--- a/lib/Module/Build/t/ppm.t
+++ b/lib/Module/Build/t/ppm.t
@@ -20,8 +20,6 @@ my $HTML_support = Module::Build::ConfigData->feature('HTML_support');
     plan skip_all => "Archive::Tar not installed to read archives.";
   } elsif ( ! eval {IO::Zlib->VERSION(1.01)} ) {
     plan skip_all => "IO::Zlib 1.01 required to read compressed archives.";
-  } elsif ( $^O eq 'VMS' ) {
-    plan skip_all => "Needs porting work on VMS";
   } else {
     plan tests => 13;
   }
diff --git a/lib/Module/Build/t/signature.t b/lib/Module/Build/t/signature.t
new file mode 100644
index 0000000..bac03e1
--- /dev/null
+++ b/lib/Module/Build/t/signature.t
@@ -0,0 +1,103 @@
+#!/usr/bin/perl -w
+
+use strict;
+use lib $ENV{PERL_CORE} ? '../lib/Module/Build/t/lib' : 't/lib';
+use MBTest;
+
+if ( $ENV{TEST_SIGNATURE} ) {
+  if ( have_module( 'Module::Signature' ) ) {
+    plan tests => 15;
+  } else {
+    plan skip_all => '$ENV{TEST_SIGNATURE} is set, but Module::Signature not found';
+  }
+} else {
+  plan skip_all => '$ENV{TEST_SIGNATURE} is not set';
+}
+
+use_ok 'Module::Build';
+ensure_blib('Module::Build');
+
+#########################
+
+my $tmp = MBTest->tmpdir;
+
+use DistGen;
+my $dist = DistGen->new( dir => $tmp );
+$dist->change_build_pl
+({
+  module_name => $dist->name,
+  license     => 'perl',
+  sign        => 1,
+});
+$dist->regen;
+
+$dist->chdir_in;
+
+#########################
+
+my $mb = Module::Build->new_from_context;
+
+
+{
+  eval {$mb->dispatch('distdir')};
+  is $@, '';
+  chdir( $mb->dist_dir ) or die "Can't chdir to '@{[$mb->dist_dir]}': $!";
+  ok -e 'SIGNATURE';
+  
+  # Make sure the signature actually verifies
+  ok Module::Signature::verify() == Module::Signature::SIGNATURE_OK();
+  $dist->chdir_in;
+}
+
+{
+  # Fake out Module::Signature and Module::Build - the first one to
+  # run should be distmeta.
+  my @run_order;
+  {
+    local $^W; # Skip 'redefined' warnings
+    local *Module::Signature::sign;
+    *Module::Signature::sign = sub { push @run_order, 'sign' };
+    local *Module::Build::Base::ACTION_distmeta;
+    *Module::Build::Base::ACTION_distmeta = sub { push @run_order, 'distmeta' };
+    eval { $mb->dispatch('distdir') };
+  }
+  is $@, '';
+  is $run_order[0], 'distmeta';
+  is $run_order[1], 'sign';
+}
+
+eval { $mb->dispatch('realclean') };
+is $@, '';
+
+
+{
+  eval {$mb->dispatch('distdir', sign => 0 )};
+  is $@, '';
+  chdir( $mb->dist_dir ) or die "Can't chdir to '@{[$mb->dist_dir]}': $!";
+  ok !-e 'SIGNATURE', './Build distdir --sign 0 does not sign';
+}
+
+eval { $mb->dispatch('realclean') };
+is $@, '';
+
+$dist->chdir_in;
+
+{
+    local @ARGV = '--sign=1';
+    $dist->change_build_pl({
+        module_name => $dist->name,
+        license     => 'perl',
+    });
+    $dist->regen;
+    
+    my $mb = Module::Build->new_from_context;
+    is $mb->{properties}{sign}, 1;
+    
+    eval {$mb->dispatch('distdir')};
+    is $@, '';
+    chdir( $mb->dist_dir ) or die "Can't chdir to '@{[$mb->dist_dir]}': $!";
+    ok -e 'SIGNATURE', 'Build.PL --sign=1 signs';
+}
+
+# cleanup
+$dist->remove;
diff --git a/lib/Module/Build/t/test_type.t b/lib/Module/Build/t/test_type.t
index 598ddb1..9b05a27 100644
--- a/lib/Module/Build/t/test_type.t
+++ b/lib/Module/Build/t/test_type.t
@@ -1,12 +1,5 @@
 #!/usr/bin/perl -w
 
-BEGIN {
-    if ($^O eq 'VMS') {
-        print '1..0 # Child test output confuses harness';
-        exit;
-    }
-}
-
 use strict;
 use lib $ENV{PERL_CORE} ? '../lib/Module/Build/t/lib' : 't/lib';
 use MBTest tests => 9;
diff --git a/lib/Module/Build/t/tilde.t b/lib/Module/Build/t/tilde.t
index 7dfcf1e..d1cdc9e 100644
--- a/lib/Module/Build/t/tilde.t
+++ b/lib/Module/Build/t/tilde.t
@@ -4,7 +4,7 @@
 
 use strict;
 use lib $ENV{PERL_CORE} ? '../lib/Module/Build/t/lib' : 't/lib';
-use MBTest tests => 17;
+use MBTest tests => 18;
 
 use_ok 'Module::Build';
 ensure_blib('Module::Build');
@@ -68,6 +68,13 @@ SKIP: {
     is( run_sample( prefix => '~' )->prefix,
 	$home );
 
+    # Test when HOME is different from getpwuid(), as in sudo.
+    {
+        local $ENV{HOME} = '/wibble/whomp';
+
+        is( run_sample( $p => '~' )->$p(),    "/wibble/whomp" );
+    }
+
     my $mb = run_sample( install_path => { html => '~/html',
 					   lib  => '~/lib'   }
 		       );
diff --git a/lib/Module/Build/t/xs.t b/lib/Module/Build/t/xs.t
index 4319a68..560ca10 100644
--- a/lib/Module/Build/t/xs.t
+++ b/lib/Module/Build/t/xs.t
@@ -12,8 +12,6 @@ use Module::Build;
     plan skip_all => 'C_support not enabled';
   } elsif ( !$have_c_compiler ) {
     plan skip_all => 'C_support enabled, but no compiler found';
-  } elsif ( $^O eq 'VMS' ) {
-    plan skip_all => 'Child test output confuses harness';
   } else {
     plan tests => 23;
   }
diff --git a/utils.lst b/utils.lst
index b92c513..58a3875 100644
--- a/utils.lst
+++ b/utils.lst
@@ -23,6 +23,7 @@ utils/pl2pm
 utils/prove
 utils/ptar
 utils/ptardiff
+utils/bundle.pl
 utils/cpanp-run-perl
 utils/cpanp
 utils/cpan2dist
diff --git a/utils/Makefile.SH b/utils/Makefile.SH
index b5a2f12..df67a84 100644
--- a/utils/Makefile.SH
+++ b/utils/Makefile.SH
@@ -39,9 +39,9 @@ cat >>Makefile <<'!NO!SUBS!'
 # Files to be built with variable substitution after miniperl is
 # available.  Dependencies handled manually below (for now).
 
-pl = c2ph.PL config_data.PL corelist.PL cpan.PL h2ph.PL h2xs.PL instmodsh.PL perlbug.PL perldoc.PL perlivp.PL pl2pm.PL prove.PL ptar.PL ptardiff.PL cpanp-run-perl.PL cpanp.PL cpan2dist.PL shasum.PL splain.PL dprofpp.PL libnetcfg.PL piconv.PL enc2xs.PL xsubpp.PL
-plextract = c2ph config_data corelist cpan h2ph h2xs instmodsh perlbug perldoc perlivp pl2pm prove ptar ptardiff cpanp-run-perl cpanp cpan2dist shasum splain dprofpp libnetcfg piconv enc2xs xsubpp
-plextractexe = ./c2ph ./config_data ./corelist ./cpan ./h2ph ./h2xs ./instmodsh ./perlbug ./perldoc ./perlivp ./pl2pm ./prove ./ptar ./ptardiff ./cpanp-run-perl ./cpanp ./cpan2dist ./shasum ./splain ./dprofpp ./libnetcfg ./piconv ./enc2xs ./xsubpp
+pl = c2ph.PL config_data.PL corelist.PL cpan.PL h2ph.PL h2xs.PL instmodsh.PL perlbug.PL perldoc.PL perlivp.PL pl2pm.PL prove.PL ptar.PL ptardiff.PL bundle.pl.PL cpanp-run-perl.PL cpanp.PL cpan2dist.PL shasum.PL splain.PL dprofpp.PL libnetcfg.PL piconv.PL enc2xs.PL xsubpp.PL
+plextract = c2ph config_data corelist cpan h2ph h2xs instmodsh perlbug perldoc perlivp pl2pm prove ptar ptardiff bundle.pl cpanp-run-perl cpanp cpan2dist shasum splain dprofpp libnetcfg piconv enc2xs xsubpp
+plextractexe = ./c2ph ./config_data ./corelist ./cpan ./h2ph ./h2xs ./instmodsh ./perlbug ./perldoc ./perlivp ./pl2pm ./prove ./ptar ./ptardiff ./bundle.pl ./cpanp-run-perl ./cpanp ./cpan2dist ./shasum ./splain ./dprofpp ./libnetcfg ./piconv ./enc2xs ./xsubpp
 
 all: $(plextract) 
 
@@ -74,6 +74,8 @@ ptar:		ptar.PL ../config.sh
 
 ptardiff:	ptardiff.PL ../config.sh
 
+bundle.pl:	bundle.pl.PL ../config.sh
+
 cpanp-run-perl:	cpanp-run-perl.PL ../config.sh
 
 cpanp:	cpanp.PL ../config.sh
diff --git a/utils/bundle.pl.PL b/utils/bundle.pl.PL
new file mode 100644
index 0000000..c69db5b
--- /dev/null
+++ b/utils/bundle.pl.PL
@@ -0,0 +1,51 @@
+#!/usr/local/bin/perl
+
+use Config;
+use File::Basename qw(&basename &dirname);
+use Cwd;
+
+# List explicitly here the variables you want Configure to
+# generate.  Metaconfig only looks for shell variables, so you
+# have to mention them as if they were shell variables, not
+# %Config entries.  Thus you write
+#  $startperl
+# to ensure Configure will look for $Config{startperl}.
+
+# This forces PL files to create target in same directory as PL file.
+# This is so that make depend always knows where to find PL derivatives.
+my $origdir = cwd;
+chdir dirname($0);
+my $file = basename($0, '.PL');
+$file .= '.com' if $^O eq 'VMS';
+
+open OUT,">$file" or die "Can't create $file: $!";
+
+print "Extracting $file (with variable substitutions)\n";
+
+# In this section, perl variables will be expanded during extraction.
+# You can use $Config{...} to use Configure variables.
+
+print OUT <<"!GROK!THIS!";
+$Config{startperl}
+    eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
+	if \$running_under_some_shell;
+!GROK!THIS!
+
+use File::Spec;
+
+my $script = File::Spec->catfile(
+            File::Spec->catdir(
+                File::Spec->updir, qw[ lib Module Build scripts ]
+            ), "bundle.pl");
+
+if (open(IN, $script)) {
+    print OUT <IN>;
+    close IN;
+} else {
+    die "$0: cannot find '$script'\n";
+}
+
+close OUT or die "Can't close $file: $!";
+chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
+exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';
+chdir $origdir;
diff --git a/win32/Makefile b/win32/Makefile
index 1f1120c..407a4c1 100644
--- a/win32/Makefile
+++ b/win32/Makefile
@@ -611,6 +611,7 @@ UTILS		=			\
 		..\utils\prove		\
 		..\utils\ptar		\
 		..\utils\ptardiff	\
+		..\utils\bundle.pl	\
 		..\utils\cpanp-run-perl	\
 		..\utils\cpanp	\
 		..\utils\cpan2dist	\
@@ -1214,7 +1215,7 @@ distclean: realclean
 	    podchecker podselect
 	-cd ..\utils && del /f h2ph splain perlbug pl2pm c2ph pstruct h2xs \
 	    perldoc perlivp dprofpp libnetcfg enc2xs piconv cpan *.bat \
-	    xsubpp instmodsh prove ptar ptardiff cpanp-run-perl cpanp cpan2dist shasum corelist config_data
+	    xsubpp instmodsh prove ptar ptardiff bundle.pl cpanp-run-perl cpanp cpan2dist shasum corelist config_data
 	-cd ..\x2p && del /f find2perl s2p psed *.bat
 	-del /f ..\config.sh ..\splittree.pl perlmain.c dlutils.c config.h.new \
 	        perlmainst.c
diff --git a/win32/makefile.mk b/win32/makefile.mk
index eac3619..9c60994 100644
--- a/win32/makefile.mk
+++ b/win32/makefile.mk
@@ -753,6 +753,7 @@ UTILS		=			\
 		..\utils\prove		\
 		..\utils\ptar		\
 		..\utils\ptardiff	\
+		..\utils\bundle.pl	\
 		..\utils\cpanp-run-perl	\
 		..\utils\cpanp	\
 		..\utils\cpan2dist	\
@@ -1538,7 +1539,7 @@ distclean: realclean
 	    podselect
 	-cd ..\utils && del /f h2ph splain perlbug pl2pm c2ph pstruct h2xs \
 	    perldoc perlivp dprofpp libnetcfg enc2xs piconv cpan *.bat \
-	    xsubpp instmodsh prove ptar ptardiff cpanp-run-perl cpanp cpan2dist shasum corelist config_data
+	    xsubpp instmodsh prove ptar ptardiff bundle.pl cpanp-run-perl cpanp cpan2dist shasum corelist config_data
 	-cd ..\x2p && del /f find2perl s2p psed *.bat
 	-del /f ..\config.sh ..\splittree.pl perlmain.c dlutils.c config.h.new \
 	    perlmainst.c
-- 
1.5.4.3




nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About