3 # This is a subclass of Module::Build so we can override certain methods and do
6 # It was first written against Module::Build::Base v0.2805. Many of the methods
7 # here are copy/pasted from there in their entirety just to change one or two
8 # minor things, since for the most part Module::Build::Base code is hard to
11 # This was written by Sendu Bala and is released under the same license as
14 package ModuleBuildBioperl
;
17 # we really need Module::Build to be installed
18 unless (eval "use Module::Build 0.2805; 1") {
19 print "This package requires Module::Build v0.2805 or greater to install itself.\n";
21 require ExtUtils
::MakeMaker
;
22 my $yn = ExtUtils
::MakeMaker
::prompt
(' Install Module::Build now from CPAN?', 'y');
24 unless ($yn =~ /^y/i) {
25 die " *** Cannot install without Module::Build. Exiting ...\n";
33 # Save this because CPAN will chdir all over the place.
36 my $build_pl = File
::Spec
->catfile($cwd, "Build.PL");
38 File
::Copy
::move
($build_pl, $build_pl."hidden"); # avoid bizarre bug with Module::Build tests using the wrong Build.PL if it happens to be in PERL5LIB
39 CPAN
::Shell
->install('Module::Build');
40 File
::Copy
::move
($build_pl."hidden", $build_pl);
41 CPAN
::Shell
->expand("Module", "Module::Build")->uptodate or die "Couldn't install Module::Build, giving up.\n";
43 chdir $cwd or die "Cannot chdir() back to $cwd: $!\n\n***\nInstallation will probably work fine if you now quit CPAN and try again.\n***\n\n";
46 eval "use base Module::Build; 1" or die $@
;
48 # ensure we'll be able to reload this module later by adding its path to inc
56 our $VERSION = 1.005002103;
57 our @extra_types = qw(options excludes_os feature_requires test); # test must always be last in the list!
58 our $checking_types = "requires|conflicts|".join("|", @extra_types);
61 # our modules are in Bio, not lib
64 foreach my $pm (@
{$self->rscan_dir('Bio', qr/\.pm$/)}) {
65 $self->{properties
}{pm_files
}->{$pm} = File
::Spec
->catfile('lib', $pm);
68 $self->_find_file_by_type('pm', 'lib');
71 # ask what scripts to install (this method is unique to bioperl)
76 # we can offer interactive installation by groups only if we have subdirs
77 # in scripts and no .PLS files there
78 opendir(my $scripts_dir, 'scripts') or die "Can't open directory 'scripts': $!\n";
81 while (my $thing = readdir($scripts_dir)) {
82 next if $thing =~ /^\./;
83 next if $thing eq 'CVS';
84 if ($thing =~ /PLS$|pl$/) {
88 $thing = File
::Spec
->catfile('scripts', $thing);
91 push(@group_dirs, $thing);
94 closedir($scripts_dir);
95 my $question = $int_ok ?
"Install [a]ll Bioperl scripts, [n]one, or choose groups [i]nteractively?" : "Install [a]ll Bioperl scripts or [n]one?";
97 my $prompt = $accept ?
'a' : $self->prompt($question, 'a');
99 if ($prompt =~ /^[aA]/) {
100 $self->log_info(" - will install all scripts\n");
101 $self->notes(chosen_scripts
=> 'all');
103 elsif ($prompt =~ /^[iI]/) {
104 $self->log_info(" - will install interactively:\n");
107 foreach my $group_dir (@group_dirs) {
108 my $group = File
::Basename
::basename
($group_dir);
109 print " * group '$group' has:\n";
111 my @script_files = @
{$self->rscan_dir($group_dir, qr/\.PLS$|\.pl$/)};
112 foreach my $script_file (@script_files) {
113 my $script = File
::Basename
::basename
($script_file);
117 my $result = $self->prompt(" Install scripts for group '$group'? [y]es [n]o [q]uit", 'n');
118 die if $result =~ /^[qQ]/;
119 if ($result =~ /^[yY]/) {
120 $self->log_info(" + will install group '$group'\n");
121 push(@chosen_scripts, @script_files);
124 $self->log_info(" - will not install group '$group'\n");
128 my $chosen_scripts = @chosen_scripts ?
join("|", @chosen_scripts) : 'none';
130 $self->notes(chosen_scripts
=> $chosen_scripts);
133 $self->log_info(" - won't install any scripts\n");
134 $self->notes(chosen_scripts
=> 'none');
140 # our version of script_files doesn't take args but just installs those scripts
141 # requested by the user after choose_scripts() is called. If it wasn't called,
142 # installs all scripts in scripts directory
146 unless (-d
'scripts') {
150 my $chosen_scripts = $self->notes('chosen_scripts');
151 if ($chosen_scripts) {
152 return if $chosen_scripts eq 'none';
153 return { map {$_, 1} split(/\|/, $chosen_scripts) } unless $chosen_scripts eq 'all';
156 return $_ = { map {$_,1} @
{$self->rscan_dir('scripts', qr/\.PLS$|\.pl$/)} };
159 # process scripts normally, except that we change name from *.PLS to bp_*.pl
160 sub process_script_files
{
162 my $files = $self->find_script_files;
163 return unless keys %$files;
165 my $script_dir = File
::Spec
->catdir($self->blib, 'script');
166 File
::Path
::mkpath
( $script_dir );
168 foreach my $file (keys %$files) {
169 my $result = $self->copy_if_modified($file, $script_dir, 'flatten') or next;
170 $self->fix_shebang_line($result) unless $self->os_type eq 'VMS';
171 $self->make_executable($result);
173 my $final = File
::Basename
::basename
($result);
174 $final =~ s/\.PLS$/\.pl/; # change from .PLS to .pl
175 $final =~ s/^/bp_/ unless $final =~ /^bp/; # add the "bp" prefix
176 $final = File
::Spec
->catfile($script_dir, $final);
177 $self->log_info("$result -> $final\n");
178 File
::Copy
::move
($result, $final) or die "Can't rename '$result' to '$final': $!";
182 # extended to handle extra checking types
185 my $ph = $self->{phash
};
189 if ($ph->{features
}->exists($key)) {
190 return $ph->{features
}->access($key, @_);
193 if (my $info = $ph->{auto_features
}->access($key)) {
194 my $failures = $self->prereq_failures($info);
195 my $disabled = grep( /^(?:\w+_)?(?:$checking_types)$/, keys %$failures ) ?
1 : 0;
199 return $ph->{features
}->access($key, @_);
202 # No args - get the auto_features & overlay the regular features
204 my %auto_features = $ph->{auto_features
}->access();
205 while (my ($name, $info) = each %auto_features) {
206 my $failures = $self->prereq_failures($info);
207 my $disabled = grep( /^(?:\w+_)?(?:$checking_types)$/, keys %$failures ) ?
1 : 0;
208 $features{$name} = $disabled ?
0 : 1;
210 %features = (%features, $ph->{features
}->access());
212 return wantarray ?
%features : \
%features;
214 *feature
= \
&features
;
216 # overridden to fix a stupid bug in Module::Build and extended to handle extra
218 sub check_autofeatures
{
220 my $features = $self->auto_features;
222 return unless %$features;
224 $self->log_info("Checking features:\n");
226 my $max_name_len = 0; # this wasn't set to 0 in Module::Build, causing warning in next line
227 $max_name_len = ( length($_) > $max_name_len ) ?
length($_) : $max_name_len for keys %$features;
229 while (my ($name, $info) = each %$features) {
230 $self->log_info(" $name" . '.' x
($max_name_len - length($name) + 4));
231 if ($name eq 'PL_files') {
232 print "got $name => $info\n";
234 while (my ($key, $val) = each %$info) {
235 print " $key => $val\n";
239 if ( my $failures = $self->prereq_failures($info) ) {
240 my $disabled = grep( /^(?:\w+_)?(?:$checking_types)$/, keys %$failures ) ?
1 : 0;
241 $self->log_info( $disabled ?
"disabled\n" : "enabled\n" );
244 while (my ($type, $prereqs) = each %$failures) {
245 while (my ($module, $status) = each %$prereqs) {
246 my $required = ($type =~ /^(?:\w+_)?(?:requires|conflicts)$/) ?
1 : 0;
247 my $prefix = ($required) ?
'-' : '*';
248 $log_text .= " $prefix $status->{message}\n";
251 $self->log_warn($log_text) if $log_text && ! $self->quiet;
254 $self->log_info("enabled\n");
258 $self->log_info("\n");
261 # overriden just to hide pointless ugly warnings
262 sub check_installed_status
{
264 open (my $olderr, ">&", \
*STDERR
);
265 open(STDERR
, "/dev/null");
266 my $return = $self->SUPER::check_installed_status
(@_);
267 open(STDERR
, ">&", $olderr);
271 # extend to handle option checking (which takes an array ref) and code test
272 # checking (which takes a code ref and must return a message only on failure)
273 # and excludes_os (which takes an array ref of regexps).
274 # also handles more informative output of recommends section
275 sub prereq_failures
{
276 my ($self, $info) = @_;
278 my @types = (@
{ $self->prereq_action_types }, @extra_types);
279 $info ||= {map {$_, $self->$_()} @types};
282 foreach my $type (@types) {
283 my $prereqs = $info->{$type} || next;
286 if ($type eq 'test') {
287 unless (keys %$out) {
288 if (ref($prereqs) eq 'CODE') {
289 $status->{message
} = &{$prereqs};
291 # drop the code-ref to avoid Module::Build trying to store
292 # it with Data::Dumper, generating warnings. (And also, may
293 # be expensive to run the sub multiple times.)
294 $info->{$type} = $status->{message
};
297 $status->{message
} = $prereqs;
299 $out->{$type}{'test'} = $status if $status->{message
};
302 elsif ($type eq 'options') {
304 foreach my $wanted_option (@
{$prereqs}) {
305 unless ($self->args($wanted_option)) {
306 push(@not_ok, $wanted_option);
311 $status->{message
} = "Command line option(s) '@not_ok' not supplied";
312 $out->{$type}{'options'} = $status;
315 elsif ($type eq 'excludes_os') {
316 foreach my $os (@
{$prereqs}) {
318 $status->{message
} = "This feature isn't supported under your OS ($os)";
319 $out->{$type}{'excludes_os'} = $status;
325 while ( my ($modname, $spec) = each %$prereqs ) {
326 $status = $self->check_installed_status($modname, $spec);
328 if ($type =~ /^(?:\w+_)?conflicts$/) {
329 next if !$status->{ok
};
330 $status->{conflicts
} = delete $status->{need
};
331 $status->{message
} = "$modname ($status->{have}) conflicts with this distribution";
333 elsif ($type =~ /^(?:\w+_)?recommends$/) {
334 next if $status->{ok
};
336 my ($preferred_version, $why, $by_what) = split("/", $spec);
337 $by_what = join(", ", split(",", $by_what));
338 $by_what =~ s/, (\S+)$/ and $1/;
340 $status->{message
} = (!ref($status->{have
}) && $status->{have
} eq '<none>'
341 ?
"Optional prerequisite $modname is not installed"
342 : "$modname ($status->{have}) is installed, but we prefer to have $preferred_version");
344 $status->{message
} .= "\n (wanted for $why, used by $by_what)";
346 if ($by_what =~ /\[circular dependency!\]/) {
347 $preferred_version = -1;
350 my $installed = $self->install_optional($modname, $preferred_version, $status->{message
});
351 next if $installed eq 'ok';
352 $status->{message
} = $installed unless $installed eq 'skip';
354 elsif ($type =~ /^feature_requires/) {
355 next if $status->{ok
};
357 # if there is a test code-ref, drop it to avoid
358 # Module::Build trying to store it with Data::Dumper,
359 # generating warnings.
360 delete $info->{test
};
363 next if $status->{ok
};
365 my $installed = $self->install_required($modname, $spec, $status->{message
});
366 next if $installed eq 'ok';
367 $status->{message
} = $installed;
370 $out->{$type}{$modname} = $status;
375 return keys %{$out} ?
$out : return;
378 # install an external module using CPAN prior to testing and installation
379 # should only be called by install_required or install_optional
381 my ($self, $desired, $version) = @_;
383 if ($self->under_cpan) {
384 # Just add to the required hash, which CPAN >= 1.81 will check prior
386 $self->{properties
}{requires
}->{$desired} = $version;
387 $self->log_info(" I'll get CPAN to prepend the installation of this\n");
391 # Here we use CPAN to actually install the desired module, the benefit
392 # being we continue even if installation fails, and that this works
393 # even when not using CPAN to install.
397 # Save this because CPAN will chdir all over the place.
398 my $cwd = Cwd
::cwd
();
400 CPAN
::Shell
->install($desired);
402 my $expanded = CPAN
::Shell
->expand("Module", $desired);
403 if ($expanded && $expanded->uptodate) {
404 $self->log_info("\n\n*** (back in Bioperl Build.PL) ***\n * You chose to install $desired and it installed fine\n");
408 $self->log_info("\n\n*** (back in Bioperl Build.PL) ***\n");
409 $msg = "You chose to install $desired but it failed to install";
412 chdir $cwd or die "Cannot chdir() back to $cwd: $!";
417 # install required modules listed in 'requires' or 'build_requires' arg to
418 # new that weren't already installed. Should only be called by prereq_failures
419 sub install_required
{
420 my ($self, $desired, $version, $msg) = @_;
422 $self->log_info(" - ERROR: $msg\n");
424 return $self->install_prereq($desired, $version);
427 # install optional modules listed in 'recommends' arg to new that weren't
428 # already installed. Should only be called by prereq_failures
429 sub install_optional
{
430 my ($self, $desired, $version, $msg) = @_;
432 unless (defined $self->{ask_optional
}) {
433 $self->{ask_optional
} = $self->args->{accept}
434 ?
'n' : $self->prompt("Install [a]ll optional external modules, [n]one, or choose [i]nteractively?", 'n');
436 return 'skip' if $self->{ask_optional
} =~ /^n/i;
439 if ($self->{ask_optional
} =~ /^a/i) {
440 $self->log_info(" * $msg\n");
444 $install = $self->y_n(" * $msg\n Do you want to install it? y/n", 'n');
447 my $orig_version = $version;
448 $version = 0 if $version == -1;
449 if ($install && ! ($self->{ask_optional
} =~ /^a/i && $orig_version == -1)) {
450 return $self->install_prereq($desired, $version);
453 my $circular = ($self->{ask_optional
} =~ /^a/i && $orig_version == -1) ?
" - this is a circular dependency so doesn't get installed when installing 'all' modules. If you really want it, choose modules interactively." : '';
454 $self->log_info(" * You chose not to install $desired$circular\n");
459 # there's no official way to discover if being run by CPAN, we take an approach
460 # similar to that of Module::AutoInstall
464 unless (defined $self->{under_cpan
}) {
465 ## modified from Module::AutoInstall
469 if ($CPAN::HandleConfig
::VERSION
) {
470 # Newer versions of CPAN have a HandleConfig module
471 CPAN
::HandleConfig
->load;
474 # Older versions had the load method in Config directly
478 # Find the CPAN lock-file
479 my $lock = File
::Spec
->catfile($CPAN::Config
->{cpan_home
}, '.lock');
481 # Module::AutoInstall now goes on to open the lock file and compare
482 # its pid to ours, but we're not in a situation where we expect
483 # the pids to match, so we take the windows approach for all OSes:
484 # find out if we're in cpan_home
485 my $cwd = File
::Spec
->canonpath(Cwd
::cwd
());
486 my $cpan = File
::Spec
->canonpath($CPAN::Config
->{cpan_home
});
488 $self->{under_cpan
} = index($cwd, $cpan) > -1;
491 if ($self->{under_cpan
}) {
492 $self->log_info("(I think I'm being run by CPAN, so will rely on CPAN to handle prerequisite installation)\n");
495 $self->log_info("(I think you ran Build.PL directly, so will use CPAN to install prerequisites on demand)\n");
496 $self->{under_cpan
} = 0;
500 return $self->{under_cpan
};
503 # overridden simply to not print the default answer if chosen by hitting return
506 my $mess = shift or die "prompt() called without a prompt message";
509 if ( $self->_is_unattended && !@_ ) {
511 ERROR: This build seems to be unattended, but there is no default value
512 for this question. Aborting.
516 ($def, my $dispdef) = defined $def ?
($def, "[$def] ") : ('', ' ');
519 print "$mess $dispdef";
521 my $ans = $self->_readline();
523 if ( !defined($ans) # Ctrl-D or unattended
524 or !length($ans) ) { # User hit return
525 #print "$def\n"; didn't like this!
532 # like the Module::Build version, except that we always get version from
534 sub find_dist_packages
{
537 # Only packages in .pm files are candidates for inclusion here.
538 # Only include things in the MANIFEST, not things in developer's
541 my $manifest = $self->_read_manifest('MANIFEST') or die "Can't find dist packages without a MANIFEST file - run 'manifest' action first";
544 my %dist_files = map { $self->localize_file_path($_) => $_ } keys %$manifest;
546 my @pm_files = grep {exists $dist_files{$_}} keys %{ $self->find_pm_files };
548 my $actual_version = $self->dist_version;
550 # First, we enumerate all packages & versions,
551 # seperating into primary & alternative candidates
553 foreach my $file (@pm_files) {
554 next if $dist_files{$file} =~ m{^t/}; # Skip things in t/
556 my @path = split( /\//, $dist_files{$file} );
557 (my $prime_package = join( '::', @path[1..$#path] )) =~ s/\.pm$//;
559 my $pm_info = Module
::Build
::ModuleInfo
->new_from_file( $file );
561 foreach my $package ( $pm_info->packages_inside ) {
562 next if $package eq 'main'; # main can appear numerous times, ignore
563 next if grep /^_/, split( /::/, $package ); # private package, ignore
565 my $version = $pm_info->version( $package );
566 if ($version && $version != $actual_version) {
567 $self->log_warn("Package $package had version $version!\n");
569 $version = $actual_version;
571 if ( $package eq $prime_package ) {
572 if ( exists( $prime{$package} ) ) {
573 # M::B::ModuleInfo will handle this conflict
574 die "Unexpected conflict in '$package'; multiple versions found.\n";
577 $prime{$package}{file
} = $dist_files{$file};
578 $prime{$package}{version
} = $version if defined( $version );
582 push( @
{$alt{$package}}, { file
=> $dist_files{$file}, version
=> $version } );
587 # Then we iterate over all the packages found above, identifying conflicts
588 # and selecting the "best" candidate for recording the file & version
590 foreach my $package ( keys( %alt ) ) {
591 my $result = $self->_resolve_module_versions( $alt{$package} );
593 if ( exists( $prime{$package} ) ) { # primary package selected
594 if ( $result->{err
} ) {
595 # Use the selected primary package, but there are conflicting
596 # errors amoung multiple alternative packages that need to be
598 $self->log_warn("Found conflicting versions for package '$package'\n" .
599 " $prime{$package}{file} ($prime{$package}{version})\n" . $result->{err
});
601 elsif ( defined( $result->{version
} ) ) {
602 # There is a primary package selected, and exactly one
603 # alternative package
605 if ( exists( $prime{$package}{version
} ) && defined( $prime{$package}{version
} ) ) {
606 # Unless the version of the primary package agrees with the
607 # version of the alternative package, report a conflict
608 if ( $self->compare_versions( $prime{$package}{version
}, '!=', $result->{version
} ) ) {
609 $self->log_warn("Found conflicting versions for package '$package'\n" .
610 " $prime{$package}{file} ($prime{$package}{version})\n" .
611 " $result->{file} ($result->{version})\n");
615 # The prime package selected has no version so, we choose to
616 # use any alternative package that does have a version
617 $prime{$package}{file
} = $result->{file
};
618 $prime{$package}{version
} = $result->{version
};
622 # no alt package found with a version, but we have a prime
623 # package so we use it whether it has a version or not
626 else { # No primary package was selected, use the best alternative
627 if ( $result->{err
} ) {
628 $self->log_warn("Found conflicting versions for package '$package'\n" . $result->{err
});
631 # Despite possible conflicting versions, we choose to record
632 # something rather than nothing
633 $prime{$package}{file
} = $result->{file
};
634 $prime{$package}{version
} = $result->{version
} if defined( $result->{version
} );
639 for (grep exists $_->{version
}, values %prime) {
640 $_->{version
} = $_->{version
}->stringify if ref($_->{version
});
646 # our recommends syntax contains extra info that needs to be ignored at this
648 sub _parse_conditions
{
649 my ($self, $spec) = @_;
651 ($spec) = split("/", $spec);
653 if ($spec =~ /^\s*([\w.]+)\s*$/) { # A plain number, maybe with dots, letters, and underscores
657 return split /\s*,\s*/, $spec;
661 # when generating META.yml, we output optional_features syntax (instead of
662 # recommends syntax). Note that as of CPAN v1.8802 nothing useful is done
663 # with this information, which is why we implement our own request to install
664 # the optional modules in install_optional()
665 sub prepare_metadata
{
666 my ($self, $node, $keys) = @_;
667 my $p = $self->{properties
};
669 # A little helper sub
671 my ($name, $val) = @_;
672 $node->{$name} = $val;
673 push @
$keys, $name if $keys;
676 foreach (qw(dist_name dist_version dist_author dist_abstract license)) {
677 (my $name = $_) =~ s/^dist_//;
678 $add_node->($name, $self->$_());
679 die "ERROR: Missing required field '$_' for META.yml\n" unless defined($node->{$name}) && length($node->{$name});
681 $node->{version
} = '' . $node->{version
}; # Stringify version objects
683 if (defined( $self->license ) && defined( my $url = $self->valid_licenses->{ $self->license } )) {
684 $node->{resources
}{license
} = $url;
687 foreach ( @
{$self->prereq_action_types} ) {
688 if (exists $p->{$_} and keys %{ $p->{$_} }) {
689 if ($_ eq 'recommends') {
691 while (my ($req, $val) = each %{ $p->{$_} }) {
692 my ($ver, $why, $used_by) = split("/", $val);
694 $info->{description
} = $why;
695 $info->{requires
} = { $req => $ver };
696 $hash->{$used_by} = $info;
698 $add_node->('optional_features', $hash);
701 $add_node->($_, $p->{$_});
706 if (exists $p->{dynamic_config
}) {
707 $add_node->('dynamic_config', $p->{dynamic_config
});
709 my $pkgs = eval { $self->find_dist_packages };
711 $self->log_warn("$@\nWARNING: Possible missing or corrupt 'MANIFEST' file.\n" . "Nothing to enter for 'provides' field in META.yml\n");
714 $node->{provides
} = $pkgs if %$pkgs;
717 if (exists $p->{no_index
}) {
718 $add_node->('no_index', $p->{no_index
});
721 $add_node->('generated_by', "Module::Build version $Module::Build::VERSION");
723 $add_node->('meta-spec',
725 url
=> 'http://module-build.sourceforge.net/META-spec-v1.2.html',
728 while (my($k, $v) = each %{$self->meta_add}) {
732 while (my($k, $v) = each %{$self->meta_merge}) {
733 $self->_hash_merge($node, $k, $v);
739 # let us store extra things persistently in _build
743 # calling SUPER::_construct will dump some of the input to this sub out
744 # with Data::Dumper, which will complain about code refs. So we replace
745 # any code refs with dummies first, then put them back afterwards
747 my $auto_features = $in_hash{auto_features
} if defined $in_hash{auto_features
};
749 if ($auto_features) {
750 while (my ($key, $hash) = each %{$auto_features}) {
751 while (my ($sub_key, $val) = each %{$hash}) {
752 if (ref($val) && ref($val) eq 'CODE') {
753 $hash->{$sub_key} = 'CODE_ref';
754 $code_refs{$key}->{$sub_key} = $val;
760 $self = $self->SUPER::_construct
(@_);
762 my ($p, $ph) = ($self->{properties
}, $self->{phash
});
764 if (keys %code_refs) {
765 while (my ($key, $hash) = each %{$auto_features}) {
766 if (defined $code_refs{$key}) {
767 while (my ($sub_key, $code_ref) = each %{$code_refs{$key}}) {
768 $hash->{$sub_key} = $code_ref;
770 $ph->{auto_features
}->{$key} = $hash;
775 foreach (qw(manifest_skip post_install_scripts)) {
776 my $file = File
::Spec
->catfile($self->config_dir, $_);
777 $ph->{$_} = Module
::Build
::Notes
->new(file
=> $file);
778 $ph->{$_}->restore if -e
$file;
785 $self->SUPER::write_config
;
788 $self->{phash
}{$_}->write() foreach qw(manifest_skip post_install_scripts);
790 # be even more certain we can reload ourselves during a resume by copying
791 # ourselves to _build\lib
792 my $filename = File
::Spec
->catfile($self->{properties
}{config_dir
}, 'lib', 'ModuleBuildBioperl.pm');
793 my $filedir = File
::Basename
::dirname
($filename);
795 File
::Path
::mkpath
($filedir);
796 warn "Can't create directory $filedir: $!" unless -d
$filedir;
798 File
::Copy
::copy
('ModuleBuildBioperl.pm', $filename);
799 warn "Unable to copy 'ModuleBuildBioperl.pm' to '$filename'\n" unless -e
$filename;
802 # add a file to the default MANIFEST.SKIP
803 sub add_to_manifest_skip
{
805 my %files = map {$self->localize_file_path($_), 1} @_;
806 $self->{phash
}{manifest_skip
}->write(\
%files);
809 # we always generate a new MANIFEST and MANIFEST.SKIP here, instead of allowing
810 # existing files to remain
811 sub ACTION_manifest
{
814 my $maniskip = 'MANIFEST.SKIP';
815 if ( -e
'MANIFEST' || -e
$maniskip ) {
816 $self->log_warn("MANIFEST files already exist, will overwrite them\n");
820 $self->_write_default_maniskip($maniskip);
822 require ExtUtils
::Manifest
; # ExtUtils::Manifest is not warnings clean.
823 local ($^W
, $ExtUtils::Manifest
::Quiet
) = (0,1);
824 ExtUtils
::Manifest
::mkmanifest
();
827 # extended to add extra things to the default MANIFEST.SKIP
828 sub _write_default_maniskip
{
830 $self->SUPER::_write_default_maniskip
;
832 my @extra = keys %{$self->{phash
}{manifest_skip
}->read};
834 open(my $fh, '>>', 'MANIFEST.SKIP') or die "Could not open MANIFEST.SKIP file\n";
835 print $fh "\n# Avoid additional run-time generated things\n";
836 foreach my $line (@extra) {
837 print $fh $line, "\n";
843 # extended to run scripts post-installation
846 require ExtUtils
::Install
;
847 $self->depends_on('build');
848 ExtUtils
::Install
::install
($self->install_map, !$self->quiet, 0, $self->{args
}{uninst
}||0);
849 $self->run_post_install_scripts;
851 sub add_post_install_script
{
853 my %files = map {$self->localize_file_path($_), 1} @_;
854 $self->{phash
}{post_install_scripts
}->write(\
%files);
856 sub run_post_install_scripts
{
858 my @scripts = keys %{$self->{phash
}{post_install_scripts
}->read};
859 foreach my $script (@scripts) {
860 $self->run_perl_script($script);
864 # for use with auto_features, which should require LWP::UserAgent as one of
867 eval {require LWP
::UserAgent
;};
869 # ideally this won't happen because auto_feature already specified
870 # LWP::UserAgent, so this sub wouldn't get called if LWP not installed
871 return "LWP::UserAgent not installed";
873 my $ua = LWP
::UserAgent
->new;
876 my $response = $ua->get('http://search.cpan.org/');
877 unless ($response->is_success) {
878 return "Could not connect to the internet (http://search.cpan.org/)";
883 # nice directory names for dist-related actions
886 my $version = $self->dist_version;
887 if ($version =~ /^\d\.\d{6}\d$/) {
888 # 1.x.x.100 returned as 1.x.x.1
891 $version =~ s/00(\d)/$1./g;
894 if (my ($minor, $rev) = $version =~ /^\d\.(\d)\.\d\.(\d+)$/) {
895 my $dev = ! ($minor % 2 == 0);
897 my $replace = $dev ?
"_$rev" : '';
898 $version =~ s/\.\d+$/$replace/;
901 $rev = sprintf("%03d", $rev);
902 $version =~ s/\.\d+$/_$rev-RC/;
905 $rev -= 100 unless $dev;
906 my $replace = $dev ?
"_$rev" : ".$rev";
907 $version =~ s/\.\d+$/$replace/;
911 return "$self->{properties}{dist_name}-$version";
915 return $self->dist_dir.'-ppm';
918 # generate complete ppd4 version file
922 my $file = $self->make_ppd(%{$self->{args
}});
923 $self->add_to_cleanup($file);
924 $self->add_to_manifest_skip($file);
927 # add pod2htm temp files to MANIFEST.SKIP, generated during ppmdist most likely
930 $self->SUPER::htmlify_pods
(@_);
931 $self->add_to_manifest_skip('pod2htm*');
934 # don't copy across man3 docs since they're of little use under Windows and
938 my @types = $self->install_types(1);
939 $self->SUPER::ACTION_ppmdist
(@_);
940 $self->install_types(0);
943 # when supplied a true value, pretends libdoc doesn't exist (preventing man3
944 # installation for ppmdist). when supplied false, they exist again
946 my ($self, $no_libdoc) = @_;
947 $self->{no_libdoc
} = $no_libdoc if defined $no_libdoc;
948 my @types = $self->SUPER::install_types
;
949 if ($self->{no_libdoc
}) {
951 foreach my $type (@types) {
952 push(@altered_types, $type) unless $type eq 'libdoc';
954 return @altered_types;
959 # overridden from Module::Build::PPMMaker for ppd4 compatability
961 my ($self, %args) = @_;
963 require Module
::Build
::PPMMaker
;
964 my $mbp = Module
::Build
::PPMMaker
->new();
967 foreach my $info (qw(name author abstract version)) {
968 my $method = "dist_$info";
969 $dist{$info} = $self->$method() or die "Can't determine distribution's $info\n";
971 $dist{codebase
} = $self->ppm_name.'.tar.gz';
972 $mbp->_simple_xml_escape($_) foreach $dist{abstract
}, $dist{codebase
}, @
{$dist{author
}};
974 my (undef, undef, undef, $mday, $mon, $year) = localtime();
977 my $date = "$year-$mon-$mday";
979 my $softpkg_version = $self->dist_dir;
980 $softpkg_version =~ s/^$dist{name}-//;
982 # to avoid a ppm bug, instead of including the requires in the softpackage
983 # for the distribution we're making, we'll make a seperate Bundle::
984 # softpackage that contains all the requires, and require only the Bundle in
985 # the real softpackage
986 my ($bundle_name) = $dist{name
} =~ /^.+-(.+)/;
987 $bundle_name ||= 'core';
988 $bundle_name =~ s/^(\w)/\U$1/;
989 my $bundle_dir = "Bundle-BioPerl-$bundle_name-$softpkg_version-ppm";
990 my $bundle_file = "$bundle_dir.tar.gz";
991 my $bundle_softpkg_name = "Bundle-BioPerl-$bundle_name";
992 $bundle_name = "Bundle::BioPerl::$bundle_name";
996 <SOFTPKG NAME=\"$dist{name}\" VERSION=\"$softpkg_version\" DATE=\"$date\">
997 <TITLE>$dist{name}</TITLE>
998 <ABSTRACT>$dist{abstract}</ABSTRACT>
999 @{[ join "\n", map " <AUTHOR>$_</AUTHOR>", @{$dist{author}} ]}
1000 <PROVIDE NAME=\"$dist{name}::\" VERSION=\"$dist{version}\"/>
1004 foreach my $pm (@
{$self->rscan_dir('Bio', qr/\.pm$/)}) {
1005 # convert these filepaths to Module names
1009 $ppd .= sprintf(<<'EOF', $pm, $dist{version});
1010 <PROVIDE NAME="%s" VERSION="%s"/>
1017 <ARCHITECTURE NAME=\"MSWin32-x86-multi-thread-5.8\"/>
1018 <CODEBASE HREF=\"$dist{codebase}\"/>
1019 <REQUIRE NAME=\"$bundle_name\" VERSION=\"$dist{version}\"/>
1024 # now a new softpkg for the bundle
1027 <SOFTPKG NAME=\"$bundle_softpkg_name\" VERSION=\"$softpkg_version\" DATE=\"$date\">
1028 <TITLE>$bundle_name</TITLE>
1029 <ABSTRACT>Bundle of pre-requisites for $dist{name}</ABSTRACT>
1030 @{[ join "\n", map " <AUTHOR>$_</AUTHOR>", @{$dist{author}} ]}
1031 <PROVIDE NAME=\"$bundle_name\" VERSION=\"$dist{version}\"/>
1033 <ARCHITECTURE NAME=\"MSWin32-x86-multi-thread-5.8\"/>
1034 <CODEBASE HREF=\"$bundle_file\"/>
1038 # we do both requires and recommends to make installation on Windows as
1039 # easy (mindless) as possible
1040 for my $type ('requires', 'recommends') {
1041 my $prereq = $self->$type;
1042 while (my ($modname, $version) = each %$prereq) {
1043 next if $modname eq 'perl';
1044 ($version) = split("/", $version) if $version =~ /\
//;
1046 # Module names must have at least one ::
1047 unless ($modname =~ /::/) {
1051 # Bio::Root::Version number comes out as triplet number like 1.5.2;
1052 # convert to our own version
1053 if ($modname eq 'Bio::Root::Version') {
1054 $version = $dist{version
};
1057 $ppd .= sprintf(<<'EOF', $modname, $version || '');
1058 <REQUIRE NAME="%s" VERSION="%s"/>
1069 my $ppd_file = "$dist{name}.ppd";
1070 my $fh = IO
::File
->new(">$ppd_file") or die "Cannot write to $ppd_file: $!";
1074 $self->delete_filetree($bundle_dir);
1075 mkdir($bundle_dir) or die "Cannot create '$bundle_dir': $!";
1076 $self->make_tarball($bundle_dir);
1077 $self->delete_filetree($bundle_dir);
1078 $self->add_to_cleanup($bundle_file);
1079 $self->add_to_manifest_skip($bundle_file);
1084 # we make all archive formats we want, not just .tar.gz
1085 # we also auto-run manifest action, since we always want to re-create
1086 # MANIFEST and MANIFEST.SKIP just-in-time
1090 $self->depends_on('manifest');
1091 $self->depends_on('distdir');
1093 my $dist_dir = $self->dist_dir;
1095 $self->make_zip($dist_dir);
1096 $self->make_tarball($dist_dir);
1097 $self->delete_filetree($dist_dir);
1100 # makes zip file for windows users and bzip2 files as well
1102 my ($self, $dir, $file) = @_;
1105 $self->log_info("Creating $file.zip\n");
1106 my $zip_flags = $self->verbose ?
'-r' : '-rq';
1107 $self->do_system($self->split_like_shell("zip"), $zip_flags, "$file.zip", $dir);
1109 $self->log_info("Creating $file.bz2\n");
1110 require Archive
::Tar
;
1111 # Archive::Tar versions >= 1.09 use the following to enable a compatibility
1112 # hack so that the resulting archive is compatible with older clients.
1113 $Archive::Tar
::DO_NOT_USE_PREFIX
= 0;
1114 my $files = $self->rscan_dir($dir);
1115 Archive
::Tar
->create_archive("$file.tar", 0, @
$files);
1116 $self->do_system($self->split_like_shell("bzip2"), "-k", "$file.tar");