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