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