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