Alien-PNG

 view release on metacpan or  search on metacpan

Build.PL  view on Meta::CPAN

print "\nWelcome to Alien::PNG module installation";
print "\n-----------------------------------------\n\n";

#### check what options we have for our platform
my $rv; my @candidates = ();

if(defined($ENV{PNG_INST_DIR})) {
  print "Gonna use PNG_INST_DIR environment variable...\n";
  print "(PNG_INST_DIR=$ENV{PNG_INST_DIR})\n";
  if (-d $ENV{PNG_INST_DIR}) {
    my @pnginst = File::Spec->splitdir($ENV{PNG_INST_DIR});
    if($rv=check_config_script(File::Spec->catdir(@pnginst, 'bin', 'libpng-config'))) {
      push @candidates, $rv;
    }
    elsif($rv=check_config_script(File::Spec->catdir(@pnginst, 'libpng-config'))) {
      push @candidates, $rv;
    }
  }
  else {
    warn "###WARN### Non-existing directory '$ENV{PNG_INST_DIR}' - skipping";
  }
}

if($rv=check_config_script("libpng-config")) {
  push @candidates, $rv;
};

if ($rv = check_win32_pkgconfig()) {
  push @candidates, $rv;
}

if($rv=check_prebuilt_binaries($build->os_type)) {
  push @candidates, @{$rv};
};

CHANGELOG  view on Meta::CPAN

Revision history for Perl module Alien::PNG

0.4  Tue Apr 21 2020
     - use pkgconfig on Windows to use installed libpng [FROGGS]

0.2  Wed Apr 15 2020
     - switch to function form of tempfile() [plicease]

0.1  Sun Apr 18 2010
     - initial release [FROGGS]

README  view on Meta::CPAN

NAME
    Alien::PNG - building, finding and using PNG binaries

VERSION
    Version 0.4

SYNOPSIS
    Alien::PNG tries (in given order) during its installation:

    *   Locate an already installed PNG via 'libpng-config' script.

    *   Check for PNG libs in directory specified by PNG_INST_DIR variable.
        In this case the module performs PNG library detection via
        '$PNG_INST_DIR/bin/libpng-config' script.

    *   Download prebuilt PNG binaries (if available for your platform).

    *   Build PNG binaries from source codes (if possible on your system).

    Later you can use Alien::PNG in your module that needs to link agains
    PNG and/or related libraries like this:

        # Sample Makefile.pl
        use ExtUtils::MakeMaker;

README  view on Meta::CPAN


    *   If you use prebuild binaries and/or binaries built from sources it
        happens that some of the dynamic libraries (*.so, *.dll) will not
        automaticly loadable as they will be stored somewhere under perl
        module's 'share' directory. To handle this scenario Alien::PNG
        offers some special functionality (see below).

METHODS
  config()
    This function is the main public interface to this module. Basic
    functionality works in a very similar maner to 'libpng-config' script:

        Alien::PNG->config('prefix');   # gives the same string as 'libpng-config --prefix'
        Alien::PNG->config('version');  # gives the same string as 'libpng-config --version'
        Alien::PNG->config('libs');     # gives the same string as 'libpng-config --libs'
        Alien::PNG->config('cflags');   # gives the same string as 'libpng-config --cflags'

    On top of that this function supports special parameters:

        Alien::PNG->config('ld_shared_libs');

    Returns a list of full paths to shared libraries (*.so, *.dll) that will
    be required for running the resulting binaries you have linked with PNG
    libs.

        Alien::PNG->config('ld_paths');

README  view on Meta::CPAN

    linked with PNG libs.

        Alien::PNG->config('ld_shlib_map');

    Returns a reference to hash of value pairs '<libnick>' =>
    '<full_path_to_shlib'>, where '<libnick>' is shortname for PNG related
    library like: PNG.

    NOTE: config('ld_<something>') return an empty list/hash if you have
    decided to use PNG libraries already installed on your system. This
    concerns 'libpng-config' detection and detection via
    '$PNG_INST_DIR/bin/libpng-config'.

  check_header()
    This function checks the availability of given header(s) when using
    compiler options provided by "Alien::PNG->config('cflags')".

        Alien::PNG->check_header('png.h');
        Alien::PNG->check_header('png.h', 'pngconf.h');

    Returns 1 if all given headers are available, 0 otherwise.

  get_header_version()
    Tries to find a header file specified as a param in PNG prefix direcotry
    and based on "#define" macros inside this header file tries to get a
    version triplet.

        Alien::PNG->get_header_version('png.h');

    Returns string like '1.2.3' or undef if not able to find and parse
    version info.

BUGS
    Please post issues and bugs at
    <http://rt.cpan.org/NoAuth/Bugs.html?Dist=Alien-PNG>

AUTHOR
        Tobias Leich

inc/My/Builder.pm  view on Meta::CPAN

sub extract_binaries {
  my ($self, $download, $build_out) = @_;

  # do extract binaries
  my $bp = $self->notes('build_params');
  my $archive = catfile($download, File::Fetch->new(uri => $bp->{url})->file);
  print "Extracting $archive...\n";
  my $ae = Archive::Extract->new( archive => $archive );
  die "###ERROR###: Cannot extract $archive ", $ae->error unless $ae->extract(to => $build_out);

  # fix hardcoded prefix path in bin/libpng-config
  my ($version, $prefix, $incdir, $libdir) = find_PNG_dir(rel2abs($build_out));
  sed_inplace("$prefix/bin/libpng-config", 's/^prefix=.*/prefix=\''.quotemeta($prefix).'\'/');
}

