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