Makefile.pm 11.5 KB
Newer Older
Ruslan Zakirov's avatar
Ruslan Zakirov committed
1
2
3
4
#line 1
package Module::Install::Makefile;

use strict 'vars';
Kevin Falcone's avatar
Kevin Falcone committed
5
6
use ExtUtils::MakeMaker   ();
use Module::Install::Base ();
7
use Fcntl qw/:flock :seek/;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
8

Kevin Falcone's avatar
Kevin Falcone committed
9
use vars qw{$VERSION @ISA $ISCORE};
Ruslan Zakirov's avatar
Ruslan Zakirov committed
10
BEGIN {
11
	$VERSION = '1.00';
Kevin Falcone's avatar
Kevin Falcone committed
12
	@ISA     = 'Module::Install::Base';
Ruslan Zakirov's avatar
Ruslan Zakirov committed
13
14
15
16
17
18
19
20
	$ISCORE  = 1;
}

sub Makefile { $_[0] }

my %seen = ();

sub prompt {
Kevin Falcone's avatar
Kevin Falcone committed
21
22
23
24
25
26
27
28
	shift;

	# Infinite loop protection
	my @c = caller();
	if ( ++$seen{"$c[1]|$c[2]|$_[0]"} > 3 ) {
		die "Caught an potential prompt infinite loop ($c[1]|$c[2]|$_[0])";
	}

29
30
	# In automated testing or non-interactive session, always use defaults
	if ( ($ENV{AUTOMATED_TESTING} or -! -t STDIN) and ! $ENV{PERL_MM_USE_DEFAULT} ) {
Kevin Falcone's avatar
Kevin Falcone committed
31
32
33
34
35
		local $ENV{PERL_MM_USE_DEFAULT} = 1;
		goto &ExtUtils::MakeMaker::prompt;
	} else {
		goto &ExtUtils::MakeMaker::prompt;
	}
Ruslan Zakirov's avatar
Ruslan Zakirov committed
36
37
}

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# Store a cleaned up version of the MakeMaker version,
# since we need to behave differently in a variety of
# ways based on the MM version.
my $makemaker = eval $ExtUtils::MakeMaker::VERSION;

# If we are passed a param, do a "newer than" comparison.
# Otherwise, just return the MakeMaker version.
sub makemaker {
	( @_ < 2 or $makemaker >= eval($_[1]) ) ? $makemaker : 0
}

# Ripped from ExtUtils::MakeMaker 6.56, and slightly modified
# as we only need to know here whether the attribute is an array
# or a hash or something else (which may or may not be appendable).
my %makemaker_argtype = (
 C                  => 'ARRAY',
 CONFIG             => 'ARRAY',
# CONFIGURE          => 'CODE', # ignore
 DIR                => 'ARRAY',
 DL_FUNCS           => 'HASH',
 DL_VARS            => 'ARRAY',
 EXCLUDE_EXT        => 'ARRAY',
 EXE_FILES          => 'ARRAY',
 FUNCLIST           => 'ARRAY',
 H                  => 'ARRAY',
 IMPORTS            => 'HASH',
 INCLUDE_EXT        => 'ARRAY',
 LIBS               => 'ARRAY', # ignore ''
 MAN1PODS           => 'HASH',
 MAN3PODS           => 'HASH',
 META_ADD           => 'HASH',
 META_MERGE         => 'HASH',
 PL_FILES           => 'HASH',
 PM                 => 'HASH',
 PMLIBDIRS          => 'ARRAY',
 PMLIBPARENTDIRS    => 'ARRAY',
 PREREQ_PM          => 'HASH',
 CONFIGURE_REQUIRES => 'HASH',
 SKIP               => 'ARRAY',
 TYPEMAPS           => 'ARRAY',
 XS                 => 'HASH',
# VERSION            => ['version',''],  # ignore
# _KEEP_AFTER_FLUSH  => '',

 clean      => 'HASH',
 depend     => 'HASH',
 dist       => 'HASH',
 dynamic_lib=> 'HASH',
 linkext    => 'HASH',
 macro      => 'HASH',
 postamble  => 'HASH',
 realclean  => 'HASH',
 test       => 'HASH',
 tool_autosplit => 'HASH',

 # special cases where you can use makemaker_append
 CCFLAGS   => 'APPENDABLE',
 DEFINE    => 'APPENDABLE',
 INC       => 'APPENDABLE',
 LDDLFLAGS => 'APPENDABLE',
 LDFROM    => 'APPENDABLE',
);

