Commit | Line | Data |
146ec120 |
1 | #line 1 |
2 | package Module::Install::Makefile; |
3 | |
4 | use strict 'vars'; |
5 | use ExtUtils::MakeMaker (); |
6 | use Module::Install::Base (); |
7 | |
8 | use vars qw{$VERSION @ISA $ISCORE}; |
9 | BEGIN { |
10 | $VERSION = '0.95'; |
11 | @ISA = 'Module::Install::Base'; |
12 | $ISCORE = 1; |
13 | } |
14 | |
15 | sub Makefile { $_[0] } |
16 | |
17 | my %seen = (); |
18 | |
19 | sub prompt { |
20 | shift; |
21 | |
22 | # Infinite loop protection |
23 | my @c = caller(); |
24 | if ( ++$seen{"$c[1]|$c[2]|$_[0]"} > 3 ) { |
25 | die "Caught an potential prompt infinite loop ($c[1]|$c[2]|$_[0])"; |
26 | } |
27 | |
28 | # In automated testing or non-interactive session, always use defaults |
29 | if ( ($ENV{AUTOMATED_TESTING} or -! -t STDIN) and ! $ENV{PERL_MM_USE_DEFAULT} ) { |
30 | local $ENV{PERL_MM_USE_DEFAULT} = 1; |
31 | goto &ExtUtils::MakeMaker::prompt; |
32 | } else { |
33 | goto &ExtUtils::MakeMaker::prompt; |
34 | } |
35 | } |
36 | |
37 | # Store a cleaned up version of the MakeMaker version, |
38 | # since we need to behave differently in a variety of |
39 | # ways based on the MM version. |
40 | my $makemaker = eval $ExtUtils::MakeMaker::VERSION; |
41 | |
42 | # If we are passed a param, do a "newer than" comparison. |
43 | # Otherwise, just return the MakeMaker version. |
44 | sub makemaker { |
45 | ( @_ < 2 or $makemaker >= eval($_[1]) ) ? $makemaker : 0 |
46 | } |
47 | |
48 | # Ripped from ExtUtils::MakeMaker 6.56, and slightly modified |
49 | # as we only need to know here whether the attribute is an array |
50 | # or a hash or something else (which may or may not be appendable). |
51 | my %makemaker_argtype = ( |
52 | C => 'ARRAY', |
53 | CONFIG => 'ARRAY', |
54 | # CONFIGURE => 'CODE', # ignore |
55 | DIR => 'ARRAY', |
56 | DL_FUNCS => 'HASH', |
57 | DL_VARS => 'ARRAY', |
58 | EXCLUDE_EXT => 'ARRAY', |
59 | EXE_FILES => 'ARRAY', |
60 | FUNCLIST => 'ARRAY', |
61 | H => 'ARRAY', |
62 | IMPORTS => 'HASH', |
63 | INCLUDE_EXT => 'ARRAY', |
64 | LIBS => 'ARRAY', # ignore '' |
65 | MAN1PODS => 'HASH', |
66 | MAN3PODS => 'HASH', |
67 | META_ADD => 'HASH', |
68 | META_MERGE => 'HASH', |
69 | PL_FILES => 'HASH', |
70 | PM => 'HASH', |
71 | PMLIBDIRS => 'ARRAY', |
72 | PMLIBPARENTDIRS => 'ARRAY', |
73 | PREREQ_PM => 'HASH', |
74 | CONFIGURE_REQUIRES => 'HASH', |
75 | SKIP => 'ARRAY', |
76 | TYPEMAPS => 'ARRAY', |
77 | XS => 'HASH', |
78 | # VERSION => ['version',''], # ignore |
79 | # _KEEP_AFTER_FLUSH => '', |
80 | |
81 | clean => 'HASH', |
82 | depend => 'HASH', |
83 | dist => 'HASH', |
84 | dynamic_lib=> 'HASH', |
85 | linkext => 'HASH', |
86 | macro => 'HASH', |
87 | postamble => 'HASH', |
88 | realclean => 'HASH', |
89 | test => 'HASH', |
90 | tool_autosplit => 'HASH', |
91 | |
92 | # special cases where you can use makemaker_append |
93 | CCFLAGS => 'APPENDABLE', |
94 | DEFINE => 'APPENDABLE', |
95 | INC => 'APPENDABLE', |
96 | LDDLFLAGS => 'APPENDABLE', |
97 | LDFROM => 'APPENDABLE', |
98 | ); |
99 | |
100 | sub makemaker_args { |
101 | my ($self, %new_args) = @_; |
102 | my $args = ( $self->{makemaker_args} ||= {} ); |
103 | foreach my $key (keys %new_args) { |
104 | if ($makemaker_argtype{$key} eq 'ARRAY') { |
105 | $args->{$key} = [] unless defined $args->{$key}; |
106 | unless (ref $args->{$key} eq 'ARRAY') { |
107 | $args->{$key} = [$args->{$key}] |
108 | } |
109 | push @{$args->{$key}}, |
110 | ref $new_args{$key} eq 'ARRAY' |
111 | ? @{$new_args{$key}} |
112 | : $new_args{$key}; |
113 | } |
114 | elsif ($makemaker_argtype{$key} eq 'HASH') { |
115 | $args->{$key} = {} unless defined $args->{$key}; |
116 | foreach my $skey (keys %{ $new_args{$key} }) { |
117 | $args->{$key}{$skey} = $new_args{$key}{$skey}; |
118 | } |
119 | } |
120 | elsif ($makemaker_argtype{$key} eq 'APPENDABLE') { |
121 | $self->makemaker_append($key => $new_args{$key}); |
122 | } |
123 | else { |
124 | if (defined $args->{$key}) { |
125 | warn qq{MakeMaker attribute "$key" is overriden; use "makemaker_append" to append values\n}; |
126 | } |
127 | $args->{$key} = $new_args{$key}; |
128 | } |
129 | } |
130 | return $args; |
131 | } |
132 | |
133 | # For mm args that take multiple space-seperated args, |
134 | # append an argument to the current list. |
135 | sub makemaker_append { |
136 | my $self = shift; |
137 | my $name = shift; |
138 | my $args = $self->makemaker_args; |
139 | $args->{$name} = defined $args->{$name} |
140 | ? join( ' ', $args->{$name}, @_ ) |
141 | : join( ' ', @_ ); |
142 | } |
143 | |
144 | sub build_subdirs { |
145 | my $self = shift; |
146 | my $subdirs = $self->makemaker_args->{DIR} ||= []; |
147 | for my $subdir (@_) { |
148 | push @$subdirs, $subdir; |
149 | } |
150 | } |
151 | |
152 | sub clean_files { |
153 | my $self = shift; |
154 | my $clean = $self->makemaker_args->{clean} ||= {}; |
155 | %$clean = ( |
156 | %$clean, |
157 | FILES => join ' ', grep { length $_ } ($clean->{FILES} || (), @_), |
158 | ); |
159 | } |
160 | |
161 | sub realclean_files { |
162 | my $self = shift; |
163 | my $realclean = $self->makemaker_args->{realclean} ||= {}; |
164 | %$realclean = ( |
165 | %$realclean, |
166 | FILES => join ' ', grep { length $_ } ($realclean->{FILES} || (), @_), |
167 | ); |
168 | } |
169 | |
170 | sub libs { |
171 | my $self = shift; |
172 | my $libs = ref $_[0] ? shift : [ shift ]; |
173 | $self->makemaker_args( LIBS => $libs ); |
174 | } |
175 | |
176 | sub inc { |
177 | my $self = shift; |
178 | $self->makemaker_args( INC => shift ); |
179 | } |
180 | |
181 | my %test_dir = (); |
182 | |
183 | sub _wanted_t { |
184 | /\.t$/ and -f $_ and $test_dir{$File::Find::dir} = 1; |
185 | } |
186 | |
187 | sub tests_recursive { |
188 | my $self = shift; |
189 | if ( $self->tests ) { |
190 | die "tests_recursive will not work if tests are already defined"; |
191 | } |
192 | my $dir = shift || 't'; |
193 | unless ( -d $dir ) { |
194 | die "tests_recursive dir '$dir' does not exist"; |
195 | } |
196 | %test_dir = (); |
197 | require File::Find; |
198 | File::Find::find( \&_wanted_t, $dir ); |
199 | if ( -d 'xt' and ($Module::Install::AUTHOR or $ENV{RELEASE_TESTING}) ) { |
200 | File::Find::find( \&_wanted_t, 'xt' ); |
201 | } |
202 | $self->tests( join ' ', map { "$_/*.t" } sort keys %test_dir ); |
203 | } |
204 | |
205 | sub write { |
206 | my $self = shift; |
207 | die "&Makefile->write() takes no arguments\n" if @_; |
208 | |
209 | # Check the current Perl version |
210 | my $perl_version = $self->perl_version; |
211 | if ( $perl_version ) { |
212 | eval "use $perl_version; 1" |
213 | or die "ERROR: perl: Version $] is installed, " |
214 | . "but we need version >= $perl_version"; |
215 | } |
216 | |
217 | # Make sure we have a new enough MakeMaker |
218 | require ExtUtils::MakeMaker; |
219 | |
220 | if ( $perl_version and $self->_cmp($perl_version, '5.006') >= 0 ) { |
221 | # MakeMaker can complain about module versions that include |
222 | # an underscore, even though its own version may contain one! |
223 | # Hence the funny regexp to get rid of it. See RT #35800 |
224 | # for details. |
225 | my $v = $ExtUtils::MakeMaker::VERSION =~ /^(\d+\.\d+)/; |
226 | $self->build_requires( 'ExtUtils::MakeMaker' => $v ); |
227 | $self->configure_requires( 'ExtUtils::MakeMaker' => $v ); |
228 | } else { |
229 | # Allow legacy-compatibility with 5.005 by depending on the |
230 | # most recent EU:MM that supported 5.005. |
231 | $self->build_requires( 'ExtUtils::MakeMaker' => 6.42 ); |
232 | $self->configure_requires( 'ExtUtils::MakeMaker' => 6.42 ); |
233 | } |
234 | |
235 | # Generate the MakeMaker params |
236 | my $args = $self->makemaker_args; |
237 | $args->{DISTNAME} = $self->name; |
238 | $args->{NAME} = $self->module_name || $self->name; |
239 | $args->{NAME} =~ s/-/::/g; |
240 | $args->{VERSION} = $self->version or die <<'EOT'; |
241 | ERROR: Can't determine distribution version. Please specify it |
242 | explicitly via 'version' in Makefile.PL, or set a valid $VERSION |
243 | in a module, and provide its file path via 'version_from' (or |
244 | 'all_from' if you prefer) in Makefile.PL. |
245 | EOT |
246 | |
247 | $DB::single = 1; |
248 | if ( $self->tests ) { |
249 | my @tests = split ' ', $self->tests; |
250 | my %seen; |
251 | $args->{test} = { |
252 | TESTS => (join ' ', grep {!$seen{$_}++} @tests), |
253 | }; |
254 | } elsif ( -d 'xt' and ($Module::Install::AUTHOR or $ENV{RELEASE_TESTING}) ) { |
255 | $args->{test} = { |
256 | TESTS => join( ' ', map { "$_/*.t" } grep { -d $_ } qw{ t xt } ), |
257 | }; |
258 | } |
259 | if ( $] >= 5.005 ) { |
260 | $args->{ABSTRACT} = $self->abstract; |
261 | $args->{AUTHOR} = join ', ', @{$self->author || []}; |
262 | } |
263 | if ( $self->makemaker(6.10) ) { |
264 | $args->{NO_META} = 1; |
265 | #$args->{NO_MYMETA} = 1; |
266 | } |
267 | if ( $self->makemaker(6.17) and $self->sign ) { |
268 | $args->{SIGN} = 1; |
269 | } |
270 | unless ( $self->is_admin ) { |
271 | delete $args->{SIGN}; |
272 | } |
273 | if ( $self->makemaker(6.31) and $self->license ) { |
274 | $args->{LICENSE} = $self->license; |
275 | } |
276 | |
277 | my $prereq = ($args->{PREREQ_PM} ||= {}); |
278 | %$prereq = ( %$prereq, |
279 | map { @$_ } # flatten [module => version] |
280 | map { @$_ } |
281 | grep $_, |
282 | ($self->requires) |
283 | ); |
284 | |
285 | # Remove any reference to perl, PREREQ_PM doesn't support it |
286 | delete $args->{PREREQ_PM}->{perl}; |
287 | |
288 | # Merge both kinds of requires into BUILD_REQUIRES |
289 | my $build_prereq = ($args->{BUILD_REQUIRES} ||= {}); |
290 | %$build_prereq = ( %$build_prereq, |
291 | map { @$_ } # flatten [module => version] |
292 | map { @$_ } |
293 | grep $_, |
294 | ($self->configure_requires, $self->build_requires) |
295 | ); |
296 | |
297 | # Remove any reference to perl, BUILD_REQUIRES doesn't support it |
298 | delete $args->{BUILD_REQUIRES}->{perl}; |
299 | |
300 | # Delete bundled dists from prereq_pm |
301 | my $subdirs = ($args->{DIR} ||= []); |
302 | if ($self->bundles) { |
303 | foreach my $bundle (@{ $self->bundles }) { |
304 | my ($file, $dir) = @$bundle; |
305 | push @$subdirs, $dir if -d $dir; |
306 | delete $build_prereq->{$file}; #Delete from build prereqs only |
307 | } |
308 | } |
309 | |
310 | unless ( $self->makemaker('6.55_03') ) { |
311 | %$prereq = (%$prereq,%$build_prereq); |
312 | delete $args->{BUILD_REQUIRES}; |
313 | } |
314 | |
315 | if ( my $perl_version = $self->perl_version ) { |
316 | eval "use $perl_version; 1" |
317 | or die "ERROR: perl: Version $] is installed, " |
318 | . "but we need version >= $perl_version"; |
319 | |
320 | if ( $self->makemaker(6.48) ) { |
321 | $args->{MIN_PERL_VERSION} = $perl_version; |
322 | } |
323 | } |
324 | |
325 | if ($self->installdirs) { |
326 | warn qq{old INSTALLDIRS (probably set by makemaker_args) is overriden by installdirs\n} if $args->{INSTALLDIRS}; |
327 | $args->{INSTALLDIRS} = $self->installdirs; |
328 | } |
329 | |
330 | my %args = map { |
331 | ( $_ => $args->{$_} ) } grep {defined($args->{$_} ) |
332 | } keys %$args; |
333 | |
334 | my $user_preop = delete $args{dist}->{PREOP}; |
335 | if ( my $preop = $self->admin->preop($user_preop) ) { |
336 | foreach my $key ( keys %$preop ) { |
337 | $args{dist}->{$key} = $preop->{$key}; |
338 | } |
339 | } |
340 | |
341 | my $mm = ExtUtils::MakeMaker::WriteMakefile(%args); |
342 | $self->fix_up_makefile($mm->{FIRST_MAKEFILE} || 'Makefile'); |
343 | } |
344 | |
345 | sub fix_up_makefile { |
346 | my $self = shift; |
347 | my $makefile_name = shift; |
348 | my $top_class = ref($self->_top) || ''; |
349 | my $top_version = $self->_top->VERSION || ''; |
350 | |
351 | my $preamble = $self->preamble |
352 | ? "# Preamble by $top_class $top_version\n" |
353 | . $self->preamble |
354 | : ''; |
355 | my $postamble = "# Postamble by $top_class $top_version\n" |
356 | . ($self->postamble || ''); |
357 | |
358 | local *MAKEFILE; |
359 | open MAKEFILE, "< $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!"; |
360 | my $makefile = do { local $/; <MAKEFILE> }; |
361 | close MAKEFILE or die $!; |
362 | |
363 | $makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /; |
364 | $makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g; |
365 | $makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g; |
366 | $makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m; |
367 | $makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m; |
368 | |
369 | # Module::Install will never be used to build the Core Perl |
370 | # Sometimes PERL_LIB and PERL_ARCHLIB get written anyway, which breaks |
371 | # PREFIX/PERL5LIB, and thus, install_share. Blank them if they exist |
372 | $makefile =~ s/^PERL_LIB = .+/PERL_LIB =/m; |
373 | #$makefile =~ s/^PERL_ARCHLIB = .+/PERL_ARCHLIB =/m; |
374 | |
375 | # Perl 5.005 mentions PERL_LIB explicitly, so we have to remove that as well. |
376 | $makefile =~ s/(\"?)-I\$\(PERL_LIB\)\1//g; |
377 | |
378 | # XXX - This is currently unused; not sure if it breaks other MM-users |
379 | # $makefile =~ s/^pm_to_blib\s+:\s+/pm_to_blib :: /mg; |
380 | |
381 | open MAKEFILE, "> $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!"; |
382 | print MAKEFILE "$preamble$makefile$postamble" or die $!; |
383 | close MAKEFILE or die $!; |
384 | |
385 | 1; |
386 | } |
387 | |
388 | sub preamble { |
389 | my ($self, $text) = @_; |
390 | $self->{preamble} = $text . $self->{preamble} if defined $text; |
391 | $self->{preamble}; |
392 | } |
393 | |
394 | sub postamble { |
395 | my ($self, $text) = @_; |
396 | $self->{postamble} ||= $self->admin->postamble; |
397 | $self->{postamble} .= $text if defined $text; |
398 | $self->{postamble} |
399 | } |
400 | |
401 | 1; |
402 | |
403 | __END__ |
404 | |
405 | #line 531 |