This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Update CPANPLUS-Dist-Build to CPAN version 0.60
[perl5.git] / cpan / CPANPLUS-Dist-Build / lib / CPANPLUS / Dist / Build.pm
1 package CPANPLUS::Dist::Build;
2
3 use strict;
4 use warnings;
5 use vars    qw[@ISA $STATUS $VERSION];
6 @ISA =      qw[CPANPLUS::Dist];
7
8 use CPANPLUS::Internals::Constants;
9
10 ### these constants were exported by CPANPLUS::Internals::Constants
11 ### in previous versions.. they do the same though. If we want to have
12 ### a normal 'use' here, up the dependency to CPANPLUS 0.056 or higher
13 BEGIN {
14     require CPANPLUS::Dist::Build::Constants;
15     CPANPLUS::Dist::Build::Constants->import()
16         if not __PACKAGE__->can('BUILD') && __PACKAGE__->can('BUILD_DIR');
17 }
18
19 use CPANPLUS::Error;
20
21 use Config;
22 use FileHandle;
23 use Cwd;
24 use version;
25
26 use IPC::Cmd                    qw[run];
27 use Params::Check               qw[check];
28 use Module::Load::Conditional   qw[can_load check_install];
29 use Locale::Maketext::Simple    Class => 'CPANPLUS', Style => 'gettext';
30
31 local $Params::Check::VERBOSE = 1;
32
33 $VERSION = '0.60';
34
35 =pod
36
37 =head1 NAME
38
39 CPANPLUS::Dist::Build - CPANPLUS plugin to install packages that use Build.PL
40
41 =head1 SYNOPSIS
42
43     my $build = CPANPLUS::Dist->new(
44                                 format  => 'CPANPLUS::Dist::Build',
45                                 module  => $modobj,
46                             );
47
48     $build->prepare;    # runs Build.PL
49     $build->create;     # runs build && build test
50     $build->install;    # runs build install
51
52
53 =head1 DESCRIPTION
54
55 C<CPANPLUS::Dist::Build> is a distribution class for C<Module::Build>
56 related modules.
57 Using this package, you can create, install and uninstall perl
58 modules. It inherits from C<CPANPLUS::Dist>.
59
60 Normal users won't have to worry about the interface to this module,
61 as it functions transparently as a plug-in to C<CPANPLUS> and will
62 just C<Do The Right Thing> when it's loaded.
63
64 =head1 ACCESSORS
65
66 =over 4
67
68 =item C<parent()>
69
70 Returns the C<CPANPLUS::Module> object that parented this object.
71
72 =item C<status()>
73
74 Returns the C<Object::Accessor> object that keeps the status for
75 this module.
76
77 =back
78
79 =head1 STATUS ACCESSORS
80
81 All accessors can be accessed as follows:
82     $build->status->ACCESSOR
83
84 =over 4
85
86 =item C<build_pl ()>
87
88 Location of the Build file.
89 Set to 0 explicitly if something went wrong.
90
91 =item C<build ()>
92
93 BOOL indicating if the C<Build> command was successful.
94
95 =item C<test ()>
96
97 BOOL indicating if the C<Build test> command was successful.
98
99 =item C<prepared ()>
100
101 BOOL indicating if the C<prepare> call exited successfully
102 This gets set after C<perl Build.PL>
103
104 =item C<distdir ()>
105
106 Full path to the directory in which the C<prepare> call took place,
107 set after a call to C<prepare>.
108
109 =item C<created ()>
110
111 BOOL indicating if the C<create> call exited successfully. This gets
112 set after C<Build> and C<Build test>.
113
114 =item C<installed ()>
115
116 BOOL indicating if the module was installed. This gets set after
117 C<Build install> exits successfully.
118
119 =item uninstalled ()
120
121 BOOL indicating if the module was uninstalled properly.
122
123 =item C<_create_args ()>
124
125 Storage of the arguments passed to C<create> for this object. Used
126 for recursive calls when satisfying prerequisites.
127
128 =item C<_install_args ()>
129
130 Storage of the arguments passed to C<install> for this object. Used
131 for recursive calls when satisfying prerequisites.
132
133 =back
134
135 =cut
136
137 =head1 METHODS
138
139 =head2 $bool = CPANPLUS::Dist::Build->format_available();
140
141 Returns a boolean indicating whether or not you can use this package
142 to create and install modules in your environment.
143
144 =cut
145
146 ### check if the format is available ###
147 sub format_available {
148     my $mod = 'Module::Build';
149     unless( can_load( modules => { $mod => '0.2611' }, nocache => 1 ) ) {
150         error( loc( "You do not have '%1' -- '%2' not available",
151                     $mod, __PACKAGE__ ) );
152         return;
153     }
154
155     return 1;
156 }
157
158
159 =head2 $bool = $dist->init();
160
161 Sets up the C<CPANPLUS::Dist::Build> object for use.
162 Effectively creates all the needed status accessors.
163
164 Called automatically whenever you create a new C<CPANPLUS::Dist> object.
165
166 =cut
167
168 sub init {
169     my $dist    = shift;
170     my $status  = $dist->status;
171
172     $status->mk_accessors(qw[build_pl build test created installed uninstalled
173                              _create_args _install_args _prepare_args
174                              _mb_object _buildflags
175                             ]);
176
177     ### just in case 'format_available' didn't get called
178     require Module::Build;
179
180     return 1;
181 }
182
183 =pod
184
185 =head2 $bool = $dist->prepare([perl => '/path/to/perl', buildflags => 'EXTRA=FLAGS', force => BOOL, verbose => BOOL])
186
187 C<prepare> prepares a distribution, running C<Build.PL>
188 and establishing any prerequisites this
189 distribution has.
190
191 The variable C<PERL5_CPANPLUS_IS_EXECUTING> will be set to the full path
192 of the C<Build.PL> that is being executed. This enables any code inside
193 the C<Build.PL> to know that it is being installed via CPANPLUS.
194
195 After a successful C<prepare> you may call C<create> to create the
196 distribution, followed by C<install> to actually install it.
197
198 Returns true on success and false on failure.
199
200 =cut
201
202 sub prepare {
203     ### just in case you already did a create call for this module object
204     ### just via a different dist object
205     my $dist = shift;
206     my $self = $dist->parent;
207
208     ### we're also the cpan_dist, since we don't need to have anything
209     ### prepared from another installer
210     $dist    = $self->status->dist_cpan if      $self->status->dist_cpan;
211     $self->status->dist_cpan( $dist )   unless  $self->status->dist_cpan;
212
213     my $cb   = $self->parent;
214     my $conf = $cb->configure_object;
215     my %hash = @_;
216
217     my $dir;
218     unless( $dir = $self->status->extract ) {
219         error( loc( "No dir found to operate on!" ) );
220         return;
221     }
222
223     my $args;
224     my( $force, $verbose, $buildflags, $perl, $prereq_target, $prereq_format,
225         $prereq_build );
226     {   local $Params::Check::ALLOW_UNKNOWN = 1;
227         my $tmpl = {
228             force           => {    default => $conf->get_conf('force'),
229                                     store   => \$force },
230             verbose         => {    default => $conf->get_conf('verbose'),
231                                     store   => \$verbose },
232             perl            => {    default => $^X, store => \$perl },
233             buildflags      => {    default => $conf->get_conf('buildflags'),
234                                     store   => \$buildflags },
235             prereq_target   => {    default => '', store => \$prereq_target },
236             prereq_format   => {    default => '',
237                                     store   => \$prereq_format },
238             prereq_build    => {    default => 0, store => \$prereq_build },
239         };
240
241         $args = check( $tmpl, \%hash ) or return;
242     }
243
244     return 1 if $dist->status->prepared && !$force;
245
246     $dist->status->_prepare_args( $args );
247
248     ### chdir to work directory ###
249     my $orig = cwd();
250     unless( $cb->_chdir( dir => $dir ) ) {
251         error( loc( "Could not chdir to build directory '%1'", $dir ) );
252         return;
253     }
254
255     ### by now we've loaded module::build, and we're using the API, so
256     ### it's safe to remove CPANPLUS::inc from our inc path, especially
257     ### because it can trip up tests run under taint (just like EU::MM).
258     ### turn off our PERL5OPT so no modules from CPANPLUS::inc get
259     ### included in make test -- it should build without.
260     ### also, modules that run in taint mode break if we leave
261     ### our code ref in perl5opt
262     ### XXX we've removed the ENV settings from cp::inc, so only need
263     ### to reset the @INC
264     #local $ENV{PERL5OPT} = CPANPLUS::inc->original_perl5opt;
265     #local $ENV{PERL5LIB} = CPANPLUS::inc->original_perl5lib;
266     #local @INC           = CPANPLUS::inc->original_inc;
267
268     ### this will generate warnings under anything lower than M::B 0.2606
269     my @buildflags = $dist->_buildflags_as_list( $buildflags );
270     $dist->status->_buildflags( $buildflags );
271
272     my $fail;
273     RUN: {
274         # 0.85_01
275         ### we resolve 'configure requires' here, so we can run the 'perl
276         ### Makefile.PL' command
277         ### XXX for tests: mock f_c_r to something that *can* resolve and
278         ### something that *doesn't* resolve. Check the error log for ok
279         ### on this step or failure
280         ### XXX make a separate tarball to test for this scenario: simply
281         ### containing a makefile.pl/build.pl for test purposes?
282         my $safe_ver = version->new('0.85_01');
283         if ( version->new($CPANPLUS::Internals::VERSION) >= $safe_ver )
284         {   my $configure_requires = $dist->find_configure_requires;
285             my $ok = $dist->_resolve_prereqs(
286                             format          => $prereq_format,
287                             verbose         => $verbose,
288                             prereqs         => $configure_requires,
289                             target          => $prereq_target,
290                             force           => $force,
291                             prereq_build    => $prereq_build,
292                     );
293
294             unless( $ok ) {
295
296                 #### use $dist->flush to reset the cache ###
297                 error( loc( "Unable to satisfy '%1' for '%2' " .
298                             "-- aborting install",
299                             'configure_requires', $self->module ) );
300                 $dist->status->prepared(0);
301                 $fail++;
302                 last RUN;
303             }
304             ### end of prereq resolving ###
305         }
306
307         # Wrap the exception that may be thrown here (should likely be
308         # done at a much higher level).
309         my $prep_output;
310
311         my $env = ENV_CPANPLUS_IS_EXECUTING;
312         local $ENV{$env} = BUILD_PL->( $dir );
313         my @run_perl    = ( '-e', CPDB_PERL_WRAPPER );
314         my $cmd = [$perl, @run_perl, BUILD_PL->($dir), @buildflags];
315
316         unless ( scalar run(    command => $cmd,
317                                 buffer  => \$prep_output,
318                                 verbose => $verbose )
319         ) {
320             error( loc( "Build.PL failed: %1", $prep_output ) );
321             $fail++; last RUN;
322         }
323
324         msg( $prep_output, 0 );
325
326         my $prereqs = $self->status->prereqs;
327
328         $prereqs ||= $dist->_find_prereqs( verbose => $verbose,
329                                            dir => $dir,
330                                            perl => $perl,
331                                            buildflags => $buildflags );
332
333     }
334
335     ### send out test report? ###
336     if( $fail and $conf->get_conf('cpantest') ) {
337            $cb->_send_report(
338             module  => $self,
339             failed  => $fail,
340             buffer  => CPANPLUS::Error->stack_as_string,
341             verbose => $verbose,
342             force   => $force,
343         ) or error(loc("Failed to send test report for '%1'",
344                     $self->module ) );
345     }
346
347     unless( $cb->_chdir( dir => $orig ) ) {
348         error( loc( "Could not chdir back to start dir '%1'", $orig ) );
349     }
350
351     ### save where we wrote this stuff -- same as extract dir in normal
352     ### installer circumstances
353     $dist->status->distdir( $self->status->extract );
354
355     return $dist->status->prepared( $fail ? 0 : 1 );
356 }
357
358 sub _find_prereqs {
359     my $dist = shift;
360     my $self = $dist->parent;
361     my $cb   = $self->parent;
362     my $conf = $cb->configure_object;
363     my %hash = @_;
364
365     my ($verbose, $dir, $buildflags, $perl);
366     my $tmpl = {
367         verbose => { default => $conf->get_conf('verbose'), store => \$verbose },
368         dir     => { default => $self->status->extract, store => \$dir },
369         perl    => { default => $^X, store => \$perl },
370         buildflags => { default => $conf->get_conf('buildflags'),
371                         store   => \$buildflags },
372     };
373
374     my $args = check( $tmpl, \%hash ) or return;
375
376     my $prereqs = {};
377
378     $prereqs = $dist->find_mymeta_requires()
379        if $dist->can('find_mymeta_requires');
380
381     if ( keys %$prereqs ) {
382         # Ugly hack
383     }
384     else {
385       my $safe_ver = version->new('0.31_03');
386       my $content;
387       PREREQS: {
388         if ( version->new( $Module::Build::VERSION ) >= $safe_ver and IPC::Cmd->can_capture_buffer ) {
389           my @buildflags = $dist->_buildflags_as_list( $buildflags );
390
391           # Use the new Build action 'prereq_data'
392           my @run_perl    = ( '-e', CPDB_PERL_WRAPPER );
393
394           unless ( scalar run(    command => [$perl, @run_perl, BUILD->($dir), 'prereq_data', @buildflags],
395                                 buffer  => \$content,
396                                 verbose => 0 )
397           ) {
398             error( loc( "Build 'prereq_data' failed: %1 %2", $!, $content ) );
399             #return;
400           }
401           else {
402             last PREREQS;
403           }
404
405         }
406
407         my $file = File::Spec->catfile( $dir, '_build', 'prereqs' );
408         return unless -f $file;
409
410         my $fh = FileHandle->new();
411
412         unless( $fh->open( $file ) ) {
413           error( loc( "Cannot open '%1': %2", $file, $! ) );
414           return;
415         }
416
417         $content = do { local $/; <$fh> };
418
419       }
420
421       return unless $content;
422       my $bphash = eval $content;
423       return unless $bphash and ref $bphash eq 'HASH';
424       foreach my $type ('requires', 'build_requires') {
425         next unless $bphash->{$type} and ref $bphash->{$type} eq 'HASH';
426         $prereqs->{$_} = $bphash->{$type}->{$_} for keys %{ $bphash->{$type} };
427       }
428     }
429
430     {
431       delete $prereqs->{'perl'}
432          unless version->new($CPANPLUS::Internals::VERSION)
433              >= version->new('0.9102');
434     }
435
436     ### allows for a user defined callback to filter the prerequisite
437     ### list as they see fit, to remove (or add) any prereqs they see
438     ### fit. The default installed callback will return the hashref in
439     ### an unmodified form
440     ### this callback got added after cpanplus 0.0562, so use a 'can'
441     ### to find out if it's supported. For older versions, we'll just
442     ### return the hashref as is ourselves.
443     my $href    = $cb->_callbacks->can('filter_prereqs')
444                     ? $cb->_callbacks->filter_prereqs->( $cb, $prereqs )
445                     : $prereqs;
446
447     $self->status->prereqs( $href );
448
449     ### make sure it's not the same ref
450     return { %$href };
451 }
452
453 =pod
454
455 =head2 $dist->create([perl => '/path/to/perl', buildflags => 'EXTRA=FLAGS', prereq_target => TARGET, force => BOOL, verbose => BOOL, skiptest => BOOL])
456
457 C<create> preps a distribution for installation. This means it will
458 run C<Build> and C<Build test>.
459 This will also satisfy any prerequisites the module may have.
460
461 If you set C<skiptest> to true, it will skip the C<Build test> stage.
462 If you set C<force> to true, it will go over all the stages of the
463 C<Build> process again, ignoring any previously cached results. It
464 will also ignore a bad return value from C<Build test> and still allow
465 the operation to return true.
466
467 Returns true on success and false on failure.
468
469 You may then call C<< $dist->install >> on the object to actually
470 install it.
471
472 =cut
473
474 sub create {
475     ### just in case you already did a create call for this module object
476     ### just via a different dist object
477     my $dist = shift;
478     my $self = $dist->parent;
479
480     ### we're also the cpan_dist, since we don't need to have anything
481     ### prepared from another installer
482     $dist    = $self->status->dist_cpan if      $self->status->dist_cpan;
483     $self->status->dist_cpan( $dist )   unless  $self->status->dist_cpan;
484
485     my $cb   = $self->parent;
486     my $conf = $cb->configure_object;
487     my %hash = @_;
488
489     my $dir;
490     unless( $dir = $self->status->extract ) {
491         error( loc( "No dir found to operate on!" ) );
492         return;
493     }
494
495     my $args;
496     my( $force, $verbose, $buildflags, $skiptest, $prereq_target,
497         $perl, $prereq_format, $prereq_build);
498     {   local $Params::Check::ALLOW_UNKNOWN = 1;
499         my $tmpl = {
500             force           => {    default => $conf->get_conf('force'),
501                                     store   => \$force },
502             verbose         => {    default => $conf->get_conf('verbose'),
503                                     store   => \$verbose },
504             perl            => {    default => $^X, store => \$perl },
505             buildflags      => {    default => $conf->get_conf('buildflags'),
506                                     store   => \$buildflags },
507             skiptest        => {    default => $conf->get_conf('skiptest'),
508                                     store   => \$skiptest },
509             prereq_target   => {    default => '', store => \$prereq_target },
510             ### don't set the default format to 'build' -- that is wrong!
511             prereq_format   => {    #default => $self->status->installer_type,
512                                     default => '',
513                                     store   => \$prereq_format },
514             prereq_build    => {    default => 0, store => \$prereq_build },
515         };
516
517         $args = check( $tmpl, \%hash ) or return;
518     }
519
520     # restore the state as we have created this already.
521     if ( $dist->status->created && !$force ) {
522         ### add this directory to your lib ###
523         $self->add_to_includepath();
524         return 1;
525     }
526
527     $dist->status->_create_args( $args );
528
529     ### is this dist prepared?
530     unless( $dist->status->prepared ) {
531         error( loc( "You have not successfully prepared a '%2' distribution ".
532                     "yet -- cannot create yet", __PACKAGE__ ) );
533         return;
534     }
535
536     ### chdir to work directory ###
537     my $orig = cwd();
538     unless( $cb->_chdir( dir => $dir ) ) {
539         error( loc( "Could not chdir to build directory '%1'", $dir ) );
540         return;
541     }
542
543     ### by now we've loaded module::build, and we're using the API, so
544     ### it's safe to remove CPANPLUS::inc from our inc path, especially
545     ### because it can trip up tests run under taint (just like EU::MM).
546     ### turn off our PERL5OPT so no modules from CPANPLUS::inc get
547     ### included in make test -- it should build without.
548     ### also, modules that run in taint mode break if we leave
549     ### our code ref in perl5opt
550     ### XXX we've removed the ENV settings from cp::inc, so only need
551     ### to reset the @INC
552     #local $ENV{PERL5OPT} = CPANPLUS::inc->original_perl5opt;
553     #local $ENV{PERL5LIB} = CPANPLUS::inc->original_perl5lib;
554     #local @INC           = CPANPLUS::inc->original_inc;
555
556     ### but do it *before* the new_from_context, as M::B seems
557     ### to be actually running the file...
558     ### an unshift in the block seems to be ignored.. somehow...
559     #{   my $lib = $self->best_path_to_module_build;
560     #    unshift @INC, $lib if $lib;
561     #}
562     unshift @INC, $self->best_path_to_module_build
563                 if $self->best_path_to_module_build;
564
565     ### this will generate warnings under anything lower than M::B 0.2606
566     my @buildflags = $dist->_buildflags_as_list( $buildflags );
567     $dist->status->_buildflags( $buildflags );
568
569     my $fail; my $prereq_fail; my $test_fail;
570     RUN: {
571
572         my @run_perl    = ( '-e', CPDB_PERL_WRAPPER );
573
574         ### this will set the directory back to the start
575         ### dir, so we must chdir /again/
576         my $ok = $dist->_resolve_prereqs(
577                         force           => $force,
578                         format          => $prereq_format,
579                         verbose         => $verbose,
580                         prereqs         => $self->status->prereqs,
581                         target          => $prereq_target,
582                         prereq_build    => $prereq_build,
583                     );
584
585         unless( $cb->_chdir( dir => $dir ) ) {
586             error( loc( "Could not chdir to build directory '%1'", $dir ) );
587             return;
588         }
589
590         unless( $ok ) {
591             #### use $dist->flush to reset the cache ###
592             error( loc( "Unable to satisfy prerequisites for '%1' " .
593                         "-- aborting install", $self->module ) );
594             $dist->status->build(0);
595             $fail++; $prereq_fail++;
596             last RUN;
597         }
598
599         my ($captured, $cmd);
600         if ( ON_VMS ) {
601             $cmd = [$perl, BUILD->($dir), @buildflags];
602         }
603         else {
604             $cmd = [$perl, @run_perl, BUILD->($dir), @buildflags];
605         }
606
607         unless ( scalar run(    command => $cmd,
608                                 buffer  => \$captured,
609                                 verbose => $verbose )
610         ) {
611             error( loc( "MAKE failed:\n%1", $captured ) );
612             $dist->status->build(0);
613             $fail++; last RUN;
614         }
615
616         msg( $captured, 0 );
617
618         $dist->status->build(1);
619
620         ### add this directory to your lib ###
621         $self->add_to_includepath();
622
623         ### this buffer will not include what tests failed due to a
624         ### M::B/Test::Harness bug. Reported as #9793 with patch
625         ### against 0.2607 on 26/1/2005
626         unless( $skiptest ) {
627             my $test_output;
628             if ( ON_VMS ) {
629                 $cmd     = [$perl, BUILD->($dir), "test", @buildflags];
630             }
631             else {
632                 $cmd     = [$perl, @run_perl, BUILD->($dir), "test", @buildflags];
633             }
634             unless ( scalar run(    command => $cmd,
635                                     buffer  => \$test_output,
636                                     verbose => $verbose )
637             ) {
638                 error( loc( "MAKE TEST failed:\n%1 ", $test_output ), ( $verbose ? 0 : 1 ) );
639
640                 ### mark specifically *test* failure.. so we dont
641                 ### send success on force...
642                 $test_fail++;
643
644                 if( !$force and !$cb->_callbacks->proceed_on_test_failure->(
645                                       $self, $@ )
646                 ) {
647                     $dist->status->test(0);
648                     $fail++; last RUN;
649                 }
650
651             }
652             else {
653                 msg( loc( "MAKE TEST passed:\n%1", $test_output ), 0 );
654                 $dist->status->test(1);
655             }
656         }
657         else {
658             msg(loc("Tests skipped"), $verbose);
659         }
660     }
661
662     unless( $cb->_chdir( dir => $orig ) ) {
663         error( loc( "Could not chdir back to start dir '%1'", $orig ) );
664     }
665
666     ### send out test report? ###
667     if( $conf->get_conf('cpantest') and not $prereq_fail ) {
668         $cb->_send_report(
669             module          => $self,
670             failed          => $test_fail || $fail,
671             buffer          => CPANPLUS::Error->stack_as_string,
672             verbose         => $verbose,
673             force           => $force,
674             tests_skipped   => $skiptest,
675         ) or error(loc("Failed to send test report for '%1'",
676                     $self->module ) );
677     }
678
679     return $dist->status->created( $fail ? 0 : 1 );
680 }
681
682 =head2 $dist->install([verbose => BOOL, perl => /path/to/perl])
683
684 Actually installs the created dist.
685
686 Returns true on success and false on failure.
687
688 =cut
689
690 sub install {
691     ### just in case you already did a create call for this module object
692     ### just via a different dist object
693     my $dist = shift;
694     my $self = $dist->parent;
695
696     ### we're also the cpan_dist, since we don't need to have anything
697     ### prepared from another installer
698     $dist    = $self->status->dist_cpan if $self->status->dist_cpan;
699
700     my $cb   = $self->parent;
701     my $conf = $cb->configure_object;
702     my %hash = @_;
703
704
705     my $verbose; my $perl; my $force; my $buildflags;
706     {   local $Params::Check::ALLOW_UNKNOWN = 1;
707         my $tmpl = {
708             verbose => { default => $conf->get_conf('verbose'),
709                          store   => \$verbose },
710             force   => { default => $conf->get_conf('force'),
711                          store   => \$force },
712             buildflags => { default => $conf->get_conf('buildflags'),
713                             store   => \$buildflags },
714             perl    => { default => $^X, store   => \$perl },
715         };
716
717         my $args = check( $tmpl, \%hash ) or return;
718         $dist->status->_install_args( $args );
719     }
720
721     my $dir;
722     unless( $dir = $self->status->extract ) {
723         error( loc( "No dir found to operate on!" ) );
724         return;
725     }
726
727     my $orig = cwd();
728
729     unless( $cb->_chdir( dir => $dir ) ) {
730         error( loc( "Could not chdir to build directory '%1'", $dir ) );
731         return;
732     }
733
734     ### value set and false -- means failure ###
735     if( defined $self->status->installed &&
736         !$self->status->installed && !$force
737     ) {
738         error( loc( "Module '%1' has failed to install before this session " .
739                     "-- aborting install", $self->module ) );
740         return;
741     }
742
743     my $fail;
744     my @buildflags = $dist->_buildflags_as_list( $buildflags );
745     my @run_perl    = ( '-e', CPDB_PERL_WRAPPER );
746
747     ### hmm, how is this going to deal with sudo?
748     ### for now, check effective uid, if it's not root,
749     ### shell out, otherwise use the method
750     if( $> ) {
751
752         ### don't worry about loading the right version of M::B anymore
753         ### the 'new_from_context' already added the 'right' path to
754         ### M::B at the top of the build.pl
755         my $cmd;
756         if ( ON_VMS ) {
757             $cmd     = [$perl, BUILD->($dir), "install", @buildflags];
758         }
759         else {
760             $cmd     = [$perl, @run_perl, BUILD->($dir), "install", @buildflags];
761         }
762
763         ### Detect local::lib type behaviour. Do not use 'sudo' in these cases
764         my $sudo    = $conf->get_program('sudo');
765         SUDO: {
766           ### Actual local::lib in use
767           last SUDO if defined $ENV{PERL_MB_OPT} and $ENV{PERL_MB_OPT} =~ m!install_base!;
768           ### 'buildflags' is configured with '--install_base'
769           last SUDO if scalar grep { m!install_base! } @buildflags;
770           ### oh well 'sudo make me a sandwich'
771           unshift @$cmd, $sudo;
772         }
773
774         my $buffer;
775         unless( scalar run( command => $cmd,
776                             buffer  => \$buffer,
777                             verbose => $verbose )
778         ) {
779             error(loc("Could not run '%1': %2", 'Build install', $buffer));
780             $fail++;
781         }
782     } else {
783         my ($install_output, $cmd);
784         if ( ON_VMS ) {
785             $cmd     = [$perl, BUILD->($dir), "install", @buildflags];
786         }
787         else {
788             $cmd     = [$perl, @run_perl, BUILD->($dir), "install", @buildflags];
789         }
790         unless( scalar run( command => $cmd,
791                             buffer  => \$install_output,
792                             verbose => $verbose )
793         ) {
794             error(loc("Could not run '%1': %2", 'Build install', $install_output));
795             $fail++;
796         }
797         else {
798             msg( $install_output, 0 );
799         }
800     }
801
802
803     unless( $cb->_chdir( dir => $orig ) ) {
804         error( loc( "Could not chdir back to start dir '%1'", $orig ) );
805     }
806
807     return $dist->status->installed( $fail ? 0 : 1 );
808 }
809
810 ### returns the string 'foo=bar --zot quux'
811 ###        as the list 'foo=bar', '--zot', 'qux'
812 sub _buildflags_as_list {
813     my $self    = shift;
814     my $flags   = shift or return;
815
816     return Module::Build->split_like_shell($flags);
817 }
818
819 =head1 AUTHOR
820
821 Originally by Jos Boumans E<lt>kane@cpan.orgE<gt>.  Brought to working
822 condition by Ken Williams E<lt>kwilliams@cpan.orgE<gt>.
823
824 Other hackery and currently maintained by Chris C<BinGOs> Williams ( no relation ). E<lt>bingos@cpan.orgE<gt>.
825
826 =head1 LICENSE
827
828 The CPAN++ interface (of which this module is a part of) is
829 copyright (c) 2001, 2002, 2003, 2004, 2005 Jos Boumans E<lt>kane@cpan.orgE<gt>.
830 All rights reserved.
831
832 This library is free software;
833 you may redistribute and/or modify it under the same
834 terms as Perl itself.
835
836 =cut
837
838 qq[Putting the Module::Build into CPANPLUS];
839
840
841 # Local variables:
842 # c-indentation-style: bsd
843 # c-basic-offset: 4
844 # indent-tabs-mode: nil
845 # End:
846 # vim: expandtab shiftwidth=4:
847