1 package CPANPLUS::Dist::MM;
4 use vars qw[@ISA $STATUS];
5 @ISA = qw[CPANPLUS::Dist];
8 use CPANPLUS::Internals::Constants;
9 use CPANPLUS::Internals::Constants::Report;
15 use Params::Check qw[check];
16 use File::Basename qw[dirname];
17 use Module::Load::Conditional qw[can_load check_install];
18 use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
20 local $Params::Check::VERBOSE = 1;
30 my $mm = CPANPLUS::Dist->new(
31 format => 'makemaker',
34 $mm->create; # runs make && make test
35 $mm->install; # runs make install
40 C<CPANPLUS::Dist::MM> is a distribution class for MakeMaker related
42 Using this package, you can create, install and uninstall perl
43 modules. It inherits from C<CPANPLUS::Dist>.
51 Returns the C<CPANPLUS::Module> object that parented this object.
55 Returns the C<Object::Accessor> object that keeps the status for
60 =head1 STATUS ACCESSORS
62 All accessors can be accessed as follows:
69 Location of the Makefile (or Build file).
70 Set to 0 explicitly if something went wrong.
74 BOOL indicating if the C<make> (or C<Build>) command was successful.
78 BOOL indicating if the C<make test> (or C<Build test>) command was
83 BOOL indicating if the C<prepare> call exited succesfully
84 This gets set after C<perl Makefile.PL>
88 Full path to the directory in which the C<prepare> call took place,
89 set after a call to C<prepare>.
93 BOOL indicating if the C<create> call exited succesfully. This gets
94 set after C<make> and C<make test>.
98 BOOL indicating if the module was installed. This gets set after
99 C<make install> (or C<Build install>) exits successfully.
103 BOOL indicating if the module was uninstalled properly.
105 =item _create_args ()
107 Storage of the arguments passed to C<create> for this object. Used
108 for recursive calls when satisfying prerequisites.
110 =item _install_args ()
112 Storage of the arguments passed to C<install> for this object. Used
113 for recursive calls when satisfying prerequisites.
121 =head2 $bool = $dist->format_available();
123 Returns a boolean indicating whether or not you can use this package
124 to create and install modules in your environment.
128 ### check if the format is available ###
129 sub format_available {
132 ### we might be called as $class->format_available =/
133 require CPANPLUS::Internals;
134 my $cb = CPANPLUS::Internals->_retrieve_id(
135 CPANPLUS::Internals->_last_id );
136 my $conf = $cb->configure_object;
138 my $mod = "ExtUtils::MakeMaker";
139 unless( can_load( modules => { $mod => 0.0 } ) ) {
140 error( loc( "You do not have '%1' -- '%2' not available",
141 $mod, __PACKAGE__ ) );
145 for my $pgm ( qw[make] ) {
146 unless( $conf->get_program( $pgm ) ) {
148 "You do not have '%1' in your path -- '%2' not available\n" .
149 "Please check your config entry for '%1'",
150 $pgm, __PACKAGE__ , $pgm
159 =pod $bool = $dist->init();
161 Sets up the C<CPANPLUS::Dist::MM> object for use.
162 Effectively creates all the needed status accessors.
164 Called automatically whenever you create a new C<CPANPLUS::Dist> object.
170 my $status = $dist->status;
172 $status->mk_accessors(qw[makefile make test created installed uninstalled
173 bin_make _prepare_args _create_args _install_args]
179 =pod $bool = $dist->prepare([perl => '/path/to/perl', makemakerflags => 'EXTRA=FLAGS', force => BOOL, verbose => BOOL])
181 C<prepare> preps a distribution for installation. This means it will
182 run C<perl Makefile.PL> and determine what prerequisites this distribution
185 If you set C<force> to true, it will go over all the stages of the
186 C<prepare> process again, ignoring any previously cached results.
188 When running C<perl Makefile.PL>, the environment variable
189 C<PERL5_CPANPLUS_IS_EXECUTING> will be set to the full path of the
190 C<Makefile.PL> that is being executed. This enables any code inside
191 the C<Makefile.PL> to know that it is being installed via CPANPLUS.
193 Returns true on success and false on failure.
195 You may then call C<< $dist->create >> on the object to create the
201 ### just in case you already did a create call for this module object
202 ### just via a different dist object
204 my $self = $dist->parent;
206 ### we're also the cpan_dist, since we don't need to have anything
208 $dist = $self->status->dist_cpan if $self->status->dist_cpan;
209 $self->status->dist_cpan( $dist ) unless $self->status->dist_cpan;
211 my $cb = $self->parent;
212 my $conf = $cb->configure_object;
216 unless( $dir = $self->status->extract ) {
217 error( loc( "No dir found to operate on!" ) );
222 my( $force, $verbose, $perl, $mmflags );
223 { local $Params::Check::ALLOW_UNKNOWN = 1;
225 perl => { default => $^X, store => \$perl },
226 makemakerflags => { default =>
227 $conf->get_conf('makemakerflags'),
228 store => \$mmflags },
229 force => { default => $conf->get_conf('force'),
231 verbose => { default => $conf->get_conf('verbose'),
232 store => \$verbose },
235 $args = check( $tmpl, \%hash ) or return;
238 ### maybe we already ran a create on this object? ###
239 return 1 if $dist->status->prepared && !$force;
241 ### store the arguments, so ->install can use them in recursive loops ###
242 $dist->status->_prepare_args( $args );
244 ### chdir to work directory ###
246 unless( $cb->_chdir( dir => $dir ) ) {
247 error( loc( "Could not chdir to build directory '%1'", $dir ) );
253 ### don't run 'perl makefile.pl' again if there's a makefile already
254 if( -e MAKEFILE->() && (-M MAKEFILE->() < -M $dir) && !$force ) {
255 msg(loc("'%1' already exists, not running '%2 %3' again ".
257 MAKEFILE->(), $perl, MAKEFILE_PL->() ), $verbose );
260 unless( -e MAKEFILE_PL->() ) {
261 msg(loc("No '%1' found - attempting to generate one",
262 MAKEFILE_PL->() ), $verbose );
264 $dist->write_makefile_pl(
269 ### bail out if there's no makefile.pl ###
270 unless( -e MAKEFILE_PL->() ) {
271 error( loc( "Could not find '%1' - cannot continue",
274 ### mark that we screwed up ###
275 $dist->status->makefile(0);
280 ### you can turn off running this verbose by changing
281 ### the config setting below, although it is really not
283 my $run_verbose = $verbose ||
284 $conf->get_conf('allow_build_interactivity') ||
287 ### this makes MakeMaker use defaults if possible, according
288 ### to schwern. See ticket 8047 for details.
289 local $ENV{PERL_MM_USE_DEFAULT} = 1 unless $run_verbose;
291 ### turn off our PERL5OPT so no modules from CPANPLUS::inc get
292 ### included in the makefile.pl -- it should build without
293 ### also, modules that run in taint mode break if we leave
294 ### our code ref in perl5opt
295 ### XXX we've removed the ENV settings from cp::inc, so only need
296 ### to reset the @INC
297 #local $ENV{PERL5OPT} = CPANPLUS::inc->original_perl5opt || '';
299 ### make sure it's a string, so that mmflags that have more than
300 ### one key value pair are passed as is, rather than as:
301 ### perl Makefile.PL "key=val key=>val"
304 #### XXX this needs to be the absolute path to the Makefile.PL
305 ### since cpanp-run-perl uses 'do' to execute the file, and do()
306 ### checks your @INC.. so, if there's _another_ makefile.pl in
307 ### your @INC, it will execute that one...
308 my $makefile_pl = $cb->_safe_path( path => MAKEFILE_PL->( $dir ) );
310 ### setting autoflush to true fixes issue from rt #8047
311 ### XXX this means that we need to keep the path to CPANPLUS
312 ### in @INC, stopping us from resolving dependencies on CPANPLUS
313 ### at bootstrap time properly.
315 ### XXX this fails under ipc::run due to the extra quotes,
316 ### but it works in ipc::open3. however, ipc::open3 doesn't work
317 ### on win32/cygwin. XXX TODO get a windows box and sort this out
318 # my $cmd = qq[$perl -MEnglish -le ] .
319 # QUOTE_PERL_ONE_LINER->(
320 # qq[\$OUTPUT_AUTOFLUSH++,do(q($makefile_pl))]
324 # my $flush = OPT_AUTOFLUSH;
325 # my $cmd = "$perl $flush $makefile_pl $mmflags";
327 my $run_perl = $conf->get_program('perlwrapper');
328 my $cmd = "$perl $run_perl $makefile_pl $mmflags";
330 ### set ENV var to tell underlying code this is what we're
334 my $env = ENV_CPANPLUS_IS_EXECUTING;
335 local $ENV{$env} = $makefile_pl;
336 scalar run( command => $cmd,
337 buffer => \$captured,
338 verbose => $run_verbose, # may be interactive
343 error( loc( "Could not run '%1 %2': %3 -- cannot continue",
344 $perl, MAKEFILE_PL->(), $captured ) );
346 $dist->status->makefile(0);
350 ### put the output on the stack, don't print it
354 ### so, nasty feature in Module::Build, that when a Makefile.PL
355 ### is a disguised Build.PL, it generates a Build file, not a
356 ### Makefile. this breaks everything :( see rt bug #19741
357 if( not -e MAKEFILE->( $dir ) and -e BUILD_PL->( $dir ) ) {
359 "We just ran '%1' without errors, but no '%2' is ".
360 "present. However, there is a '%3' file, so this may ".
361 "be related to bug #19741 in %4, which describes a ".
362 "fake '%5' which generates a '%6' file instead of a '%7'. ".
363 "You could try to work around this issue by setting '%8' ".
364 "to false and trying again. This will attempt to use the ".
366 "$^X ".MAKEFILE_PL->(), MAKEFILE->(), BUILD_PL->(),
367 'Module::Build', MAKEFILE_PL->(), 'Build', MAKEFILE->(),
368 'prefer_makefile', BUILD_PL->()
374 ### if we got here, we managed to make a 'makefile' ###
375 $dist->status->makefile( MAKEFILE->($dir) );
377 ### start resolving prereqs ###
378 my $prereqs = $self->status->prereqs;
380 ### a hashref of prereqs on success, undef on failure ###
381 $prereqs ||= $dist->_find_prereqs(
383 file => $dist->status->makefile
387 error( loc( "Unable to scan '%1' for prereqs",
388 $dist->status->makefile ) );
394 unless( $cb->_chdir( dir => $orig ) ) {
395 error( loc( "Could not chdir back to start dir '%1'", $orig ) );
398 ### save where we wrote this stuff -- same as extract dir in normal
399 ### installer circumstances
400 $dist->status->distdir( $self->status->extract );
402 return $dist->status->prepared( $fail ? 0 : 1);
407 =head2 $href = $dist->_find_prereqs( file => '/path/to/Makefile', [verbose => BOOL])
409 Parses a C<Makefile> for C<PREREQ_PM> entries and distills from that
410 any prerequisites mentioned in the C<Makefile>
412 Returns a hash with module-version pairs on success and false on
419 my $self = $dist->parent;
420 my $cb = $self->parent;
421 my $conf = $cb->configure_object;
424 my ($verbose, $file);
426 verbose => { default => $conf->get_conf('verbose'), store => \$verbose },
427 file => { required => 1, allow => FILE_READABLE, store => \$file },
430 my $args = check( $tmpl, \%hash ) or return;
432 my $fh = FileHandle->new();
433 unless( $fh->open( $file ) ) {
434 error( loc( "Cannot open '%1': %2", $file, $! ) );
440 my ($found) = m|^[\#]\s+PREREQ_PM\s+=>\s+(.+)|;
444 while( $found =~ m/(?:\s)([\w\:]+)=>(?:q\[(.*?)\],?|undef)/g ) {
445 if( defined $p{$1} ) {
446 msg(loc("Warning: PREREQ_PM mentions '%1' more than once. " .
447 "Last mention wins.", $1 ), $verbose );
450 $p{$1} = $cb->_version_to_number(version => $2);
455 my $href = $cb->_callbacks->filter_prereqs->( $cb, \%p );
457 $self->status->prereqs( $href );
459 ### just to make sure it's not the same reference ###
465 =head2 $bool = $dist->create([perl => '/path/to/perl', make => '/path/to/make', makeflags => 'EXTRA=FLAGS', prereq_target => TARGET, skiptest => BOOL, force => BOOL, verbose => BOOL])
467 C<create> creates the files necessary for installation. This means
468 it will run C<make> and C<make test>. This will also scan for and
469 attempt to satisfy any prerequisites the module may have.
471 If you set C<skiptest> to true, it will skip the C<make test> stage.
472 If you set C<force> to true, it will go over all the stages of the
473 C<make> process again, ignoring any previously cached results. It
474 will also ignore a bad return value from C<make test> and still allow
475 the operation to return true.
477 Returns true on success and false on failure.
479 You may then call C<< $dist->install >> on the object to actually
485 ### just in case you already did a create call for this module object
486 ### just via a different dist object
488 my $self = $dist->parent;
490 ### we're also the cpan_dist, since we don't need to have anything
492 $dist = $self->status->dist_cpan if $self->status->dist_cpan;
493 $self->status->dist_cpan( $dist ) unless $self->status->dist_cpan;
495 my $cb = $self->parent;
496 my $conf = $cb->configure_object;
500 unless( $dir = $self->status->extract ) {
501 error( loc( "No dir found to operate on!" ) );
506 my( $force, $verbose, $make, $makeflags, $skiptest, $prereq_target, $perl,
507 $mmflags, $prereq_format, $prereq_build);
508 { local $Params::Check::ALLOW_UNKNOWN = 1;
510 perl => { default => $^X, store => \$perl },
511 force => { default => $conf->get_conf('force'),
513 verbose => { default => $conf->get_conf('verbose'),
514 store => \$verbose },
515 make => { default => $conf->get_program('make'),
517 makeflags => { default => $conf->get_conf('makeflags'),
518 store => \$makeflags },
519 skiptest => { default => $conf->get_conf('skiptest'),
520 store => \$skiptest },
521 prereq_target => { default => '', store => \$prereq_target },
522 ### don't set the default prereq format to 'makemaker' -- wrong!
523 prereq_format => { #default => $self->status->installer_type,
525 store => \$prereq_format },
526 prereq_build => { default => 0, store => \$prereq_build },
529 $args = check( $tmpl, \%hash ) or return;
532 ### maybe we already ran a create on this object? ###
533 return 1 if $dist->status->created && !$force;
535 ### store the arguments, so ->install can use them in recursive loops ###
536 $dist->status->_create_args( $args );
538 unless( $dist->status->prepared ) {
539 error( loc( "You have not successfully prepared a '%2' distribution ".
540 "yet -- cannot create yet", __PACKAGE__ ) );
545 ### chdir to work directory ###
547 unless( $cb->_chdir( dir => $dir ) ) {
548 error( loc( "Could not chdir to build directory '%1'", $dir ) );
552 my $fail; my $prereq_fail; my $test_fail;
554 ### this will set the directory back to the start
555 ### dir, so we must chdir /again/
556 my $ok = $dist->_resolve_prereqs(
557 format => $prereq_format,
559 prereqs => $self->status->prereqs,
560 target => $prereq_target,
562 prereq_build => $prereq_build,
565 unless( $cb->_chdir( dir => $dir ) ) {
566 error( loc( "Could not chdir to build directory '%1'", $dir ) );
572 #### use $dist->flush to reset the cache ###
573 error( loc( "Unable to satisfy prerequisites for '%1' " .
574 "-- aborting install", $self->module ) );
575 $dist->status->make(0);
576 $fail++; $prereq_fail++;
579 ### end of prereq resolving ###
583 ### 'make' section ###
584 if( -d BLIB->($dir) && (-M BLIB->($dir) < -M $dir) && !$force ) {
585 msg(loc("Already ran '%1' for this module [%2] -- " .
586 "not running again unless you force",
587 $make, $self->module ), $verbose );
589 unless(scalar run( command => [$make, $makeflags],
590 buffer => \$captured,
591 verbose => $verbose )
593 error( loc( "MAKE failed: %1 %2", $!, $captured ) );
594 $dist->status->make(0);
598 ### put the output on the stack, don't print it
601 $dist->status->make(1);
603 ### add this directory to your lib ###
604 $self->add_to_includepath();
606 ### dont bail out here, there's a conditional later on
607 #last RUN if $skiptest;
610 ### 'make test' section ###
611 unless( $skiptest ) {
613 ### turn off our PERL5OPT so no modules from CPANPLUS::inc get
614 ### included in make test -- it should build without
615 ### also, modules that run in taint mode break if we leave
616 ### our code ref in perl5opt
617 ### XXX CPANPLUS::inc functionality is now obsolete.
618 #local $ENV{PERL5OPT} = CPANPLUS::inc->original_perl5opt || '';
620 ### you can turn off running this verbose by changing
621 ### the config setting below, although it is really not
625 $conf->get_conf('allow_build_interactivity') ||
628 ### XXX need to add makeflags here too?
629 ### yes, but they should really be split out -- see bug #4143
631 command => [$make, 'test', $makeflags],
632 buffer => \$captured,
633 verbose => $run_verbose,
635 ### tests might pass because it doesn't have any tests defined
636 ### log this occasion non-verbosely, so our test reporter can
638 if ( NO_TESTS_DEFINED->( $captured ) ) {
639 msg( NO_TESTS_DEFINED->( $captured ), 0 )
641 msg( loc( "MAKE TEST passed: %2", $captured ), $verbose );
644 $dist->status->test(1);
646 error( loc( "MAKE TEST failed: %1 %2", $!, $captured ) );
648 ### send out error report here? or do so at a higher level?
649 ### --higher level --kane.
650 $dist->status->test(0);
652 ### mark specifically *test* failure.. so we dont
653 ### send success on force...
656 if( !$force and !$cb->_callbacks->proceed_on_test_failure->(
665 unless( $cb->_chdir( dir => $orig ) ) {
666 error( loc( "Could not chdir back to start dir '%1'", $orig ) );
669 ### send out test report?
670 ### only do so if the failure is this module, not its prereq
671 if( $conf->get_conf('cpantest') and not $prereq_fail) {
674 failed => $test_fail || $fail,
675 buffer => CPANPLUS::Error->stack_as_string,
678 ) or error(loc("Failed to send test report for '%1'",
682 return $dist->status->created( $fail ? 0 : 1);
687 =head2 $bool = $dist->install([make => '/path/to/make', makemakerflags => 'EXTRA=FLAGS', force => BOOL, verbose => BOOL])
689 C<install> runs the following command:
692 Returns true on success, false on failure.
698 ### just in case you did the create with ANOTHER dist object linked
699 ### to the same module object
701 my $self = $dist->parent;
702 $dist = $self->status->dist_cpan if $self->status->dist_cpan;
704 my $cb = $self->parent;
705 my $conf = $cb->configure_object;
709 unless( $dist->status->created ) {
710 error(loc("You have not successfully created a '%2' distribution yet " .
711 "-- cannot install yet", __PACKAGE__ ));
716 unless( $dir = $self->status->extract ) {
717 error( loc( "No dir found to operate on!" ) );
722 my($force,$verbose,$make,$makeflags);
723 { local $Params::Check::ALLOW_UNKNOWN = 1;
725 force => { default => $conf->get_conf('force'),
727 verbose => { default => $conf->get_conf('verbose'),
728 store => \$verbose },
729 make => { default => $conf->get_program('make'),
731 makeflags => { default => $conf->get_conf('makeflags'),
732 store => \$makeflags },
735 $args = check( $tmpl, \%hash ) or return;
738 ### value set and false -- means failure ###
739 if( defined $self->status->installed &&
740 !$self->status->installed && !$force
742 error( loc( "Module '%1' has failed to install before this session " .
743 "-- aborting install", $self->module ) );
748 $dist->status->_install_args( $args );
751 unless( $cb->_chdir( dir => $dir ) ) {
752 error( loc( "Could not chdir to build directory '%1'", $dir ) );
756 my $fail; my $captured;
758 ### 'make install' section ###
759 ### XXX need makeflags here too?
760 ### yes, but they should really be split out.. see bug #4143
761 my $cmd = [$make, 'install', $makeflags];
762 my $sudo = $conf->get_program('sudo');
763 unshift @$cmd, $sudo if $sudo and $>;
766 unless(scalar run( command => $cmd,
768 buffer => \$captured,
770 error( loc( "MAKE INSTALL failed: %1 %2", $!, $captured ) );
774 ### put the output on the stack, don't print it
777 unless( $cb->_chdir( dir => $orig ) ) {
778 error( loc( "Could not chdir back to start dir '%1'", $orig ) );
781 return $dist->status->installed( $fail ? 0 : 1 );
787 =head2 $bool = $dist->write_makefile_pl([force => BOOL, verbose => BOOL])
789 This routine can write a C<Makefile.PL> from the information in a
790 module object. It is used to write a C<Makefile.PL> when the original
791 author forgot it (!!).
793 Returns 1 on success and false on failure.
795 The file gets written to the directory the module's been extracted
800 sub write_makefile_pl {
801 ### just in case you already did a call for this module object
802 ### just via a different dist object
804 my $self = $dist->parent;
805 $dist = $self->status->dist_cpan if $self->status->dist_cpan;
806 $self->status->dist_cpan( $dist ) unless $self->status->dist_cpan;
808 my $cb = $self->parent;
809 my $conf = $cb->configure_object;
813 unless( $dir = $self->status->extract ) {
814 error( loc( "No dir found to operate on!" ) );
818 my ($force, $verbose);
820 force => { default => $conf->get_conf('force'),
822 verbose => { default => $conf->get_conf('verbose'),
823 store => \$verbose },
826 my $args = check( $tmpl, \%hash ) or return;
828 my $file = MAKEFILE_PL->($dir);
829 if( -s $file && !$force ) {
830 msg(loc("Already created '%1' - not doing so again without force",
835 ### due to a bug with AS perl 5.8.4 built 810 (and maybe others)
836 ### opening files with content in them already does nasty things;
837 ### seek to pos 0 and then print, but not truncating the file
838 ### bug reported to activestate on 19 sep 2004:
839 ### http://bugs.activestate.com/show_bug.cgi?id=34051
840 unlink $file if $force;
842 my $fh = new FileHandle;
843 unless( $fh->open( ">$file" ) ) {
844 error( loc( "Could not create file '%1': %2", $file, $! ) );
848 my $mf = MAKEFILE_PL->();
849 my $name = $self->module;
850 my $version = $self->version;
851 my $author = $self->author->author;
852 my $href = $self->status->prereqs;
853 my $prereqs = join ",\n", map {
854 (' ' x 25) . "'$_'\t=> '$href->{$_}'"
856 $prereqs ||= ''; # just in case there are none;
859 ### Auto-generated $mf by CPANPLUS ###
861 use ExtUtils::MakeMaker;
865 VERSION => '$version',
878 ### just in case you already did a call for this module object
879 ### just via a different dist object
881 my $self = $dist->parent;
882 $dist = $self->status->dist_cpan if $self->status->dist_cpan;
883 $self->status->dist_cpan( $dist ) unless $self->status->dist_cpan;
885 my $cb = $self->parent;
886 my $conf = $cb->configure_object;
889 my $make; my $verbose;
890 { local $Params::Check::ALLOW_UNKNOWN = 1;
892 make => { default => $conf->get_program('make'),
894 verbose => { default => $conf->get_conf('verbose'),
895 store => \$verbose },
898 check( $tmpl, \%hash ) or return;
903 unless( $dir = $self->status->extract ) {
904 error( loc( "No dir found to operate on!" ) );
908 ### chdir to work directory ###
910 unless( $cb->_chdir( dir => $dir ) ) {
911 error( loc( "Could not chdir to build directory '%1'", $dir ) );
915 my $fail; my $distdir;
917 $dist->prepare( @_ ) or (++$fail, last TRY);
921 unless(scalar run( command => [$make, 'distdir'],
922 buffer => \$captured,
923 verbose => $verbose )
925 error( loc( "MAKE DISTDIR failed: %1 %2", $!, $captured ) );
929 ### /path/to/Foo-Bar-1.2/Foo-Bar-1.2
930 $distdir = File::Spec->catdir( $dir, $self->package_name . '-' .
931 $self->package_version );
933 unless( -d $distdir ) {
934 error(loc("Do not know where '%1' got created", 'distdir'));
939 unless( $cb->_chdir( dir => $orig ) ) {
940 error( loc( "Could not chdir to start directory '%1'", $orig ) );
952 # c-indentation-style: bsd
954 # indent-tabs-mode: nil
956 # vim: expandtab shiftwidth=4: