📄 build.pm
字号:
package CPANPLUS::Dist::Build;use strict;use vars qw[@ISA $STATUS $VERSION];@ISA = qw[CPANPLUS::Dist];use CPANPLUS::inc;use CPANPLUS::Internals::Constants;### these constants were exported by CPANPLUS::Internals::Constants### in previous versions.. they do the same though. If we want to have### a normal 'use' here, up the dependency to CPANPLUS 0.056 or higherBEGIN { require CPANPLUS::Dist::Build::Constants; CPANPLUS::Dist::Build::Constants->import() if not __PACKAGE__->can('BUILD') && __PACKAGE__->can('BUILD_DIR');}use CPANPLUS::Error;use Config;use FileHandle;use Cwd;use IPC::Cmd qw[run];use Params::Check qw[check];use Module::Load::Conditional qw[can_load check_install];use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';local $Params::Check::VERBOSE = 1;$VERSION = '0.06_02';=pod=head1 NAMECPANPLUS::Dist::Build=head1 SYNOPSIS my $build = CPANPLUS::Dist->new( format => 'CPANPLUS::Dist::Build', module => $modobj, ); $build->prepare; # runs Module::Build->new_from_context; $build->create; # runs build && build test $build->install; # runs build install=head1 DESCRIPTIONC<CPANPLUS::Dist::Build> is a distribution class for C<Module::Build>related modules.Using this package, you can create, install and uninstall perlmodules. It inherits from C<CPANPLUS::Dist>.Normal users won't have to worry about the interface to this module,as it functions transparently as a plug-in to C<CPANPLUS> and will just C<Do The Right Thing> when it's loaded.=head1 ACCESSORS=over 4=item parent()Returns the C<CPANPLUS::Module> object that parented this object.=item status()Returns the C<Object::Accessor> object that keeps the status forthis module.=back=head1 STATUS ACCESSORSAll accessors can be accessed as follows: $build->status->ACCESSOR=over 4=item build_pl ()Location of the Build file.Set to 0 explicitly if something went wrong.=item build ()BOOL indicating if the C<Build> command was successful.=item test ()BOOL indicating if the C<Build test> command was successful.=item prepared ()BOOL indicating if the C<prepare> call exited succesfullyThis gets set after C<perl Build.PL>=item distdir ()Full path to the directory in which the C<prepare> call took place,set after a call to C<prepare>. =item created ()BOOL indicating if the C<create> call exited succesfully. This getsset after C<Build> and C<Build test>.=item installed ()BOOL indicating if the module was installed. This gets set afterC<Build install> exits successfully.=item uninstalled ()BOOL indicating if the module was uninstalled properly.=item _create_args ()Storage of the arguments passed to C<create> for this object. Usedfor recursive calls when satisfying prerequisites.=item _install_args ()Storage of the arguments passed to C<install> for this object. Usedfor 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();Returns a boolean indicating whether or not you can use this packageto create and install modules in your environment.=cut### check if the format is available ###sub format_available { my $mod = "Module::Build"; unless( can_load( modules => { $mod => '0.2611' } ) ) { error( loc( "You do not have '%1' -- '%2' not available", $mod, __PACKAGE__ ) ); return; } return 1;}=head2 $bool = $dist->init();Sets up the C<CPANPLUS::Dist::Build> object for use.Effectively creates all the needed status accessors.Called automatically whenever you create a new C<CPANPLUS::Dist> object.=cutsub init { my $dist = shift; my $status = $dist->status; $status->mk_accessors(qw[build_pl build test created installed uninstalled _create_args _install_args _prepare_args _mb_object _buildflags ]); ### just in case 'format_available' didn't get called require Module::Build; return 1;}=pod=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 thisdistribution has.When running C<< Module::Build->new_from_context >>, the environment 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 insidethe C<Build.PL> to know that it is being installed via CPANPLUS.After a succcesfull C<prepare> you may call C<create> to create thedistribution, followed by C<install> to actually install it.Returns true on success and false on failure.=cutsub prepare { ### 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; $self->status->dist_cpan( $dist ) unless $self->status->dist_cpan; 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; } my $args; my( $force, $verbose, $buildflags, $perl); { local $Params::Check::ALLOW_UNKNOWN = 1; my $tmpl = { force => { default => $conf->get_conf('force'), store => \$force }, verbose => { default => $conf->get_conf('verbose'), store => \$verbose }, perl => { default => $^X, store => \$perl }, buildflags => { default => $conf->get_conf('buildflags'), store => \$buildflags }, }; $args = check( $tmpl, \%hash ) or return; } return 1 if $dist->status->prepared && !$force; $dist->status->_prepare_args( $args ); ### chdir to work directory ### my $orig = cwd(); unless( $cb->_chdir( dir => $dir ) ) { error( loc( "Could not chdir to build directory '%1'", $dir ) ); return; } ### by now we've loaded module::build, and we're using the API, so ### it's safe to remove CPANPLUS::inc from our inc path, especially ### because it can trip up tests run under taint (just like EU::MM). ### turn off our PERL5OPT so no modules from CPANPLUS::inc get ### included in make test -- it should build without. ### also, modules that run in taint mode break if we leave ### our code ref in perl5opt ### XXX we've removed the ENV settings from cp::inc, so only need ### to reset the @INC #local $ENV{PERL5OPT} = CPANPLUS::inc->original_perl5opt; #local $ENV{PERL5LIB} = CPANPLUS::inc->original_perl5lib; local @INC = CPANPLUS::inc->original_inc; ### this will generate warnings under anything lower than M::B 0.2606 my %buildflags = $dist->_buildflags_as_hash( $buildflags ); $dist->status->_buildflags( $buildflags ); my $fail; 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","$@")); $fail++; last RUN; } $dist->status->_mb_object( $mb ); $self->status->prereqs( $dist->_find_prereqs( verbose => $verbose ) ); } ### send out test report? ### if( $fail and $conf->get_conf('cpantest') ) { $cb->_send_report( module => $self, failed => $fail, buffer => CPANPLUS::Error->stack_as_string, verbose => $verbose, force => $force, ) or error(loc("Failed to send test report for '%1'", $self->module ) ); } unless( $cb->_chdir( dir => $orig ) ) { error( loc( "Could not chdir back to start dir '%1'", $orig ) ); } ### save where we wrote this stuff -- same as extract dir in normal ### installer circumstances $dist->status->distdir( $self->status->extract ); return $dist->status->prepared( $fail ? 0 : 1 );}sub _find_prereqs { my $dist = shift; my $mb = $dist->status->_mb_object; my $self = $dist->parent; my $cb = $self->parent; my $prereqs = {}; foreach my $type ('requires', 'build_requires') { my $p = $mb->$type() || {}; $prereqs->{$_} = $p->{$_} foreach keys %$p; } ### 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 ### an unmodified form ### this callback got added after cpanplus 0.0562, so use a 'can' ### to find out if it's supported. For older versions, we'll just ### return the hashref as is ourselves. my $href = $cb->_callbacks->can('filter_prereqs') ? $cb->_callbacks->filter_prereqs->( $cb, $prereqs ) : $prereqs; $self->status->prereqs( $href ); ### make sure it's not the same ref 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 willrun C<Build> and C<Build test>, via the C<Module::Build> API.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.If you set C<force> to true, it will go over all the stages of theC<Build> process again, ignoring any previously cached results. Itwill also ignore a bad return value from C<Build test> and still allowthe operation to return true.Returns true on success and false on failure.You may then call C<< $dist->install >> on the object to actuallyinstall it.=cutsub create { ### 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -