use
5.010;
BEGIN {
foreach
my
$make
(
qw( make gmake gnumake )
) {
no
warnings
'exec'
;
my
$output
= `
$make
--version`;
next
if
$?;
next
unless
$output
=~ m/^GNU Make /;
constant->
import
(
MAKE
=>
$make
);
last
;
}
foreach
my
$libtool
(
qw( libtool glibtool )
) {
no
warnings
'exec'
;
my
$output
= `
$libtool
--version`;
next
if
$?;
next
unless
$output
=~ m/^.*\(GNU libtool\)/;
constant->
import
(
LIBTOOL
=>
$libtool
);
last
;
}
}
sub
MAKEARGS {
"LIBTOOL="
.LIBTOOL() }
__PACKAGE__->add_property(
'tarball'
);
__PACKAGE__->add_property(
'pkgconfig_module'
);
__PACKAGE__->add_property(
'pkgconfig_version'
);
__PACKAGE__->add_property(
'alien_requires'
);
my
%more_configure_requires
= (
'File::Basename'
=> 0,
'File::Spec'
=> 0,
'File::Path'
=>
'2.07'
,
'Module::Build'
=> 0,
);
sub
apply_extra_pkgconfig_paths
{
my
%added
;
my
@pkg_config_path
;
foreach
my
$inc
(
@INC
) {
my
$dir
=
"$inc/pkgconfig"
;
next
unless
-d
$dir
;
$added
{
$dir
}++ and
next
;
push
@pkg_config_path
,
$dir
;
}
push
@pkg_config_path
,
$ENV
{PKG_CONFIG_PATH}
if
defined
$ENV
{PKG_CONFIG_PATH};
$ENV
{PKG_CONFIG_PATH} =
join
":"
,
@pkg_config_path
;
}
sub
new
{
my
$class
=
shift
;
my
%args
=
@_
;
my
$use_bundled
= !!
$args
{use_bundled};
$args
{get_options}{bundled} = {
store
=> \
$use_bundled
,
type
=>
"+"
,
};
my
$self
=
$class
->SUPER::new(
%args
);
my
$module
=
$self
->pkgconfig_module;
my
$version
=
$self
->pkgconfig_version;
$use_bundled
= 1
if
!
$use_bundled
and
defined
$self
->do_requires_pkgconfig(
$module
,
atleast_version
=>
$version
);
$self
->configure_requires->{
$_
} ||=
$more_configure_requires
{
$_
}
for
keys
%more_configure_requires
;
$self
->apply_extra_pkgconfig_paths;
my
@reqs
= @{
$self
->alien_requires || [] };
while
(
@reqs
) {
my
(
$name
,
@args
) = @{
shift
@reqs
};
push
(
@reqs
,
@args
),
next
if
$name
eq
"any"
;
$self
->configure_requires->{
"ExtUtils::CChecker"
} //= 0
if
$name
eq
"header"
;
}
if
(
$use_bundled
) {
foreach
my
$req
( @{
$self
->alien_requires || [] } ) {
my
$missing
=
$self
->do_requires(
@$req
);
die
"OS unsupported - missing $missing\n"
if
defined
$missing
;
}
die
"OS unsupported - unable to find GNU make\n"
unless
defined
&MAKE
;
die
"OS unsupported - unable to find GNU libtool\n"
unless
defined
&LIBTOOL
;
print
"Building bundled source\n"
;
}
else
{
print
"Using $module version >= $version from pkg-config\n"
;
}
$self
->notes(
use_bundled
=>
$use_bundled
);
return
$self
;
}
{
my
$eucc
;
sub
cchecker
{
my
$self
=
shift
;
return
$eucc
||=
do
{
return
ExtUtils::CChecker->new;
};
}
}
sub
do_requires
{
my
$self
=
shift
;
my
(
$name
,
@args
) =
@_
;
my
$code
=
$self
->can(
"do_requires_$name"
) or
die
"Unrecognised 'alien_requires' requirement type '$name'\n"
;
return
$self
->
$code
(
@args
);
}
sub
do_requires_any
{
my
$self
=
shift
;
my
@alts
=
@_
;
my
@missing
;
foreach
my
$alt
(
@alts
) {
my
$ret
=
$self
->do_requires(
@$alt
);
return
if
!
$ret
;
push
@missing
,
$ret
;
}
return
$missing
[0]
if
@missing
< 2;
return
"either $missing[0] or $missing[1]"
if
@missing
== 2;
return
"any of "
.
join
(
", "
,
@missing
[0 ..
$#missing
-1] ) .
" or "
.
$missing
[-1];
}
sub
do_requires_pkgconfig
{
my
$self
=
shift
;
my
(
$module
,
%args
) =
@_
;
print
"Looking for pkg-config $module... "
;
my
@cmdline
;
push
@cmdline
,
"--atleast-version=$args{atleast_version}"
if
defined
$args
{atleast_version};
if
(
system
(
"pkg-config"
,
$module
,
@cmdline
) == 0 ) {
print
"found\n"
;
return
;
}
print
"not found\n"
;
return
"$module"
;
}
sub
do_requires_alien
{
my
$self
=
shift
;
my
(
$module
,
$version
) =
@_
;
print
"Depending on $module "
,
(
defined
$version
?
"version $version"
:
"any version"
),
"\n"
;
$self
->requires->{
$module
} =
$version
;
return
undef
;
}
sub
do_requires_header
{
my
$self
=
shift
;
my
(
$header
) =
@_
;
print
"Looking for <$header>... "
;
my
$success
=
$self
->cchecker->try_compile_run(
source
=>
<<"EOC"
#include <$header>
int main(int argc, char *argv[]) {return 0;}
EOC
);
if
(
$success
) {
print
"found\n"
;
return
;
}
print
"not found\n"
;
return
"<$header>"
;
}
sub
_srcdir
{
my
$self
=
shift
;
return
File::Spec->catdir(
$self
->base_dir, SRCDIR );
}
sub
_stampfile
{
my
$self
=
shift
;
my
(
$name
) =
@_
;
return
File::Spec->catfile(
$self
->base_dir,
".$name-stamp"
);
}
sub
in_srcdir
{
my
$self
=
shift
;
chdir
(
$self
->_srcdir ) or
die
"Unable to chdir to srcdir - $!"
;
shift
->();
}
sub
make_in_srcdir
{
my
$self
=
shift
;
my
@args
=
@_
;
$self
->in_srcdir(
sub
{
system
( MAKE(), MAKEARGS(),
@args
) == 0 or
die
"Unable to make - returned exit code $?"
;
} );
}
sub
ACTION_src
{
my
$self
=
shift
;
return
unless
$self
->notes(
'use_bundled'
);
-d
$self
->_srcdir and
return
;
my
$tarball
=
$self
->tarball;
system
(
"tar"
,
"xzf"
,
$tarball
) == 0 or
die
"Unable to untar $tarball - $!"
;
(
my
$untardir
=
$tarball
) =~ s{\.tar\.[a-z]+$}{};
-d
$untardir
or
die
"Expected to find a directory called $untardir\n"
;
rename
(
$untardir
,
$self
->_srcdir ) or
die
"Unable to rename src dir - $!"
;
}
sub
ACTION_code
{
my
$self
=
shift
;
$self
->apply_extra_pkgconfig_paths;
my
$blib
= File::Spec->catdir(
$self
->base_dir,
"blib"
);
my
$libdir
= File::Spec->catdir(
$blib
,
"arch"
);
my
$incdir
= File::Spec->catdir(
$libdir
,
"include"
);
my
$mandir
= File::Spec->catdir(
$blib
,
"libdoc"
);
-d
$_
or
mkdir
$_
for
$blib
,
$libdir
;
my
$pkgconfig_module
=
$self
->pkgconfig_module;
my
$buildstamp
=
$self
->_stampfile(
"build"
);
if
(
$self
->notes(
'use_bundled'
) and !-f
$buildstamp
) {
$self
->depends_on(
'src'
);
my
$instlibdir
=
$self
->install_destination(
"arch"
);
$self
->make_in_srcdir( (),
"LIBDIR=$instlibdir"
,
);
$self
->make_in_srcdir(
"install"
,
"LIBDIR=$libdir"
,
"INCDIR=$incdir"
,
"MAN3DIR=$mandir"
,
"MAN7DIR=$mandir"
,
);
open
(
my
$stamp
,
">"
,
$buildstamp
) or
die
"Unable to touch .build-stamp file - $!"
;
}
my
@module_file
=
split
m/::/,
$self
->module_name .
".pm"
;
my
$srcfile
= File::Spec->catfile(
$self
->base_dir,
"lib"
,
@module_file
);
my
$dstfile
= File::Spec->catfile(
$blib
,
"lib"
,
@module_file
);
unless
(
$self
->up_to_date(
$srcfile
,
$dstfile
) ) {
my
%replace
= (
USE_BUNDLED
=>
$self
->notes(
'use_bundled'
),
PKGCONFIG_MODULE
=>
$pkgconfig_module
,
);
s/
'/\\'
/g
for
values
%replace
;
$self
->cp_file_with_replacement(
srcfile
=>
$srcfile
,
dstfile
=>
$dstfile
,
replace
=> \
%replace
,
);
}
}
sub
cp_file_with_replacement
{
my
$self
=
shift
;
my
%args
=
@_
;
my
$srcfile
=
$args
{srcfile};
my
$dstfile
=
$args
{dstfile};
my
$replace
=
$args
{replace};
make_path( dirname(
$dstfile
), {
mode
=> 0777 } );
open
(
my
$inh
,
"<"
,
$srcfile
) or
die
"Cannot read $srcfile - $!"
;
open
(
my
$outh
,
">"
,
$dstfile
) or
die
"Cannot write $dstfile - $!"
;
while
(
my
$line
= <
$inh
> ) {
$line
=~ s/\
@$_
\@/
$replace
->{
$_
}/g
for
keys
%$replace
;
print
$outh
$line
;
}
}
sub
ACTION_test
{
my
$self
=
shift
;
return
unless
$self
->notes(
'use_bundled'
);
$self
->apply_extra_pkgconfig_paths;
$self
->depends_on(
"code"
);
$self
->make_in_srcdir(
"test"
);
}
sub
ACTION_install
{
my
$self
=
shift
;
$self
->apply_extra_pkgconfig_paths;
$self
->SUPER::ACTION_install;
my
$buildlibdir
= File::Spec->catdir(
$self
->base_dir,
"blib"
,
"arch"
);
my
$instlibdir
=
$self
->install_destination(
"arch"
);
my
$pkgconfig_module
=
$self
->pkgconfig_module;
my
$pcfile
=
"$instlibdir/pkgconfig/$pkgconfig_module.pc"
;
if
( -f
$pcfile
) {
print
"Relocating $pcfile"
;
open
my
$in
,
"<"
,
$pcfile
or
die
"Cannot open $pcfile for reading - $!"
;
open
my
$out
,
">"
,
"$pcfile.new"
or
die
"Cannot open $pcfile.new for writing - $!"
;
print
{
$out
}
join
"\n"
,
"# pkg-config paths rewritten by Alien::make::Module::Build"
,
"# buildlibdir=$buildlibdir"
,
"# instlibdir=$instlibdir"
,
""
;
while
( <
$in
> ) {
s{\Q
$buildlibdir
\E}{
$instlibdir
}g;
print
{
$out
}
$_
;
}
close
$in
;
close
$out
;
unlink
$pcfile
;
rename
"$pcfile.new"
,
$pcfile
;
}
}
sub
ACTION_clean
{
my
$self
=
shift
;
if
(
$self
->notes(
'use_bundled'
) ) {
$self
->apply_extra_pkgconfig_paths;
if
( -d
$self
->_srcdir ) {
$self
->make_in_srcdir(
"clean"
);
}
unlink
(
$self
->_stampfile(
"build"
) );
}
$self
->SUPER::ACTION_clean;
}
sub
ACTION_realclean
{
my
$self
=
shift
;
if
( -d
$self
->_srcdir ) {
system
(
"rm"
,
"-rf"
,
$self
->_srcdir );
}
$self
->SUPER::ACTION_realclean;
}
0x55AA;