our
$VERSION
=
'0.4234'
;
my
%convert_installdirs
= (
PERL
=>
'core'
,
SITE
=>
'site'
,
VENDOR
=>
'vendor'
,
);
my
%makefile_to_build
=
(
TEST_VERBOSE
=>
'verbose'
,
VERBINST
=>
'verbose'
,
INC
=>
sub
{
map
{(
extra_compiler_flags
=>
$_
)} Module::Build->split_like_shell(
shift
) },
POLLUTE
=>
sub
{ (
extra_compiler_flags
=>
'-DPERL_POLLUTE'
) },
INSTALLDIRS
=>
sub
{ (
installdirs
=>
$convert_installdirs
{
uc
shift
()}) },
LIB
=>
sub
{
my
$lib
=
shift
;
my
%config
= (
installprivlib
=>
$lib
,
installsitelib
=>
$lib
,
installarchlib
=>
"$lib/$Config{archname}"
,
installsitearch
=>
"$lib/$Config{archname}"
);
return
map
{ (
config
=>
"$_=$config{$_}"
) }
sort
keys
%config
;
},
(
map
{
my
$name
=
$_
;
$name
=>
sub
{
my
@ret
= (
config
=>
lc
(
$name
) .
"="
.
shift
);
print
STDERR
"# Converted to @ret\n"
;
return
@ret
;
}
}
qw(
INSTALLARCHLIB INSTALLSITEARCH INSTALLVENDORARCH
INSTALLPRIVLIB INSTALLSITELIB INSTALLVENDORLIB
INSTALLBIN INSTALLSITEBIN INSTALLVENDORBIN
INSTALLSCRIPT INSTALLSITESCRIPT INSTALLVENDORSCRIPT
INSTALLMAN1DIR INSTALLSITEMAN1DIR INSTALLVENDORMAN1DIR
INSTALLMAN3DIR INSTALLSITEMAN3DIR INSTALLVENDORMAN3DIR
)
),
map
{
$_
,
lc
(
$_
)}
qw(DESTDIR PREFIX INSTALL_BASE UNINST)
,
);
my
%macro_to_build
=
%makefile_to_build
;
delete
$macro_to_build
{LIB};
sub
_merge_prereq {
my
(
$req
,
$breq
) =
@_
;
$req
||= {};
$breq
||= {};
for
my
$p
(
$req
,
$breq
) {
for
my
$k
(
sort
keys
%$p
) {
next
if
$k
eq
'perl'
;
my
$v_obj
=
eval
{ version->new(
$p
->{
$k
}) };
if
( !
defined
$v_obj
) {
die
"A prereq of the form '$p->{$k}' for '$k' is not supported by Module::Build::Compat ( use a simpler version like '0.05' or 'v1.4.25' )\n"
;
}
if
(
$v_obj
->is_qv ) {
my
$proper_ver
=
$v_obj
->numify;
warn
"Dotted-decimal prereq '$p->{$k}' for '$k' is not portable - converting it to '$proper_ver'\n"
;
$p
->{
$k
} =
$proper_ver
;
}
}
}
my
$merge
= {
%$req
};
for
my
$k
(
keys
%$breq
) {
my
$v1
=
$merge
->{
$k
} || 0;
my
$v2
=
$breq
->{
$k
};
$merge
->{
$k
} =
$v1
>
$v2
?
$v1
:
$v2
;
}
return
%$merge
;
}
sub
create_makefile_pl {
my
(
$package
,
$type
,
$build
,
%args
) =
@_
;
die
"Don't know how to build Makefile.PL of type '$type'"
unless
$type
=~ /^(small|passthrough|traditional)$/;
if
(
$type
eq
'passthrough'
) {
$build
->log_warn(
<<"HERE");
IMPORTANT NOTE: The '$type' style of Makefile.PL is deprecated and
may be removed in a future version of Module::Build in favor of the
'configure_requires' property. See Module::Build::Compat
documentation for details.
HERE
}
my
$fh
;
if
(
$args
{fh}) {
$fh
=
$args
{fh};
}
else
{
$args
{file} ||=
'Makefile.PL'
;
local
$build
->{properties}{quiet} = 1;
$build
->delete_filetree(
$args
{file});
open
(
$fh
,
'>'
,
"$args{file}"
) or
die
"Can't write $args{file}: $!"
;
}
print
{
$fh
}
"# Note: this file was auto-generated by "
, __PACKAGE__,
" version $VERSION\n"
;
my
$requires
=
$build
->requires;
if
(
my
$minimum_perl
=
$requires
->{perl} ) {
my
$min_ver
= version->new(
$minimum_perl
)->numify;
print
{
$fh
}
"require $min_ver;\n"
;
}
my
$subclass_load
=
''
;
if
(
ref
(
$build
) ne
"Module::Build"
) {
my
$subclass_dir
=
$package
->subclass_dir(
$build
);
if
(File::Spec->file_name_is_absolute(
$subclass_dir
)) {
my
$base_dir
=
$build
->base_dir;
if
(
$build
->dir_contains(
$base_dir
,
$subclass_dir
)) {
$subclass_dir
= File::Spec->abs2rel(
$subclass_dir
,
$base_dir
);
$subclass_dir
=
$package
->unixify_dir(
$subclass_dir
);
$subclass_load
=
"use lib '$subclass_dir';"
;
}
}
else
{
$subclass_dir
=
$package
->unixify_dir(
$subclass_dir
);
$subclass_load
=
"use lib '$subclass_dir';"
;
}
}
if
(
$type
eq
'small'
) {
printf
{
$fh
}
<<'EOF', $subclass_load, ref($build), ref($build);
use Module::Build::Compat 0.02;
%s
Module::Build::Compat->run_build_pl(args => \@ARGV);
require %s;
Module::Build::Compat->write_makefile(build_class => '%s');
EOF
}
elsif
(
$type
eq
'passthrough'
) {
printf
{
$fh
}
<<'EOF', $subclass_load, ref($build), ref($build);
unless (eval "use Module::Build::Compat 0.02; 1" ) {
print "This module requires Module::Build to install itself.\n";
require ExtUtils::MakeMaker;
my $yn = ExtUtils::MakeMaker::prompt
(' Install Module::Build now from CPAN?', 'y');
unless ($yn =~ /^y/i) {
die " *** Cannot install without Module::Build. Exiting ...\n";
}
require Cwd;
require File::Spec;
require CPAN;
# Save this 'cause CPAN will chdir all over the place.
my $cwd = Cwd::cwd();
CPAN::Shell->install('Module::Build::Compat');
CPAN::Shell->expand("Module", "Module::Build::Compat")->uptodate
or die "Couldn't install Module::Build, giving up.\n";
chdir $cwd or die "Cannot chdir() back to $cwd: $!";
}
eval "use Module::Build::Compat 0.02; 1" or die $@;
%s
Module::Build::Compat->run_build_pl(args => \@ARGV);
my $build_script = 'Build';
$build_script .= '.com' if $^O eq 'VMS';
exit(0) unless(-e $build_script); # cpantesters convention
require %s;
Module::Build::Compat->write_makefile(build_class => '%s');
EOF
}
elsif
(
$type
eq
'traditional'
) {
my
(
%MM_Args
,
%prereq
);
if
(
eval
"use Tie::IxHash 1.2; 1"
) {
tie
%MM_Args
,
'Tie::IxHash'
;
tie
%prereq
,
'Tie::IxHash'
;
}
my
%name
= (
$build
->module_name
? (
NAME
=>
$build
->module_name)
: (
DISTNAME
=>
$build
->dist_name));
my
%version
= (
$build
->dist_version_from
? (
VERSION_FROM
=>
$build
->dist_version_from)
: (
VERSION
=>
$build
->dist_version)
);
%MM_Args
= (
%name
,
%version
);
%prereq
= _merge_prereq(
$build
->requires,
$build
->build_requires );
%prereq
=
map
{
$_
,
$prereq
{
$_
}}
sort
keys
%prereq
;
delete
$prereq
{perl};
$MM_Args
{PREREQ_PM} = \
%prereq
;
$MM_Args
{INSTALLDIRS} =
$build
->installdirs eq
'core'
?
'perl'
:
$build
->installdirs;
$MM_Args
{EXE_FILES} = [
sort
keys
%{
$build
->script_files} ]
if
$build
->script_files;
$MM_Args
{PL_FILES} =
$build
->PL_files || {};
if
(
$build
->recursive_test_files) {
$MM_Args
{test} = {
TESTS
=>
join
q{ }
,
$package
->_test_globs(
$build
) };
}
local
$Data::Dumper::Terse
= 1;
my
$args
= Data::Dumper::Dumper(\
%MM_Args
);
$args
=~ s/\{(.*)\}/($1)/s;
print
$fh
<<"EOF";
use ExtUtils::MakeMaker;
WriteMakefile
$args;
EOF
}
}
sub
_test_globs {
my
(
$self
,
$build
) =
@_
;
return
map
{ File::Spec->catfile(
$_
,
'*.t'
) }
@{
$build
->rscan_dir(
't'
,
sub
{ -d
$File::Find::name
})};
}
sub
subclass_dir {
my
(
$self
,
$build
) =
@_
;
return
(Module::Metadata->find_module_dir_by_name(
ref
$build
)
|| File::Spec->catdir(
$build
->config_dir,
'lib'
));
}
sub
unixify_dir {
my
(
$self
,
$path
) =
@_
;
return
join
'/'
, File::Spec->splitdir(
$path
);
}
sub
makefile_to_build_args {
my
$class
=
shift
;
my
@out
;
foreach
my
$arg
(
@_
) {
next
if
$arg
eq
''
;
my
(
$key
,
$val
) = (
$arg
=~ /^(\w+)=(.+)/ ? ($1, $2) :
die
"Malformed argument '$arg'"
);
(
$val
) = Module::Build->_detildefy(
$val
)
if
$val
=~ /^~/;
if
(
exists
$makefile_to_build
{
$key
}) {
my
$trans
=
$makefile_to_build
{
$key
};
push
@out
,
$class
->_argvify(
ref
(
$trans
) ?
$trans
->(
$val
) : (
$trans
=>
$val
) );
}
elsif
(
exists
$Config
{
lc
(
$key
)}) {
push
@out
,
$class
->_argvify(
config
=>
lc
(
$key
) .
"=$val"
);
}
else
{
push
@out
,
$class
->_argvify(
"\L$key"
=>
$val
);
}
}
return
@out
;
}
sub
_argvify {
my
(
$self
,
@pairs
) =
@_
;
my
@out
;
while
(
@pairs
) {
my
(
$k
,
$v
) =
splice
@pairs
, 0, 2;
push
@out
, (
"--$k"
,
$v
);
}
return
@out
;
}
sub
makefile_to_build_macros {
my
@out
;
my
%config
;
foreach
my
$macro
(
sort
keys
%macro_to_build
) {
my
$trans
=
$macro_to_build
{
$macro
};
next
unless
exists
$ENV
{
$macro
} &&
length
$ENV
{
$macro
};
my
$val
=
$ENV
{
$macro
};
my
@args
=
ref
(
$trans
) ?
$trans
->(
$val
) : (
$trans
=>
$val
);
while
(
@args
) {
my
(
$k
,
$v
) =
splice
(
@args
, 0, 2);
if
(
$k
eq
'config'
) {
if
(
$v
=~ /^([^=]+)=(.*)$/ ) {
$config
{$1} = $2;
}
else
{
warn
"Couldn't parse config '$v'\n"
;
}
}
else
{
push
@out
, (
$k
=>
$v
);
}
}
}
push
@out
, (
config
=> \
%config
)
if
%config
;
return
@out
;
}
sub
run_build_pl {
my
(
$pack
,
%in
) =
@_
;
$in
{script} ||=
'Build.PL'
;
my
@args
=
$in
{args} ?
$pack
->makefile_to_build_args(@{
$in
{args}}) : ();
print
"# running $in{script} @args\n"
;
Module::Build->run_perl_script(
$in
{script}, [], \
@args
) or
die
"Couldn't run $in{script}: $!"
;
}
sub
fake_makefile {
my
(
$self
,
%args
) =
@_
;
unless
(
exists
$args
{build_class}) {
warn
"Unknown 'build_class', defaulting to 'Module::Build'\n"
;
$args
{build_class} =
'Module::Build'
;
}
my
$class
=
$args
{build_class};
my
$perl
=
$class
->find_perl_interpreter;
$perl
=
'MCR '
.
$perl
if
$self
->_is_vms_mms;
my
$noop
= (
$class
->is_windowsish ?
'rem>nul'
:
$self
->_is_vms_mms ?
'Continue'
:
'true'
);
my
$filetype
=
$class
->is_vmsish ?
'.COM'
:
''
;
my
$Build
=
'Build'
.
$filetype
.
' --makefile_env_macros 1'
;
my
$unlink
=
$class
->oneliner(
'1 while unlink $ARGV[0]'
, [], [
$args
{makefile}]);
$unlink
=~ s/\$/\$\$/g
unless
$class
->is_vmsish;
my
$maketext
=
join
''
,
map
{
"$_=\n"
}
sort
keys
%macro_to_build
;
$maketext
.= ($^O eq
'os2'
?
"SHELL = sh\n\n"
: $^O eq
'MSWin32'
&&
$Config
{make} =~ /gmake/
?
"SHELL = $ENV{COMSPEC}\n\n"
:
"\n\n"
);
$maketext
.=
<<"EOF";
all : force_do_it
$perl $Build
realclean : force_do_it
$perl $Build realclean
$unlink
distclean : force_do_it
$perl $Build distclean
$unlink
force_do_it :
@ $noop
EOF
foreach
my
$action
(
$class
->known_actions) {
next
if
$action
=~ /^(all|distclean|realclean|force_do_it)$/;
$maketext
.=
<<"EOF";
$action : force_do_it
$perl $Build $action
EOF
}
if
(
$self
->_is_vms_mms) {
$maketext
.=
"\n.FIRST\n\t\@ $noop\n"
;
for
my
$macro
(
sort
keys
%macro_to_build
) {
$maketext
.=
".IFDEF $macro\n\tDEFINE $macro \"\$($macro)\"\n.ENDIF\n"
;
}
$maketext
.=
"\n"
;
}
else
{
$maketext
.=
"\n.EXPORT : "
.
join
(
' '
,
sort
keys
%macro_to_build
) .
"\n\n"
;
}
return
$maketext
;
}
sub
fake_prereqs {
my
$file
= File::Spec->catfile(
'_build'
,
'prereqs'
);
open
(
my
$fh
,
'<'
,
"$file"
) or
die
"Can't read $file: $!"
;
my
$prereqs
=
eval
do
{
local
$/; <
$fh
>};
close
$fh
;
my
%merged
= _merge_prereq(
$prereqs
->{requires},
$prereqs
->{build_requires} );
my
@prereq
;
foreach
(
sort
keys
%merged
) {
next
if
$_
eq
'perl'
;
push
@prereq
,
"$_=>q[$merged{$_}]"
;
}
return
unless
@prereq
;
return
"# PREREQ_PM => { "
.
join
(
", "
,
@prereq
) .
" }\n\n"
;
}
sub
write_makefile {
my
(
$pack
,
%in
) =
@_
;
unless
(
exists
$in
{build_class}) {
warn
"Unknown 'build_class', defaulting to 'Module::Build'\n"
;
$in
{build_class} =
'Module::Build'
;
}
my
$class
=
$in
{build_class};
$in
{makefile} ||=
$pack
->_is_vms_mms ?
'Descrip.MMS'
:
'Makefile'
;
open
MAKE,
"> $in{makefile}"
or
die
"Cannot write $in{makefile}: $!"
;
print
MAKE
$pack
->fake_prereqs;
print
MAKE
$pack
->fake_makefile(
%in
);
close
MAKE;
}
sub
_is_vms_mms {
return
Module::Build->is_vmsish && (
$Config
{make} =~ m/MM[SK]/i);
}
1;