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