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