package CPANPLUS::Dist::Build;
use strict;
+use warnings;
use vars qw[@ISA $STATUS $VERSION];
@ISA = qw[CPANPLUS::Dist];
use Config;
use FileHandle;
use Cwd;
+use version;
use IPC::Cmd qw[run];
use Params::Check qw[check];
local $Params::Check::VERBOSE = 1;
-$VERSION = '0.06_02';
+$VERSION = '0.08';
=pod
=head1 NAME
-CPANPLUS::Dist::Build
+CPANPLUS::Dist::Build - CPANPLUS plugin to install packages that use Build.PL
=head1 SYNOPSIS
module => $modobj,
);
- $build->prepare; # runs Module::Build->new_from_context;
+ $build->prepare; # runs Build.PL
$build->create; # runs build && build test
$build->install; # runs build install
=over 4
-=item parent()
+=item C<parent()>
Returns the C<CPANPLUS::Module> object that parented this object.
-=item status()
+=item C<status()>
Returns the C<Object::Accessor> object that keeps the status for
this module.
=over 4
-=item build_pl ()
+=item C<build_pl ()>
Location of the Build file.
Set to 0 explicitly if something went wrong.
-=item build ()
+=item C<build ()>
BOOL indicating if the C<Build> command was successful.
-=item test ()
+=item C<test ()>
BOOL indicating if the C<Build test> command was successful.
-=item prepared ()
+=item C<prepared ()>
BOOL indicating if the C<prepare> call exited succesfully
This gets set after C<perl Build.PL>
-=item distdir ()
+=item C<distdir ()>
Full path to the directory in which the C<prepare> call took place,
set after a call to C<prepare>.
-=item created ()
+=item C<created ()>
BOOL indicating if the C<create> call exited succesfully. This gets
set after C<Build> and C<Build test>.
-=item installed ()
+=item C<installed ()>
BOOL indicating if the module was installed. This gets set after
C<Build install> exits successfully.
BOOL indicating if the module was uninstalled properly.
-=item _create_args ()
+=item C<_create_args ()>
Storage of the arguments passed to C<create> for this object. Used
for recursive calls when satisfying prerequisites.
-=item _install_args ()
+=item C<_install_args ()>
Storage of the arguments passed to C<install> for this object. Used
for recursive calls when satisfying prerequisites.
-=item _mb_object ()
-
-Storage of the C<Module::Build> object we used for this installation.
-
=back
=cut
-
=head1 METHODS
=head2 $bool = CPANPLUS::Dist::Build->format_available();
=head2 $bool = $dist->prepare([perl => '/path/to/perl', buildflags => 'EXTRA=FLAGS', force => BOOL, verbose => BOOL])
-C<prepare> prepares a distribution, running C<Module::Build>'s
-C<new_from_context> method, and establishing any prerequisites this
+C<prepare> prepares a distribution, running C<Build.PL>
+and establishing any prerequisites this
distribution has.
-When running C<< Module::Build->new_from_context >>, the environment
-variable C<PERL5_CPANPLUS_IS_EXECUTING> will be set to the full path
+The variable C<PERL5_CPANPLUS_IS_EXECUTING> will be set to the full path
of the C<Build.PL> that is being executed. This enables any code inside
the C<Build.PL> to know that it is being installed via CPANPLUS.
RUN: {
# Wrap the exception that may be thrown here (should likely be
# done at a much higher level).
- my $mb = eval {
- my $env = 'ENV_CPANPLUS_IS_EXECUTING';
- local $ENV{$env} = BUILD_PL->( $dir );
- Module::Build->new_from_context( %buildflags )
- };
- if( !$mb or $@ ) {
- error(loc("Could not create Module::Build object: %1","$@"));
+ my $prep_output;
+
+ my $env = 'ENV_CPANPLUS_IS_EXECUTING';
+ local $ENV{$env} = BUILD_PL->( $dir );
+
+ unless ( scalar run( command => [$perl, BUILD_PL->($dir), $buildflags],
+ buffer => \$prep_output,
+ verbose => $verbose )
+ ) {
+ error( loc( "Build.PL failed: %1", $prep_output ) );
$fail++; last RUN;
}
- $dist->status->_mb_object( $mb );
+ msg( $prep_output, 0 );
- $self->status->prereqs( $dist->_find_prereqs( verbose => $verbose ) );
+ $self->status->prereqs( $dist->_find_prereqs( verbose => $verbose,
+ dir => $dir,
+ perl => $perl,
+ buildflags => $buildflags ) );
}
sub _find_prereqs {
my $dist = shift;
- my $mb = $dist->status->_mb_object;
my $self = $dist->parent;
my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my ($verbose, $dir, $buildflags, $perl);
+ my $tmpl = {
+ verbose => { default => $conf->get_conf('verbose'), store => \$verbose },
+ dir => { default => $self->status->extract, store => \$dir },
+ perl => { default => $^X, store => \$perl },
+ buildflags => { default => $conf->get_conf('buildflags'),
+ store => \$buildflags },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
my $prereqs = {};
+
+ my $safe_ver = version->new('0.31_03');
+
+ my $content;
+
+ if ( version->new( $Module::Build::VERSION ) >= $safe_ver ) {
+ # Use the new Build action 'prereq_data'
+
+ unless ( scalar run( command => [$perl, BUILD->($dir), 'prereq_data', $buildflags],
+ buffer => \$content,
+ verbose => 0 )
+ ) {
+ error( loc( "Build 'prereq_data' failed: %1 %2", $!, $content ) );
+ return;
+ }
+
+ }
+ else {
+ my $file = File::Spec->catfile( $dir, '_build', 'prereqs' );
+ return unless -f $file;
+
+ my $fh = FileHandle->new();
+
+ unless( $fh->open( $file ) ) {
+ error( loc( "Cannot open '%1': %2", $file, $! ) );
+ return;
+ }
+
+ $content = do { local $/; <$fh> };
+ }
+
+ my $bphash = eval $content;
+ return unless $bphash and ref $bphash eq 'HASH';
foreach my $type ('requires', 'build_requires') {
- my $p = $mb->$type() || {};
- $prereqs->{$_} = $p->{$_} foreach keys %$p;
+ next unless $bphash->{$type} and ref $bphash->{$type} eq 'HASH';
+ $prereqs->{$_} = $bphash->{$type}->{$_} for keys %{ $bphash->{$type} };
}
+ # Temporary fix
+ delete $prereqs->{'perl'};
+
### allows for a user defined callback to filter the prerequisite
### list as they see fit, to remove (or add) any prereqs they see
### fit. The default installed callback will return the hashref in
return { %$href };
}
-sub prereq_satisfied {
- # Return true if this prereq is satisfied. Return false if it's
- # not. Also issue an error if the latest CPAN version doesn't
- # satisfy it.
-
- my ($dist, %args) = @_;
- my $mb = $dist->status->_mb_object;
- my $cb = $dist->parent->parent;
- my $mod = $args{modobj}->module;
-
- my $status = $mb->check_installed_status($mod, $args{version});
- return 1 if $status->{ok};
-
- # Check the latest version from the CPAN index
- {
- no strict 'refs';
- local ${$mod . '::VERSION'} = $args{modobj}->version;
- $status = $mb->check_installed_status($mod, $args{version});
- }
- unless( $status->{ok} ) {
- error(loc("This distribution depends on $mod, but the latest version of $mod on CPAN ".
- "doesn't satisfy the specific version dependency ($args{version}). ".
- "Please try to resolve this dependency manually."));
- }
-
- return 0;
-}
-
=pod
=head2 $dist->create([perl => '/path/to/perl', buildflags => 'EXTRA=FLAGS', prereq_target => TARGET, force => BOOL, verbose => BOOL, skiptest => BOOL])
C<create> preps a distribution for installation. This means it will
-run C<Build> and C<Build test>, via the C<Module::Build> API.
+run C<Build> and C<Build test>.
This will also satisfy any prerequisites the module may have.
If you set C<skiptest> to true, it will skip the C<Build test> stage.
my $cb = $self->parent;
my $conf = $cb->configure_object;
- my $mb = $dist->status->_mb_object;
my %hash = @_;
my $dir;
last RUN;
}
- eval { $mb->dispatch('build', %buildflags) };
- if( $@ ) {
- error(loc("Could not run '%1': %2", 'Build', "$@"));
+ my $captured;
+
+ unless ( scalar run( command => [$perl, BUILD->($dir), $buildflags],
+ buffer => \$captured,
+ verbose => $verbose )
+ ) {
+ error( loc( "MAKE failed:\n%1", $captured ) );
$dist->status->build(0);
$fail++; last RUN;
}
+ msg( $captured, 0 );
+
$dist->status->build(1);
### add this directory to your lib ###
- $cb->_add_to_includepath(
- directories => [ BLIB_LIBDIR->( $self->status->extract ) ]
- );
+ $self->add_to_includepath();
### this buffer will not include what tests failed due to a
### M::B/Test::Harness bug. Reported as #9793 with patch
### against 0.2607 on 26/1/2005
unless( $skiptest ) {
- eval { $mb->dispatch('test', %buildflags) };
- if( $@ ) {
- error(loc("Could not run '%1': %2", 'Build test', "$@"));
+ my $test_output;
+ my $flag = ON_VMS ? '"test"' : 'test';
+ my $cmd = [$perl, BUILD->($dir), $flag, $buildflags];
+ unless ( scalar run( command => $cmd,
+ buffer => \$test_output,
+ verbose => $verbose )
+ ) {
+ error( loc( "MAKE TEST failed:\n%1 ", $test_output ) );
### mark specifically *test* failure.. so we dont
### send success on force...
$test_fail++;
if( !$force and !$cb->_callbacks->proceed_on_test_failure->(
- $self, $@ )
+ $self, $@ )
) {
- $dist->status->test(0);
- $fail++; last RUN;
+ $dist->status->test(0);
+ $fail++; last RUN;
}
-
- } else {
+
+ }
+ else {
+ msg( $test_output, 0 );
$dist->status->test(1);
}
- } else {
+ }
+ else {
msg(loc("Tests skipped"), $verbose);
- }
+ }
}
unless( $cb->_chdir( dir => $orig ) ) {
### we're also the cpan_dist, since we don't need to have anything
### prepared from another installer
$dist = $self->status->dist_cpan if $self->status->dist_cpan;
- my $mb = $dist->status->_mb_object;
my $cb = $self->parent;
my $conf = $cb->configure_object;
} else {
my %buildflags = $dist->_buildflags_as_hash($buildflags);
- eval { $mb->dispatch('install', %buildflags) };
- if( $@ ) {
- error(loc("Could not run '%1': %2", 'Build install', "$@"));
+ my $install_output;
+ my $flag = ON_VMS ? '"install"' : 'install';
+ my $cmd = [$perl, BUILD->($dir), $flag, $buildflags];
+ unless( scalar run( command => $cmd,
+ buffer => \$install_output,
+ verbose => $verbose )
+ ) {
+ error(loc("Could not run '%1': %2", 'Build install', $install_output));
$fail++;
}
+ else {
+ msg( $install_output, 0 );
+ }
}
return %$argv;
}
-
-sub dist_dir {
- ### just in case you already did a create call for this module object
- ### just via a different dist object
- my $dist = shift;
- my $self = $dist->parent;
-
- ### we're also the cpan_dist, since we don't need to have anything
- ### prepared from another installer
- $dist = $self->status->dist_cpan if $self->status->dist_cpan;
- my $mb = $dist->status->_mb_object;
-
- my $cb = $self->parent;
- my $conf = $cb->configure_object;
- my %hash = @_;
-
-
- my $dir;
- unless( $dir = $self->status->extract ) {
- error( loc( "No dir found to operate on!" ) );
- return;
- }
-
- ### chdir to work directory ###
- my $orig = cwd();
- unless( $cb->_chdir( dir => $dir ) ) {
- error( loc( "Could not chdir to build directory '%1'", $dir ) );
- return;
- }
-
- my $fail; my $distdir;
- TRY: {
- $dist->prepare( @_ ) or (++$fail, last TRY);
-
-
- eval { $mb->dispatch('distdir') };
- if( $@ ) {
- error(loc("Could not run '%1': %2", 'Build distdir', "$@"));
- ++$fail, last TRY;
- }
-
- ### /path/to/Foo-Bar-1.2/Foo-Bar-1.2
- $distdir = File::Spec->catdir( $dir, $self->package_name . '-' .
- $self->package_version );
-
- unless( -d $distdir ) {
- error(loc("Do not know where '%1' got created", 'distdir'));
- ++$fail, last TRY;
- }
- }
-
- unless( $cb->_chdir( dir => $orig ) ) {
- error( loc( "Could not chdir to start directory '%1'", $orig ) );
- return;
- }
-
- return if $fail;
- return $distdir;
-}
-
-=head1 KNOWN ISSUES
-
-Below are some of the known issues with Module::Build, that we hope
-the authors will resolve at some point, so we can make full use of
-Module::Build's power.
-The number listed is the bug number on C<rt.cpan.org>.
-
-=over 4
-
-=item * Module::Build can not be upgraded using its own API (#13169)
-
-This is due to the fact that the Build file insists on adding a path
-to C<@INC> which force the loading of the C<not yet installed>
-Module::Build when it shells out to run it's own build procedure:
-
-=item * Module::Build does not provide access to install history (#9793)
-
-C<Module::Build> runs the create, test and install procedures in it's
-own processes, but does not provide access to any diagnostic messages of
-those processes. As an end result, we can not offer these diagnostic
-messages when, for example, reporting automated build failures to sites
-like C<testers.cpan.org>.
-
-=back
-
=head1 AUTHOR
Originally by Jos Boumans E<lt>kane@cpan.orgE<gt>. Brought to working
-condition and currently maintained by Ken Williams E<lt>kwilliams@cpan.orgE<gt>.
+condition by Ken Williams E<lt>kwilliams@cpan.orgE<gt>.
+
+Other hackery and currently maintained by Chris 'BinGOs' Williams ( no relation ). E<lt>bingos@cpan.orgE<gt>.
-=head1 COPYRIGHT
+=head1 LICENSE
The CPAN++ interface (of which this module is a part of) is
copyright (c) 2001, 2002, 2003, 2004, 2005 Jos Boumans E<lt>kane@cpan.orgE<gt>.
1;
+
# Local variables:
# c-indentation-style: bsd
# c-basic-offset: 4
# indent-tabs-mode: nil
# End:
# vim: expandtab shiftwidth=4:
+