Alien-Libarchive-Installer
view release on metacpan or search on metacpan
lib/Alien/Libarchive/Installer.pm view on Meta::CPAN
close $fh;
wantarray ? ($fn, $version) : $fn;
}
sub build_requires
{
my %prereqs = (
'HTTP::Tiny' => 0,
'Archive::Tar' => 0,
'Alien::patch' => '0.08',
);
if($^O eq 'MSWin32')
{
require Config;
if($Config::Config{cc} =~ /cl(\.exe)?$/i)
{
$prereqs{'Alien::CMake'} = '0.05';
}
else
{
$prereqs{'Alien::MSYS'} = '0.07';
$prereqs{'PkgConfig'} = '0.07620';
}
}
\%prereqs;
}
sub system_requires
{
my %prereqs = ();
\%prereqs;
}
sub system_install
{
my($class, %options) = @_;
$options{alien} = 1 unless defined $options{alien};
$options{test} ||= 'compile';
die "test must be one of compile, ffi or both"
unless $options{test} =~ /^(compile|ffi|both)$/;
if($options{alien} && eval q{ use Alien::Libarchive 0.21; 1 })
{
my $alien = Alien::Libarchive->new;
require File::Spec;
my $dir;
my(@dlls) = map {
my($v,$d,$f) = File::Spec->splitpath($_);
$dir = [$v,File::Spec->splitdir($d)];
$f;
} $alien->dlls;
my $build = bless {
cflags => [$alien->cflags],
libs => [$alien->libs],
dll_dir => $dir,
dlls => \@dlls,
prefix => File::Spec->rootdir,
}, $class;
eval {
$build->test_compile_run || die $build->error if $options{test} =~ /^(compile|both)$/;
$build->test_ffi || die $build->error if $options{test} =~ /^(ffi|both)$/;
};
return $build unless $@;
}
my $build = bless {
cflags => _try_pkg_config(undef, 'cflags', '', ''),
libs => _try_pkg_config(undef, 'libs', '-larchive', ''),
}, $class;
if($options{test} =~ /^(ffi|both)$/)
{
my @dir_search_list;
if($^O eq 'MSWin32')
{
# On MSWin32 the entire path is not included in dl_library_path
# but that is the most likely place that we will find dlls.
@dir_search_list = grep { -d $_ } split /;/, $ENV{PATH};
}
else
{
require DynaLoader;
@dir_search_list = grep { -d $_ } @DynaLoader::dl_library_path
}
found_dll: foreach my $dir (@dir_search_list)
{
my $dh;
opendir($dh, $dir) || next;
# sort by filename length so that libarchive.so.12.0.4
# is preferred over libarchive.so.12 or libarchive.so
# if only to make diagnostics point to the more specific
# version.
foreach my $file (sort { length $b <=> length $a } readdir $dh)
{
if($^O eq 'MSWin32')
{
next unless $file =~ /^libarchive-[0-9]+\.dll$/i;
}
elsif($^O eq 'cygwin')
{
next unless $file =~ /^cygarchive-[0-9]+\.dll$/i;
}
else
{
next unless $file =~ /^libarchive\.(dylib|so(\.[0-9]+)*)$/;
}
require File::Spec;
my($v,$d) = File::Spec->splitpath($dir, 1);
$build->{dll_dir} = [File::Spec->splitdir($d)];
$build->{prefix} = $v;
$build->{dlls} = [$file];
closedir $dh;
last found_dll;
}
closedir $dh;
}
}
$build->test_compile_run || die $build->error if $options{test} =~ /^(compile|both)$/;
$build->test_ffi || die $build->error if $options{test} =~ /^(ffi|both)$/;
$build;
}
lib/Alien/Libarchive/Installer.pm view on Meta::CPAN
{
symlink(readlink $from, $to);
unlink($from);
}
else
{
require File::Copy;
File::Copy::move($from, $to);
}
}
};
}
my $pkg_config_dir = File::Spec->catdir($prefix, 'lib', 'pkgconfig');
my $pcfile = File::Spec->catfile($pkg_config_dir, 'libarchive.pc');
do {
my @content;
if($Config::Config{cc} !~ /cl(\.exe)?$/i)
{
open my $fh, '<', $pcfile;
@content = map { s{$prefix}{'${pcfiledir}/../..'}eg; $_ } do { <$fh> };
close $fh;
}
else
{
# TODO: later when we know the version with more
# certainty, we can update this file with the
# Version
@content = join "\n", "prefix=\${pcfiledir}/../..",
"exec_prefix=\${prefix}",
"libdir=\${exec_prefix}/lib",
"includedir=\${prefix}/include",
"Name: libarchive",
"Description: library that can create and read several streaming archive formats",
"Cflags: -I\${includedir}",
"Libs: advapi32.lib \${libdir}/archive_static.lib",
"Libs.private: ",
"";
require File::Path;
File::Path::mkpath($pkg_config_dir, 0, 0755);
}
my($version) = map { /^Version:\s*(.*)$/; $1 } grep /^Version: /, @content;
# older versions apparently didn't include the necessary -I and -L flags
if(defined $version && $version =~ /^[12]\./)
{
for(@content)
{
s/^Libs: /Libs: -L\${libdir} /;
}
push @content, "Cflags: -I\${includedir}\n";
}
open my $fh, '>', $pcfile;
print $fh @content;
close $fh;
};
my $build = bless {
cflags => _try_pkg_config($pkg_config_dir, 'cflags', '-I' . File::Spec->catdir($prefix, 'include'), '--static'),
libs => _try_pkg_config($pkg_config_dir, 'libs', '-L' . File::Spec->catdir($prefix, 'lib'), '--static'),
prefix => $prefix,
dll_dir => [ 'dll' ],
dlls => do {
opendir(my $dh, File::Spec->catdir($prefix, 'dll'));
[grep { ! -l File::Spec->catfile($prefix, 'dll', $_) } grep { /\.so/ || /\.(dll|dylib)$/ } grep !/^\./, readdir $dh];
},
}, $class;
if($^O eq 'cygwin' || $^O eq 'MSWin32')
{
# TODO: should this go in the munged pc file?
unshift @{ $build->{cflags} }, '-DLIBARCHIVE_STATIC';
}
$build->test_compile_run || die $build->error if $options{test} =~ /^(compile|both)$/;
$build->test_ffi || die $build->error if $options{test} =~ /^(ffi|both)$/;
$build;
};
my $error = $@;
chdir $save;
die $error if $error;
$build;
}
sub cflags { shift->{cflags} }
sub libs { shift->{libs} }
sub version { shift->{version} }
sub dlls
{
my($self, $prefix) = @_;
$prefix = $self->{prefix} unless defined $prefix;
$prefix = '' if $^O eq 'MSWin32' && $prefix eq '\\';
unless(defined $self->{dlls} && defined $self->{dll_dir})
{
# Question: is this necessary in light of the better
# dll detection now done in system_install ?
if($^O eq 'cygwin')
{
# /usr/bin/cygarchive-13.dll
opendir my $dh, '/usr/bin';
$self->{dlls} = [grep /^cygarchive-[0-9]+.dll$/i, readdir $dh];
$self->{dll_dir} = [];
$prefix = '/usr/bin';
closedir $dh;
}
else
{
require DynaLoader;
$self->{libs} = [] unless defined $self->{libs};
$self->{libs} = [ $self->{libs} ] unless ref $self->{libs};
my $path = DynaLoader::dl_findfile(grep /^-l/, @{ $self->libs });
die "unable to find dynamic library" unless defined $path;
require File::Spec;
( run in 2.368 seconds using v1.01-cache-2.11-cpan-140bd7fdf52 )