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