add Module::Build 0.27_08
[p5sagit/p5-mst-13.2.git] / lib / Module / Build / Compat.pm
1 package Module::Build::Compat;
2
3 use strict;
4 use vars qw($VERSION);
5 $VERSION = '0.03';
6
7 use File::Spec;
8 use IO::File;
9 use Config;
10 use Module::Build;
11 use Module::Build::ModuleInfo;
12 use Data::Dumper;
13
14 my %makefile_to_build = 
15   (
16    TEST_VERBOSE => 'verbose',
17    VERBINST     => 'verbose',
18    INC     => sub { map {('--extra_compiler_flags', "-I$_")} Module::Build->split_like_shell(shift) },
19    POLLUTE => sub { ('--extra_compiler_flags', '-DPERL_POLLUTE') },
20    INSTALLDIRS => sub {local $_ = shift; 'installdirs=' . (/^perl$/ ? 'core' : $_) },
21    LIB => sub { ('--install_path', 'lib='.shift()) },
22
23    # Some names they have in common
24    map {$_, lc($_)} qw(DESTDIR PREFIX INSTALL_BASE UNINST),
25   );
26
27
28
29 sub create_makefile_pl {
30   my ($package, $type, $build, %args) = @_;
31   
32   die "Don't know how to build Makefile.PL of type '$type'"
33     unless $type =~ /^(small|passthrough|traditional)$/;
34
35   my $fh;
36   if ($args{fh}) {
37     $fh = $args{fh};
38   } else {
39     $args{file} ||= 'Makefile.PL';
40     $fh = IO::File->new("> $args{file}") or die "Can't write $args{file}: $!";
41   }
42
43   print {$fh} "# Note: this file was auto-generated by ", __PACKAGE__, " version $VERSION\n";
44
45   # If a custom subclass is being used, make sure we add its directory to @INC
46   my $subclass_load = '';
47   if (ref($build) ne "Module::Build") {
48     my $subclass_dir = $package->subclass_dir($build);
49     
50     if (File::Spec->file_name_is_absolute($subclass_dir)) {
51       my $base_dir = $build->base_dir;
52
53       if ($build->dir_contains($base_dir, $subclass_dir)) {
54         $subclass_dir = File::Spec->abs2rel($subclass_dir, $base_dir);
55       } else {
56         $build->log_warn("Warning: builder subclass " . ref($build) . 
57                          " doesn't seem to have been loaded from within $base_dir");
58       }
59     }
60     $subclass_load = "use lib '$subclass_dir';";
61   }
62   
63   if ($type eq 'small') {
64     printf {$fh} <<'EOF', $subclass_load, ref($build), ref($build);
65     use Module::Build::Compat 0.02;
66     %s
67     Module::Build::Compat->run_build_pl(args => \@ARGV);
68     require %s;
69     Module::Build::Compat->write_makefile(build_class => '%s');
70 EOF
71
72   } elsif ($type eq 'passthrough') {
73     printf {$fh} <<'EOF', $subclass_load, ref($build), ref($build);
74     
75     unless (eval "use Module::Build::Compat 0.02; 1" ) {
76       print "This module requires Module::Build to install itself.\n";
77       
78       require ExtUtils::MakeMaker;
79       my $yn = ExtUtils::MakeMaker::prompt
80         ('  Install Module::Build now from CPAN?', 'y');
81       
82       unless ($yn =~ /^y/i) {
83         die " *** Cannot install without Module::Build.  Exiting ...\n";
84       }
85       
86       require Cwd;
87       require File::Spec;
88       require CPAN;
89       
90       # Save this 'cause CPAN will chdir all over the place.
91       my $cwd = Cwd::cwd();
92       
93       # There seems to be no way to determine if this install was successful
94       CPAN::Shell->install('Module::Build::Compat');
95       
96       chdir $cwd or die "Cannot chdir() back to $cwd: $!";
97     }
98     eval "use Module::Build::Compat 0.02; 1" or die $@;
99     %s
100     Module::Build::Compat->run_build_pl(args => \@ARGV);
101     require %s;
102     Module::Build::Compat->write_makefile(build_class => '%s');
103 EOF
104     
105   } elsif ($type eq 'traditional') {
106
107     my (%MM_Args, %prereq);
108     if (eval "use Tie::IxHash; 1") {
109       tie %MM_Args, 'Tie::IxHash'; # Don't care if it fails here
110       tie %prereq,  'Tie::IxHash'; # Don't care if it fails here
111     }
112     
113     my %name = ($build->module_name
114                 ? (NAME => $build->module_name)
115                 : (DISTNAME => $build->dist_name));
116     
117     my %version = ($build->dist_version_from
118                    ? (VERSION_FROM => $build->dist_version_from)
119                    : (VERSION      => $build->dist_version)
120                   );
121     %MM_Args = (%name, %version);
122     
123     %prereq = ( %{$build->requires}, %{$build->build_requires} );
124     %prereq = map {$_, $prereq{$_}} sort keys %prereq;
125     
126     delete $prereq{perl};
127     $MM_Args{PREREQ_PM} = \%prereq;
128     
129     $MM_Args{INSTALLDIRS} = $build->installdirs eq 'core' ? 'perl' : $build->installdirs;
130     
131     $MM_Args{EXE_FILES} = [ sort keys %{$build->script_files} ] if $build->script_files;
132     
133     $MM_Args{PL_FILES} = {};
134     
135     local $Data::Dumper::Terse = 1;
136     my $args = Data::Dumper::Dumper(\%MM_Args);
137     $args =~ s/\{(.*)\}/($1)/s;
138     
139     print $fh <<"EOF";
140 use ExtUtils::MakeMaker;
141 WriteMakefile
142 $args;
143 EOF
144   }
145 }
146
147
148 sub subclass_dir {
149   my ($self, $build) = @_;
150   
151   return (Module::Build::ModuleInfo->find_module_dir_by_name(ref $build)
152           || File::Spec->catdir($build->config_dir, 'lib'));
153 }
154
155 sub makefile_to_build_args {
156   shift;
157   my @out;
158   foreach my $arg (@_) {
159     next if $arg eq '';
160     
161     my ($key, $val) = ($arg =~ /^(\w+)=(.+)/ ? ($1, $2) :
162                        die "Malformed argument '$arg'");
163
164     # Do tilde-expansion if it looks like a tilde prefixed path
165     ( $val ) = glob( $val ) if $val =~ /^~/;
166
167     if (exists $makefile_to_build{$key}) {
168       my $trans = $makefile_to_build{$key};
169       push @out, ref($trans) ? $trans->($val) : ("--$trans", $val);
170     } elsif (exists $Config{lc($key)}) {
171       push @out, '--config', lc($key) . "=$val";
172     } else {
173       # Assume M::B can handle it in lowercase form
174       push @out, "--\L$key", $val;
175     }
176   }
177   return @out;
178 }
179
180 sub makefile_to_build_macros {
181   my @out;
182   while (my ($macro, $trans) = each %makefile_to_build) {
183     # On some platforms (e.g. Cygwin with 'make'), the mere presence
184     # of "EXPORT: FOO" in the Makefile will make $ENV{FOO} defined.
185     # Therefore we check length() too.
186     next unless exists $ENV{$macro} && length $ENV{$macro};
187     my $val = $ENV{$macro};
188     push @out, ref($trans) ? $trans->($val) : ($trans => $val);
189   }
190   return @out;
191 }
192
193 sub run_build_pl {
194   my ($pack, %in) = @_;
195   $in{script} ||= 'Build.PL';
196   my @args = $in{args} ? $pack->makefile_to_build_args(@{$in{args}}) : ();
197   print "# running $in{script} @args\n";
198   Module::Build->run_perl_script($in{script}, [], \@args) or die "Couldn't run $in{script}: $!";
199 }
200
201 sub fake_makefile {
202   my ($self, %args) = @_;
203   unless (exists $args{build_class}) {
204     warn "Unknown 'build_class', defaulting to 'Module::Build'\n";
205     $args{build_class} = 'Module::Build';
206   }
207
208   my $perl = $args{build_class}->find_perl_interpreter;
209   my $os_type = $args{build_class}->os_type;
210   my $noop = ($os_type eq 'Windows' ? 'rem>nul' :
211               $os_type eq 'VMS'     ? 'Continue' :
212               'true');
213   my $Build = 'Build --makefile_env_macros 1';
214
215   # Start with a couple special actions
216   my $maketext = <<"EOF";
217 all : force_do_it
218         $perl $Build
219 realclean : force_do_it
220         $perl $Build realclean
221         $perl -e unlink -e shift $args{makefile}
222
223 force_do_it :
224         @ $noop
225 EOF
226
227   foreach my $action ($args{build_class}->known_actions) {
228     next if $action =~ /^(all|realclean|force_do_it)$/;  # Don't double-define
229     $maketext .= <<"EOF";
230 $action : force_do_it
231         $perl $Build $action
232 EOF
233   }
234   
235   $maketext .= "\n.EXPORT : " . join(' ', keys %makefile_to_build) . "\n\n";
236   
237   return $maketext;
238 }
239
240 sub fake_prereqs {
241   my $file = File::Spec->catfile('_build', 'prereqs');
242   my $fh = IO::File->new("< $file") or die "Can't read $file: $!";
243   my $prereqs = eval do {local $/; <$fh>};
244   close $fh;
245   
246   my @prereq;
247   foreach my $section (qw/build_requires requires/) {
248     foreach (keys %{$prereqs->{$section}}) {
249       next if $_ eq 'perl';
250       push @prereq, "$_=>q[$prereqs->{$section}{$_}]";
251     }
252   }
253
254   return unless @prereq;
255   return "#     PREREQ_PM => { " . join(", ", @prereq) . " }\n\n";
256 }
257
258
259 sub write_makefile {
260   my ($pack, %in) = @_;
261   $in{makefile} ||= 'Makefile';
262   open  MAKE, "> $in{makefile}" or die "Cannot write $in{makefile}: $!";
263   print MAKE $pack->fake_prereqs;
264   print MAKE $pack->fake_makefile(%in);
265   close MAKE;
266 }
267
268 1;
269 __END__
270
271
272 =head1 NAME
273
274 Module::Build::Compat - Compatibility with ExtUtils::MakeMaker
275
276
277 =head1 SYNOPSIS
278
279   # In a Build.PL :
280   use Module::Build;
281   my $build = Module::Build->new
282     ( module_name => 'Foo::Bar',
283       license     => 'perl',
284       create_makefile_pl => 'passthrough' );
285   ...
286
287
288 =head1 DESCRIPTION
289
290 Because ExtUtils::MakeMaker has been the standard way to distribute
291 modules for a long time, many tools (CPAN.pm, or your system
292 administrator) may expect to find a working Makefile.PL in every
293 distribution they download from CPAN.  If you want to throw them a
294 bone, you can use Module::Build::Compat to automatically generate a
295 Makefile.PL for you, in one of several different styles.
296
297 Module::Build::Compat also provides some code that helps out the
298 Makefile.PL at runtime.
299
300
301 =head1 METHODS
302
303 =over 4
304
305 =item create_makefile_pl($style, $build)
306
307 Creates a Makefile.PL in the current directory in one of several
308 styles, based on the supplied Module::Build object C<$build>.  This is
309 typically controlled by passing the desired style as the
310 C<create_makefile_pl> parameter to Module::Build's C<new()> method;
311 the Makefile.PL will then be automatically created during the
312 C<distdir> action.
313
314 The currently supported styles are:
315
316 =over 4
317
318 =item small
319
320 A small Makefile.PL will be created that passes all functionality
321 through to the Build.PL script in the same directory.  The user must
322 already have Module::Build installed in order to use this, or else
323 they'll get a module-not-found error.
324
325 =item passthrough
326
327 This is just like the C<small> option above, but if Module::Build is
328 not already installed on the user's system, the script will offer to
329 use C<CPAN.pm> to download it and install it before continuing with
330 the build.
331
332 =item traditional
333
334 A Makefile.PL will be created in the "traditional" style, i.e. it will
335 use C<ExtUtils::MakeMaker> and won't rely on C<Module::Build> at all.
336 In order to create the Makefile.PL, we'll include the C<requires> and
337 C<build_requires> dependencies as the C<PREREQ_PM> parameter.
338
339 You don't want to use this style if during the C<perl Build.PL> stage
340 you ask the user questions, or do some auto-sensing about the user's
341 environment, or if you subclass Module::Build to do some
342 customization, because the vanilla Makefile.PL won't do any of that.
343
344 =back
345
346 =item run_build_pl(args => \@ARGV)
347
348 This method runs the Build.PL script, passing it any arguments the
349 user may have supplied to the C<perl Makefile.PL> command.  Because
350 ExtUtils::MakeMaker and Module::Build accept different arguments, this
351 method also performs some translation between the two.
352
353 C<run_build_pl()> accepts the following named parameters:
354
355 =over 4
356
357 =item args
358
359 The C<args> parameter specifies the parameters that would usually
360 appear on the command line of the C<perl Makefile.PL> command -
361 typically you'll just pass a reference to C<@ARGV>.
362
363 =item script
364
365 This is the filename of the script to run - it defaults to C<Build.PL>.
366
367 =back
368
369 =item write_makefile()
370
371 This method writes a 'dummy' Makefile that will pass all commands
372 through to the corresponding Module::Build actions.
373
374 C<write_makefile()> accepts the following named parameters:
375
376 =over 4
377
378 =item makefile
379
380 The name of the file to write - defaults to the string C<Makefile>.
381
382 =back
383
384 =back
385
386
387 =head1 SCENARIOS
388
389 So, some common scenarios are:
390
391 =over 4
392
393 =item 1.
394
395 Just include a Build.PL script (without a Makefile.PL
396 script), and give installation directions in a README or INSTALL
397 document explaining how to install the module.  In particular, explain
398 that the user must install Module::Build before installing your
399 module.
400
401 Note that if you do this, you may make things easier for yourself, but
402 harder for people with older versions of CPAN or CPANPLUS on their
403 system, because those tools generally only understand the
404 F<Makefile.PL>/C<ExtUtils::MakeMaker> way of doing things.
405
406 =item 2.
407
408 Include a Build.PL script and a "traditional" Makefile.PL,
409 created either manually or with C<create_makefile_pl()>.  Users won't
410 ever have to install Module::Build if they use the Makefile.PL, but
411 they won't get to take advantage of Module::Build's extra features
412 either.
413
414 If you go this route, make sure you explicitly set C<PL_FILES> in the
415 call to C<WriteMakefile()> (probably to an empty hash reference), or
416 else MakeMaker will mistakenly run the Build.PL and you'll get an
417 error message about "Too early to run Build script" or something.  For
418 good measure, of course, test both the F<Makefile.PL> and the
419 F<Build.PL> before shipping.
420
421 =item 3.
422
423 Include a Build.PL script and a "pass-through" Makefile.PL
424 built using Module::Build::Compat.  This will mean that people can
425 continue to use the "old" installation commands, and they may never
426 notice that it's actually doing something else behind the scenes.  It
427 will also mean that your installation process is compatible with older
428 versions of tools like CPAN and CPANPLUS.
429
430 =back
431
432
433 =head1 AUTHOR
434
435 Ken Williams <ken@cpan.org>
436
437
438 =head1 COPYRIGHT
439
440 Copyright (c) 2001-2005 Ken Williams.  All rights reserved.
441
442 This library is free software; you can redistribute it and/or
443 modify it under the same terms as Perl itself.
444
445
446 =head1 SEE ALSO
447
448 Module::Build(3), ExtUtils::MakeMaker(3)
449
450
451 =cut