Ruslan Zakirov's avatar
Ruslan Zakirov committed
101
sub makemaker_args {
102
	my ($self, %new_args) = @_;
Kevin Falcone's avatar
Kevin Falcone committed
103
	my $args = ( $self->{makemaker_args} ||= {} );
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
	foreach my $key (keys %new_args) {
		if ($makemaker_argtype{$key}) {
			if ($makemaker_argtype{$key} eq 'ARRAY') {
				$args->{$key} = [] unless defined $args->{$key};
				unless (ref $args->{$key} eq 'ARRAY') {
					$args->{$key} = [$args->{$key}]
				}
				push @{$args->{$key}},
					ref $new_args{$key} eq 'ARRAY'
						? @{$new_args{$key}}
						: $new_args{$key};
			}
			elsif ($makemaker_argtype{$key} eq 'HASH') {
				$args->{$key} = {} unless defined $args->{$key};
				foreach my $skey (keys %{ $new_args{$key} }) {
					$args->{$key}{$skey} = $new_args{$key}{$skey};
				}
			}
			elsif ($makemaker_argtype{$key} eq 'APPENDABLE') {
				$self->makemaker_append($key => $new_args{$key});
			}
		}
		else {
			if (defined $args->{$key}) {
				warn qq{MakeMaker attribute "$key" is overriden; use "makemaker_append" to append values\n};
			}
			$args->{$key} = $new_args{$key};
		}
	}
Kevin Falcone's avatar
Kevin Falcone committed
133
	return $args;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
134
135
136
137
138
}

# For mm args that take multiple space-seperated args,
# append an argument to the current list.
sub makemaker_append {
139
	my $self = shift;
Kevin Falcone's avatar
Kevin Falcone committed
140
141
	my $name = shift;
	my $args = $self->makemaker_args;
142
143
	$args->{$name} = defined $args->{$name}
		? join( ' ', $args->{$name}, @_ )
Kevin Falcone's avatar
Kevin Falcone committed
144
		: join( ' ', @_ );
Ruslan Zakirov's avatar
Ruslan Zakirov committed
145
146
147
}

sub build_subdirs {
Kevin Falcone's avatar
Kevin Falcone committed
148
149
150
151
152
	my $self    = shift;
	my $subdirs = $self->makemaker_args->{DIR} ||= [];
	for my $subdir (@_) {
		push @$subdirs, $subdir;
	}
Ruslan Zakirov's avatar
Ruslan Zakirov committed
153
154
155
}

sub clean_files {
Kevin Falcone's avatar
Kevin Falcone committed
156
157
	my $self  = shift;
	my $clean = $self->makemaker_args->{clean} ||= {};
Kevin Falcone's avatar
Kevin Falcone committed
158
159
160
	  %$clean = (
		%$clean,
		FILES => join ' ', grep { length $_ } ($clean->{FILES} || (), @_),
Kevin Falcone's avatar
Kevin Falcone committed
161
	);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
162
163
164
}

sub realclean_files {
Kevin Falcone's avatar
Kevin Falcone committed
165
	my $self      = shift;
Kevin Falcone's avatar
Kevin Falcone committed
166
	my $realclean = $self->makemaker_args->{realclean} ||= {};
Kevin Falcone's avatar
Kevin Falcone committed
167
168
169
	  %$realclean = (
		%$realclean,
		FILES => join ' ', grep { length $_ } ($realclean->{FILES} || (), @_),
Kevin Falcone's avatar
Kevin Falcone committed
170
	);
Ruslan Zakirov's avatar
Ruslan Zakirov committed
171
172
173
}

sub libs {
Kevin Falcone's avatar
Kevin Falcone committed
174
175
176
	my $self = shift;
	my $libs = ref $_[0] ? shift : [ shift ];
	$self->makemaker_args( LIBS => $libs );
Ruslan Zakirov's avatar
Ruslan Zakirov committed
177
178
179
}

