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