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