This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Updated Module::Build to 0.35_08
[perl5.git] / cpan / Module-Build / lib / inc / latest.pm
CommitLineData
613f422f
DG
1package inc::latest;
2use strict;
3use vars qw($VERSION);
4$VERSION = '0.35_08';
5$VERSION = eval $VERSION;
6
7use Carp;
8use File::Basename ();
9use File::Spec ();
10use File::Path ();
11use IO::File ();
12use File::Copy ();
13
14# track and return modules loaded by inc::latest
15my @loaded_modules;
16sub loaded_modules {@loaded_modules}
17
18# must ultimately "goto" the import routine of the module to be loaded
19# so that the calling package is correct when $mod->import() runs.
20sub import {
21 my ($package, $mod, @args) = @_;
22 return unless(defined $mod);
23
24 my $inc_path = './inc/latest.pm';
25 my $private_path = './inc/latest/private.pm';
26 if(-e $inc_path) {
27 # delete our methods
28 delete $inc::latest::{$_} for(keys %inc::latest::);
29 # load the bundled module
30 require $inc_path;
31 require $private_path;
32 my $import = inc::latest->can('import');
33 goto $import;
34 }
35
36 # author mode - just record and load the modules
37 push(@loaded_modules, $mod);
38 require inc::latest::private;
39 goto \&inc::latest::private::_load_module;
40}
41
42sub write {
43 my $package = shift;
44 my ($where, @preload) = @_;
45
46 warn "should really be writing in inc/" unless $where =~ /inc$/;
47
48 # write inc/latest.pm
49 File::Path::mkpath( $where );
50 my $fh = IO::File->new( File::Spec->catfile($where,'latest.pm'), "w" );
51 print {$fh} "# This stub created by inc::latest $VERSION\n";
52 print {$fh} <<'HERE';
53package inc::latest;
54use strict;
55use vars '@ISA';
56require inc::latest::private;
57@ISA = qw/inc::latest::private/;
58HERE
59 if (@preload) {
60 print {$fh} "\npackage inc::latest::preload;\n";
61 for my $mod (@preload) {
62 print {$fh} "inc::latest->import('$mod');\n";
63 }
64 }
65 print {$fh} "\n1;\n";
66 close $fh;
67
68 # write inc/latest/private;
69 require inc::latest::private;
70 File::Path::mkpath( File::Spec->catdir( $where, 'latest' ) );
71 my $from = $INC{'inc/latest/private.pm'};
72 my $to = File::Spec->catfile($where,'latest','private.pm');
73 File::Copy::copy( $from, $to ) or die "Couldn't copy '$from' to '$to': $!";
74
75 return 1;
76}
77
78sub bundle_module {
79 my ($package, $module, $where) = @_;
80
81 # create inc/inc_$foo
82 (my $dist = $module) =~ s{::}{-}g;
83 my $inc_lib = File::Spec->catdir($where,"inc_$dist");
84 File::Path::mkpath $inc_lib;
85
86 # get list of files to copy
87 require ExtUtils::Installed;
88 # workaround buggy EU::Installed check of @INC
89 my $inst = ExtUtils::Installed->new(extra_libs => [@INC]);
90 my $packlist = $inst->packlist( $module ) or die "Couldn't find packlist";
91 my @files = grep { /\.pm$/ } keys %$packlist;
92
93
94 # figure out prefix
95 my $mod_path = quotemeta $package->_mod2path( $module );
96 my ($prefix) = grep { /$mod_path$/ } @files;
97 $prefix =~ s{$mod_path$}{};
98
99 # copy files
100 for my $from ( @files ) {
101 next unless $from =~ /\.pm$/;
102 (my $mod_path = $from) =~ s{^\Q$prefix\E}{};
103 my $to = File::Spec->catfile( $inc_lib, $mod_path );
104 File::Path::mkpath(File::Basename::dirname($to));
105 File::Copy::copy( $from, $to ) or die "Couldn't copy '$from' to '$to': $!";
106 }
107 return 1;
108}
109
110# Translate a module name into a directory/file.pm to search for in @INC
111sub _mod2path {
112 my ($self, $mod) = @_;
113 my @parts = split /::/, $mod;
114 $parts[-1] .= '.pm';
115 return $parts[0] if @parts == 1;
116 return File::Spec->catfile(@parts);
117}
118
1191;
120
121
122=head1 NAME
123
124inc::latest - use modules bundled in inc/ if they are newer than installed ones
125
126=head1 SYNOPSIS
127
128 # in Build.PL
129 use inc::latest 'Module::Build';
130
131=head1 DESCRIPTION
132
133The C<inc::latest> module helps bootstrap configure-time dependencies for CPAN
134distributions. These dependencies get bundled into the C<inc> directory within
135a distribution and are used by Build.PL (or Makefile.PL).
136
137Arguments to C<inc::latest> are module names that are checked against both the
138current C<@INC> array and against specially-named directories in C<inc>. If
139the bundled verison is newer than the installed one (or the module isn't
140installed, then, the bundled directory is added to the start of <@INC> and the
141module is loaded from there.
142
143There are actually two variations of C<inc::latest> -- one for authors and one
144for the C<inc> directory. For distribution authors, the C<inc::latest>
145installed in the system will record modules loaded via C<inc::latest> and can
146be used to create the bundled files in C<inc>, including writing the second
147variation as C<inc/latest.pm>.
148
149This second C<inc::latest> is the one that is loaded in a distribution being
150installed (e.g. from Build.PL). This bundled C<inc::latest> is the one
151that determines which module to load.
152
153=head2 Special notes on bundling
154
155The C<inc::latest> module creates bundled directories based on the packlist
156file of an installed distribution. Even though C<inc::latest> takes module
157name arguments, it is better to think of it as bundling and making available
158entire I<distributions>. When a module is loaded through C<inc::latest>,
159it looks in all bundled distributions in C<inc/> for a newer module than
160can be found in the existing C<@INC> array.
161
162Thus, the module-name provided should usually be the "top-level" module name of
163a distribution, though this is not strictly required. For example,
164L<Module::Build> has a number of heuristics to map module names to packlists,
165allowing users to do things like this:
166
167 use inc::latest 'Devel::AssertOS::Unix';
168
169even though Devel::AssertOS::Unix is contained within the Devel-CheckOS
170distribution.
171
172At the current time, packlists are required. Thus, bundling dual-core modules
173may require a 'forced install' over versions in the latest version of perl
174in order to create the necessary packlist for bundling.
175
176=head1 USAGE
177
178When calling C<use>, the bundled C<inc::latest> takes a single module name and
179optional arguments to pass to that module's own import method.
180
181 use 'inc::latest' 'Foo::Bar' qw/foo bar baz/;
182
183=head2 Author-mode
184
185You are in author-mode inc::latest if any of the Author-mode methods are
186available. For example:
187
188 if ( inc::latest->can('write') ) {
189 inc::latest->write('inc');
190 }
191
192=over 4
193
194=item loaded_modules()
195
196 my @list = inc::latest->loaded_modules;
197
198This takes no arguments and always returns a list of module names requested for
199loading via "use inc::latest 'MODULE'", regardless of wether the load was
200successful or not.
201
202=item write()
203
204 inc::latest->write( 'inc' );
205
206This writes the bundled version of inc::latest to the directory name given as an
207argument. It almost all cases, it should be 'C<inc>'.
208
209=item bundle_module()
210
211 for my $mod ( inc::latest->loaded_modules ) {
212 inc::latest->bundle_module($mod, $dir);
213 }
214
215If $mod corresponds to a packlist, then this function creates a specially-named
216directory in $dir and copies all .pm files from the modlist to the new
217directory (which almost always should just be 'inc'). For example, if Foo::Bar
218is the name of the module, and $dir is 'inc', then the directory would be
219'inc/inc_Foo-Bar' and contain files like this:
220
221 inc/inc_Foo-Bar/Foo/Bar.pm
222
223Currently, $mod B<must> have a packlist. If this is not the case (e.g. for a
224dual-core module), then the bundling will fail. You may be able to create a
225packlist by forced installing the module on top of the version that came with
226core Perl.
227
228=back
229
230=head2 As bundled in inc/
231
232All methods are private. Only the C<import> method is public.
233
234=head1 AUTHOR
235
236Eric Wilhelm <ewilhelm@cpan.org>, David Golden <dagolden@cpan.org>
237
238=head1 COPYRIGHT
239
240Copyright (c) 2009 by Eric Wilhelm and David Golden
241
242This library is free software; you can redistribute it and/or
243modify it under the same terms as Perl itself.
244
245=head1 SEE ALSO
246
247L<Module::Build>
248
249=cut
250