Alien-Libarchive

 view release on metacpan or  search on metacpan

inc/Alien/LZO/Installer.pm  view on Meta::CPAN

=head2 fetch

 my($location, $version) = Alien::LZO::Installer->fetch(%options);
 my $location = Alien::LZO::Installer->fetch(%options);

B<NOTE:> using this method may (and probably does) require modules
returned by the L<build_requires|Alien::LZO::Installer#build_requires>
method.

Download lzo source from the internet.  By default it will
download the latest version to a temporary directory which will
be removed when Perl exits.  Will throw an exception on
failure.  Options include:

=over 4

=item dir

Directory to download to

=item version

Version to download

=back

=cut

sub fetch
{
  my($class, %options) = @_;
  
  my $dir = $options{dir} || eval { require File::Temp; File::Temp::tempdir( CLEANUP => 1 ) };

  require HTTP::Tiny;  
  my $version = $options{version} || do {
    my @versions = $class->versions_available;
    die "unable to determine latest version from listing"
      unless @versions > 0;
    $versions[-1];
  };

  if(defined $ENV{ALIEN_LZO_INSTALL_MIRROR})
  {
    my $fn = _catfile($ENV{ALIEN_LZO_INSTALL_MIRROR}, "lzo-$version.tar.gz");
    return wantarray ? ($fn, $version) : $fn;
  }

  my $url = "http://www.oberhumer.com/opensource/lzo/download/lzo-$version.tar.gz";
  
  my $response = HTTP::Tiny->new->get($url);
  
  die sprintf("%s %s %s", $response->{status}, $response->{reason}, $url)
    unless $response->{success};
  
  require File::Spec;
  
  my $fn = _catfile($dir, "lzo-$version.tar.gz");
  
  open my $fh, '>', $fn;
  binmode $fh;
  print $fh $response->{content};
  close $fh;
  
  wantarray ? ($fn, $version) : $fn;
}

=head2 build_requires

 my $prereqs = Alien::LZO::Installer->build_requires;
 while(my($module, $version) = each %$prereqs)
 {
   ...
 }

Returns a hash reference of the build requirements.  The
keys are the module names and the values are the versions.

The requirements may be different depending on your
platform.

=cut

sub build_requires
{
  my %prereqs = (
    'HTTP::Tiny'   => 0,
    'Archive::Tar' => 0,
  );
  
  if($^O eq 'MSWin32')
  {
    $prereqs{'Alien::MSYS'} = '0.07';
    $prereqs{'Archive::Ar'} = '2.00';
  }
  
  \%prereqs;
}

=head2 system_requires

This is like L<build_requires|Alien::LZO::Installer#build_requires>,
except it is used when using the lzo that comes with the operating
system.

=cut

sub system_requires
{
  my %prereqs = ();
  \%prereqs;
}

=head2 system_install

 my $installer = Alien::LZO::Installer->system_install(%options);

B<NOTE:> using this method may require modules returned by the
L<system_requires|Alien::LZO::Installer> method.

B<NOTE:> This form will also use the lzo provided by L<Alien::LZO>

inc/Alien/LZO/Installer.pm  view on Meta::CPAN

{
  my($class, $prefix, %options) = @_;

  require File::Spec;
  
  $options{test} ||= 'compile';
  die "test must be one of compile, ffi or both"
    unless $options{test} =~ /^(compile|ffi|both)$/;
  die "need an install prefix" unless $prefix;
  
  $prefix =~ s{\\}{/}g;
  
  my $dir = $options{dir} || do { require File::Temp; File::Temp::tempdir( CLEANUP => 1 ) };
  
  require Archive::Tar;
  my $tar = Archive::Tar->new;
  $tar->read($options{tar} || $class->fetch);
  
  require Cwd;
  my $save = Cwd::getcwd();
  
  chdir $dir;  
  my $build = eval {
  
    $tar->extract;

    chdir do {
      opendir my $dh, '.';
      my(@list) = grep !/^\./,readdir $dh;
      close $dh;
      die "unable to find source in build root" if @list == 0;
      die "confused by multiple entries in the build root" if @list > 1;
      $list[0];
    };
  
    _msys(sub {
      # TODO this will only work with gcc
      my($make) = @_;
      system 'sh', 'configure', "--prefix=$prefix", '--with-pic', '--enable-shared';
      die "configure failed" if $?;
      system $make, 'all';
      die "make all failed" if $?;
      system $make, 'install';
      die "make install failed" if $?;
    });

    if($^O eq 'MSWin32')
    {
      # TODO: this will only work with gcc
      require File::Temp;
      my $dir = File::Temp::tempdir( CLEANUP => 1 );
      # TODO: use Archive::Ar when it is a little less broken
      require Archive::Ar;
      my $ar = Archive::Ar->new(_catfile($prefix, 'lib', 'liblzo2.a'));
      my @objects = grep { $_ ne '/' } $ar->list_files;
      foreach my $object (@objects)
      {
        my $fh;
        my $fn = _catfile($dir, $object);
        open($fh, '>', $fn) || die "unable to write $fn $!";
        binmode $fh;
        print $fh $ar->get_content($object)->{data};
        close $fh;
      }      
      system 'dlltool',
        '--export-all-symbols',
        -e => _catfile($dir, 'exports.o'),
        -l => _catfile($prefix, 'lib', 'liblzo2.dll.a'),
        map { _catfile($dir, $_) } @objects;
      die "dlltool failed" if $?;
      system 'gcc',
        '--shared',
        -o => _catfile($prefix, 'lib', 'liblzo2.dll'),
        _catfile($dir, 'exports.o'),
        map { _catfile($dir, $_) } @objects;
      
      do {
        my($in,$out);
        open($in, '<', _catfile($prefix, 'lib', 'liblzo2.la'));
        open($out, '>', _catfile($prefix, 'lib', 'liblzo2.la.tmp'));
        while(<$in>)
        {
          s{^dlname='.*?'}{dlname='../dll/liblzo2.dll'};
          s{^library_names='.*?'}{library_names='../dll/liblzo2.dll.a'};
          print $out $_;
        }
        close $in;
        close $out;
        unlink _catfile($prefix, 'lib', 'liblzo2.la');
        rename _catfile($prefix, 'lib', 'liblzo2.la.tmp'),
               _catfile($prefix, 'lib', 'liblzo2.la');
      };
    }

    foreach my $name ('lib')
    {
      do {
        my $static_dir = _catdir($prefix, $name);
        my $dll_dir    = _catdir($prefix, 'dll');
        require File::Path;
        File::Path::mkpath($dll_dir, 0, 0755);
        my $dh;
        opendir $dh, $static_dir;
        my @list = readdir $dh;
        @list = grep { /\.so/ || /\.(dylib|la|dll|dll\.a)$/} grep !/^\./, @list;
        closedir $dh;
        foreach my $basename (@list)
        {
          my $from = _catfile($static_dir, $basename);
          my $to   = _catfile($dll_dir,    $basename);
          if(-l $from)
          {
            symlink(readlink $from, $to);
            unlink($from);
          }
          else
          {
            require File::Copy;
            File::Copy::move($from, $to);
          }
        }



( run in 0.838 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )