Alien-Libarchive-Installer

 view release on metacpan or  search on metacpan

lib/Alien/Libarchive/Installer.pm  view on Meta::CPAN

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;
}


sub _try_pkg_config
{
  my($dir, $field, $guess, $extra) = @_;
  
  unless(defined $dir)
  {
    require File::Temp;
    $dir = File::Temp::tempdir(CLEANUP => 1);
  }
  
  require Config;
  local $ENV{PKG_CONFIG_PATH} = join $Config::Config{path_sep}, $dir, split /$Config::Config{path_sep}/, ($ENV{PKG_CONFIG_PATH}||'');

  my $value = eval {
    # you probably think I am crazy...
    eval q{ use PkgConfig 0.07620 };
    die $@ if $@;
    my $value = `$^X $INC{'PkgConfig.pm'} --silence-errors libarchive $extra --$field`;
    die if $?;
    $value;
  };

  unless(defined $value) {
    no warnings;
    $value = `pkg-config --silence-errors libarchive $extra --$field`;
    return $guess if $?;
  }
  
  chomp $value;



( run in 0.713 second using v1.01-cache-2.11-cpan-140bd7fdf52 )