sub extract_sources {
  my ($self, $download, $patches, $build_src) = @_;
  my $bp = $self->notes('build_params');
  foreach my $pack (@{$bp->{members}}) {
    my $srcdir = catfile($build_src, $pack->{dirname});
    my $unpack = 'y';
    $unpack = $self->prompt("Dir '$srcdir' exists, wanna replace with clean sources?", "n") if (-d $srcdir);
    if (lc($unpack) eq 'y') {

inc/My/Builder.pm  view on Meta::CPAN

  # try to find PNG root dir
  my ($version, $prefix, $incdir, $libdir) = find_PNG_dir(rel2abs($build_out));
  die "###ERROR### Cannot find PNG directory in 'sharedir'" unless $version;
  $self->config_data('share_subdir', abs2rel($prefix, rel2abs('sharedir')));

  # set defaults
  my $cfg = {
    # defaults
    version     => $version,
    prefix      => '@PrEfIx@',
    libs        => '-L' . $self->get_path('@PrEfIx@/lib') . ' -lpng',
    cflags      => '-I' . $self->get_path('@PrEfIx@/include') . ' -D_GNU_SOURCE=1', # -Dmain=SDL_main
    shared_libs => [ ],
  };

  # overwrite values available via libpng-config
  my $bp = $self->config_data('build_prefix') || $prefix;
  my $devnull = File::Spec->devnull();
  my $script = rel2abs("$prefix/bin/libpng-config");
  foreach my $p (qw(version prefix L_opts libs I_opts cflags)) {
    my $o=`$script --$p 2>$devnull`;
    if ($o) {
      $o =~ s/[\r\n]*$//;
      $o =~ s/\Q$prefix\E/\@PrEfIx\@/g;
      $cfg->{$p} = $o;
      
      if($p eq 'libs') {
        $cfg->{$p} = $cfg->{L_opts} . ' ' . $cfg->{$p};
        delete $cfg->{L_opts};

inc/My/Builder.pm  view on Meta::CPAN

  $_ =~ s/^\Q$prefix\E/\@PrEfIx\@/ foreach (@shlibs);
  $cfg->{ld_shared_libs} = [ @shlibs ];

  # set ld_paths and ld_shlib_map
  my %tmp = ();
  my %shlib_map = ();
  foreach my $full (@shlibs) {
    my ($v, $d, $f) = splitpath($full);
    $tmp{ catpath($v, $d, '') } = 1;
    # available shared libs detection
    if ($f =~ /^(lib)?(png12)/) {
      $shlib_map{png12} = $full unless $shlib_map{png12};
    }
    elsif ($f =~ /^(lib)?(tiff|jpeg|png)[^a-zA-Z]/) {
      $shlib_map{$2} = $full unless $shlib_map{$2};
    }
  };
  $cfg->{ld_paths} = [ keys %tmp ];
  $cfg->{ld_shlib_map} = \%shlib_map;

  # write config
  $self->config_data('additional_cflags', '-I' . $self->get_path('@PrEfIx@/include') . ' ' .
                                          $self->get_additional_cflags);
  $self->config_data('additional_libs', $self->get_additional_libs);

inc/My/Utility.pm  view on Meta::CPAN

use File::Find qw(find);
use File::Copy qw(cp);
use Cwd qw(realpath);

#### packs with prebuilt binaries
# - all regexps has to match: arch_re ~ $Config{archname}, cc_re ~ $Config{cc}, os_re ~ $^O
# - the order matters, we offer binaries to user in the same order (1st = preffered)
my $prebuilt_binaries = [
    {
      title    => "Binaries Win/32bit PNG-1.2.40 (20100328) RECOMMENDED",
      url      => 'http://froggs.de/libpng/Win32_libpng-1.2.40_bin-20100328.zip',
      sha1sum  => 'f414f5c5d3cb8cafb4fec7f4bdf2ab4146da9630',
      arch_re  => qr/^MSWin32-x86-multi-thread$/,
      os_re    => qr/^MSWin32$/,
      cc_re    => qr/gcc/,
    },
 ];

#### tarballs with source codes
my $source_packs = [
## the first set for source code build will be a default option
  {
    title   => "Source code build: PNG-1.4.1",
    members => [
#      {
#        pack => 'zlib',
#        dirname => 'zlib-1.2.4',
#        url => 'http://www.zlib.net/zlib-1.2.4.tar.gz',
#        sha1sum  => '22965d40e5ca402847f778d4d10ce4cba17459d1',
#      },
      {
        pack => 'libpng',
        dirname => 'libpng-1.4.1',
        url => 'http://downloads.sourceforge.net/libpng/libpng-1.4.1.tar.gz',
        sha1sum  => '7a3488f5844068d67074f2507dd8a7ed9c69ff04',
      },
    ],
  },
];

sub check_config_script
{
  my $script = shift || 'libpng-config';
  print "Gonna check config script...\n";
  print "(scriptname=$script)\n";
  my $devnull = File::Spec->devnull();
  my $cflags  = `$script --cflags 2>$devnull`;
  $cflags =~ s/^-I//;
  $cflags =~ s/[\s\n\r]*$//;
  my ($version) = find_PNG_dir($cflags);
  return if($? >> 8);
  my $prefix = `$script --prefix 2>$devnull`;
  return if($? >> 8);

inc/My/Utility.pm  view on Meta::CPAN

}

sub check_win32_pkgconfig
{
  return unless $^O eq 'MSWin32';

  my ($prefix) = map { s/\/perl\/lib$/\/c/; $_ } grep { /\/perl\/lib$/ } @INC;
  return unless $prefix;

  my $pcfiledir = "$prefix/lib/pkgconfig";
  my $pkgconfig = "$pcfiledir/libpng.pc";
  return unless -f $pkgconfig;

  print "Gonna check win32 pkgconfig...\n";
  print "(path=$pkgconfig)\n";
  my $devnull = File::Spec->devnull();
  my %pc_var  = (
    pcfiledir => $pcfiledir,
  );

  open(DAT, $pkgconfig) || return;

inc/My/Utility.pm  view on Meta::CPAN

    $pc_var{$name} = $value;
  }

  for my $name (keys %pc_var) {
    $pc_var{$name} =~ s/^\Q$prefix\E/\@PrEfIx\@/;
  }

  return unless $pc_var{version};

  # find and set ld_shared_libs
  my @shlibs              = find_file("$prefix/bin", qr/libpng(\d.*)\.dll$/);
  $_                      =~ s/^\Q$prefix\E/\@PrEfIx\@/ foreach @shlibs;
  $pc_var{ld_shared_libs} = \@shlibs;

  # set ld_paths and ld_shlib_map
  my %tmp       = ();
  my %shlib_map = ();
  foreach my $full (@shlibs) {
    my ($v, $d, $f) = splitpath($full);
    $tmp{ catpath($v, $d, '') } = 1;
    # available shared libs detection
    if ($f =~ /^(lib)?(png12)/) {
      $shlib_map{png12} = $full unless $shlib_map{png12};
    }
    elsif ($f =~ /^(lib)?(tiff|jpeg|png)[^a-zA-Z]/) {
      $shlib_map{$2} = $full unless $shlib_map{$2};
    }
  };
  $pc_var{ld_paths}     = [ keys %tmp ];
  $pc_var{ld_shlib_map} = \%shlib_map;

  return {
    title           => "Already installed PNG-$pc_var{version} path=$pkgconfig",
    buildtype       => 'use_win32_pkgconfig',
    win32_pkgconfig => \%pc_var,

inc/My/Utility.pm  view on Meta::CPAN

  $re ||= qr/.*/;
  find({ wanted => sub { push @files, rel2abs($_) if /$re/ }, follow => 1, no_chdir => 1 , follow_skip => 2}, $dir);
  return @files;
}

sub find_PNG_dir {
  my $root = shift;
  my ($version, $prefix, $incdir, $libdir);
  return unless $root;

  # try to find png.h
  my ($found) = find_file($root, qr/png\.h$/i ); # take just the first one
  return unless $found;

  # get version info
  open(DAT, $found) || return;
  my @raw=<DAT>;
  close(DAT);
  my ($v_maj) = grep(/^#define[ \t]+PNG_LIBPNG_VER_MAJOR[ \t]+[0-9]+/, @raw);
  $v_maj =~ s/^#define[ \t]+PNG_LIBPNG_VER_MAJOR[ \t]+([0-9]+)[.\r\n]*$/$1/;
  my ($v_min) = grep(/^#define[ \t]+PNG_LIBPNG_VER_MINOR[ \t]+[0-9]+/, @raw);
  $v_min =~ s/^#define[ \t]+PNG_LIBPNG_VER_MINOR[ \t]+([0-9]+)[.\r\n]*$/$1/;
  my ($v_pat) = grep(/^#define[ \t]+PNG_LIBPNG_VER_RELEASE[ \t]+[0-9]+/, @raw);
  $v_pat =~ s/^#define[ \t]+PNG_LIBPNG_VER_RELEASE[ \t]+([0-9]+)[.\r\n]*$/$1/;
  return if (($v_maj eq '')||($v_min eq '')||($v_pat eq ''));
  $version = "$v_maj.$v_min.$v_pat";

  # get prefix dir
  my ($v, $d, $f) = splitpath($found);
  my @pp = reverse splitdir($d);
  shift(@pp) if(defined($pp[0]) && $pp[0] eq '');
  shift(@pp) if(defined($pp[0]) && $pp[0] =~ /libpng\d+/);
  if(defined($pp[0]) && $pp[0] eq 'include') {
    shift(@pp);
    @pp = reverse @pp;
    return (
      $version,
      catpath($v, catdir(@pp), ''),
      catpath($v, catdir(@pp, 'include'), ''),
      catpath($v, catdir(@pp, 'lib'), ''),
    );
  }

lib/Alien/PNG.pm  view on Meta::CPAN


our $VERSION = '0.4';
$VERSION = eval $VERSION;

=head1 SYNOPSIS

Alien::PNG tries (in given order) during its installation:

=over

=item * Locate an already installed PNG via 'libpng-config' script.

=item * Check for PNG libs in directory specified by PNG_INST_DIR variable.
In this case the module performs PNG library detection via
'$PNG_INST_DIR/bin/libpng-config' script.

=item * Download prebuilt PNG binaries (if available for your platform).

=item * Build PNG binaries from source codes (if possible on your system).

=back

Later you can use Alien::PNG in your module that needs to link agains PNG
and/or related libraries like this:

lib/Alien/PNG.pm  view on Meta::CPAN

'share' directory. To handle this scenario Alien::PNG offers some special
functionality (see below).

=back

=head1 METHODS

=head2 config()

This function is the main public interface to this module. Basic
functionality works in a very similar maner to 'libpng-config' script:

    Alien::PNG->config('prefix');   # gives the same string as 'libpng-config --prefix'
    Alien::PNG->config('version');  # gives the same string as 'libpng-config --version'
    Alien::PNG->config('libs');     # gives the same string as 'libpng-config --libs'
    Alien::PNG->config('cflags');   # gives the same string as 'libpng-config --cflags'

On top of that this function supports special parameters:

    Alien::PNG->config('ld_shared_libs');

Returns a list of full paths to shared libraries (*.so, *.dll) that will be
required for running the resulting binaries you have linked with PNG libs.

    Alien::PNG->config('ld_paths');

Returns a list of full paths to directories with shared libraries (*.so, *.dll)
that will be required for running the resulting binaries you have linked with
PNG libs.

    Alien::PNG->config('ld_shlib_map');

Returns a reference to hash of value pairs '<libnick>' => '<full_path_to_shlib'>,
where '<libnick>' is shortname for PNG related library like: PNG.

NOTE: config('ld_<something>') return an empty list/hash if you have decided to
use PNG libraries already installed on your system. This concerns 'libpng-config' 
detection and detection via '$PNG_INST_DIR/bin/libpng-config'.

=head2 check_header()

This function checks the availability of given header(s) when using compiler
options provided by "Alien::PNG->config('cflags')".

    Alien::PNG->check_header('png.h');
    Alien::PNG->check_header('png.h', 'pngconf.h');

Returns 1 if all given headers are available, 0 otherwise.

=head2 get_header_version()

Tries to find a header file specified as a param in PNG prefix direcotry and
based on "#define" macros inside this header file tries to get a version triplet.

    Alien::PNG->get_header_version('png.h');

Returns string like '1.2.3' or undef if not able to find and parse version info.

=head1 BUGS

Please post issues and bugs at L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Alien-PNG>

=head1 AUTHOR

    Tobias Leich

lib/Alien/PNG.pm  view on Meta::CPAN

The full text of the license can be found in the
LICENSE file included with this module.

=cut

### get config params
sub config
{
  my $package = shift;
  my @params  = @_;
  return _png_config_via_script(@params)          if Alien::PNG::ConfigData->config('script');
  return _png_config_via_win32_pkgconfig(@params) if Alien::PNG::ConfigData->config('win32_pkgconfig');
  return _png_config_via_config_data(@params)     if Alien::PNG::ConfigData->config('config');
}

### get version info from given header file
sub get_header_version {
  my ($package, $header) = @_;
  return unless $header;

  # try to find header
  my $root = Alien::PNG->config('prefix');
  #warn 'Finding in '.$root.'/include';

lib/Alien/PNG.pm  view on Meta::CPAN

    unlink $obj;
    return 1;
  }
  else {
    print STDERR "###TEST FAILED### for: " . join(', ', @header) . "\n";
    return 0;
  }
}

### internal functions
sub _png_config_via_script
{
  my $param    = shift;
  my @add_libs = @_;
  my $devnull = File::Spec->devnull();
  my $script = Alien::PNG::ConfigData->config('script');
  return unless ($script && ($param =~ /[a-z0-9_]*/i));
  my $val = `$script --$param 2>$devnull`;
  $val =~ s/[\r\n]*$//;
  if($param eq 'cflags') {
    $val .= ' ' . Alien::PNG::ConfigData->config('additional_cflags');
  }
  elsif($param eq 'libs') {
    $val .= ' ' . join(' ', @add_libs) if scalar @add_libs;
    $val .= ' ' . Alien::PNG::ConfigData->config('additional_libs');
  }
  return $val;
}

sub _png_config_via_win32_pkgconfig
{
  my $param     = shift;
  my @add_libs  = @_;
  my $devnull   = File::Spec->devnull();
  my $pkgconfig = Alien::PNG::ConfigData->config('win32_pkgconfig');
  return unless ($pkgconfig && ($param =~ /[a-z0-9_]*/i));

  my ($prefix) = grep { /\/perl\/lib$/ } @INC;
  return unless $prefix;
  $prefix              =~ s/\/perl\/lib$/\/c/;

lib/Alien/PNG.pm  view on Meta::CPAN

  elsif (ref $pkgconfig->{$param} eq 'HASH') {
    map { $pkgconfig->{$param}{$_} =~ s/\@PrEfIx\@/$prefix/g } keys %{$pkgconfig->{$param}};
  }
  else {
    $pkgconfig->{$param} =~ s/\@PrEfIx\@/$prefix/g;
  }

  $pkgconfig->{$param};
}

sub _png_config_via_config_data
{
  my $param    = shift;
  my @add_libs = @_;
  my $share_dir = dist_dir('Alien-PNG');
  my $subdir = Alien::PNG::ConfigData->config('share_subdir');
  return unless $subdir;
  my $real_prefix = catdir($share_dir, $subdir);
  return unless ($param =~ /[a-z0-9_]*/i);
  my $val = Alien::PNG::ConfigData->config('config')->{$param};
  return unless $val;

t/001_load.t  view on Meta::CPAN

# t/001_load.t - test module loading and basic functionality

use Test::More tests => 1;

BEGIN { use_ok( 'Alien::PNG' ); }

diag( "Testing Alien::PNG $Alien::PNG::VERSION, Perl $], $^X" );

diag( "Build type: " . (Alien::PNG::ConfigData->config('build_params')->{buildtype} || 'n.a.') );
diag( "Detected libpng-config script: " . (Alien::PNG::ConfigData->config('build_params')->{script} || 'n.a.') );
diag( "Build option used:\n\t" . (Alien::PNG::ConfigData->config('build_params')->{title} || 'n.a.') );
diag( "URL: " . (Alien::PNG::ConfigData->config('build_params')->{url} || 'n.a.') );
diag( "SHA1: " . (Alien::PNG::ConfigData->config('build_params')->{sha1sum} || 'n.a.') );

t/003_check_header.t  view on Meta::CPAN

# t/003_check_headers.t - test check_header() functionality

use Test::More tests => 2;
use Alien::PNG;

diag("Testing basic headers png.h + pngconf.h");
is( Alien::PNG->check_header('png.h'),              1, "Testing availability of 'png.h'" );
is( Alien::PNG->check_header('png.h', 'pngconf.h'), 1, "Testing availability of 'png.h, pngconf.h'" );

t/004_get_header_version.t  view on Meta::CPAN

# t/004_config.t

use Test::More tests => 1;
use Alien::PNG;

like( Alien::PNG->get_header_version('png.h'), qr/([0-9]+\.)*[0-9]+/, "Testing png.h" );

diag 'Core version: '.Alien::PNG->get_header_version('png.h');



( run in 0.685 second using v1.01-cache-2.11-cpan-df04353d9ac )