use strict;
use warnings;
use 5.014;
use vars qw/$DEVNULL $is_Win32/;
use ExtUtils::MakeMaker;
use Config;
use Cwd qw/ cwd /;
use File::Spec ();
BEGIN {
$::is_Win32 = ($^O =~ /Win32/);
if ($::is_Win32) {
$DEVNULL = 'DEVNULL';
}
else {
$DEVNULL = eval { File::Spec->devnull };
if ($@) { $DEVNULL = '/dev/null' }
}
};
STDOUT->autoflush(1);
my %config;
while (my $arg = shift(@ARGV)) {
my ($key, $val) = split(/=/, $arg, 2);
$config{$key} = $val;
}
my $DEBUG = delete $config{DEBUG};
if ( $config{NO_THREADS} ) {
warn "disabling XML::LibXML support for Perl threads\n";
$config{DEFINE} .= " -DNO_XML_LIBXML_THREADS";
}
delete $config{NO_THREADS};
# We use it several times later. See:
# https://rt.cpan.org/Public/Bug/Display.html?id=116461
my $HAVE_USER_DEFINED = (defined($config{LIBS}) or defined($config{INC}) );
unless ( $::is_Win32 ) { # cannot get config in W32
my $xsltcfg = "pkg-config libxslt";
my $libprefix = $ENV{XSLTPREFIX} || $config{XSLTPREFIX};
delete $config{XSLTPREFIX}; # delete if exists, otherwise MakeMaker gets confused
if ( defined $libprefix ) {
$xsltcfg = $libprefix . '/bin/' . $xsltcfg;
}
# if a user defined INC and LIBS on the command line we must not
# override them
if ( ! $HAVE_USER_DEFINED ) {
# get libs and inc from gnome-config
eval {
print "running $xsltcfg... ";
my $ver = backtick("$xsltcfg --modversion");
my ($major, $minor, $point) = $ver =~ /(\d+)\.(\d+)\.(\d+)/g;
if (not
(
($major > 1)
or
(($major == 1) && ($minor > 1))
or
(($major == 1) && ($minor == 1) && ($point >= 18))
)
)
{
die +{ type => "ver", msg => <<'EOF'};
libxslt versions before 1.1.18 are buggy. Please install the latest version
EOF
}
elsif ($major == 1 and $minor == 1 and $point == 25)
{
die +{ type => "ver", msg => <<'EOF'};
libxslt-1.1.25 contains a deadlock that breaks the tests, and is not supported.
See: https://rt.cpan.org/Ticket/Display.html?id=50487 .
EOF
}
elsif ($major == 1 and $minor == 1 and $point == 27)
{
die +{ type => "ver", msg => <<'EOF'};
libxslt-1.1.27 does not handle namespaces well, and is not supported.
See: https://bugzilla.gnome.org/show_bug.cgi?id=684564 .
EOF
}
$config{LIBS} ||= backtick("$xsltcfg --libs");
$config{INC} ||= backtick("$xsltcfg --cflags");
print "ok\n";
};
my $Err = $@;
if ($Err) {
print "failed\n";
if ((ref($Err) eq 'HASH') && (($Err->{type} || '') eq 'ver')) {
print {*STDERR} ($Err->{msg}, "\n");
exit 0; # 0 recommended by http://cpantest.grango.org (Notes for CPAN Authors)
}
warn "*** ", $@ if $DEBUG;
warn "using fallback values for LIBS and INC\n";
# backtick fails if gnome-config didn't exist...
$config{LIBS} = '-L/usr/local/lib -L/usr/lib -lxslt -lxml2 -lz -lm';
$config{INC} = '-I/usr/local/include -I/usr/include';
print <<"OPT";
options:
LIBS='$config{LIBS}'
INC='$config{INC}'
If this is wrong, Re-run as:
\$ $^X Makefile.PL LIBS='-L/path/to/lib' INC='-I/path/to/include'
OPT
}
}
}
if ($config{LIBS} !~ /\-l(lib)?xslt\b/) {
# in this case we are not able to run xml2-config. therefore we need to
# expand the libz as well.
if ($::is_Win32) {
if( $ENV{ACTIVEPERL_MINGW} ) {
$config{LIBS} .= ' -llibxslt.lib -llibxml2.lib';
} else {
$config{LIBS} .= ' -llibxslt -llibxml2';
}
} else {
$config{LIBS} .= ' -lxml2 -lz';
}
}
if ($config{LIBS} !~ /\-lz(lib)?\b/ and !($::is_Win32 && $config{LIBS} !~ /\-lzlib\b/)) {
# note if libxml2 has not -lz within its cflags, we should not use
# it! We should trust libxml2 and assume libz is not available on the
# current system (this is ofcourse not true with win32 systems.
# $config{LIBS} .= $::is_Win32 ? ' -lzlib' :' -lz';
if ( $config{DEBUG} ) {
warn "zlib was not configured\n";
warn "set zlib\n" if $::is_Win32;
}
if ($::is_Win32) {
if( $ENV{ACTIVEPERL_MINGW} ) {
$config{LIBS} .= '';
} else {
$config{LIBS} .= ' -lzlib';
}
} else {
$config{LIBS} .= ' -lz';
}
}
if ($config{LIBS} !~ /\-lm\b/) {
# math support is important, but is not available separately in W32
$config{LIBS} .= $::is_Win32 ? '' :' -lm';
}
if (!have_library($::is_Win32 ? "libxslt" : "xslt")) {
print STDERR <<"DEATH";
libxslt not found
Try setting LIBS and INC values on the command line
Or get libxslt and libxml2 from
http://www.libxml.org/
If you install via RPMs, make sure you also install the -devel
RPMs, as this is where the headers (.h files) are.
DEATH
exit 0; # 0 recommended by http://cpantest.grango.org (Notes for CPAN Authors)
}
if (have_library($::is_Win32 ? "libexslt" : "exslt")) {
if (! $HAVE_USER_DEFINED) {
my $exslt_defaults = $::is_Win32 ?
($ENV{ACTIVEPERL_MINGW} ? q/-llibexslt.lib/ : q/-llibexslt/) :
q/-lexslt/; # -lgcrypt -lgpg-error/;
my $exsltcfg = 'pkg-config libexslt';
my ($exslt_libs,$exslt_inc);
eval {
print "running $exsltcfg... ";
$exslt_libs = backtick("$exsltcfg --libs");
$exslt_inc = backtick("$exsltcfg --cflags");
$exslt_libs =~ s/-l(xml2|xslt|z|m)\s+//g;
print "ok\n";
};
if ($@) {
print "failed\n";
warn "*** ", $@ if $DEBUG;
warn "using fallback values for LIBS and INC\n";
# backtick fails if gnome-config didn't exist...
$exslt_libs = $exslt_defaults;
$exslt_inc = '';
}
$config{LIBS} .= ' '.$exslt_libs;
$config{INC} .= ' '.$exslt_inc;
}
$config{DEFINE} .= " -DHAVE_EXSLT"
}
if ($DEBUG) {
print "LIBS: $config{LIBS}\n";
print "INC: $config{INC}\n";
}
my $ldflags = delete $config{LDFLAGS};
if ($ldflags) {
$config{dynamic_lib} = { OTHERLDFLAGS => " $ldflags " };
}
# Avoid possible shared library name conflict. On Win32 systems
# the name of system DLL libxlst.dll clashes with module's LibXSLT.dll.
# To handle this we are gonna rename module's DLL to LibXSLT.xs.dll.
if ($::is_Win32)
{
# Fix for RT #94516 :
# https://rt.cpan.org/Ticket/Display.html?id=94516
$config{DLEXT} = 'xs.'.$Config{dlext};
}
WriteMakefile(
'NAME' => 'XML::LibXSLT',
'VERSION_FROM' => 'lib/XML/LibXSLT.pm', # finds $VERSION
'AUTHOR' => 'Matt Sergeant',
'ABSTRACT' => 'Interface to GNOME libxslt library',
'LICENSE' => 'perl_5',
'PREREQ_PM' =>
{
'Encode' => 0,
'XML::LibXML' => "1.70",
'strict' => 0,
'warnings' => 0,
},
'OBJECT' => '$(O_FILES)',
(($ExtUtils::MakeMaker::VERSION >= 6.48)
? (MIN_PERL_VERSION => '5.014',)
: ()
),
'META_MERGE' => {
'meta-spec' => {
'version' => 2,
},
'resources' => {
'repository' => {
'type' => 'git',
'url' => 'https://github.com/shlomif/perl-XML-LibXSLT',
'web' => 'https://github.com/shlomif/perl-XML-LibXSLT',
},
},
},
%config,
);
###################################################################
# Functions
# - these should really be in MakeMaker... But &shrug;
###################################################################
sub rm_f {
my @files = @_;
my @realfiles;
foreach my $pat (@files) {
push @realfiles, glob($pat);
}
if (@realfiles) {
chmod(0777, @realfiles);
unlink(@realfiles);
}
}
sub rm_fr {
my @files = @_;
my @realfiles;
foreach my $pat (@files) {
push @realfiles, glob($pat);
}
foreach my $file (@realfiles) {
if (-d $file) {
# warn("$file is a directory\n");
rm_fr("$file/*");
rm_fr("$file/.exists");
rmdir($file) || die "Couldn't remove $file: $!";
}
else {
# warn("removing $file\n");
chmod(0777, $file);
unlink($file);
}
}
}
sub xsystem {
my (@command)=@_;
if ($DEBUG) {
print "@command\n";
if (system(@command) != 0) {
die "system call to '@command' failed";
}
return 1;
}
open(OLDOUT, ">&STDOUT");
open(OLDERR, ">&STDERR");
open(STDOUT, ">$DEVNULL");
open(STDERR, ">$DEVNULL");
my $retval = system(@command);
open(STDOUT, ">&OLDOUT");
open(STDERR, ">&OLDERR");
if ($retval != 0) {
die "system call to '@command' failed";
}
return 1;
}
sub backtick {
my $command = shift;
if ($DEBUG) {
print $command, "\n";
my $results = `$command`;
chomp $results;
if ($? != 0) {
die "backticks call to '$command' failed";
}
return $results;
}
open(OLDOUT, ">&STDOUT");
open(OLDERR, ">&STDERR");
open(STDOUT, ">$DEVNULL");
open(STDERR, ">$DEVNULL");
my $results = `$command`;
my $retval = $?;
open(STDOUT, ">&OLDOUT");
open(STDERR, ">&OLDERR");
if ($retval != 0) {
die "backticks call to '$command' failed";
}
chomp $results;
return $results;
}
sub _write_utf8_file
{
my ($out_path, $contents) = @_;
open my $out_fh, '>:encoding(utf8)', $out_path
or die "Cannot open '$out_path' for writing - $!";
print {$out_fh} $contents;
close($out_fh);
return;
}
sub _write_raw_file
{
my ($out_path, $contents) = @_;
open my $out_fh, '>:raw', $out_path
or die "Cannot open '$out_path' for writing - $!";
print {$out_fh} $contents;
close($out_fh);
return;
}
sub try_link0 {
my ($src, $opt) = @_;
# local $config{LIBS};
# $config{LIBS} .= $opt;
unless (mkdir(".testlink", 0777)) {
rm_fr(".testlink");
mkdir(".testlink", 0777) || die "Cannot create .testlink dir: $!";
}
chdir(".testlink");
_write_utf8_file("Conftest.xs", <<"EOT");
#ifdef __cplusplus
extern "C" {
#endif
#include <EXTERN.h>
#include <perl.h>
#include <XSUB.h>
#ifdef __cplusplus
}
#endif
$src
MODULE = Conftest PACKAGE = Conftest
PROTOTYPES: DISABLE
EOT
_write_utf8_file("Conftest.pm", <<'EOT');
package Conftest;
$VERSION = 1.0;
require DynaLoader;
@ISA = ('DynaLoader');
bootstrap Conftest $VERSION;
1;
EOT
_write_utf8_file("Makefile.PL", <<'EOT');
use ExtUtils::MakeMaker;
my %config;
while($_ = shift @ARGV) {
my ($k, $v) = split /=/, $_, 2;
warn("$k = $v\n");
$config{$k} = $v;
}
WriteMakefile(NAME => "Conftest", VERSION_FROM => "Conftest.pm", %config);
EOT
_write_utf8_file("test.pl", <<"EOT");
use Test::More tests => 1;
use Conftest;
++\$::loaded;
ok(\$::loaded, "loaded") ;
EOT
xsystem($^X, 'Makefile.PL', map { "$_=$config{$_}" } keys %config);
xsystem($Config{make},
($config{MAKEAPERL} ? qw(-f Makefile.aperl FIRST_MAKEFILE=Makefile.aperl) : ()),
'test'); #,"OTHERLDFLAGS=".$opt);
}
sub try_link {
my $start_dir = cwd();
my $result = eval {
try_link0(@_);
};
warn $@ if $DEBUG && $@;
chdir($start_dir);
rm_fr(".testlink");
return $result;
}
sub have_library {
my ($lib, $func) = (@_, "blank");
if ($func eq "blank")
{
printf("looking for -l%s... ", $lib);
}
else
{
printf("checking for %s() in -l%s... ", $func, $lib);
}
my $result;
if ($func) {
my $libs = $::is_Win32 ? " $lib.lib " : "-l$lib";
if ($::is_Win32) {
$result = try_link(<<"SRC", $libs);
#include <windows.h>
#include <winsock.h>
blank() { return 0; }
int t() { ${func}(); return 0; }
SRC
unless ($result) {
$result = try_link(<<"SRC", $libs);
#include <windows.h>
#include <winsock.h>
blank() { return 0; }
int t() { void ((*p)()); p = (void ((*)()))${func}; return 0; }
SRC
}
}
else {
$result = try_link(<<"SRC", $libs);
blank() { return 0; }
int t() { ${func}(); return 0; }
SRC
}
}
unless ($result) {
print "no\n";
return 0;
}
if ($func ne "main") {
$config{DEFINE} .= uc(" -Dhave_$func");
}
print "yes\n";
return 1;
}
sub MY::postamble {
return <<'MAKE_FRAG';
runtest: pure_all
perl -MFile::Spec -MTest::Run::CmdLine::Iface -e \
"local @INC = @INC; unshift @INC, map { File::Spec->rel2abs(\$$_) } ('$(INST_LIB)', '$(INST_ARCHLIB)'); Test::Run::CmdLine::Iface->new({test_files => [glob(q{t/*.t})]})->run();"
distruntest: distdir
cd $(DISTVNAME) && $(ABSPERLRUN) Makefile.PL
cd $(DISTVNAME) && $(MAKE) $(PASTHRU)
cd $(DISTVNAME) && $(MAKE) runtest $(PASTHRU)
MAKE_FRAG
}