sub inc {
Kevin Falcone's avatar
Kevin Falcone committed
180
181
182
183
184
185
186
187
188
189
190
191
192
	my $self = shift;
	$self->makemaker_args( INC => shift );
}

sub _wanted_t {
}

sub tests_recursive {
	my $self = shift;
	my $dir = shift || 't';
	unless ( -d $dir ) {
		die "tests_recursive dir '$dir' does not exist";
	}
193
	my %tests = map { $_ => 1 } split / /, ($self->tests || '');
Kevin Falcone's avatar
Kevin Falcone committed
194
	require File::Find;
195
196
197
198
199
	File::Find::find(
        sub { /\.t$/ and -f $_ and $tests{"$File::Find::dir/*.t"} = 1 },
        $dir
    );
	$self->tests( join ' ', sort keys %tests );
Ruslan Zakirov's avatar
Ruslan Zakirov committed
200
201
202
}

sub write {
Kevin Falcone's avatar
Kevin Falcone committed
203
204
205
	my $self = shift;
	die "&Makefile->write() takes no arguments\n" if @_;

Kevin Falcone's avatar
Kevin Falcone committed
206
207
208
209
210
211
212
213
214
	# Check the current Perl version
	my $perl_version = $self->perl_version;
	if ( $perl_version ) {
		eval "use $perl_version; 1"
			or die "ERROR: perl: Version $] is installed, "
			. "but we need version >= $perl_version";
	}

	# Make sure we have a new enough MakeMaker
Kevin Falcone's avatar
Kevin Falcone committed
215
216
	require ExtUtils::MakeMaker;

Kevin Falcone's avatar
Kevin Falcone committed
217
218
219
220
221
	if ( $perl_version and $self->_cmp($perl_version, '5.006') >= 0 ) {
		# MakeMaker can complain about module versions that include
		# an underscore, even though its own version may contain one!
		# Hence the funny regexp to get rid of it.  See RT #35800
		# for details.
222
223
224
		my $v = $ExtUtils::MakeMaker::VERSION =~ /^(\d+\.\d+)/;
		$self->build_requires(     'ExtUtils::MakeMaker' => $v );
		$self->configure_requires( 'ExtUtils::MakeMaker' => $v );
Kevin Falcone's avatar
Kevin Falcone committed
225
226
227
	} else {
		# Allow legacy-compatibility with 5.005 by depending on the
		# most recent EU:MM that supported 5.005.
228
		$self->build_requires(     'ExtUtils::MakeMaker' => 6.42 );
Kevin Falcone's avatar
Kevin Falcone committed
229
230
231
232
		$self->configure_requires( 'ExtUtils::MakeMaker' => 6.42 );
	}

	# Generate the MakeMaker params
Kevin Falcone's avatar
Kevin Falcone committed
233
234
	my $args = $self->makemaker_args;
	$args->{DISTNAME} = $self->name;
Kevin Falcone's avatar
Kevin Falcone committed
235
	$args->{NAME}     = $self->module_name || $self->name;
Kevin Falcone's avatar
Kevin Falcone committed
236
	$args->{NAME}     =~ s/-/::/g;
237
238
239
240
241
242
243
244
	$args->{VERSION}  = $self->version or die <<'EOT';
ERROR: Can't determine distribution version. Please specify it
explicitly via 'version' in Makefile.PL, or set a valid $VERSION
in a module, and provide its file path via 'version_from' (or
'all_from' if you prefer) in Makefile.PL.
EOT

	$DB::single = 1;
Kevin Falcone's avatar
Kevin Falcone committed
245
	if ( $self->tests ) {
246
247
248
249
250
251
252
253
254
255
256
257
		my @tests = split ' ', $self->tests;
		my %seen;
		$args->{test} = {
			TESTS => (join ' ', grep {!$seen{$_}++} @tests),
		};
    } elsif ( $Module::Install::ExtraTests::use_extratests ) {
        # Module::Install::ExtraTests doesn't set $self->tests and does its own tests via harness.
        # So, just ignore our xt tests here.
	} elsif ( -d 'xt' and ($Module::Install::AUTHOR or $ENV{RELEASE_TESTING}) ) {
		$args->{test} = {
			TESTS => join( ' ', map { "$_/*.t" } grep { -d $_ } qw{ t xt } ),
		};
Kevin Falcone's avatar
Kevin Falcone committed
258
	}
Kevin Falcone's avatar
Kevin Falcone committed
259
	if ( $] >= 5.005 ) {
Kevin Falcone's avatar
Kevin Falcone committed
260
		$args->{ABSTRACT} = $self->abstract;
261
		$args->{AUTHOR}   = join ', ', @{$self->author || []};
Kevin Falcone's avatar
Kevin Falcone committed
262
	}
