use vars qw($VERSION @ISA);
@ISA = qw(Module::Build::Base);
-$VERSION = '0.28';
+$VERSION = '0.2801';
$VERSION = eval $VERSION;
# Okay, this is the brute-force method of finding out what kind of
C<File::Spec> to make the pathnames work correctly on whatever
platform you're installing on.
-=back
-
-
-=head2 About PREFIX Support
-
-[version 0.28]
-
-First, it is necessary to understand the original idea behind
-C<PREFIX>. If, for example, the default installation locations for
-your machine are F</usr/local/lib/perl5/5.8.5> for modules,
-F</usr/local/bin> for executables, F</usr/local/man/man1> and
-F</usr/local/man/man3> for manual pages, etc., then they all share the
-same "prefix" F</usr/local>. MakeMaker's C<PREFIX> mechanism was
-intended as a way to change an existing prefix that happened to occur
-in all those paths - essentially a C<< s{/usr/local}{/foo/bar} >> for
-each path.
-
-However, the real world is more complicated than that. The C<PREFIX>
-idea is fundamentally broken when your machine doesn't jibe with
-C<PREFIX>'s worldview.
-
-
-=over 4
-
-=item Why PREFIX is not recommended
-
-=over 4
-
-=item *
-
-Many systems have Perl configs that make little sense with PREFIX.
-For example, OS X, where core modules go in
-F</System/Library/Perl/...>, user-installed modules go in
-F</Library/Perl/...>, and man pages go in F</usr/share/man/...>. The
-PREFIX is thus set to F</>. Install L<Foo::Bar> on OS X with
-C<PREFIX=/home/spurkis> and you get things like
-F</home/spurkis/Library/Perl/5.8.1/Foo/Bar.pm> and
-F</home/spurkis/usr/share/man/man3/Foo::Bar.3pm>. Not too pretty.
-
-The problem is not limited to Unix-like platforms, either - on Windows
-builds (e.g. ActiveState perl 5.8.0), we have user-installed modules
-going in F<C:\Perl\site\lib>, user-installed executables going in
-F<C:\Perl\bin>, and PREFIX=F<C:\Perl\site>. The prefix just doesn't
-apply neatly to the executables.
-
-=item *
-
-The PREFIX logic is too complicated and hard to predict for the user.
-It's hard to document what exactly is going to happen. You can't give
-a user simple instructions like "run perl Makefile.PL PREFIX=~ and
-then set PERL5LIB=~/lib/perl5".
-
-=item *
-
-The results from PREFIX will change if your configuration of Perl
-changes (for example, if you upgrade Perl). This means your modules
-will end up in different places.
-
-=item *
-
-The results from PREFIX can change with different releases of
-MakeMaker. The logic of PREFIX is subtle and it has been altered in
-the past (mostly to limit damage in the many "edge cases" when its
-behavior was undesirable).
-
-=item *
-
-PREFIX imposes decisions made by the person who configured Perl onto
-the person installing a module. The person who configured Perl could
-have been you or it could have been some guy at Redhat.
-
-=back
-
-
-=item Alternatives to PREFIX
-
-Module::Build offers L</install_base> as a simple, predictable, and
-user-configurable alternative to ExtUtils::MakeMaker's C<PREFIX>.
-What's more, MakeMaker will soon accept C<INSTALL_BASE> -- we strongly
-urge you to make the switch.
-
-Here's a quick comparison of the two when installing modules to your
-home directory on a unix box:
-
-MakeMaker [*]:
-
- % perl Makefile.PL PREFIX=/home/spurkis
- PERL5LIB=/home/spurkis/lib/perl5/5.8.5:/home/spurkis/lib/perl5/site_perl/5.8.5
- PATH=/home/spurkis/bin
- MANPATH=/home/spurkis/man
+=item prefix
-Module::Build:
+Provided for compatibility with ExtUtils::MakeMaker's PREFIX argument.
+C<prefix> should be used when you wish Module::Build to install your
+modules, documentation and scripts in the same place
+ExtUtils::MakeMaker does.
- % perl Build.PL install_base=/home/spurkis
- PERL5LIB=/home/spurkis/lib/perl5
- PATH=/home/spurkis/bin
- MANPATH=/home/spurkis/man
+The following are equivalent.
-[*] Note that MakeMaker's behaviour cannot be guaranteed in even this
-common scenario, and differs among different versions of MakeMaker.
+ perl Build.PL --prefix /tmp/foo
+ perl Makefile.PL PREFIX=/tmp/foo
-In short, using C<install_base> is similar to the following MakeMaker usage:
+Because of the very complex nature of the prefixification logic, the
+behavior of PREFIX in MakeMaker has changed subtly over time.
+Module::Build's --prefix logic is equivalent to the PREFIX logic found
+in ExtUtils::MakeMaker 6.30.
- perl Makefile.PL PREFIX=/home/spurkis LIB=/home/spurkis/lib/perl5
+If you do not need to retain compatibility with ExtUtils::MakeMaker or
+are starting a fresh Perl installation we recommand you use
+C<install_base> instead (and C<INSTALL_BASE> in ExtUtils::MakeMaker).
+See L<Module::Build::Cookbook/Instaling in the same location as
+ExtUtils::MakeMaker> for further information.
-See L</"INSTALL PATHS"> for details on other
-installation options available and how to configure them.
=back
}
}
+sub is_executable {
+ # We assume this does the right thing on generic platforms, though
+ # we do some other more specific stuff on Unixish platforms.
+ my ($self, $file) = @_;
+ return -x $file;
+}
+
sub _startperl { shift()->config('startperl') }
# Return any directories in @INC which are not in the default @INC for
my $pods = $self->_find_pods( $self->{properties}{"${type}doc_dirs"},
exclude => [ qr/\.(?:bat|com|html)$/ ] );
- next unless %$pods; # nothing to do
+ return unless %$pods; # nothing to do
unless ( -d $htmldir ) {
File::Path::mkpath($htmldir, 0, 0755)
$self->log_info("$file -> $to_path\n") if $args{verbose};
File::Copy::copy($file, $to_path) or die "Can't copy('$file', '$to_path'): $!";
# mode is read-only + (executable if source is executable)
- my $mode = 0444 | ( -x $file ? 0111 : 0 );
+ my $mode = 0444 | ( $self->is_executable($file) ? 0111 : 0 );
chmod( $mode, $to_path );
return $to_path;
Revision history for Perl extension Module::Build.
+0.2801 Sun May 21 00:07:40 CDT 2006
+
+ - Module::Build::Compat's emulation of INC is incorrectly prepending
+ a -I to the value of INC. This is incorrect because there should
+ already be a -I on the value. I.E. it's "perl Makefile.PL INC=-Ifoo"
+ not "perl Makefile.PL INC=foo" so Compat should not prefix a -I.
+ [Michael Schwern]
+
+ - Native batch scripts under Windows should not be converted by
+ pl2bat. [Spotted by Ron Savage]
+
+ - Tweaked the way we determine whether a file is executable on Unix.
+ We use this determination to decide whether to make it executable
+ during installation. [Julian Mehnle]
+
+ - Replaced a vestigial 'next' with 'return' now that the code is in a
+ subroutine (htmlify_pods()), not a loop. [Ron Savage]
+
+ - Fixed a guaranteed failure in t/signature.t when TEST_SIGNATURE was
+ set. [Eric R. Meyers]
+
+ - Fixed a test failure that occurred when testing or installing in
+ unattended mode - the code to test whether unattended mode and
+ attended mode are working properly was assuming that we started out
+ in attended mode. [Steve Peters]
+
+ - Improved our stand-in YAML generator that we use to generate
+ META.yaml when authors don't have a copy of YAML.pm installed on
+ their machine. It was unable to handle things like embedded
+ newlines in the data, now it has a much more extensive escaping
+ mechanism. [Stephen Adkins]
+
+ - Revised the docs for --prefix and PREFIX. [Michael Schwern]
+
0.28 Thu Apr 27 22:25:00 CDT 2006
- When y_n() or prompt() are called without a default value and the
(
TEST_VERBOSE => 'verbose',
VERBINST => 'verbose',
- INC => sub { map {('--extra_compiler_flags', "-I$_")} Module::Build->split_like_shell(shift) },
+ INC => sub { map {('--extra_compiler_flags', $_)} Module::Build->split_like_shell(shift) },
POLLUTE => sub { ('--extra_compiler_flags', '-DPERL_POLLUTE') },
INSTALLDIRS => sub {local $_ = shift; 'installdirs=' . (/^perl$/ ? 'core' : $_) },
LIB => sub { ('--install_path', 'lib='.shift()) },
To install to a non-standard directory (for example, if you don't have
permission to install in the system-wide directories), you can use the
-C<install_base> or C<prefix> parameters:
+C<install_base>:
./Build install --install_base /foo/bar
- or
- ./Build install --prefix /foo/bar
-
-Note that these have somewhat different effects - C<prefix> is an
-emulation of C<ExtUtils::MakeMaker>'s old C<PREFIX> setting, and
-inherits all its nasty gotchas. C<install_base> is more predictable,
-and newer versions of C<ExtUtils::MakeMaker> also support it, so it's
-often your best choice.
See L<Module::Build/"INSTALL PATHS"> for a much more complete
discussion of how installation paths are determined.
+=head2 Installing in the same location as ExtUtils::MakeMaker
+
+With the introduction of C<--prefix> in Module::Build 0.28 and
+C<INSTALL_BASE> in ExtUtils::MakeMaker 6.31 its easy to get them both
+to install to the same locations.
+
+First, ensure you have at least version 0.28 of Module::Build
+installed and 6.31 of ExtUtils::MakeMaker. Prior versions have
+differing installation behaviors.
+
+The following installation flags are equivalent between
+ExtUtils::MakeMaker and Module::Build.
+
+ MakeMaker Module::Build
+ PREFIX=... --prefix ...
+ INSTALL_BASE=... --install_base ...
+ DESTDIR=... --destdir ...
+ LIB=... --install_path lib=...
+ INSTALLDIRS=... --installdirs ...
+ INSTALLDIRS=perl --installdirs core
+ UNINST=... --uninst ...
+ INC=... --extra_compiler_flags ...
+ POLLUTE=1 --extra_compiler_flags -DPERL_POLLUTE
+
+For example, if you are currently installing MakeMaker modules with
+this command:
+
+ perl Makefile.PL PREFIX=~
+ make test
+ make install UNINST=1
+
+You can install into the same location with Module::Build using this:
+
+ perl Build.PL --prefix ~
+ ./Build test
+ ./Build install --uninst 1
+
+=head3 C<prefix> vs C<install_base>
+
+The behavior of C<prefix> is complicated and depends closely on
+how your Perl is configured. The resulting installation locations
+will vary from machine to machine and even different installations of
+Perl on the same machine. Because of this, its difficult to document
+where C<prefix> will place your modules.
+
+In contrast, C<install_base> has predictable, easy to explain
+installation locations. Now that Module::Build and MakeMaker both
+have C<install_base> there is little reason to use C<prefix> other
+than to preserve your existing installation locations. If you are
+starting a fresh Perl installation we encourage you to use
+C<install_base>. If you have an existing installation installed via
+C<prefix>, consider moving it to an installation structure matching
+C<install_base> and using that instead.
+
+
=head2 Running a single test file
C<Module::Build> supports running a single test, which enables you to
$self->SUPER::make_tarball(@_);
}
+sub is_executable {
+ # We consider the owner bit to be authoritative on a file, because
+ # -x will always return true if the user is root and *any*
+ # executable bit is set. The -x test seems to try to answer the
+ # question "can I execute this file", but I think we want "is this
+ # file executable".
+
+ my ($self, $file) = @_;
+ return +(stat $file)[2] & 0100;
+}
+
sub _startperl { "#! " . shift()->perl }
sub _construct {
$self->SUPER::make_executable(@_);
foreach my $script (@_) {
- my %opts = ();
- if ( $script eq $self->build_script ) {
- $opts{ntargs} = q(-x -S %0 --build_bat %*);
- $opts{otherargs} = q(-x -S "%0" --build_bat %1 %2 %3 %4 %5 %6 %7 %8 %9);
- }
- my $out = eval {$self->pl2bat(in => $script, update => 1, %opts)};
- if ( $@ ) {
- $self->log_warn("WARNING: Unable to convert file '$script' to an executable script:\n$@");
+ # Native batch script
+ if ( $script =~ /\.(bat|cmd)$/ ) {
+ $self->SUPER::make_executable($script);
+ next;
+
+ # Perl script that needs to be wrapped in a batch script
} else {
- $self->SUPER::make_executable($out);
+ my %opts = ();
+ if ( $script eq $self->build_script ) {
+ $opts{ntargs} = q(-x -S %0 --build_bat %*);
+ $opts{otherargs} = q(-x -S "%0" --build_bat %1 %2 %3 %4 %5 %6 %7 %8 %9);
+ }
+
+ my $out = eval {$self->pl2bat(in => $script, update => 1, %opts)};
+ if ( $@ ) {
+ $self->log_warn("WARNING: Unable to convert file '$script' to an executable script:\n$@");
+ } else {
+ $self->SUPER::make_executable($out);
+ }
}
}
}
}
sub _yaml_value {
- # XXX doesn't handle embedded newlines
my ($value) = @_;
- # undefs and empty strings will become empty strings
- if (! defined $value || $value eq "") {
- return('""');
+ # undefs become ~
+ if (! defined $value) {
+ return("~");
}
- # allow simple scalars (without embedded quote chars) to be unquoted
- elsif ($value !~ /["'\\]/) {
- return($value);
+ # empty strings will become empty strings
+ elsif (! defined $value || $value eq "") {
+ return('""');
}
- # strings without double-quotes get double-quoted
- elsif ($value !~ /\"/) {
- $value =~ s{\\}{\\\\}g;
- return qq{"$value"};
+ # quote and escape strings with special values
+ elsif ($value =~ /["'`~\n!\@\#^\&\*\(\)\{\}\[\]\|<>\?]/) {
+ if ($value !~ /['`~\n!\#^\&\*\(\)\{\}\[\]\|\?]/) { # nothing but " or @ or < or > (email addresses)
+ return("'" . $value . "'");
+ }
+ else {
+ $value =~ s/\n/\\n/g; # handle embedded newlines
+ $value =~ s/"/\\"/g; # handle embedded quotes
+ return('"' . $value . '"');
+ }
}
- # other strings get single-quoted
+ # allow simple scalars (without embedded quote chars) to be unquoted
+ # (includes $%_+=-\;:,./)
else {
- $value =~ s{([\\'])}{\\$1}g;
- return qq{'$value'};
+ return($value);
}
}
# We have a few extra exports, but Test::More has a special import()
# that won't take extra additions.
-my @extra_exports = qw(stdout_of stderr_of slurp find_in_path check_compiler);
+my @extra_exports = qw(stdout_of stderr_of slurp find_in_path check_compiler have_module);
push @EXPORT, @extra_exports;
__PACKAGE__->export(scalar caller, @extra_exports);
return ($have_c_compiler, $mb->feature('C_support'));
}
+sub have_module {
+ my $module = shift;
+ return eval "use $module; 1";
+}
+
1;
$dir = "t" if (-d "t");
{
- use_ok("Module::Build::YAML");
- my ($expected, $got, $var);
- $var = {
+ use_ok("Module::Build::YAML");
+ my ($expected, $got, $var);
+ ##########################################################
+ # Test a typical-looking Module::Build structure (alphabetized)
+ ##########################################################
+ $var = {
'resources' => {
'license' => 'http://opensource.org/licenses/artistic-license.php'
},
},
'abstract' => 'A framework for building dynamic widgets or full applications in Javascript'
};
- $expected = <<EOF;
+ $expected = <<'EOF';
---
abstract: A framework for building dynamic widgets or full applications in Javascript
author:
- - '"Stephen Adkins" <spadkins\@gmail.com>'
+ - '"Stephen Adkins" <spadkins@gmail.com>'
build_requires:
App::Build: 0
File::Spec: 0
$got = &Module::Build::YAML::Dump($var);
is($got, $expected, "Dump(): single deep hash");
- $expected = <<EOF;
+ ##########################################################
+ # Test a typical-looking Module::Build structure (ordered)
+ ##########################################################
+ $expected = <<'EOF';
---
name: js-app
version: 0.13
author:
- - '"Stephen Adkins" <spadkins\@gmail.com>'
+ - '"Stephen Adkins" <spadkins@gmail.com>'
abstract: A framework for building dynamic widgets or full applications in Javascript
license: lgpl
resources:
$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;
+ $expected = <<'EOF';
---
e
---
- is
- 3.1416
---
-6: ""
+6: ~
fun: under_sun
-more: ""
+more: ~
EOF
$got = &Module::Build::YAML::Dump(@$var);
is($got, $expected, "Dump(): multiple, various");
- $expected = <<EOF;
+ ##########################################################
+ # Test that a single array ref turns into one document
+ ##########################################################
+ $expected = <<'EOF';
---
- e
- 2.71828
- is
- 3.1416
-
- 6: ""
+ 6: ~
fun: under_sun
- more: ""
+ 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)");
+
}
use strict;
use lib $ENV{PERL_CORE} ? '../lib/Module/Build/t/lib' : 't/lib';
-use MBTest tests => 28;
+use MBTest tests => 32;
use Module::Build;
use Module::Build::ConfigData;
ok ! -e $mb->config_dir;
ok ! -e $mb->dist_dir;
+chdir( $cwd ) or die "Can''t chdir to '$cwd': $!";
+$dist->remove;
+
+SKIP: {
+ skip( 'Windows only test', 4 ) unless $^O =~ /^MSWin/;
+
+ my $script_data = <<'---';
+@echo off
+echo Hello, World!
+---
+
+ $dist = DistGen->new( dir => $tmp );
+ $dist->change_file( 'Build.PL', <<'---' );
+use Module::Build;
+my $build = new Module::Build(
+ module_name => 'Simple',
+ scripts => [ 'bin/script.bat' ],
+ license => 'perl',
+);
+$build->create_build_script;
+---
+ $dist->add_file( 'bin/script.bat', $script_data );
+
+ $dist->regen;
+ chdir( $dist->dirname ) or die "Can't chdir to '@{[$dist->dirname]}': $!";
+
+ $mb = Module::Build->new_from_context;
+ ok $mb;
+
+ eval{ $mb->dispatch('build') };
+ is $@, '';
+
+ my $script_file = File::Spec->catfile( qw(blib script), 'script.bat' );
+ ok -f $script_file, "Native batch file copied to 'scripts'";
+
+ my $out = slurp( $script_file );
+ is $out, $script_data, ' unmodified by pl2bat';
+
+ chdir( $cwd ) or die "Can''t chdir to '$cwd': $!";
+ $dist->remove;
+}
# cleanup
chdir( $cwd ) or die "Can''t chdir to '$cwd': $!";