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