263
264
265
	if ( $self->makemaker(6.10) ) {
		$args->{NO_META}   = 1;
		#$args->{NO_MYMETA} = 1;
Kevin Falcone's avatar
Kevin Falcone committed
266
	}
267
	if ( $self->makemaker(6.17) and $self->sign ) {
Kevin Falcone's avatar
Kevin Falcone committed
268
269
270
271
272
		$args->{SIGN} = 1;
	}
	unless ( $self->is_admin ) {
		delete $args->{SIGN};
	}
273
274
275
	if ( $self->makemaker(6.31) and $self->license ) {
		$args->{LICENSE} = $self->license;
	}
Kevin Falcone's avatar
Kevin Falcone committed
276
277
278

	my $prereq = ($args->{PREREQ_PM} ||= {});
	%$prereq = ( %$prereq,
279
		map { @$_ } # flatten [module => version]
Kevin Falcone's avatar
Kevin Falcone committed
280
281
		map { @$_ }
		grep $_,
282
		($self->requires)
Kevin Falcone's avatar
Kevin Falcone committed
283
284
285
286
287
	);

	# Remove any reference to perl, PREREQ_PM doesn't support it
	delete $args->{PREREQ_PM}->{perl};

288
289
290
291
292
293
294
295
296
297
298
299
300
301
	# Merge both kinds of requires into BUILD_REQUIRES
	my $build_prereq = ($args->{BUILD_REQUIRES} ||= {});
	%$build_prereq = ( %$build_prereq,
		map { @$_ } # flatten [module => version]
		map { @$_ }
		grep $_,
		($self->configure_requires, $self->build_requires)
	);

	# Remove any reference to perl, BUILD_REQUIRES doesn't support it
	delete $args->{BUILD_REQUIRES}->{perl};

	# Delete bundled dists from prereq_pm, add it to Makefile DIR
	my $subdirs = ($args->{DIR} || []);
Kevin Falcone's avatar
Kevin Falcone committed
302
	if ($self->bundles) {
303
		my %processed;
Kevin Falcone's avatar
Kevin Falcone committed
304
		foreach my $bundle (@{ $self->bundles }) {
305
306
307
308
309
310
311
312
313
314
315
			my ($mod_name, $dist_dir) = @$bundle;
			delete $prereq->{$mod_name};
			$dist_dir = File::Basename::basename($dist_dir); # dir for building this module
			if (not exists $processed{$dist_dir}) {
				if (-d $dist_dir) {
					# List as sub-directory to be processed by make
					push @$subdirs, $dist_dir;
				}
				# Else do nothing: the module is already present on the system
				$processed{$dist_dir} = undef;
			}
Kevin Falcone's avatar
Kevin Falcone committed
316
317
318
		}
	}

319
320
321
322
323
	unless ( $self->makemaker('6.55_03') ) {
		%$prereq = (%$prereq,%$build_prereq);
		delete $args->{BUILD_REQUIRES};
	}

Kevin Falcone's avatar
Kevin Falcone committed
324
325
326
327
	if ( my $perl_version = $self->perl_version ) {
		eval "use $perl_version; 1"
			or die "ERROR: perl: Version $] is installed, "
			. "but we need version >= $perl_version";
328
329
330
331

		if ( $self->makemaker(6.48) ) {
			$args->{MIN_PERL_VERSION} = $perl_version;
		}
Kevin Falcone's avatar
Kevin Falcone committed
332
333
	}

