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 )