add Devel::CheckLib to each sub-module and ensure it stays packaged
authorTony Cook <tony@develop-help.com>
Sat, 18 Jun 2011 13:48:57 +0000 (23:48 +1000)
committerTony Cook <tony@develop-help.com>
Sat, 18 Jun 2011 13:48:57 +0000 (23:48 +1000)
FT2/inc/Devel/CheckLib.pm [new file with mode: 0644]
GIF/inc/Devel/CheckLib.pm [new file with mode: 0644]
JPEG/inc/Devel/CheckLib.pm [new file with mode: 0644]
MANIFEST.SKIP
PNG/inc/Devel/CheckLib.pm [new file with mode: 0644]
T1/inc/Devel/CheckLib.pm [new file with mode: 0644]
TIFF/inc/Devel/CheckLib.pm [new file with mode: 0644]
W32/inc/Devel/CheckLib.pm [new file with mode: 0644]
t/x40checklib.t [new file with mode: 0644]

diff --git a/FT2/inc/Devel/CheckLib.pm b/FT2/inc/Devel/CheckLib.pm
new file mode 100644 (file)
index 0000000..57cc8e6
--- /dev/null
@@ -0,0 +1,480 @@
+# $Id: CheckLib.pm,v 1.25 2008/10/27 12:16:23 drhyde Exp $
+
+package #
+Devel::CheckLib;
+
+use strict;
+use vars qw($VERSION @ISA @EXPORT);
+$VERSION = '0.699_002';
+use Config;
+
+use File::Spec;
+use File::Temp;
+
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(assert_lib check_lib_or_exit check_lib);
+
+# localising prevents the warningness leaking out of this module
+local $^W = 1;    # use warnings is a 5.6-ism
+
+_findcc(); # bomb out early if there's no compiler
+
+=head1 NAME
+
+Devel::CheckLib - check that a library is available
+
+=head1 DESCRIPTION
+
+Devel::CheckLib is a perl module that checks whether a particular C
+library and its headers are available.
+
+=head1 SYNOPSIS
+
+    use Devel::CheckLib;
+
+    check_lib_or_exit( lib => 'jpeg', header => 'jpeglib.h' );
+    check_lib_or_exit( lib => [ 'iconv', 'jpeg' ] );
+  
+    # or prompt for path to library and then do this:
+    check_lib_or_exit( lib => 'jpeg', libpath => $additional_path );
+
+=head1 USING IT IN Makefile.PL or Build.PL
+
+If you want to use this from Makefile.PL or Build.PL, do
+not simply copy the module into your distribution as this may cause
+problems when PAUSE and search.cpan.org index the distro.  Instead, use
+the use-devel-checklib script.
+
+=head1 HOW IT WORKS
+
+You pass named parameters to a function, describing to it how to build
+and link to the libraries.
+
+It works by trying to compile some code - which defaults to this:
+
+    int main(void) { return 0; }
+
+and linking it to the specified libraries.  If something pops out the end
+which looks executable, it gets executed, and if main() returns 0 we know
+that it worked.  That tiny program is
+built once for each library that you specify, and (without linking) once
+for each header file.
+
+If you want to check for the presence of particular functions in a
+library, or even that those functions return particular results, then
+you can pass your own function body for main() thus:
+
+    check_lib_or_exit(
+        function => 'foo();if(libversion() > 5) return 0; else return 1;'
+        incpath  => ...
+        libpath  => ...
+        lib      => ...
+        header   => ...
+    );
+
+In that case, it will fail to build if either foo() or libversion() don't
+exist, and main() will return the wrong value if libversion()'s return
+value isn't what you want.
+
+=head1 FUNCTIONS
+
+All of these take the same named parameters and are exported by default.
+To avoid exporting them, C<use Devel::CheckLib ()>.
+
+=head2 assert_lib
+
+This takes several named parameters, all of which are optional, and dies
+with an error message if any of the libraries listed can
+not be found.  B<Note>: dying in a Makefile.PL or Build.PL may provoke
+a 'FAIL' report from CPAN Testers' automated smoke testers.  Use 
+C<check_lib_or_exit> instead.
+
+The named parameters are:
+
+=over
+
+=item lib
+
+Must be either a string with the name of a single 
+library or a reference to an array of strings of library names.  Depending
+on the compiler found, library names will be fed to the compiler either as
+C<-l> arguments or as C<.lib> file names.  (E.g. C<-ljpeg> or C<jpeg.lib>)
+
+=item libpath
+
+a string or an array of strings
+representing additional paths to search for libraries.
+
+=item LIBS
+
+a C<ExtUtils::MakeMaker>-style space-seperated list of
+libraries (each preceded by '-l') and directories (preceded by '-L').
+
+This can also be supplied on the command-line.
+
+=back
+
+And libraries are no use without header files, so ...
+
+=over
+
+=item header
+
+Must be either a string with the name of a single 
+header file or a reference to an array of strings of header file names.
+
+=item incpath
+
+a string or an array of strings
+representing additional paths to search for headers.
+
+=item INC
+
+a C<ExtUtils::MakeMaker>-style space-seperated list of
+incpaths, each preceded by '-I'.
+
+This can also be supplied on the command-line.
+
+=back
+
+If you need to perform know more than "does it link?" you can provide
+code to be compiled and run:
+
+=over
+
+=item function
+
+the body of the <main()> function.  If not provided C<return 0;> is
+used.
+
+=item prologue
+
+code to insert between the C<#include> of the headers and the
+definition of main.
+
+=back
+
+=head2 check_lib_or_exit
+
+This behaves exactly the same as C<assert_lib()> except that instead of
+dieing, it warns (with exactly the same error message) and exits.
+This is intended for use in Makefile.PL / Build.PL
+when you might want to prompt the user for various paths and
+things before checking that what they've told you is sane.
+
+If any library or header is missing, it exits with an exit value of 0 to avoid
+causing a CPAN Testers 'FAIL' report.  CPAN Testers should ignore this
+result -- which is what you want if an external library dependency is not
+available.
+
+=head2 check_lib
+
+This behaves exactly the same as C<assert_lib()> except that it is silent,
+returning false instead of dieing, or true otherwise.
+
+=cut
+
+sub check_lib_or_exit {
+    eval 'assert_lib(@_)';
+    if($@) {
+        warn $@;
+        exit;
+    }
+}
+
+sub check_lib {
+    eval 'assert_lib(@_)';
+    return $@ ? 0 : 1;
+}
+
+sub assert_lib {
+    my %args = @_;
+    my (@libs, @libpaths, @headers, @incpaths);
+
+    # FIXME: these four just SCREAM "refactor" at me
+    @libs = (ref($args{lib}) ? @{$args{lib}} : $args{lib}) 
+        if $args{lib};
+    @libpaths = (ref($args{libpath}) ? @{$args{libpath}} : $args{libpath}) 
+        if $args{libpath};
+    @headers = (ref($args{header}) ? @{$args{header}} : $args{header}) 
+        if $args{header};
+    @incpaths = (ref($args{incpath}) ? @{$args{incpath}} : $args{incpath}) 
+        if $args{incpath};
+
+    # each entry is an arrayref containing:
+    # 0: arrayref of library search paths
+    # 1: arrayref of library names
+    my @link_cfgs = map [ \@libpaths, [ $_ ] ], @libs;
+
+    # work-a-like for Makefile.PL's LIBS and INC arguments
+    # if given as command-line argument, append to %args
+    for my $arg (@ARGV) {
+        for my $mm_attr_key qw(LIBS INC) {
+            if (my ($mm_attr_value) = $arg =~ /\A $mm_attr_key = (.*)/x) {
+            # it is tempting to put some \s* into the expression, but the
+            # MM command-line parser only accepts LIBS etc. followed by =,
+            # so we should not be any more lenient with whitespace than that
+                $args{$mm_attr_key} .= " $mm_attr_value";
+            }
+        }
+    }
+    # using special form of split to trim whitespace
+    if(defined($args{LIBS})) {
+        if (ref $args{LIBS}) {
+           foreach my $arg (@{$args{LIBS}}) {
+               my @sep = split ' ', $arg;
+               my @libs = map { /^-l(.+)$/ ? $1 : () } @sep;
+               my @paths = map { /^-L(.+)$/ ? $1 : () } @sep;
+               push @link_cfgs, [ \@paths, \@libs ];
+           }
+       }
+       else {
+           my @libs;
+           my @paths;
+           foreach my $arg (split(' ', $args{LIBS})) {
+               die("LIBS argument badly-formed: $arg\n") unless($arg =~ /^-l/i);
+               push @{$arg =~ /^-l/ ? \@libs : \@paths}, substr($arg, 2);
+           }
+           push @link_cfgs, map [ \@paths, [ $_ ] ], @libs;
+       }
+    }
+    if(defined($args{INC})) {
+        foreach my $arg (split(' ', $args{INC})) {
+            die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
+            push @incpaths, substr($arg, 2);
+        }
+    }
+
+    my @cc = _findcc();
+    my @missing;
+    my @wrongresult;
+
+    # first figure out which headers we can't find ...
+    my @use_headers;
+    for my $header (@headers) {
+        push @use_headers, $header;
+        my($ch, $cfile) = File::Temp::tempfile(
+            'assertlibXXXXXXXX', SUFFIX => '.c'
+        );
+        print $ch qq{#include <$_>\n} for @use_headers;
+        print $ch qq{int main(void) { return 0; }\n};
+        close($ch);
+        my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
+        my @sys_cmd;
+        # FIXME: re-factor - almost identical code later when linking
+        if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
+            require Win32;
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                "/Fe$exefile",
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths)
+            );
+        } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
+            @sys_cmd = (
+                @cc,
+                (map { "-I$_" } @incpaths),
+                "-o$exefile",
+                $cfile
+            );
+        } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                (map { "-I$_" } @incpaths),
+                "-o", "$exefile"
+            );
+        }
+        warn "# @sys_cmd\n" if $args{debug};
+        my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
+        push @missing, $header if $rv != 0 || ! -x $exefile; 
+        _cleanup_exe($exefile);
+        unlink $cfile;
+    } 
+
+    # now do each library in turn with headers
+    my($ch, $cfile) = File::Temp::tempfile(
+        'assertlibXXXXXXXX', SUFFIX => '.c'
+    );
+    print $ch qq{#include <$_>\n} foreach (@headers);
+    print $ch "\n$args{prologue}\n" if $args{prologue};
+    print $ch "int main(void) { ".($args{function} || 'return 0;')." }\n";
+    close($ch);
+    for my $link_cfg ( @link_cfgs ) {
+       my ($paths, $libs) = @$link_cfg;
+        my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
+        my @sys_cmd;
+        if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
+            require Win32;
+            my @libpath = map { 
+                q{/libpath:} . Win32::GetShortPathName($_)
+            } @libpaths; 
+            # this is horribly sensitive to the order of arguments
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                ( map { "$_.lib" } @$libs ),
+                "/Fe$exefile", 
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
+                "/link",
+                (map {'/libpath:'.Win32::GetShortPathName($_)} @$paths),
+            );
+        } elsif($Config{cc} eq 'CC/DECC') {          # VMS
+        } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
+            @sys_cmd = (
+                @cc,
+                "-o$exefile",
+                (map { "-l$_" } @$libs ),
+                (map { "-I$_" } @incpaths),
+                (map { "-L$_" } @$paths),
+                $cfile);
+        } else {                                     # Unix-ish
+                                                     # gcc, Sun, AIX (gcc, cc)
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                "-o", "$exefile",
+                (map { "-l$_" } @$libs ),
+                (map { "-I$_" } @incpaths),
+                (map { "-L$_" } @$paths)
+            );
+        }
+        warn "# @sys_cmd\n" if $args{debug};
+        my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
+        push @missing, @$libs if $rv != 0 || ! -x $exefile;
+        push @wrongresult, @$libs if $rv == 0 && -x $exefile && system(File::Spec->rel2abs($exefile)) != 0; 
+        _cleanup_exe($exefile);
+    } 
+    unlink $cfile;
+
+    my $miss_string = join( q{, }, map { qq{'$_'} } @missing );
+    die("Can't link/include $miss_string\n") if @missing;
+    my $wrong_string = join( q{, }, map { qq{'$_'} } @wrongresult);
+    die("wrong result: $wrong_string\n") if @wrongresult;
+}
+
+sub _cleanup_exe {
+    my ($exefile) = @_;
+    my $ofile = $exefile;
+    $ofile =~ s/$Config{_exe}$/$Config{_o}/;
+    unlink $exefile if -f $exefile;
+    unlink $ofile if -f $ofile;
+    unlink "$exefile\.manifest" if -f "$exefile\.manifest";
+    return
+}
+    
+sub _findcc {
+    my @paths = split(/$Config{path_sep}/, $ENV{PATH});
+    my @cc = split(/\s+/, $Config{cc});
+    return @cc if -x $cc[0];
+    foreach my $path (@paths) {
+        my $compiler = File::Spec->catfile($path, $cc[0]) . $Config{_exe};
+        return ($compiler, @cc[1 .. $#cc]) if -x $compiler;
+    }
+    die("Couldn't find your C compiler\n");
+}
+
+# code substantially borrowed from IPC::Run3
+sub _quiet_system {
+    my (@cmd) = @_;
+
+    # save handles
+    local *STDOUT_SAVE;
+    local *STDERR_SAVE;
+    open STDOUT_SAVE, ">&STDOUT" or die "CheckLib: $! saving STDOUT";
+    open STDERR_SAVE, ">&STDERR" or die "CheckLib: $! saving STDERR";
+    
+    # redirect to nowhere
+    local *DEV_NULL;
+    open DEV_NULL, ">" . File::Spec->devnull 
+        or die "CheckLib: $! opening handle to null device";
+    open STDOUT, ">&" . fileno DEV_NULL
+        or die "CheckLib: $! redirecting STDOUT to null handle";
+    open STDERR, ">&" . fileno DEV_NULL
+        or die "CheckLib: $! redirecting STDERR to null handle";
+
+    # run system command
+    my $rv = system(@cmd);
+
+    # restore handles
+    open STDOUT, ">&" . fileno STDOUT_SAVE
+        or die "CheckLib: $! restoring STDOUT handle";
+    open STDERR, ">&" . fileno STDERR_SAVE
+        or die "CheckLib: $! restoring STDERR handle";
+
+    return $rv;
+}
+
+=head1 PLATFORMS SUPPORTED
+
+You must have a C compiler installed.  We check for C<$Config{cc}>,
+both literally as it is in Config.pm and also in the $PATH.
+
+It has been tested with varying degrees on rigourousness on:
+
+=over
+
+=item gcc (on Linux, *BSD, Mac OS X, Solaris, Cygwin)
+
+=item Sun's compiler tools on Solaris
+
+=item IBM's tools on AIX
+
+=item SGI's tools on Irix 6.5
+
+=item Microsoft's tools on Windows
+
+=item MinGW on Windows (with Strawberry Perl)
+
+=item Borland's tools on Windows
+
+=item QNX
+
+=back
+
+=head1 WARNINGS, BUGS and FEEDBACK
+
+This is a very early release intended primarily for feedback from
+people who have discussed it.  The interface may change and it has
+not been adequately tested.
+
+Feedback is most welcome, including constructive criticism.
+Bug reports should be made using L<http://rt.cpan.org/> or by email.
+
+When submitting a bug report, please include the output from running:
+
+    perl -V
+    perl -MDevel::CheckLib -e0
+
+=head1 SEE ALSO
+
+L<Devel::CheckOS>
+
+L<Probe::Perl>
+
+=head1 AUTHORS
+
+David Cantrell E<lt>david@cantrell.org.ukE<gt>
+
+David Golden E<lt>dagolden@cpan.orgE<gt>
+
+Thanks to the cpan-testers-discuss mailing list for prompting us to write it
+in the first place;
+
+to Chris Williams for help with Borland support.
+
+=head1 COPYRIGHT and LICENCE
+
+Copyright 2007 David Cantrell. Portions copyright 2007 David Golden.
+
+This module is free-as-in-speech software, and may be used, distributed,
+and modified under the same conditions as perl itself.
+
+=head1 CONSPIRACY
+
+This module is also free-as-in-mason software.
+
+=cut
+
+1;
diff --git a/GIF/inc/Devel/CheckLib.pm b/GIF/inc/Devel/CheckLib.pm
new file mode 100644 (file)
index 0000000..57cc8e6
--- /dev/null
@@ -0,0 +1,480 @@
+# $Id: CheckLib.pm,v 1.25 2008/10/27 12:16:23 drhyde Exp $
+
+package #
+Devel::CheckLib;
+
+use strict;
+use vars qw($VERSION @ISA @EXPORT);
+$VERSION = '0.699_002';
+use Config;
+
+use File::Spec;
+use File::Temp;
+
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(assert_lib check_lib_or_exit check_lib);
+
+# localising prevents the warningness leaking out of this module
+local $^W = 1;    # use warnings is a 5.6-ism
+
+_findcc(); # bomb out early if there's no compiler
+
+=head1 NAME
+
+Devel::CheckLib - check that a library is available
+
+=head1 DESCRIPTION
+
+Devel::CheckLib is a perl module that checks whether a particular C
+library and its headers are available.
+
+=head1 SYNOPSIS
+
+    use Devel::CheckLib;
+
+    check_lib_or_exit( lib => 'jpeg', header => 'jpeglib.h' );
+    check_lib_or_exit( lib => [ 'iconv', 'jpeg' ] );
+  
+    # or prompt for path to library and then do this:
+    check_lib_or_exit( lib => 'jpeg', libpath => $additional_path );
+
+=head1 USING IT IN Makefile.PL or Build.PL
+
+If you want to use this from Makefile.PL or Build.PL, do
+not simply copy the module into your distribution as this may cause
+problems when PAUSE and search.cpan.org index the distro.  Instead, use
+the use-devel-checklib script.
+
+=head1 HOW IT WORKS
+
+You pass named parameters to a function, describing to it how to build
+and link to the libraries.
+
+It works by trying to compile some code - which defaults to this:
+
+    int main(void) { return 0; }
+
+and linking it to the specified libraries.  If something pops out the end
+which looks executable, it gets executed, and if main() returns 0 we know
+that it worked.  That tiny program is
+built once for each library that you specify, and (without linking) once
+for each header file.
+
+If you want to check for the presence of particular functions in a
+library, or even that those functions return particular results, then
+you can pass your own function body for main() thus:
+
+    check_lib_or_exit(
+        function => 'foo();if(libversion() > 5) return 0; else return 1;'
+        incpath  => ...
+        libpath  => ...
+        lib      => ...
+        header   => ...
+    );
+
+In that case, it will fail to build if either foo() or libversion() don't
+exist, and main() will return the wrong value if libversion()'s return
+value isn't what you want.
+
+=head1 FUNCTIONS
+
+All of these take the same named parameters and are exported by default.
+To avoid exporting them, C<use Devel::CheckLib ()>.
+
+=head2 assert_lib
+
+This takes several named parameters, all of which are optional, and dies
+with an error message if any of the libraries listed can
+not be found.  B<Note>: dying in a Makefile.PL or Build.PL may provoke
+a 'FAIL' report from CPAN Testers' automated smoke testers.  Use 
+C<check_lib_or_exit> instead.
+
+The named parameters are:
+
+=over
+
+=item lib
+
+Must be either a string with the name of a single 
+library or a reference to an array of strings of library names.  Depending
+on the compiler found, library names will be fed to the compiler either as
+C<-l> arguments or as C<.lib> file names.  (E.g. C<-ljpeg> or C<jpeg.lib>)
+
+=item libpath
+
+a string or an array of strings
+representing additional paths to search for libraries.
+
+=item LIBS
+
+a C<ExtUtils::MakeMaker>-style space-seperated list of
+libraries (each preceded by '-l') and directories (preceded by '-L').
+
+This can also be supplied on the command-line.
+
+=back
+
+And libraries are no use without header files, so ...
+
+=over
+
+=item header
+
+Must be either a string with the name of a single 
+header file or a reference to an array of strings of header file names.
+
+=item incpath
+
+a string or an array of strings
+representing additional paths to search for headers.
+
+=item INC
+
+a C<ExtUtils::MakeMaker>-style space-seperated list of
+incpaths, each preceded by '-I'.
+
+This can also be supplied on the command-line.
+
+=back
+
+If you need to perform know more than "does it link?" you can provide
+code to be compiled and run:
+
+=over
+
+=item function
+
+the body of the <main()> function.  If not provided C<return 0;> is
+used.
+
+=item prologue
+
+code to insert between the C<#include> of the headers and the
+definition of main.
+
+=back
+
+=head2 check_lib_or_exit
+
+This behaves exactly the same as C<assert_lib()> except that instead of
+dieing, it warns (with exactly the same error message) and exits.
+This is intended for use in Makefile.PL / Build.PL
+when you might want to prompt the user for various paths and
+things before checking that what they've told you is sane.
+
+If any library or header is missing, it exits with an exit value of 0 to avoid
+causing a CPAN Testers 'FAIL' report.  CPAN Testers should ignore this
+result -- which is what you want if an external library dependency is not
+available.
+
+=head2 check_lib
+
+This behaves exactly the same as C<assert_lib()> except that it is silent,
+returning false instead of dieing, or true otherwise.
+
+=cut
+
+sub check_lib_or_exit {
+    eval 'assert_lib(@_)';
+    if($@) {
+        warn $@;
+        exit;
+    }
+}
+
+sub check_lib {
+    eval 'assert_lib(@_)';
+    return $@ ? 0 : 1;
+}
+
+sub assert_lib {
+    my %args = @_;
+    my (@libs, @libpaths, @headers, @incpaths);
+
+    # FIXME: these four just SCREAM "refactor" at me
+    @libs = (ref($args{lib}) ? @{$args{lib}} : $args{lib}) 
+        if $args{lib};
+    @libpaths = (ref($args{libpath}) ? @{$args{libpath}} : $args{libpath}) 
+        if $args{libpath};
+    @headers = (ref($args{header}) ? @{$args{header}} : $args{header}) 
+        if $args{header};
+    @incpaths = (ref($args{incpath}) ? @{$args{incpath}} : $args{incpath}) 
+        if $args{incpath};
+
+    # each entry is an arrayref containing:
+    # 0: arrayref of library search paths
+    # 1: arrayref of library names
+    my @link_cfgs = map [ \@libpaths, [ $_ ] ], @libs;
+
+    # work-a-like for Makefile.PL's LIBS and INC arguments
+    # if given as command-line argument, append to %args
+    for my $arg (@ARGV) {
+        for my $mm_attr_key qw(LIBS INC) {
+            if (my ($mm_attr_value) = $arg =~ /\A $mm_attr_key = (.*)/x) {
+            # it is tempting to put some \s* into the expression, but the
+            # MM command-line parser only accepts LIBS etc. followed by =,
+            # so we should not be any more lenient with whitespace than that
+                $args{$mm_attr_key} .= " $mm_attr_value";
+            }
+        }
+    }
+    # using special form of split to trim whitespace
+    if(defined($args{LIBS})) {
+        if (ref $args{LIBS}) {
+           foreach my $arg (@{$args{LIBS}}) {
+               my @sep = split ' ', $arg;
+               my @libs = map { /^-l(.+)$/ ? $1 : () } @sep;
+               my @paths = map { /^-L(.+)$/ ? $1 : () } @sep;
+               push @link_cfgs, [ \@paths, \@libs ];
+           }
+       }
+       else {
+           my @libs;
+           my @paths;
+           foreach my $arg (split(' ', $args{LIBS})) {
+               die("LIBS argument badly-formed: $arg\n") unless($arg =~ /^-l/i);
+               push @{$arg =~ /^-l/ ? \@libs : \@paths}, substr($arg, 2);
+           }
+           push @link_cfgs, map [ \@paths, [ $_ ] ], @libs;
+       }
+    }
+    if(defined($args{INC})) {
+        foreach my $arg (split(' ', $args{INC})) {
+            die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
+            push @incpaths, substr($arg, 2);
+        }
+    }
+
+    my @cc = _findcc();
+    my @missing;
+    my @wrongresult;
+
+    # first figure out which headers we can't find ...
+    my @use_headers;
+    for my $header (@headers) {
+        push @use_headers, $header;
+        my($ch, $cfile) = File::Temp::tempfile(
+            'assertlibXXXXXXXX', SUFFIX => '.c'
+        );
+        print $ch qq{#include <$_>\n} for @use_headers;
+        print $ch qq{int main(void) { return 0; }\n};
+        close($ch);
+        my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
+        my @sys_cmd;
+        # FIXME: re-factor - almost identical code later when linking
+        if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
+            require Win32;
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                "/Fe$exefile",
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths)
+            );
+        } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
+            @sys_cmd = (
+                @cc,
+                (map { "-I$_" } @incpaths),
+                "-o$exefile",
+                $cfile
+            );
+        } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                (map { "-I$_" } @incpaths),
+                "-o", "$exefile"
+            );
+        }
+        warn "# @sys_cmd\n" if $args{debug};
+        my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
+        push @missing, $header if $rv != 0 || ! -x $exefile; 
+        _cleanup_exe($exefile);
+        unlink $cfile;
+    } 
+
+    # now do each library in turn with headers
+    my($ch, $cfile) = File::Temp::tempfile(
+        'assertlibXXXXXXXX', SUFFIX => '.c'
+    );
+    print $ch qq{#include <$_>\n} foreach (@headers);
+    print $ch "\n$args{prologue}\n" if $args{prologue};
+    print $ch "int main(void) { ".($args{function} || 'return 0;')." }\n";
+    close($ch);
+    for my $link_cfg ( @link_cfgs ) {
+       my ($paths, $libs) = @$link_cfg;
+        my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
+        my @sys_cmd;
+        if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
+            require Win32;
+            my @libpath = map { 
+                q{/libpath:} . Win32::GetShortPathName($_)
+            } @libpaths; 
+            # this is horribly sensitive to the order of arguments
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                ( map { "$_.lib" } @$libs ),
+                "/Fe$exefile", 
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
+                "/link",
+                (map {'/libpath:'.Win32::GetShortPathName($_)} @$paths),
+            );
+        } elsif($Config{cc} eq 'CC/DECC') {          # VMS
+        } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
+            @sys_cmd = (
+                @cc,
+                "-o$exefile",
+                (map { "-l$_" } @$libs ),
+                (map { "-I$_" } @incpaths),
+                (map { "-L$_" } @$paths),
+                $cfile);
+        } else {                                     # Unix-ish
+                                                     # gcc, Sun, AIX (gcc, cc)
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                "-o", "$exefile",
+                (map { "-l$_" } @$libs ),
+                (map { "-I$_" } @incpaths),
+                (map { "-L$_" } @$paths)
+            );
+        }
+        warn "# @sys_cmd\n" if $args{debug};
+        my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
+        push @missing, @$libs if $rv != 0 || ! -x $exefile;
+        push @wrongresult, @$libs if $rv == 0 && -x $exefile && system(File::Spec->rel2abs($exefile)) != 0; 
+        _cleanup_exe($exefile);
+    } 
+    unlink $cfile;
+
+    my $miss_string = join( q{, }, map { qq{'$_'} } @missing );
+    die("Can't link/include $miss_string\n") if @missing;
+    my $wrong_string = join( q{, }, map { qq{'$_'} } @wrongresult);
+    die("wrong result: $wrong_string\n") if @wrongresult;
+}
+
+sub _cleanup_exe {
+    my ($exefile) = @_;
+    my $ofile = $exefile;
+    $ofile =~ s/$Config{_exe}$/$Config{_o}/;
+    unlink $exefile if -f $exefile;
+    unlink $ofile if -f $ofile;
+    unlink "$exefile\.manifest" if -f "$exefile\.manifest";
+    return
+}
+    
+sub _findcc {
+    my @paths = split(/$Config{path_sep}/, $ENV{PATH});
+    my @cc = split(/\s+/, $Config{cc});
+    return @cc if -x $cc[0];
+    foreach my $path (@paths) {
+        my $compiler = File::Spec->catfile($path, $cc[0]) . $Config{_exe};
+        return ($compiler, @cc[1 .. $#cc]) if -x $compiler;
+    }
+    die("Couldn't find your C compiler\n");
+}
+
+# code substantially borrowed from IPC::Run3
+sub _quiet_system {
+    my (@cmd) = @_;
+
+    # save handles
+    local *STDOUT_SAVE;
+    local *STDERR_SAVE;
+    open STDOUT_SAVE, ">&STDOUT" or die "CheckLib: $! saving STDOUT";
+    open STDERR_SAVE, ">&STDERR" or die "CheckLib: $! saving STDERR";
+    
+    # redirect to nowhere
+    local *DEV_NULL;
+    open DEV_NULL, ">" . File::Spec->devnull 
+        or die "CheckLib: $! opening handle to null device";
+    open STDOUT, ">&" . fileno DEV_NULL
+        or die "CheckLib: $! redirecting STDOUT to null handle";
+    open STDERR, ">&" . fileno DEV_NULL
+        or die "CheckLib: $! redirecting STDERR to null handle";
+
+    # run system command
+    my $rv = system(@cmd);
+
+    # restore handles
+    open STDOUT, ">&" . fileno STDOUT_SAVE
+        or die "CheckLib: $! restoring STDOUT handle";
+    open STDERR, ">&" . fileno STDERR_SAVE
+        or die "CheckLib: $! restoring STDERR handle";
+
+    return $rv;
+}
+
+=head1 PLATFORMS SUPPORTED
+
+You must have a C compiler installed.  We check for C<$Config{cc}>,
+both literally as it is in Config.pm and also in the $PATH.
+
+It has been tested with varying degrees on rigourousness on:
+
+=over
+
+=item gcc (on Linux, *BSD, Mac OS X, Solaris, Cygwin)
+
+=item Sun's compiler tools on Solaris
+
+=item IBM's tools on AIX
+
+=item SGI's tools on Irix 6.5
+
+=item Microsoft's tools on Windows
+
+=item MinGW on Windows (with Strawberry Perl)
+
+=item Borland's tools on Windows
+
+=item QNX
+
+=back
+
+=head1 WARNINGS, BUGS and FEEDBACK
+
+This is a very early release intended primarily for feedback from
+people who have discussed it.  The interface may change and it has
+not been adequately tested.
+
+Feedback is most welcome, including constructive criticism.
+Bug reports should be made using L<http://rt.cpan.org/> or by email.
+
+When submitting a bug report, please include the output from running:
+
+    perl -V
+    perl -MDevel::CheckLib -e0
+
+=head1 SEE ALSO
+
+L<Devel::CheckOS>
+
+L<Probe::Perl>
+
+=head1 AUTHORS
+
+David Cantrell E<lt>david@cantrell.org.ukE<gt>
+
+David Golden E<lt>dagolden@cpan.orgE<gt>
+
+Thanks to the cpan-testers-discuss mailing list for prompting us to write it
+in the first place;
+
+to Chris Williams for help with Borland support.
+
+=head1 COPYRIGHT and LICENCE
+
+Copyright 2007 David Cantrell. Portions copyright 2007 David Golden.
+
+This module is free-as-in-speech software, and may be used, distributed,
+and modified under the same conditions as perl itself.
+
+=head1 CONSPIRACY
+
+This module is also free-as-in-mason software.
+
+=cut
+
+1;
diff --git a/JPEG/inc/Devel/CheckLib.pm b/JPEG/inc/Devel/CheckLib.pm
new file mode 100644 (file)
index 0000000..57cc8e6
--- /dev/null
@@ -0,0 +1,480 @@
+# $Id: CheckLib.pm,v 1.25 2008/10/27 12:16:23 drhyde Exp $
+
+package #
+Devel::CheckLib;
+
+use strict;
+use vars qw($VERSION @ISA @EXPORT);
+$VERSION = '0.699_002';
+use Config;
+
+use File::Spec;
+use File::Temp;
+
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(assert_lib check_lib_or_exit check_lib);
+
+# localising prevents the warningness leaking out of this module
+local $^W = 1;    # use warnings is a 5.6-ism
+
+_findcc(); # bomb out early if there's no compiler
+
+=head1 NAME
+
+Devel::CheckLib - check that a library is available
+
+=head1 DESCRIPTION
+
+Devel::CheckLib is a perl module that checks whether a particular C
+library and its headers are available.
+
+=head1 SYNOPSIS
+
+    use Devel::CheckLib;
+
+    check_lib_or_exit( lib => 'jpeg', header => 'jpeglib.h' );
+    check_lib_or_exit( lib => [ 'iconv', 'jpeg' ] );
+  
+    # or prompt for path to library and then do this:
+    check_lib_or_exit( lib => 'jpeg', libpath => $additional_path );
+
+=head1 USING IT IN Makefile.PL or Build.PL
+
+If you want to use this from Makefile.PL or Build.PL, do
+not simply copy the module into your distribution as this may cause
+problems when PAUSE and search.cpan.org index the distro.  Instead, use
+the use-devel-checklib script.
+
+=head1 HOW IT WORKS
+
+You pass named parameters to a function, describing to it how to build
+and link to the libraries.
+
+It works by trying to compile some code - which defaults to this:
+
+    int main(void) { return 0; }
+
+and linking it to the specified libraries.  If something pops out the end
+which looks executable, it gets executed, and if main() returns 0 we know
+that it worked.  That tiny program is
+built once for each library that you specify, and (without linking) once
+for each header file.
+
+If you want to check for the presence of particular functions in a
+library, or even that those functions return particular results, then
+you can pass your own function body for main() thus:
+
+    check_lib_or_exit(
+        function => 'foo();if(libversion() > 5) return 0; else return 1;'
+        incpath  => ...
+        libpath  => ...
+        lib      => ...
+        header   => ...
+    );
+
+In that case, it will fail to build if either foo() or libversion() don't
+exist, and main() will return the wrong value if libversion()'s return
+value isn't what you want.
+
+=head1 FUNCTIONS
+
+All of these take the same named parameters and are exported by default.
+To avoid exporting them, C<use Devel::CheckLib ()>.
+
+=head2 assert_lib
+
+This takes several named parameters, all of which are optional, and dies
+with an error message if any of the libraries listed can
+not be found.  B<Note>: dying in a Makefile.PL or Build.PL may provoke
+a 'FAIL' report from CPAN Testers' automated smoke testers.  Use 
+C<check_lib_or_exit> instead.
+
+The named parameters are:
+
+=over
+
+=item lib
+
+Must be either a string with the name of a single 
+library or a reference to an array of strings of library names.  Depending
+on the compiler found, library names will be fed to the compiler either as
+C<-l> arguments or as C<.lib> file names.  (E.g. C<-ljpeg> or C<jpeg.lib>)
+
+=item libpath
+
+a string or an array of strings
+representing additional paths to search for libraries.
+
+=item LIBS
+
+a C<ExtUtils::MakeMaker>-style space-seperated list of
+libraries (each preceded by '-l') and directories (preceded by '-L').
+
+This can also be supplied on the command-line.
+
+=back
+
+And libraries are no use without header files, so ...
+
+=over
+
+=item header
+
+Must be either a string with the name of a single 
+header file or a reference to an array of strings of header file names.
+
+=item incpath
+
+a string or an array of strings
+representing additional paths to search for headers.
+
+=item INC
+
+a C<ExtUtils::MakeMaker>-style space-seperated list of
+incpaths, each preceded by '-I'.
+
+This can also be supplied on the command-line.
+
+=back
+
+If you need to perform know more than "does it link?" you can provide
+code to be compiled and run:
+
+=over
+
+=item function
+
+the body of the <main()> function.  If not provided C<return 0;> is
+used.
+
+=item prologue
+
+code to insert between the C<#include> of the headers and the
+definition of main.
+
+=back
+
+=head2 check_lib_or_exit
+
+This behaves exactly the same as C<assert_lib()> except that instead of
+dieing, it warns (with exactly the same error message) and exits.
+This is intended for use in Makefile.PL / Build.PL
+when you might want to prompt the user for various paths and
+things before checking that what they've told you is sane.
+
+If any library or header is missing, it exits with an exit value of 0 to avoid
+causing a CPAN Testers 'FAIL' report.  CPAN Testers should ignore this
+result -- which is what you want if an external library dependency is not
+available.
+
+=head2 check_lib
+
+This behaves exactly the same as C<assert_lib()> except that it is silent,
+returning false instead of dieing, or true otherwise.
+
+=cut
+
+sub check_lib_or_exit {
+    eval 'assert_lib(@_)';
+    if($@) {
+        warn $@;
+        exit;
+    }
+}
+
+sub check_lib {
+    eval 'assert_lib(@_)';
+    return $@ ? 0 : 1;
+}
+
+sub assert_lib {
+    my %args = @_;
+    my (@libs, @libpaths, @headers, @incpaths);
+
+    # FIXME: these four just SCREAM "refactor" at me
+    @libs = (ref($args{lib}) ? @{$args{lib}} : $args{lib}) 
+        if $args{lib};
+    @libpaths = (ref($args{libpath}) ? @{$args{libpath}} : $args{libpath}) 
+        if $args{libpath};
+    @headers = (ref($args{header}) ? @{$args{header}} : $args{header}) 
+        if $args{header};
+    @incpaths = (ref($args{incpath}) ? @{$args{incpath}} : $args{incpath}) 
+        if $args{incpath};
+
+    # each entry is an arrayref containing:
+    # 0: arrayref of library search paths
+    # 1: arrayref of library names
+    my @link_cfgs = map [ \@libpaths, [ $_ ] ], @libs;
+
+    # work-a-like for Makefile.PL's LIBS and INC arguments
+    # if given as command-line argument, append to %args
+    for my $arg (@ARGV) {
+        for my $mm_attr_key qw(LIBS INC) {
+            if (my ($mm_attr_value) = $arg =~ /\A $mm_attr_key = (.*)/x) {
+            # it is tempting to put some \s* into the expression, but the
+            # MM command-line parser only accepts LIBS etc. followed by =,
+            # so we should not be any more lenient with whitespace than that
+                $args{$mm_attr_key} .= " $mm_attr_value";
+            }
+        }
+    }
+    # using special form of split to trim whitespace
+    if(defined($args{LIBS})) {
+        if (ref $args{LIBS}) {
+           foreach my $arg (@{$args{LIBS}}) {
+               my @sep = split ' ', $arg;
+               my @libs = map { /^-l(.+)$/ ? $1 : () } @sep;
+               my @paths = map { /^-L(.+)$/ ? $1 : () } @sep;
+               push @link_cfgs, [ \@paths, \@libs ];
+           }
+       }
+       else {
+           my @libs;
+           my @paths;
+           foreach my $arg (split(' ', $args{LIBS})) {
+               die("LIBS argument badly-formed: $arg\n") unless($arg =~ /^-l/i);
+               push @{$arg =~ /^-l/ ? \@libs : \@paths}, substr($arg, 2);
+           }
+           push @link_cfgs, map [ \@paths, [ $_ ] ], @libs;
+       }
+    }
+    if(defined($args{INC})) {
+        foreach my $arg (split(' ', $args{INC})) {
+            die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
+            push @incpaths, substr($arg, 2);
+        }
+    }
+
+    my @cc = _findcc();
+    my @missing;
+    my @wrongresult;
+
+    # first figure out which headers we can't find ...
+    my @use_headers;
+    for my $header (@headers) {
+        push @use_headers, $header;
+        my($ch, $cfile) = File::Temp::tempfile(
+            'assertlibXXXXXXXX', SUFFIX => '.c'
+        );
+        print $ch qq{#include <$_>\n} for @use_headers;
+        print $ch qq{int main(void) { return 0; }\n};
+        close($ch);
+        my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
+        my @sys_cmd;
+        # FIXME: re-factor - almost identical code later when linking
+        if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
+            require Win32;
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                "/Fe$exefile",
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths)
+            );
+        } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
+            @sys_cmd = (
+                @cc,
+                (map { "-I$_" } @incpaths),
+                "-o$exefile",
+                $cfile
+            );
+        } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                (map { "-I$_" } @incpaths),
+                "-o", "$exefile"
+            );
+        }
+        warn "# @sys_cmd\n" if $args{debug};
+        my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
+        push @missing, $header if $rv != 0 || ! -x $exefile; 
+        _cleanup_exe($exefile);
+        unlink $cfile;
+    } 
+
+    # now do each library in turn with headers
+    my($ch, $cfile) = File::Temp::tempfile(
+        'assertlibXXXXXXXX', SUFFIX => '.c'
+    );
+    print $ch qq{#include <$_>\n} foreach (@headers);
+    print $ch "\n$args{prologue}\n" if $args{prologue};
+    print $ch "int main(void) { ".($args{function} || 'return 0;')." }\n";
+    close($ch);
+    for my $link_cfg ( @link_cfgs ) {
+       my ($paths, $libs) = @$link_cfg;
+        my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
+        my @sys_cmd;
+        if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
+            require Win32;
+            my @libpath = map { 
+                q{/libpath:} . Win32::GetShortPathName($_)
+            } @libpaths; 
+            # this is horribly sensitive to the order of arguments
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                ( map { "$_.lib" } @$libs ),
+                "/Fe$exefile", 
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
+                "/link",
+                (map {'/libpath:'.Win32::GetShortPathName($_)} @$paths),
+            );
+        } elsif($Config{cc} eq 'CC/DECC') {          # VMS
+        } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
+            @sys_cmd = (
+                @cc,
+                "-o$exefile",
+                (map { "-l$_" } @$libs ),
+                (map { "-I$_" } @incpaths),
+                (map { "-L$_" } @$paths),
+                $cfile);
+        } else {                                     # Unix-ish
+                                                     # gcc, Sun, AIX (gcc, cc)
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                "-o", "$exefile",
+                (map { "-l$_" } @$libs ),
+                (map { "-I$_" } @incpaths),
+                (map { "-L$_" } @$paths)
+            );
+        }
+        warn "# @sys_cmd\n" if $args{debug};
+        my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
+        push @missing, @$libs if $rv != 0 || ! -x $exefile;
+        push @wrongresult, @$libs if $rv == 0 && -x $exefile && system(File::Spec->rel2abs($exefile)) != 0; 
+        _cleanup_exe($exefile);
+    } 
+    unlink $cfile;
+
+    my $miss_string = join( q{, }, map { qq{'$_'} } @missing );
+    die("Can't link/include $miss_string\n") if @missing;
+    my $wrong_string = join( q{, }, map { qq{'$_'} } @wrongresult);
+    die("wrong result: $wrong_string\n") if @wrongresult;
+}
+
+sub _cleanup_exe {
+    my ($exefile) = @_;
+    my $ofile = $exefile;
+    $ofile =~ s/$Config{_exe}$/$Config{_o}/;
+    unlink $exefile if -f $exefile;
+    unlink $ofile if -f $ofile;
+    unlink "$exefile\.manifest" if -f "$exefile\.manifest";
+    return
+}
+    
+sub _findcc {
+    my @paths = split(/$Config{path_sep}/, $ENV{PATH});
+    my @cc = split(/\s+/, $Config{cc});
+    return @cc if -x $cc[0];
+    foreach my $path (@paths) {
+        my $compiler = File::Spec->catfile($path, $cc[0]) . $Config{_exe};
+        return ($compiler, @cc[1 .. $#cc]) if -x $compiler;
+    }
+    die("Couldn't find your C compiler\n");
+}
+
+# code substantially borrowed from IPC::Run3
+sub _quiet_system {
+    my (@cmd) = @_;
+
+    # save handles
+    local *STDOUT_SAVE;
+    local *STDERR_SAVE;
+    open STDOUT_SAVE, ">&STDOUT" or die "CheckLib: $! saving STDOUT";
+    open STDERR_SAVE, ">&STDERR" or die "CheckLib: $! saving STDERR";
+    
+    # redirect to nowhere
+    local *DEV_NULL;
+    open DEV_NULL, ">" . File::Spec->devnull 
+        or die "CheckLib: $! opening handle to null device";
+    open STDOUT, ">&" . fileno DEV_NULL
+        or die "CheckLib: $! redirecting STDOUT to null handle";
+    open STDERR, ">&" . fileno DEV_NULL
+        or die "CheckLib: $! redirecting STDERR to null handle";
+
+    # run system command
+    my $rv = system(@cmd);
+
+    # restore handles
+    open STDOUT, ">&" . fileno STDOUT_SAVE
+        or die "CheckLib: $! restoring STDOUT handle";
+    open STDERR, ">&" . fileno STDERR_SAVE
+        or die "CheckLib: $! restoring STDERR handle";
+
+    return $rv;
+}
+
+=head1 PLATFORMS SUPPORTED
+
+You must have a C compiler installed.  We check for C<$Config{cc}>,
+both literally as it is in Config.pm and also in the $PATH.
+
+It has been tested with varying degrees on rigourousness on:
+
+=over
+
+=item gcc (on Linux, *BSD, Mac OS X, Solaris, Cygwin)
+
+=item Sun's compiler tools on Solaris
+
+=item IBM's tools on AIX
+
+=item SGI's tools on Irix 6.5
+
+=item Microsoft's tools on Windows
+
+=item MinGW on Windows (with Strawberry Perl)
+
+=item Borland's tools on Windows
+
+=item QNX
+
+=back
+
+=head1 WARNINGS, BUGS and FEEDBACK
+
+This is a very early release intended primarily for feedback from
+people who have discussed it.  The interface may change and it has
+not been adequately tested.
+
+Feedback is most welcome, including constructive criticism.
+Bug reports should be made using L<http://rt.cpan.org/> or by email.
+
+When submitting a bug report, please include the output from running:
+
+    perl -V
+    perl -MDevel::CheckLib -e0
+
+=head1 SEE ALSO
+
+L<Devel::CheckOS>
+
+L<Probe::Perl>
+
+=head1 AUTHORS
+
+David Cantrell E<lt>david@cantrell.org.ukE<gt>
+
+David Golden E<lt>dagolden@cpan.orgE<gt>
+
+Thanks to the cpan-testers-discuss mailing list for prompting us to write it
+in the first place;
+
+to Chris Williams for help with Borland support.
+
+=head1 COPYRIGHT and LICENCE
+
+Copyright 2007 David Cantrell. Portions copyright 2007 David Golden.
+
+This module is free-as-in-speech software, and may be used, distributed,
+and modified under the same conditions as perl itself.
+
+=head1 CONSPIRACY
+
+This module is also free-as-in-mason software.
+
+=cut
+
+1;
index a04490d..0051bde 100644 (file)
@@ -79,6 +79,7 @@ Makefile\.old$
 
 ^.*/Changes$
 ^.*/MANIFEST(\.SKIP)?$
+^.+/inc/Devel/CheckLib\.pm$
 ^blib/
 ^Flines/Flines\.c$
 ^Imager\.c$
diff --git a/PNG/inc/Devel/CheckLib.pm b/PNG/inc/Devel/CheckLib.pm
new file mode 100644 (file)
index 0000000..57cc8e6
--- /dev/null
@@ -0,0 +1,480 @@
+# $Id: CheckLib.pm,v 1.25 2008/10/27 12:16:23 drhyde Exp $
+
+package #
+Devel::CheckLib;
+
+use strict;
+use vars qw($VERSION @ISA @EXPORT);
+$VERSION = '0.699_002';
+use Config;
+
+use File::Spec;
+use File::Temp;
+
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(assert_lib check_lib_or_exit check_lib);
+
+# localising prevents the warningness leaking out of this module
+local $^W = 1;    # use warnings is a 5.6-ism
+
+_findcc(); # bomb out early if there's no compiler
+
+=head1 NAME
+
+Devel::CheckLib - check that a library is available
+
+=head1 DESCRIPTION
+
+Devel::CheckLib is a perl module that checks whether a particular C
+library and its headers are available.
+
+=head1 SYNOPSIS
+
+    use Devel::CheckLib;
+
+    check_lib_or_exit( lib => 'jpeg', header => 'jpeglib.h' );
+    check_lib_or_exit( lib => [ 'iconv', 'jpeg' ] );
+  
+    # or prompt for path to library and then do this:
+    check_lib_or_exit( lib => 'jpeg', libpath => $additional_path );
+
+=head1 USING IT IN Makefile.PL or Build.PL
+
+If you want to use this from Makefile.PL or Build.PL, do
+not simply copy the module into your distribution as this may cause
+problems when PAUSE and search.cpan.org index the distro.  Instead, use
+the use-devel-checklib script.
+
+=head1 HOW IT WORKS
+
+You pass named parameters to a function, describing to it how to build
+and link to the libraries.
+
+It works by trying to compile some code - which defaults to this:
+
+    int main(void) { return 0; }
+
+and linking it to the specified libraries.  If something pops out the end
+which looks executable, it gets executed, and if main() returns 0 we know
+that it worked.  That tiny program is
+built once for each library that you specify, and (without linking) once
+for each header file.
+
+If you want to check for the presence of particular functions in a
+library, or even that those functions return particular results, then
+you can pass your own function body for main() thus:
+
+    check_lib_or_exit(
+        function => 'foo();if(libversion() > 5) return 0; else return 1;'
+        incpath  => ...
+        libpath  => ...
+        lib      => ...
+        header   => ...
+    );
+
+In that case, it will fail to build if either foo() or libversion() don't
+exist, and main() will return the wrong value if libversion()'s return
+value isn't what you want.
+
+=head1 FUNCTIONS
+
+All of these take the same named parameters and are exported by default.
+To avoid exporting them, C<use Devel::CheckLib ()>.
+
+=head2 assert_lib
+
+This takes several named parameters, all of which are optional, and dies
+with an error message if any of the libraries listed can
+not be found.  B<Note>: dying in a Makefile.PL or Build.PL may provoke
+a 'FAIL' report from CPAN Testers' automated smoke testers.  Use 
+C<check_lib_or_exit> instead.
+
+The named parameters are:
+
+=over
+
+=item lib
+
+Must be either a string with the name of a single 
+library or a reference to an array of strings of library names.  Depending
+on the compiler found, library names will be fed to the compiler either as
+C<-l> arguments or as C<.lib> file names.  (E.g. C<-ljpeg> or C<jpeg.lib>)
+
+=item libpath
+
+a string or an array of strings
+representing additional paths to search for libraries.
+
+=item LIBS
+
+a C<ExtUtils::MakeMaker>-style space-seperated list of
+libraries (each preceded by '-l') and directories (preceded by '-L').
+
+This can also be supplied on the command-line.
+
+=back
+
+And libraries are no use without header files, so ...
+
+=over
+
+=item header
+
+Must be either a string with the name of a single 
+header file or a reference to an array of strings of header file names.
+
+=item incpath
+
+a string or an array of strings
+representing additional paths to search for headers.
+
+=item INC
+
+a C<ExtUtils::MakeMaker>-style space-seperated list of
+incpaths, each preceded by '-I'.
+
+This can also be supplied on the command-line.
+
+=back
+
+If you need to perform know more than "does it link?" you can provide
+code to be compiled and run:
+
+=over
+
+=item function
+
+the body of the <main()> function.  If not provided C<return 0;> is
+used.
+
+=item prologue
+
+code to insert between the C<#include> of the headers and the
+definition of main.
+
+=back
+
+=head2 check_lib_or_exit
+
+This behaves exactly the same as C<assert_lib()> except that instead of
+dieing, it warns (with exactly the same error message) and exits.
+This is intended for use in Makefile.PL / Build.PL
+when you might want to prompt the user for various paths and
+things before checking that what they've told you is sane.
+
+If any library or header is missing, it exits with an exit value of 0 to avoid
+causing a CPAN Testers 'FAIL' report.  CPAN Testers should ignore this
+result -- which is what you want if an external library dependency is not
+available.
+
+=head2 check_lib
+
+This behaves exactly the same as C<assert_lib()> except that it is silent,
+returning false instead of dieing, or true otherwise.
+
+=cut
+
+sub check_lib_or_exit {
+    eval 'assert_lib(@_)';
+    if($@) {
+        warn $@;
+        exit;
+    }
+}
+
+sub check_lib {
+    eval 'assert_lib(@_)';
+    return $@ ? 0 : 1;
+}
+
+sub assert_lib {
+    my %args = @_;
+    my (@libs, @libpaths, @headers, @incpaths);
+
+    # FIXME: these four just SCREAM "refactor" at me
+    @libs = (ref($args{lib}) ? @{$args{lib}} : $args{lib}) 
+        if $args{lib};
+    @libpaths = (ref($args{libpath}) ? @{$args{libpath}} : $args{libpath}) 
+        if $args{libpath};
+    @headers = (ref($args{header}) ? @{$args{header}} : $args{header}) 
+        if $args{header};
+    @incpaths = (ref($args{incpath}) ? @{$args{incpath}} : $args{incpath}) 
+        if $args{incpath};
+
+    # each entry is an arrayref containing:
+    # 0: arrayref of library search paths
+    # 1: arrayref of library names
+    my @link_cfgs = map [ \@libpaths, [ $_ ] ], @libs;
+
+    # work-a-like for Makefile.PL's LIBS and INC arguments
+    # if given as command-line argument, append to %args
+    for my $arg (@ARGV) {
+        for my $mm_attr_key qw(LIBS INC) {
+            if (my ($mm_attr_value) = $arg =~ /\A $mm_attr_key = (.*)/x) {
+            # it is tempting to put some \s* into the expression, but the
+            # MM command-line parser only accepts LIBS etc. followed by =,
+            # so we should not be any more lenient with whitespace than that
+                $args{$mm_attr_key} .= " $mm_attr_value";
+            }
+        }
+    }
+    # using special form of split to trim whitespace
+    if(defined($args{LIBS})) {
+        if (ref $args{LIBS}) {
+           foreach my $arg (@{$args{LIBS}}) {
+               my @sep = split ' ', $arg;
+               my @libs = map { /^-l(.+)$/ ? $1 : () } @sep;
+               my @paths = map { /^-L(.+)$/ ? $1 : () } @sep;
+               push @link_cfgs, [ \@paths, \@libs ];
+           }
+       }
+       else {
+           my @libs;
+           my @paths;
+           foreach my $arg (split(' ', $args{LIBS})) {
+               die("LIBS argument badly-formed: $arg\n") unless($arg =~ /^-l/i);
+               push @{$arg =~ /^-l/ ? \@libs : \@paths}, substr($arg, 2);
+           }
+           push @link_cfgs, map [ \@paths, [ $_ ] ], @libs;
+       }
+    }
+    if(defined($args{INC})) {
+        foreach my $arg (split(' ', $args{INC})) {
+            die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
+            push @incpaths, substr($arg, 2);
+        }
+    }
+
+    my @cc = _findcc();
+    my @missing;
+    my @wrongresult;
+
+    # first figure out which headers we can't find ...
+    my @use_headers;
+    for my $header (@headers) {
+        push @use_headers, $header;
+        my($ch, $cfile) = File::Temp::tempfile(
+            'assertlibXXXXXXXX', SUFFIX => '.c'
+        );
+        print $ch qq{#include <$_>\n} for @use_headers;
+        print $ch qq{int main(void) { return 0; }\n};
+        close($ch);
+        my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
+        my @sys_cmd;
+        # FIXME: re-factor - almost identical code later when linking
+        if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
+            require Win32;
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                "/Fe$exefile",
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths)
+            );
+        } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
+            @sys_cmd = (
+                @cc,
+                (map { "-I$_" } @incpaths),
+                "-o$exefile",
+                $cfile
+            );
+        } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                (map { "-I$_" } @incpaths),
+                "-o", "$exefile"
+            );
+        }
+        warn "# @sys_cmd\n" if $args{debug};
+        my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
+        push @missing, $header if $rv != 0 || ! -x $exefile; 
+        _cleanup_exe($exefile);
+        unlink $cfile;
+    } 
+
+    # now do each library in turn with headers
+    my($ch, $cfile) = File::Temp::tempfile(
+        'assertlibXXXXXXXX', SUFFIX => '.c'
+    );
+    print $ch qq{#include <$_>\n} foreach (@headers);
+    print $ch "\n$args{prologue}\n" if $args{prologue};
+    print $ch "int main(void) { ".($args{function} || 'return 0;')." }\n";
+    close($ch);
+    for my $link_cfg ( @link_cfgs ) {
+       my ($paths, $libs) = @$link_cfg;
+        my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
+        my @sys_cmd;
+        if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
+            require Win32;
+            my @libpath = map { 
+                q{/libpath:} . Win32::GetShortPathName($_)
+            } @libpaths; 
+            # this is horribly sensitive to the order of arguments
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                ( map { "$_.lib" } @$libs ),
+                "/Fe$exefile", 
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
+                "/link",
+                (map {'/libpath:'.Win32::GetShortPathName($_)} @$paths),
+            );
+        } elsif($Config{cc} eq 'CC/DECC') {          # VMS
+        } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
+            @sys_cmd = (
+                @cc,
+                "-o$exefile",
+                (map { "-l$_" } @$libs ),
+                (map { "-I$_" } @incpaths),
+                (map { "-L$_" } @$paths),
+                $cfile);
+        } else {                                     # Unix-ish
+                                                     # gcc, Sun, AIX (gcc, cc)
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                "-o", "$exefile",
+                (map { "-l$_" } @$libs ),
+                (map { "-I$_" } @incpaths),
+                (map { "-L$_" } @$paths)
+            );
+        }
+        warn "# @sys_cmd\n" if $args{debug};
+        my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
+        push @missing, @$libs if $rv != 0 || ! -x $exefile;
+        push @wrongresult, @$libs if $rv == 0 && -x $exefile && system(File::Spec->rel2abs($exefile)) != 0; 
+        _cleanup_exe($exefile);
+    } 
+    unlink $cfile;
+
+    my $miss_string = join( q{, }, map { qq{'$_'} } @missing );
+    die("Can't link/include $miss_string\n") if @missing;
+    my $wrong_string = join( q{, }, map { qq{'$_'} } @wrongresult);
+    die("wrong result: $wrong_string\n") if @wrongresult;
+}
+
+sub _cleanup_exe {
+    my ($exefile) = @_;
+    my $ofile = $exefile;
+    $ofile =~ s/$Config{_exe}$/$Config{_o}/;
+    unlink $exefile if -f $exefile;
+    unlink $ofile if -f $ofile;
+    unlink "$exefile\.manifest" if -f "$exefile\.manifest";
+    return
+}
+    
+sub _findcc {
+    my @paths = split(/$Config{path_sep}/, $ENV{PATH});
+    my @cc = split(/\s+/, $Config{cc});
+    return @cc if -x $cc[0];
+    foreach my $path (@paths) {
+        my $compiler = File::Spec->catfile($path, $cc[0]) . $Config{_exe};
+        return ($compiler, @cc[1 .. $#cc]) if -x $compiler;
+    }
+    die("Couldn't find your C compiler\n");
+}
+
+# code substantially borrowed from IPC::Run3
+sub _quiet_system {
+    my (@cmd) = @_;
+
+    # save handles
+    local *STDOUT_SAVE;
+    local *STDERR_SAVE;
+    open STDOUT_SAVE, ">&STDOUT" or die "CheckLib: $! saving STDOUT";
+    open STDERR_SAVE, ">&STDERR" or die "CheckLib: $! saving STDERR";
+    
+    # redirect to nowhere
+    local *DEV_NULL;
+    open DEV_NULL, ">" . File::Spec->devnull 
+        or die "CheckLib: $! opening handle to null device";
+    open STDOUT, ">&" . fileno DEV_NULL
+        or die "CheckLib: $! redirecting STDOUT to null handle";
+    open STDERR, ">&" . fileno DEV_NULL
+        or die "CheckLib: $! redirecting STDERR to null handle";
+
+    # run system command
+    my $rv = system(@cmd);
+
+    # restore handles
+    open STDOUT, ">&" . fileno STDOUT_SAVE
+        or die "CheckLib: $! restoring STDOUT handle";
+    open STDERR, ">&" . fileno STDERR_SAVE
+        or die "CheckLib: $! restoring STDERR handle";
+
+    return $rv;
+}
+
+=head1 PLATFORMS SUPPORTED
+
+You must have a C compiler installed.  We check for C<$Config{cc}>,
+both literally as it is in Config.pm and also in the $PATH.
+
+It has been tested with varying degrees on rigourousness on:
+
+=over
+
+=item gcc (on Linux, *BSD, Mac OS X, Solaris, Cygwin)
+
+=item Sun's compiler tools on Solaris
+
+=item IBM's tools on AIX
+
+=item SGI's tools on Irix 6.5
+
+=item Microsoft's tools on Windows
+
+=item MinGW on Windows (with Strawberry Perl)
+
+=item Borland's tools on Windows
+
+=item QNX
+
+=back
+
+=head1 WARNINGS, BUGS and FEEDBACK
+
+This is a very early release intended primarily for feedback from
+people who have discussed it.  The interface may change and it has
+not been adequately tested.
+
+Feedback is most welcome, including constructive criticism.
+Bug reports should be made using L<http://rt.cpan.org/> or by email.
+
+When submitting a bug report, please include the output from running:
+
+    perl -V
+    perl -MDevel::CheckLib -e0
+
+=head1 SEE ALSO
+
+L<Devel::CheckOS>
+
+L<Probe::Perl>
+
+=head1 AUTHORS
+
+David Cantrell E<lt>david@cantrell.org.ukE<gt>
+
+David Golden E<lt>dagolden@cpan.orgE<gt>
+
+Thanks to the cpan-testers-discuss mailing list for prompting us to write it
+in the first place;
+
+to Chris Williams for help with Borland support.
+
+=head1 COPYRIGHT and LICENCE
+
+Copyright 2007 David Cantrell. Portions copyright 2007 David Golden.
+
+This module is free-as-in-speech software, and may be used, distributed,
+and modified under the same conditions as perl itself.
+
+=head1 CONSPIRACY
+
+This module is also free-as-in-mason software.
+
+=cut
+
+1;
diff --git a/T1/inc/Devel/CheckLib.pm b/T1/inc/Devel/CheckLib.pm
new file mode 100644 (file)
index 0000000..57cc8e6
--- /dev/null
@@ -0,0 +1,480 @@
+# $Id: CheckLib.pm,v 1.25 2008/10/27 12:16:23 drhyde Exp $
+
+package #
+Devel::CheckLib;
+
+use strict;
+use vars qw($VERSION @ISA @EXPORT);
+$VERSION = '0.699_002';
+use Config;
+
+use File::Spec;
+use File::Temp;
+
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(assert_lib check_lib_or_exit check_lib);
+
+# localising prevents the warningness leaking out of this module
+local $^W = 1;    # use warnings is a 5.6-ism
+
+_findcc(); # bomb out early if there's no compiler
+
+=head1 NAME
+
+Devel::CheckLib - check that a library is available
+
+=head1 DESCRIPTION
+
+Devel::CheckLib is a perl module that checks whether a particular C
+library and its headers are available.
+
+=head1 SYNOPSIS
+
+    use Devel::CheckLib;
+
+    check_lib_or_exit( lib => 'jpeg', header => 'jpeglib.h' );
+    check_lib_or_exit( lib => [ 'iconv', 'jpeg' ] );
+  
+    # or prompt for path to library and then do this:
+    check_lib_or_exit( lib => 'jpeg', libpath => $additional_path );
+
+=head1 USING IT IN Makefile.PL or Build.PL
+
+If you want to use this from Makefile.PL or Build.PL, do
+not simply copy the module into your distribution as this may cause
+problems when PAUSE and search.cpan.org index the distro.  Instead, use
+the use-devel-checklib script.
+
+=head1 HOW IT WORKS
+
+You pass named parameters to a function, describing to it how to build
+and link to the libraries.
+
+It works by trying to compile some code - which defaults to this:
+
+    int main(void) { return 0; }
+
+and linking it to the specified libraries.  If something pops out the end
+which looks executable, it gets executed, and if main() returns 0 we know
+that it worked.  That tiny program is
+built once for each library that you specify, and (without linking) once
+for each header file.
+
+If you want to check for the presence of particular functions in a
+library, or even that those functions return particular results, then
+you can pass your own function body for main() thus:
+
+    check_lib_or_exit(
+        function => 'foo();if(libversion() > 5) return 0; else return 1;'
+        incpath  => ...
+        libpath  => ...
+        lib      => ...
+        header   => ...
+    );
+
+In that case, it will fail to build if either foo() or libversion() don't
+exist, and main() will return the wrong value if libversion()'s return
+value isn't what you want.
+
+=head1 FUNCTIONS
+
+All of these take the same named parameters and are exported by default.
+To avoid exporting them, C<use Devel::CheckLib ()>.
+
+=head2 assert_lib
+
+This takes several named parameters, all of which are optional, and dies
+with an error message if any of the libraries listed can
+not be found.  B<Note>: dying in a Makefile.PL or Build.PL may provoke
+a 'FAIL' report from CPAN Testers' automated smoke testers.  Use 
+C<check_lib_or_exit> instead.
+
+The named parameters are:
+
+=over
+
+=item lib
+
+Must be either a string with the name of a single 
+library or a reference to an array of strings of library names.  Depending
+on the compiler found, library names will be fed to the compiler either as
+C<-l> arguments or as C<.lib> file names.  (E.g. C<-ljpeg> or C<jpeg.lib>)
+
+=item libpath
+
+a string or an array of strings
+representing additional paths to search for libraries.
+
+=item LIBS
+
+a C<ExtUtils::MakeMaker>-style space-seperated list of
+libraries (each preceded by '-l') and directories (preceded by '-L').
+
+This can also be supplied on the command-line.
+
+=back
+
+And libraries are no use without header files, so ...
+
+=over
+
+=item header
+
+Must be either a string with the name of a single 
+header file or a reference to an array of strings of header file names.
+
+=item incpath
+
+a string or an array of strings
+representing additional paths to search for headers.
+
+=item INC
+
+a C<ExtUtils::MakeMaker>-style space-seperated list of
+incpaths, each preceded by '-I'.
+
+This can also be supplied on the command-line.
+
+=back
+
+If you need to perform know more than "does it link?" you can provide
+code to be compiled and run:
+
+=over
+
+=item function
+
+the body of the <main()> function.  If not provided C<return 0;> is
+used.
+
+=item prologue
+
+code to insert between the C<#include> of the headers and the
+definition of main.
+
+=back
+
+=head2 check_lib_or_exit
+
+This behaves exactly the same as C<assert_lib()> except that instead of
+dieing, it warns (with exactly the same error message) and exits.
+This is intended for use in Makefile.PL / Build.PL
+when you might want to prompt the user for various paths and
+things before checking that what they've told you is sane.
+
+If any library or header is missing, it exits with an exit value of 0 to avoid
+causing a CPAN Testers 'FAIL' report.  CPAN Testers should ignore this
+result -- which is what you want if an external library dependency is not
+available.
+
+=head2 check_lib
+
+This behaves exactly the same as C<assert_lib()> except that it is silent,
+returning false instead of dieing, or true otherwise.
+
+=cut
+
+sub check_lib_or_exit {
+    eval 'assert_lib(@_)';
+    if($@) {
+        warn $@;
+        exit;
+    }
+}
+
+sub check_lib {
+    eval 'assert_lib(@_)';
+    return $@ ? 0 : 1;
+}
+
+sub assert_lib {
+    my %args = @_;
+    my (@libs, @libpaths, @headers, @incpaths);
+
+    # FIXME: these four just SCREAM "refactor" at me
+    @libs = (ref($args{lib}) ? @{$args{lib}} : $args{lib}) 
+        if $args{lib};
+    @libpaths = (ref($args{libpath}) ? @{$args{libpath}} : $args{libpath}) 
+        if $args{libpath};
+    @headers = (ref($args{header}) ? @{$args{header}} : $args{header}) 
+        if $args{header};
+    @incpaths = (ref($args{incpath}) ? @{$args{incpath}} : $args{incpath}) 
+        if $args{incpath};
+
+    # each entry is an arrayref containing:
+    # 0: arrayref of library search paths
+    # 1: arrayref of library names
+    my @link_cfgs = map [ \@libpaths, [ $_ ] ], @libs;
+
+    # work-a-like for Makefile.PL's LIBS and INC arguments
+    # if given as command-line argument, append to %args
+    for my $arg (@ARGV) {
+        for my $mm_attr_key qw(LIBS INC) {
+            if (my ($mm_attr_value) = $arg =~ /\A $mm_attr_key = (.*)/x) {
+            # it is tempting to put some \s* into the expression, but the
+            # MM command-line parser only accepts LIBS etc. followed by =,
+            # so we should not be any more lenient with whitespace than that
+                $args{$mm_attr_key} .= " $mm_attr_value";
+            }
+        }
+    }
+    # using special form of split to trim whitespace
+    if(defined($args{LIBS})) {
+        if (ref $args{LIBS}) {
+           foreach my $arg (@{$args{LIBS}}) {
+               my @sep = split ' ', $arg;
+               my @libs = map { /^-l(.+)$/ ? $1 : () } @sep;
+               my @paths = map { /^-L(.+)$/ ? $1 : () } @sep;
+               push @link_cfgs, [ \@paths, \@libs ];
+           }
+       }
+       else {
+           my @libs;
+           my @paths;
+           foreach my $arg (split(' ', $args{LIBS})) {
+               die("LIBS argument badly-formed: $arg\n") unless($arg =~ /^-l/i);
+               push @{$arg =~ /^-l/ ? \@libs : \@paths}, substr($arg, 2);
+           }
+           push @link_cfgs, map [ \@paths, [ $_ ] ], @libs;
+       }
+    }
+    if(defined($args{INC})) {
+        foreach my $arg (split(' ', $args{INC})) {
+            die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
+            push @incpaths, substr($arg, 2);
+        }
+    }
+
+    my @cc = _findcc();
+    my @missing;
+    my @wrongresult;
+
+    # first figure out which headers we can't find ...
+    my @use_headers;
+    for my $header (@headers) {
+        push @use_headers, $header;
+        my($ch, $cfile) = File::Temp::tempfile(
+            'assertlibXXXXXXXX', SUFFIX => '.c'
+        );
+        print $ch qq{#include <$_>\n} for @use_headers;
+        print $ch qq{int main(void) { return 0; }\n};
+        close($ch);
+        my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
+        my @sys_cmd;
+        # FIXME: re-factor - almost identical code later when linking
+        if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
+            require Win32;
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                "/Fe$exefile",
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths)
+            );
+        } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
+            @sys_cmd = (
+                @cc,
+                (map { "-I$_" } @incpaths),
+                "-o$exefile",
+                $cfile
+            );
+        } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                (map { "-I$_" } @incpaths),
+                "-o", "$exefile"
+            );
+        }
+        warn "# @sys_cmd\n" if $args{debug};
+        my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
+        push @missing, $header if $rv != 0 || ! -x $exefile; 
+        _cleanup_exe($exefile);
+        unlink $cfile;
+    } 
+
+    # now do each library in turn with headers
+    my($ch, $cfile) = File::Temp::tempfile(
+        'assertlibXXXXXXXX', SUFFIX => '.c'
+    );
+    print $ch qq{#include <$_>\n} foreach (@headers);
+    print $ch "\n$args{prologue}\n" if $args{prologue};
+    print $ch "int main(void) { ".($args{function} || 'return 0;')." }\n";
+    close($ch);
+    for my $link_cfg ( @link_cfgs ) {
+       my ($paths, $libs) = @$link_cfg;
+        my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
+        my @sys_cmd;
+        if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
+            require Win32;
+            my @libpath = map { 
+                q{/libpath:} . Win32::GetShortPathName($_)
+            } @libpaths; 
+            # this is horribly sensitive to the order of arguments
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                ( map { "$_.lib" } @$libs ),
+                "/Fe$exefile", 
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
+                "/link",
+                (map {'/libpath:'.Win32::GetShortPathName($_)} @$paths),
+            );
+        } elsif($Config{cc} eq 'CC/DECC') {          # VMS
+        } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
+            @sys_cmd = (
+                @cc,
+                "-o$exefile",
+                (map { "-l$_" } @$libs ),
+                (map { "-I$_" } @incpaths),
+                (map { "-L$_" } @$paths),
+                $cfile);
+        } else {                                     # Unix-ish
+                                                     # gcc, Sun, AIX (gcc, cc)
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                "-o", "$exefile",
+                (map { "-l$_" } @$libs ),
+                (map { "-I$_" } @incpaths),
+                (map { "-L$_" } @$paths)
+            );
+        }
+        warn "# @sys_cmd\n" if $args{debug};
+        my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
+        push @missing, @$libs if $rv != 0 || ! -x $exefile;
+        push @wrongresult, @$libs if $rv == 0 && -x $exefile && system(File::Spec->rel2abs($exefile)) != 0; 
+        _cleanup_exe($exefile);
+    } 
+    unlink $cfile;
+
+    my $miss_string = join( q{, }, map { qq{'$_'} } @missing );
+    die("Can't link/include $miss_string\n") if @missing;
+    my $wrong_string = join( q{, }, map { qq{'$_'} } @wrongresult);
+    die("wrong result: $wrong_string\n") if @wrongresult;
+}
+
+sub _cleanup_exe {
+    my ($exefile) = @_;
+    my $ofile = $exefile;
+    $ofile =~ s/$Config{_exe}$/$Config{_o}/;
+    unlink $exefile if -f $exefile;
+    unlink $ofile if -f $ofile;
+    unlink "$exefile\.manifest" if -f "$exefile\.manifest";
+    return
+}
+    
+sub _findcc {
+    my @paths = split(/$Config{path_sep}/, $ENV{PATH});
+    my @cc = split(/\s+/, $Config{cc});
+    return @cc if -x $cc[0];
+    foreach my $path (@paths) {
+        my $compiler = File::Spec->catfile($path, $cc[0]) . $Config{_exe};
+        return ($compiler, @cc[1 .. $#cc]) if -x $compiler;
+    }
+    die("Couldn't find your C compiler\n");
+}
+
+# code substantially borrowed from IPC::Run3
+sub _quiet_system {
+    my (@cmd) = @_;
+
+    # save handles
+    local *STDOUT_SAVE;
+    local *STDERR_SAVE;
+    open STDOUT_SAVE, ">&STDOUT" or die "CheckLib: $! saving STDOUT";
+    open STDERR_SAVE, ">&STDERR" or die "CheckLib: $! saving STDERR";
+    
+    # redirect to nowhere
+    local *DEV_NULL;
+    open DEV_NULL, ">" . File::Spec->devnull 
+        or die "CheckLib: $! opening handle to null device";
+    open STDOUT, ">&" . fileno DEV_NULL
+        or die "CheckLib: $! redirecting STDOUT to null handle";
+    open STDERR, ">&" . fileno DEV_NULL
+        or die "CheckLib: $! redirecting STDERR to null handle";
+
+    # run system command
+    my $rv = system(@cmd);
+
+    # restore handles
+    open STDOUT, ">&" . fileno STDOUT_SAVE
+        or die "CheckLib: $! restoring STDOUT handle";
+    open STDERR, ">&" . fileno STDERR_SAVE
+        or die "CheckLib: $! restoring STDERR handle";
+
+    return $rv;
+}
+
+=head1 PLATFORMS SUPPORTED
+
+You must have a C compiler installed.  We check for C<$Config{cc}>,
+both literally as it is in Config.pm and also in the $PATH.
+
+It has been tested with varying degrees on rigourousness on:
+
+=over
+
+=item gcc (on Linux, *BSD, Mac OS X, Solaris, Cygwin)
+
+=item Sun's compiler tools on Solaris
+
+=item IBM's tools on AIX
+
+=item SGI's tools on Irix 6.5
+
+=item Microsoft's tools on Windows
+
+=item MinGW on Windows (with Strawberry Perl)
+
+=item Borland's tools on Windows
+
+=item QNX
+
+=back
+
+=head1 WARNINGS, BUGS and FEEDBACK
+
+This is a very early release intended primarily for feedback from
+people who have discussed it.  The interface may change and it has
+not been adequately tested.
+
+Feedback is most welcome, including constructive criticism.
+Bug reports should be made using L<http://rt.cpan.org/> or by email.
+
+When submitting a bug report, please include the output from running:
+
+    perl -V
+    perl -MDevel::CheckLib -e0
+
+=head1 SEE ALSO
+
+L<Devel::CheckOS>
+
+L<Probe::Perl>
+
+=head1 AUTHORS
+
+David Cantrell E<lt>david@cantrell.org.ukE<gt>
+
+David Golden E<lt>dagolden@cpan.orgE<gt>
+
+Thanks to the cpan-testers-discuss mailing list for prompting us to write it
+in the first place;
+
+to Chris Williams for help with Borland support.
+
+=head1 COPYRIGHT and LICENCE
+
+Copyright 2007 David Cantrell. Portions copyright 2007 David Golden.
+
+This module is free-as-in-speech software, and may be used, distributed,
+and modified under the same conditions as perl itself.
+
+=head1 CONSPIRACY
+
+This module is also free-as-in-mason software.
+
+=cut
+
+1;
diff --git a/TIFF/inc/Devel/CheckLib.pm b/TIFF/inc/Devel/CheckLib.pm
new file mode 100644 (file)
index 0000000..57cc8e6
--- /dev/null
@@ -0,0 +1,480 @@
+# $Id: CheckLib.pm,v 1.25 2008/10/27 12:16:23 drhyde Exp $
+
+package #
+Devel::CheckLib;
+
+use strict;
+use vars qw($VERSION @ISA @EXPORT);
+$VERSION = '0.699_002';
+use Config;
+
+use File::Spec;
+use File::Temp;
+
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(assert_lib check_lib_or_exit check_lib);
+
+# localising prevents the warningness leaking out of this module
+local $^W = 1;    # use warnings is a 5.6-ism
+
+_findcc(); # bomb out early if there's no compiler
+
+=head1 NAME
+
+Devel::CheckLib - check that a library is available
+
+=head1 DESCRIPTION
+
+Devel::CheckLib is a perl module that checks whether a particular C
+library and its headers are available.
+
+=head1 SYNOPSIS
+
+    use Devel::CheckLib;
+
+    check_lib_or_exit( lib => 'jpeg', header => 'jpeglib.h' );
+    check_lib_or_exit( lib => [ 'iconv', 'jpeg' ] );
+  
+    # or prompt for path to library and then do this:
+    check_lib_or_exit( lib => 'jpeg', libpath => $additional_path );
+
+=head1 USING IT IN Makefile.PL or Build.PL
+
+If you want to use this from Makefile.PL or Build.PL, do
+not simply copy the module into your distribution as this may cause
+problems when PAUSE and search.cpan.org index the distro.  Instead, use
+the use-devel-checklib script.
+
+=head1 HOW IT WORKS
+
+You pass named parameters to a function, describing to it how to build
+and link to the libraries.
+
+It works by trying to compile some code - which defaults to this:
+
+    int main(void) { return 0; }
+
+and linking it to the specified libraries.  If something pops out the end
+which looks executable, it gets executed, and if main() returns 0 we know
+that it worked.  That tiny program is
+built once for each library that you specify, and (without linking) once
+for each header file.
+
+If you want to check for the presence of particular functions in a
+library, or even that those functions return particular results, then
+you can pass your own function body for main() thus:
+
+    check_lib_or_exit(
+        function => 'foo();if(libversion() > 5) return 0; else return 1;'
+        incpath  => ...
+        libpath  => ...
+        lib      => ...
+        header   => ...
+    );
+
+In that case, it will fail to build if either foo() or libversion() don't
+exist, and main() will return the wrong value if libversion()'s return
+value isn't what you want.
+
+=head1 FUNCTIONS
+
+All of these take the same named parameters and are exported by default.
+To avoid exporting them, C<use Devel::CheckLib ()>.
+
+=head2 assert_lib
+
+This takes several named parameters, all of which are optional, and dies
+with an error message if any of the libraries listed can
+not be found.  B<Note>: dying in a Makefile.PL or Build.PL may provoke
+a 'FAIL' report from CPAN Testers' automated smoke testers.  Use 
+C<check_lib_or_exit> instead.
+
+The named parameters are:
+
+=over
+
+=item lib
+
+Must be either a string with the name of a single 
+library or a reference to an array of strings of library names.  Depending
+on the compiler found, library names will be fed to the compiler either as
+C<-l> arguments or as C<.lib> file names.  (E.g. C<-ljpeg> or C<jpeg.lib>)
+
+=item libpath
+
+a string or an array of strings
+representing additional paths to search for libraries.
+
+=item LIBS
+
+a C<ExtUtils::MakeMaker>-style space-seperated list of
+libraries (each preceded by '-l') and directories (preceded by '-L').
+
+This can also be supplied on the command-line.
+
+=back
+
+And libraries are no use without header files, so ...
+
+=over
+
+=item header
+
+Must be either a string with the name of a single 
+header file or a reference to an array of strings of header file names.
+
+=item incpath
+
+a string or an array of strings
+representing additional paths to search for headers.
+
+=item INC
+
+a C<ExtUtils::MakeMaker>-style space-seperated list of
+incpaths, each preceded by '-I'.
+
+This can also be supplied on the command-line.
+
+=back
+
+If you need to perform know more than "does it link?" you can provide
+code to be compiled and run:
+
+=over
+
+=item function
+
+the body of the <main()> function.  If not provided C<return 0;> is
+used.
+
+=item prologue
+
+code to insert between the C<#include> of the headers and the
+definition of main.
+
+=back
+
+=head2 check_lib_or_exit
+
+This behaves exactly the same as C<assert_lib()> except that instead of
+dieing, it warns (with exactly the same error message) and exits.
+This is intended for use in Makefile.PL / Build.PL
+when you might want to prompt the user for various paths and
+things before checking that what they've told you is sane.
+
+If any library or header is missing, it exits with an exit value of 0 to avoid
+causing a CPAN Testers 'FAIL' report.  CPAN Testers should ignore this
+result -- which is what you want if an external library dependency is not
+available.
+
+=head2 check_lib
+
+This behaves exactly the same as C<assert_lib()> except that it is silent,
+returning false instead of dieing, or true otherwise.
+
+=cut
+
+sub check_lib_or_exit {
+    eval 'assert_lib(@_)';
+    if($@) {
+        warn $@;
+        exit;
+    }
+}
+
+sub check_lib {
+    eval 'assert_lib(@_)';
+    return $@ ? 0 : 1;
+}
+
+sub assert_lib {
+    my %args = @_;
+    my (@libs, @libpaths, @headers, @incpaths);
+
+    # FIXME: these four just SCREAM "refactor" at me
+    @libs = (ref($args{lib}) ? @{$args{lib}} : $args{lib}) 
+        if $args{lib};
+    @libpaths = (ref($args{libpath}) ? @{$args{libpath}} : $args{libpath}) 
+        if $args{libpath};
+    @headers = (ref($args{header}) ? @{$args{header}} : $args{header}) 
+        if $args{header};
+    @incpaths = (ref($args{incpath}) ? @{$args{incpath}} : $args{incpath}) 
+        if $args{incpath};
+
+    # each entry is an arrayref containing:
+    # 0: arrayref of library search paths
+    # 1: arrayref of library names
+    my @link_cfgs = map [ \@libpaths, [ $_ ] ], @libs;
+
+    # work-a-like for Makefile.PL's LIBS and INC arguments
+    # if given as command-line argument, append to %args
+    for my $arg (@ARGV) {
+        for my $mm_attr_key qw(LIBS INC) {
+            if (my ($mm_attr_value) = $arg =~ /\A $mm_attr_key = (.*)/x) {
+            # it is tempting to put some \s* into the expression, but the
+            # MM command-line parser only accepts LIBS etc. followed by =,
+            # so we should not be any more lenient with whitespace than that
+                $args{$mm_attr_key} .= " $mm_attr_value";
+            }
+        }
+    }
+    # using special form of split to trim whitespace
+    if(defined($args{LIBS})) {
+        if (ref $args{LIBS}) {
+           foreach my $arg (@{$args{LIBS}}) {
+               my @sep = split ' ', $arg;
+               my @libs = map { /^-l(.+)$/ ? $1 : () } @sep;
+               my @paths = map { /^-L(.+)$/ ? $1 : () } @sep;
+               push @link_cfgs, [ \@paths, \@libs ];
+           }
+       }
+       else {
+           my @libs;
+           my @paths;
+           foreach my $arg (split(' ', $args{LIBS})) {
+               die("LIBS argument badly-formed: $arg\n") unless($arg =~ /^-l/i);
+               push @{$arg =~ /^-l/ ? \@libs : \@paths}, substr($arg, 2);
+           }
+           push @link_cfgs, map [ \@paths, [ $_ ] ], @libs;
+       }
+    }
+    if(defined($args{INC})) {
+        foreach my $arg (split(' ', $args{INC})) {
+            die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
+            push @incpaths, substr($arg, 2);
+        }
+    }
+
+    my @cc = _findcc();
+    my @missing;
+    my @wrongresult;
+
+    # first figure out which headers we can't find ...
+    my @use_headers;
+    for my $header (@headers) {
+        push @use_headers, $header;
+        my($ch, $cfile) = File::Temp::tempfile(
+            'assertlibXXXXXXXX', SUFFIX => '.c'
+        );
+        print $ch qq{#include <$_>\n} for @use_headers;
+        print $ch qq{int main(void) { return 0; }\n};
+        close($ch);
+        my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
+        my @sys_cmd;
+        # FIXME: re-factor - almost identical code later when linking
+        if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
+            require Win32;
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                "/Fe$exefile",
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths)
+            );
+        } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
+            @sys_cmd = (
+                @cc,
+                (map { "-I$_" } @incpaths),
+                "-o$exefile",
+                $cfile
+            );
+        } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                (map { "-I$_" } @incpaths),
+                "-o", "$exefile"
+            );
+        }
+        warn "# @sys_cmd\n" if $args{debug};
+        my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
+        push @missing, $header if $rv != 0 || ! -x $exefile; 
+        _cleanup_exe($exefile);
+        unlink $cfile;
+    } 
+
+    # now do each library in turn with headers
+    my($ch, $cfile) = File::Temp::tempfile(
+        'assertlibXXXXXXXX', SUFFIX => '.c'
+    );
+    print $ch qq{#include <$_>\n} foreach (@headers);
+    print $ch "\n$args{prologue}\n" if $args{prologue};
+    print $ch "int main(void) { ".($args{function} || 'return 0;')." }\n";
+    close($ch);
+    for my $link_cfg ( @link_cfgs ) {
+       my ($paths, $libs) = @$link_cfg;
+        my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
+        my @sys_cmd;
+        if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
+            require Win32;
+            my @libpath = map { 
+                q{/libpath:} . Win32::GetShortPathName($_)
+            } @libpaths; 
+            # this is horribly sensitive to the order of arguments
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                ( map { "$_.lib" } @$libs ),
+                "/Fe$exefile", 
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
+                "/link",
+                (map {'/libpath:'.Win32::GetShortPathName($_)} @$paths),
+            );
+        } elsif($Config{cc} eq 'CC/DECC') {          # VMS
+        } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
+            @sys_cmd = (
+                @cc,
+                "-o$exefile",
+                (map { "-l$_" } @$libs ),
+                (map { "-I$_" } @incpaths),
+                (map { "-L$_" } @$paths),
+                $cfile);
+        } else {                                     # Unix-ish
+                                                     # gcc, Sun, AIX (gcc, cc)
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                "-o", "$exefile",
+                (map { "-l$_" } @$libs ),
+                (map { "-I$_" } @incpaths),
+                (map { "-L$_" } @$paths)
+            );
+        }
+        warn "# @sys_cmd\n" if $args{debug};
+        my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
+        push @missing, @$libs if $rv != 0 || ! -x $exefile;
+        push @wrongresult, @$libs if $rv == 0 && -x $exefile && system(File::Spec->rel2abs($exefile)) != 0; 
+        _cleanup_exe($exefile);
+    } 
+    unlink $cfile;
+
+    my $miss_string = join( q{, }, map { qq{'$_'} } @missing );
+    die("Can't link/include $miss_string\n") if @missing;
+    my $wrong_string = join( q{, }, map { qq{'$_'} } @wrongresult);
+    die("wrong result: $wrong_string\n") if @wrongresult;
+}
+
+sub _cleanup_exe {
+    my ($exefile) = @_;
+    my $ofile = $exefile;
+    $ofile =~ s/$Config{_exe}$/$Config{_o}/;
+    unlink $exefile if -f $exefile;
+    unlink $ofile if -f $ofile;
+    unlink "$exefile\.manifest" if -f "$exefile\.manifest";
+    return
+}
+    
+sub _findcc {
+    my @paths = split(/$Config{path_sep}/, $ENV{PATH});
+    my @cc = split(/\s+/, $Config{cc});
+    return @cc if -x $cc[0];
+    foreach my $path (@paths) {
+        my $compiler = File::Spec->catfile($path, $cc[0]) . $Config{_exe};
+        return ($compiler, @cc[1 .. $#cc]) if -x $compiler;
+    }
+    die("Couldn't find your C compiler\n");
+}
+
+# code substantially borrowed from IPC::Run3
+sub _quiet_system {
+    my (@cmd) = @_;
+
+    # save handles
+    local *STDOUT_SAVE;
+    local *STDERR_SAVE;
+    open STDOUT_SAVE, ">&STDOUT" or die "CheckLib: $! saving STDOUT";
+    open STDERR_SAVE, ">&STDERR" or die "CheckLib: $! saving STDERR";
+    
+    # redirect to nowhere
+    local *DEV_NULL;
+    open DEV_NULL, ">" . File::Spec->devnull 
+        or die "CheckLib: $! opening handle to null device";
+    open STDOUT, ">&" . fileno DEV_NULL
+        or die "CheckLib: $! redirecting STDOUT to null handle";
+    open STDERR, ">&" . fileno DEV_NULL
+        or die "CheckLib: $! redirecting STDERR to null handle";
+
+    # run system command
+    my $rv = system(@cmd);
+
+    # restore handles
+    open STDOUT, ">&" . fileno STDOUT_SAVE
+        or die "CheckLib: $! restoring STDOUT handle";
+    open STDERR, ">&" . fileno STDERR_SAVE
+        or die "CheckLib: $! restoring STDERR handle";
+
+    return $rv;
+}
+
+=head1 PLATFORMS SUPPORTED
+
+You must have a C compiler installed.  We check for C<$Config{cc}>,
+both literally as it is in Config.pm and also in the $PATH.
+
+It has been tested with varying degrees on rigourousness on:
+
+=over
+
+=item gcc (on Linux, *BSD, Mac OS X, Solaris, Cygwin)
+
+=item Sun's compiler tools on Solaris
+
+=item IBM's tools on AIX
+
+=item SGI's tools on Irix 6.5
+
+=item Microsoft's tools on Windows
+
+=item MinGW on Windows (with Strawberry Perl)
+
+=item Borland's tools on Windows
+
+=item QNX
+
+=back
+
+=head1 WARNINGS, BUGS and FEEDBACK
+
+This is a very early release intended primarily for feedback from
+people who have discussed it.  The interface may change and it has
+not been adequately tested.
+
+Feedback is most welcome, including constructive criticism.
+Bug reports should be made using L<http://rt.cpan.org/> or by email.
+
+When submitting a bug report, please include the output from running:
+
+    perl -V
+    perl -MDevel::CheckLib -e0
+
+=head1 SEE ALSO
+
+L<Devel::CheckOS>
+
+L<Probe::Perl>
+
+=head1 AUTHORS
+
+David Cantrell E<lt>david@cantrell.org.ukE<gt>
+
+David Golden E<lt>dagolden@cpan.orgE<gt>
+
+Thanks to the cpan-testers-discuss mailing list for prompting us to write it
+in the first place;
+
+to Chris Williams for help with Borland support.
+
+=head1 COPYRIGHT and LICENCE
+
+Copyright 2007 David Cantrell. Portions copyright 2007 David Golden.
+
+This module is free-as-in-speech software, and may be used, distributed,
+and modified under the same conditions as perl itself.
+
+=head1 CONSPIRACY
+
+This module is also free-as-in-mason software.
+
+=cut
+
+1;
diff --git a/W32/inc/Devel/CheckLib.pm b/W32/inc/Devel/CheckLib.pm
new file mode 100644 (file)
index 0000000..57cc8e6
--- /dev/null
@@ -0,0 +1,480 @@
+# $Id: CheckLib.pm,v 1.25 2008/10/27 12:16:23 drhyde Exp $
+
+package #
+Devel::CheckLib;
+
+use strict;
+use vars qw($VERSION @ISA @EXPORT);
+$VERSION = '0.699_002';
+use Config;
+
+use File::Spec;
+use File::Temp;
+
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(assert_lib check_lib_or_exit check_lib);
+
+# localising prevents the warningness leaking out of this module
+local $^W = 1;    # use warnings is a 5.6-ism
+
+_findcc(); # bomb out early if there's no compiler
+
+=head1 NAME
+
+Devel::CheckLib - check that a library is available
+
+=head1 DESCRIPTION
+
+Devel::CheckLib is a perl module that checks whether a particular C
+library and its headers are available.
+
+=head1 SYNOPSIS
+
+    use Devel::CheckLib;
+
+    check_lib_or_exit( lib => 'jpeg', header => 'jpeglib.h' );
+    check_lib_or_exit( lib => [ 'iconv', 'jpeg' ] );
+  
+    # or prompt for path to library and then do this:
+    check_lib_or_exit( lib => 'jpeg', libpath => $additional_path );
+
+=head1 USING IT IN Makefile.PL or Build.PL
+
+If you want to use this from Makefile.PL or Build.PL, do
+not simply copy the module into your distribution as this may cause
+problems when PAUSE and search.cpan.org index the distro.  Instead, use
+the use-devel-checklib script.
+
+=head1 HOW IT WORKS
+
+You pass named parameters to a function, describing to it how to build
+and link to the libraries.
+
+It works by trying to compile some code - which defaults to this:
+
+    int main(void) { return 0; }
+
+and linking it to the specified libraries.  If something pops out the end
+which looks executable, it gets executed, and if main() returns 0 we know
+that it worked.  That tiny program is
+built once for each library that you specify, and (without linking) once
+for each header file.
+
+If you want to check for the presence of particular functions in a
+library, or even that those functions return particular results, then
+you can pass your own function body for main() thus:
+
+    check_lib_or_exit(
+        function => 'foo();if(libversion() > 5) return 0; else return 1;'
+        incpath  => ...
+        libpath  => ...
+        lib      => ...
+        header   => ...
+    );
+
+In that case, it will fail to build if either foo() or libversion() don't
+exist, and main() will return the wrong value if libversion()'s return
+value isn't what you want.
+
+=head1 FUNCTIONS
+
+All of these take the same named parameters and are exported by default.
+To avoid exporting them, C<use Devel::CheckLib ()>.
+
+=head2 assert_lib
+
+This takes several named parameters, all of which are optional, and dies
+with an error message if any of the libraries listed can
+not be found.  B<Note>: dying in a Makefile.PL or Build.PL may provoke
+a 'FAIL' report from CPAN Testers' automated smoke testers.  Use 
+C<check_lib_or_exit> instead.
+
+The named parameters are:
+
+=over
+
+=item lib
+
+Must be either a string with the name of a single 
+library or a reference to an array of strings of library names.  Depending
+on the compiler found, library names will be fed to the compiler either as
+C<-l> arguments or as C<.lib> file names.  (E.g. C<-ljpeg> or C<jpeg.lib>)
+
+=item libpath
+
+a string or an array of strings
+representing additional paths to search for libraries.
+
+=item LIBS
+
+a C<ExtUtils::MakeMaker>-style space-seperated list of
+libraries (each preceded by '-l') and directories (preceded by '-L').
+
+This can also be supplied on the command-line.
+
+=back
+
+And libraries are no use without header files, so ...
+
+=over
+
+=item header
+
+Must be either a string with the name of a single 
+header file or a reference to an array of strings of header file names.
+
+=item incpath
+
+a string or an array of strings
+representing additional paths to search for headers.
+
+=item INC
+
+a C<ExtUtils::MakeMaker>-style space-seperated list of
+incpaths, each preceded by '-I'.
+
+This can also be supplied on the command-line.
+
+=back
+
+If you need to perform know more than "does it link?" you can provide
+code to be compiled and run:
+
+=over
+
+=item function
+
+the body of the <main()> function.  If not provided C<return 0;> is
+used.
+
+=item prologue
+
+code to insert between the C<#include> of the headers and the
+definition of main.
+
+=back
+
+=head2 check_lib_or_exit
+
+This behaves exactly the same as C<assert_lib()> except that instead of
+dieing, it warns (with exactly the same error message) and exits.
+This is intended for use in Makefile.PL / Build.PL
+when you might want to prompt the user for various paths and
+things before checking that what they've told you is sane.
+
+If any library or header is missing, it exits with an exit value of 0 to avoid
+causing a CPAN Testers 'FAIL' report.  CPAN Testers should ignore this
+result -- which is what you want if an external library dependency is not
+available.
+
+=head2 check_lib
+
+This behaves exactly the same as C<assert_lib()> except that it is silent,
+returning false instead of dieing, or true otherwise.
+
+=cut
+
+sub check_lib_or_exit {
+    eval 'assert_lib(@_)';
+    if($@) {
+        warn $@;
+        exit;
+    }
+}
+
+sub check_lib {
+    eval 'assert_lib(@_)';
+    return $@ ? 0 : 1;
+}
+
+sub assert_lib {
+    my %args = @_;
+    my (@libs, @libpaths, @headers, @incpaths);
+
+    # FIXME: these four just SCREAM "refactor" at me
+    @libs = (ref($args{lib}) ? @{$args{lib}} : $args{lib}) 
+        if $args{lib};
+    @libpaths = (ref($args{libpath}) ? @{$args{libpath}} : $args{libpath}) 
+        if $args{libpath};
+    @headers = (ref($args{header}) ? @{$args{header}} : $args{header}) 
+        if $args{header};
+    @incpaths = (ref($args{incpath}) ? @{$args{incpath}} : $args{incpath}) 
+        if $args{incpath};
+
+    # each entry is an arrayref containing:
+    # 0: arrayref of library search paths
+    # 1: arrayref of library names
+    my @link_cfgs = map [ \@libpaths, [ $_ ] ], @libs;
+
+    # work-a-like for Makefile.PL's LIBS and INC arguments
+    # if given as command-line argument, append to %args
+    for my $arg (@ARGV) {
+        for my $mm_attr_key qw(LIBS INC) {
+            if (my ($mm_attr_value) = $arg =~ /\A $mm_attr_key = (.*)/x) {
+            # it is tempting to put some \s* into the expression, but the
+            # MM command-line parser only accepts LIBS etc. followed by =,
+            # so we should not be any more lenient with whitespace than that
+                $args{$mm_attr_key} .= " $mm_attr_value";
+            }
+        }
+    }
+    # using special form of split to trim whitespace
+    if(defined($args{LIBS})) {
+        if (ref $args{LIBS}) {
+           foreach my $arg (@{$args{LIBS}}) {
+               my @sep = split ' ', $arg;
+               my @libs = map { /^-l(.+)$/ ? $1 : () } @sep;
+               my @paths = map { /^-L(.+)$/ ? $1 : () } @sep;
+               push @link_cfgs, [ \@paths, \@libs ];
+           }
+       }
+       else {
+           my @libs;
+           my @paths;
+           foreach my $arg (split(' ', $args{LIBS})) {
+               die("LIBS argument badly-formed: $arg\n") unless($arg =~ /^-l/i);
+               push @{$arg =~ /^-l/ ? \@libs : \@paths}, substr($arg, 2);
+           }
+           push @link_cfgs, map [ \@paths, [ $_ ] ], @libs;
+       }
+    }
+    if(defined($args{INC})) {
+        foreach my $arg (split(' ', $args{INC})) {
+            die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
+            push @incpaths, substr($arg, 2);
+        }
+    }
+
+    my @cc = _findcc();
+    my @missing;
+    my @wrongresult;
+
+    # first figure out which headers we can't find ...
+    my @use_headers;
+    for my $header (@headers) {
+        push @use_headers, $header;
+        my($ch, $cfile) = File::Temp::tempfile(
+            'assertlibXXXXXXXX', SUFFIX => '.c'
+        );
+        print $ch qq{#include <$_>\n} for @use_headers;
+        print $ch qq{int main(void) { return 0; }\n};
+        close($ch);
+        my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
+        my @sys_cmd;
+        # FIXME: re-factor - almost identical code later when linking
+        if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
+            require Win32;
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                "/Fe$exefile",
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths)
+            );
+        } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
+            @sys_cmd = (
+                @cc,
+                (map { "-I$_" } @incpaths),
+                "-o$exefile",
+                $cfile
+            );
+        } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                (map { "-I$_" } @incpaths),
+                "-o", "$exefile"
+            );
+        }
+        warn "# @sys_cmd\n" if $args{debug};
+        my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
+        push @missing, $header if $rv != 0 || ! -x $exefile; 
+        _cleanup_exe($exefile);
+        unlink $cfile;
+    } 
+
+    # now do each library in turn with headers
+    my($ch, $cfile) = File::Temp::tempfile(
+        'assertlibXXXXXXXX', SUFFIX => '.c'
+    );
+    print $ch qq{#include <$_>\n} foreach (@headers);
+    print $ch "\n$args{prologue}\n" if $args{prologue};
+    print $ch "int main(void) { ".($args{function} || 'return 0;')." }\n";
+    close($ch);
+    for my $link_cfg ( @link_cfgs ) {
+       my ($paths, $libs) = @$link_cfg;
+        my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
+        my @sys_cmd;
+        if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
+            require Win32;
+            my @libpath = map { 
+                q{/libpath:} . Win32::GetShortPathName($_)
+            } @libpaths; 
+            # this is horribly sensitive to the order of arguments
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                ( map { "$_.lib" } @$libs ),
+                "/Fe$exefile", 
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
+                "/link",
+                (map {'/libpath:'.Win32::GetShortPathName($_)} @$paths),
+            );
+        } elsif($Config{cc} eq 'CC/DECC') {          # VMS
+        } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
+            @sys_cmd = (
+                @cc,
+                "-o$exefile",
+                (map { "-l$_" } @$libs ),
+                (map { "-I$_" } @incpaths),
+                (map { "-L$_" } @$paths),
+                $cfile);
+        } else {                                     # Unix-ish
+                                                     # gcc, Sun, AIX (gcc, cc)
+            @sys_cmd = (
+                @cc,
+                $cfile,
+                "-o", "$exefile",
+                (map { "-l$_" } @$libs ),
+                (map { "-I$_" } @incpaths),
+                (map { "-L$_" } @$paths)
+            );
+        }
+        warn "# @sys_cmd\n" if $args{debug};
+        my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
+        push @missing, @$libs if $rv != 0 || ! -x $exefile;
+        push @wrongresult, @$libs if $rv == 0 && -x $exefile && system(File::Spec->rel2abs($exefile)) != 0; 
+        _cleanup_exe($exefile);
+    } 
+    unlink $cfile;
+
+    my $miss_string = join( q{, }, map { qq{'$_'} } @missing );
+    die("Can't link/include $miss_string\n") if @missing;
+    my $wrong_string = join( q{, }, map { qq{'$_'} } @wrongresult);
+    die("wrong result: $wrong_string\n") if @wrongresult;
+}
+
+sub _cleanup_exe {
+    my ($exefile) = @_;
+    my $ofile = $exefile;
+    $ofile =~ s/$Config{_exe}$/$Config{_o}/;
+    unlink $exefile if -f $exefile;
+    unlink $ofile if -f $ofile;
+    unlink "$exefile\.manifest" if -f "$exefile\.manifest";
+    return
+}
+    
+sub _findcc {
+    my @paths = split(/$Config{path_sep}/, $ENV{PATH});
+    my @cc = split(/\s+/, $Config{cc});
+    return @cc if -x $cc[0];
+    foreach my $path (@paths) {
+        my $compiler = File::Spec->catfile($path, $cc[0]) . $Config{_exe};
+        return ($compiler, @cc[1 .. $#cc]) if -x $compiler;
+    }
+    die("Couldn't find your C compiler\n");
+}
+
+# code substantially borrowed from IPC::Run3
+sub _quiet_system {
+    my (@cmd) = @_;
+
+    # save handles
+    local *STDOUT_SAVE;
+    local *STDERR_SAVE;
+    open STDOUT_SAVE, ">&STDOUT" or die "CheckLib: $! saving STDOUT";
+    open STDERR_SAVE, ">&STDERR" or die "CheckLib: $! saving STDERR";
+    
+    # redirect to nowhere
+    local *DEV_NULL;
+    open DEV_NULL, ">" . File::Spec->devnull 
+        or die "CheckLib: $! opening handle to null device";
+    open STDOUT, ">&" . fileno DEV_NULL
+        or die "CheckLib: $! redirecting STDOUT to null handle";
+    open STDERR, ">&" . fileno DEV_NULL
+        or die "CheckLib: $! redirecting STDERR to null handle";
+
+    # run system command
+    my $rv = system(@cmd);
+
+    # restore handles
+    open STDOUT, ">&" . fileno STDOUT_SAVE
+        or die "CheckLib: $! restoring STDOUT handle";
+    open STDERR, ">&" . fileno STDERR_SAVE
+        or die "CheckLib: $! restoring STDERR handle";
+
+    return $rv;
+}
+
+=head1 PLATFORMS SUPPORTED
+
+You must have a C compiler installed.  We check for C<$Config{cc}>,
+both literally as it is in Config.pm and also in the $PATH.
+
+It has been tested with varying degrees on rigourousness on:
+
+=over
+
+=item gcc (on Linux, *BSD, Mac OS X, Solaris, Cygwin)
+
+=item Sun's compiler tools on Solaris
+
+=item IBM's tools on AIX
+
+=item SGI's tools on Irix 6.5
+
+=item Microsoft's tools on Windows
+
+=item MinGW on Windows (with Strawberry Perl)
+
+=item Borland's tools on Windows
+
+=item QNX
+
+=back
+
+=head1 WARNINGS, BUGS and FEEDBACK
+
+This is a very early release intended primarily for feedback from
+people who have discussed it.  The interface may change and it has
+not been adequately tested.
+
+Feedback is most welcome, including constructive criticism.
+Bug reports should be made using L<http://rt.cpan.org/> or by email.
+
+When submitting a bug report, please include the output from running:
+
+    perl -V
+    perl -MDevel::CheckLib -e0
+
+=head1 SEE ALSO
+
+L<Devel::CheckOS>
+
+L<Probe::Perl>
+
+=head1 AUTHORS
+
+David Cantrell E<lt>david@cantrell.org.ukE<gt>
+
+David Golden E<lt>dagolden@cpan.orgE<gt>
+
+Thanks to the cpan-testers-discuss mailing list for prompting us to write it
+in the first place;
+
+to Chris Williams for help with Borland support.
+
+=head1 COPYRIGHT and LICENCE
+
+Copyright 2007 David Cantrell. Portions copyright 2007 David Golden.
+
+This module is free-as-in-speech software, and may be used, distributed,
+and modified under the same conditions as perl itself.
+
+=head1 CONSPIRACY
+
+This module is also free-as-in-mason software.
+
+=cut
+
+1;
diff --git a/t/x40checklib.t b/t/x40checklib.t
new file mode 100644 (file)
index 0000000..bf3f652
--- /dev/null
@@ -0,0 +1,39 @@
+#!perl -w
+#
+# Each sub-module ships with our custom Devel::CheckLib, make sure
+# they all match
+use strict;
+use Test::More;
+
+my @subs = qw(FT2 GIF JPEG PNG T1 TIFF W32);
+
+plan tests => 1 + @subs;
+
+# load the base file
+
+my $base = load("inc/Devel/CheckLib.pm");
+
+ok($base, "Loaded base file");
+
+for my $sub (@subs) {
+  my $data = load("$sub/inc/Devel/CheckLib.pm");
+
+  # I'd normally use is() here, but it's excessively noisy when
+  # comparing this size of data
+  ok(defined($data) && $data eq $base, "check $sub");
+}
+
+sub load {
+  my ($filename) = @_;
+
+  if (open my $f, "<", $filename) {
+    my $data = do { local $/; <$f> };
+    close $f;
+
+    return $data;
+  }
+  else {
+    diag "Cannot load $filename: $!\n";
+    return;
+  }
+}