334
335
336
337
	if ($self->installdirs) {
		warn qq{old INSTALLDIRS (probably set by makemaker_args) is overriden by installdirs\n} if $args->{INSTALLDIRS};
		$args->{INSTALLDIRS} = $self->installdirs;
	}
Kevin Falcone's avatar
Kevin Falcone committed
338

339
340
341
	my %args = map {
		( $_ => $args->{$_} ) } grep {defined($args->{$_} )
	} keys %$args;
Kevin Falcone's avatar
Kevin Falcone committed
342
343

	my $user_preop = delete $args{dist}->{PREOP};
344
	if ( my $preop = $self->admin->preop($user_preop) ) {
Kevin Falcone's avatar
Kevin Falcone committed
345
346
347
		foreach my $key ( keys %$preop ) {
			$args{dist}->{$key} = $preop->{$key};
		}
Kevin Falcone's avatar
Kevin Falcone committed
348
349
350
351
	}

	my $mm = ExtUtils::MakeMaker::WriteMakefile(%args);
	$self->fix_up_makefile($mm->{FIRST_MAKEFILE} || 'Makefile');
Ruslan Zakirov's avatar
Ruslan Zakirov committed
352
353
354
}

sub fix_up_makefile {
Kevin Falcone's avatar
Kevin Falcone committed
355
356
357
358
359
	my $self          = shift;
	my $makefile_name = shift;
	my $top_class     = ref($self->_top) || '';
	my $top_version   = $self->_top->VERSION || '';

Kevin Falcone's avatar
Kevin Falcone committed
360
	my $preamble = $self->preamble
Kevin Falcone's avatar
Kevin Falcone committed
361
362
363
364
365
366
367
		? "# Preamble by $top_class $top_version\n"
			. $self->preamble
		: '';
	my $postamble = "# Postamble by $top_class $top_version\n"
		. ($self->postamble || '');

	local *MAKEFILE;
368
369
	open MAKEFILE, "+< $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!";
	eval { flock MAKEFILE, LOCK_EX };
Kevin Falcone's avatar
Kevin Falcone committed
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
	my $makefile = do { local $/; <MAKEFILE> };

	$makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /;
	$makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g;
	$makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g;
	$makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m;
	$makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m;

	# Module::Install will never be used to build the Core Perl
	# Sometimes PERL_LIB and PERL_ARCHLIB get written anyway, which breaks
	# PREFIX/PERL5LIB, and thus, install_share. Blank them if they exist
	$makefile =~ s/^PERL_LIB = .+/PERL_LIB =/m;
	#$makefile =~ s/^PERL_ARCHLIB = .+/PERL_ARCHLIB =/m;

	# Perl 5.005 mentions PERL_LIB explicitly, so we have to remove that as well.
	$makefile =~ s/(\"?)-I\$\(PERL_LIB\)\1//g;

	# XXX - This is currently unused; not sure if it breaks other MM-users
	# $makefile =~ s/^pm_to_blib\s+:\s+/pm_to_blib :: /mg;

390
391
	seek MAKEFILE, 0, SEEK_SET;
	truncate MAKEFILE, 0;
Kevin Falcone's avatar
Kevin Falcone committed
392
393
394
395
	print MAKEFILE  "$preamble$makefile$postamble" or die $!;
	close MAKEFILE  or die $!;

	1;
Ruslan Zakirov's avatar
Ruslan Zakirov committed
396
397
398
}

sub preamble {
Kevin Falcone's avatar
Kevin Falcone committed
399
400
401
	my ($self, $text) = @_;
	$self->{preamble} = $text . $self->{preamble} if defined $text;
	$self->{preamble};
Ruslan Zakirov's avatar
Ruslan Zakirov committed
402
403
404
}

sub postamble {
Kevin Falcone's avatar
Kevin Falcone committed
405
406
407
408
	my ($self, $text) = @_;
	$self->{postamble} ||= $self->admin->postamble;
	$self->{postamble} .= $text if defined $text;
	$self->{postamble}
Ruslan Zakirov's avatar
Ruslan Zakirov committed
409
410
411
412
413
414
}

1;

__END__

415
#line 541