Devel-CheckLib-1.01/000075500000000000000000000000001222430313200141225ustar00rootroot00000000000000Devel-CheckLib-1.01/CHANGES000064400000000000000000000042151222430313200151170ustar00rootroot000000000000001.01 2013-07-26 Correct version 1.00 2013-07-26 Deprecate use-devel-checklib script. 0.99 2013-04-02 Allow -R rpaths as libpaths used with solaris cc (see RT #81330) 0.98 2012-03-17 Merge ldflags & perllibs. 0.97 2012-02-02 Fixed test. 0.96 2012-02-02 Pass linker options to MSVC. 0.95 2011-10-22 Clean up object files. Also MSVC generates extra files, clean them up. 0.94 2011-10-14 Better error message. 0.93 2011-04-09 Add support for gcc that have version number in the command name. Fix about that the command path include space character. 0.92 2010-12-13 Patch included, thanks to CHM and SISYPHUS (see RT #63742) 0.91 2010-09-29 Version bump up. 0.9 2010-09-29 Fix deprecated parenthesis. use "(qw())". 0.8 2010-09-15 Add include header files into dependencies files. (see RT #61297) Add minimum version number of perl. 0.7 2010-08-25 Add support for checking if a function exists in a library and it returns the right value (see RT #48332) Add check_lib function 0.6 2009-05-20 Support EU::MM-stylee command line, thanks to DAXIM (see RT #46044) 0.5 2008-03-12 Break up 'package Devel::CheckLib' in inc/ so distributions including it don't get marked as 'unauthorised' 0.4 2008-03-04 Look for headers as well as libraries; Clean up temp dirs in tests; use-devel-checklib fixed for Win32 0.3 2007-10-30 tests now skip when they need a compiler and can't find one; Borland compiler support; added bin/use-devel-checklib script; added EU::MM-stylee LIBS support 0.2 2007-10-18 better portability, more features Renamed to Devel::CheckLib 0.1 2007-10-14 Initial release Devel-CheckLib-1.01/MANIFEST000064400000000000000000000007501222430313200152550ustar00rootroot00000000000000CHANGES lib/Devel/CheckLib.pm Makefile.PL MANIFEST README t/00-load.t t/exit_with_message.t t/found.t t/lib/Helper.pm t/not_found.t TODO bin/use-devel-checklib t/multi-word-compiler.t t/bad-single-word-compiler.t t/dash-l-libs.t t/headers.t t/inc/headerfile.h VMS-notes t/coverage.sh t/cmdline-LIBS-INC.t t/custom-function.t META.yml Module meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) Devel-CheckLib-1.01/META.json000064400000000000000000000020741222430313200155460ustar00rootroot00000000000000{ "abstract" : "unknown", "author" : [ "unknown" ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 6.72, CPAN::Meta::Converter version 2.120351", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Devel-CheckLib", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "IO::CaptureOutput" : "1.0801", "Test::More" : "0.62" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "Exporter" : "0", "File::Spec" : "0", "File::Temp" : "0.16", "perl" : "5.00405" } } }, "release_status" : "stable", "resources" : { "repository" : { "url" : "http://github.com/mattn/p5-Devel-CheckLib" } }, "version" : "1.01" } Devel-CheckLib-1.01/META.yml000064400000000000000000000011021222430313200153650ustar00rootroot00000000000000--- abstract: unknown author: - unknown build_requires: IO::CaptureOutput: 1.0801 Test::More: 0.62 configure_requires: ExtUtils::MakeMaker: 0 dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 6.72, CPAN::Meta::Converter version 2.120351' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Devel-CheckLib no_index: directory: - t - inc requires: Exporter: 0 File::Spec: 0 File::Temp: 0.16 perl: 5.00405 resources: repository: http://github.com/mattn/p5-Devel-CheckLib version: 1.01 Devel-CheckLib-1.01/Makefile.PL000064400000000000000000000034031222430313200160740ustar00rootroot00000000000000# $Id: Makefile.PL,v 1.6 2008/03/04 21:49:19 drhyde Exp $ use 5.00405; use ExtUtils::MakeMaker; use strict; $^W = 1; WriteMakefile1( NAME => 'Devel::CheckLib', VERSION_FROM => 'lib/Devel/CheckLib.pm', PREREQ_PM => { 'File::Temp' => 0.16, 'Exporter' => 0, 'File::Spec' => 0, }, MIN_PERL_VERSION => '5.00405', META_MERGE => { resources => { repository => 'http://github.com/mattn/p5-Devel-CheckLib', }, }, BUILD_REQUIRES => { 'Test::More' => 0.62, # too high? but API changed here 'IO::CaptureOutput' => 1.0801, }, LICENSE => 'perl', EXE_FILES => [qw( bin/use-devel-checklib )], ); sub WriteMakefile1 { #Written by Alexandr Ciornii, version 0.21. Added by eumm-upgrade. my %params=@_; my $eumm_version=$ExtUtils::MakeMaker::VERSION; $eumm_version=eval $eumm_version; die "EXTRA_META is deprecated" if exists $params{EXTRA_META}; die "License not specified" if not exists $params{LICENSE}; if ($params{BUILD_REQUIRES} and $eumm_version < 6.5503) { #EUMM 6.5502 has problems with BUILD_REQUIRES $params{PREREQ_PM}={ %{$params{PREREQ_PM} || {}} , %{$params{BUILD_REQUIRES}} }; delete $params{BUILD_REQUIRES}; } delete $params{CONFIGURE_REQUIRES} if $eumm_version < 6.52; delete $params{MIN_PERL_VERSION} if $eumm_version < 6.48; delete $params{META_MERGE} if $eumm_version < 6.46; delete $params{META_ADD} if $eumm_version < 6.46; delete $params{LICENSE} if $eumm_version < 6.31; delete $params{AUTHOR} if $] < 5.005; delete $params{ABSTRACT_FROM} if $] < 5.005; delete $params{BINARY_LOCATION} if $] < 5.005; WriteMakefile(%params); } Devel-CheckLib-1.01/README000064400000000000000000000004011222430313200147750ustar00rootroot00000000000000This module provides a way of checking whether a particular library and its headers are available, by attempting to compile a simple program and link against it. To install, do the usual dance: perl Makefile.PL make make test make install Devel-CheckLib-1.01/TODO000064400000000000000000000000351222430313200146100ustar00rootroot00000000000000SGI (maybe) VMS pkg-config? Devel-CheckLib-1.01/VMS-notes000064400000000000000000000035761222430313200156530ustar00rootroot00000000000000http://perl-qa.hexten.net/wiki/index.php/Testing_on_VMS --- 15:32 well $Config{cc} will contain 'CC/DECC', which is the right command to use but "if -x $cc[0]" will fail 15:33 then "CC/DECC foo.c" will compile foo.c to foo.obj 15:37 how do i pass include paths? 15:38 CC/DECC/INCLUDE_DIRECTORY=foo 15:39 I'm still trying to work out the best way to do the linking bit though 15:40 is CC/DECC/INCLUDE_DIRECTORY=foo/INCLUDE_DIRECTORY=bar valid? 15:41 yes 15:41 hurrah! 15:41 I'm still trying to work out the best way to do linking though 16:17 well, buggered if I can find a standard place to put libraries on VMS. There probably is one but my VMS skills are too weak. 16:17 anyway, the command is just "LINK foo.obj, bar.obj" where foo is the previously compiled foo.c and bar is the library whose presence you are testing for 16:18 but it won't be very portable because "bar.obj" needs to be a proper path, unless it is a system library 16:26 that's a good start, so thanks! 16:34 no problem. incidentally, VMS command line options can be shortened to their shortest unambiguous form, and so /include_directory can actually just be /inc 16:50 OK, it looks like SYS$LIBRARY is the VMS sort-of-equivalent of /usr/lib on Linux 16:52 thus "LINK foo.obj, sys$library:vaxcrtl/share" links foo.obj with the shared library vaxctrl 16:54 and "LINK foo.obj, sys$library:ucx$ipc/library" links foo.obj with the static library ucx$ipc 16:54 also, "link/exe=bar.exe foo.obj" links foo.obj to create an executable called bar.exe Devel-CheckLib-1.01/bin/000075500000000000000000000000001222430313200146725ustar00rootroot00000000000000Devel-CheckLib-1.01/bin/use-devel-checklib000075500000000000000000000053171222430313200202610ustar00rootroot00000000000000#!perl -w # $Id: use-devel-checklib,v 1.9 2008/03/12 19:52:50 drhyde Exp $ use strict; $/ = undef; use File::Spec; use Devel::CheckLib; warn "----------------------- [WARNING] --------\n"; warn "THIS SCRIPT WAS DEPRECATED.\n"; warn "YOU SHOULD USE configure_requires INSTEAD.\n"; warn "---------- [/WARNING] --------------------\n"; my @files = grep { -f $_ } qw(Makefile.PL Build.PL); push @files, 'Makefile.PL' unless(@files); my @libs = @ARGV; mkdir 'inc'; mkdir 'inc/Devel'; open(CHECKLIBPM, $INC{'Devel/CheckLib.pm'}) || die("Can't read $INC{'Devel/CheckLib.pm'}: $!"); (my $checklibpm = ) =~ s/package Devel::CheckLib/package #\nDevel::CheckLib/; close(CHECKLIBPM); open(CHECKLIBPM, '>'.File::Spec->catfile(qw(inc Devel CheckLib.pm))) || die("Can't write inc/Devel/CheckLib.pm: $!"); print CHECKLIBPM $checklibpm; close(CHECKLIBPM); print "Copied Devel::CheckLib to inc/ directory\n"; foreach my $file (@files) { open(FILE, $file) || next; my $contents = ; close(FILE); open(FILE, ">$file") || die("Can't write $file\n"); print FILE q{use lib qw(inc); use Devel::CheckLib; # Prompt the user here for any paths and other configuration check_lib_or_exit( # fill in what you prompted the user for here lib => [qw(}.join(' ', @libs).q{)] ); }; print FILE "\n\n$contents"; close(FILE); print "Updated/created $file\n"; } open(MANIFEST, 'MANIFEST') || warn("Couldn't read MANIFEST, will create one\n"); my $manifest = ; close(MANIFEST); open(MANIFEST, '>MANIFEST') || die("Couldn't write MANIFEST\n"); print MANIFEST "inc/Devel/CheckLib.pm\n$manifest"; close(MANIFEST); print "Updated/created MANIFEST\n"; =head1 NAME use-devel-checklib - (DEPRECATED)a script to package Devel::CheckLib with your code. =head1 DESCRIPTION This script was DEPRECATED. If you need to depend on this library, you should use `configure_requires` in Makefile.PL or Build.PL instead. =head1 WARNINGS, BUGS and FEEDBACK This script has not been thoroughly tested. You should check by hand that it has done what you expected after running it. If you use Module::Build::Compat to write a Makefile.PL, then you will need to re-run this script whenever you have generated a new Makefile.PL. I welcome feedback about my code, including constructive criticism. Bug reports should be made using L or by email. =head1 SEE ALSO L =head1 AUTHOR David Cantrell EFE =head1 COPYRIGHT and LICENCE Copyright 2007 David Cantrell This software 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 Devel-CheckLib-1.01/lib/000075500000000000000000000000001222430313200146705ustar00rootroot00000000000000Devel-CheckLib-1.01/lib/Devel/000075500000000000000000000000001222430313200157275ustar00rootroot00000000000000Devel-CheckLib-1.01/lib/Devel/CheckLib.pm000064400000000000000000000354371222430313200177450ustar00rootroot00000000000000# $Id: CheckLib.pm,v 1.25 2008/10/27 12:16:23 drhyde Exp $ package Devel::CheckLib; use 5.00405; #postfix foreach use strict; use vars qw($VERSION @ISA @EXPORT); $VERSION = '1.01'; use Config qw(%Config); use Text::ParseWords 'quotewords'; 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. =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: dying in a Makefile.PL or Build.PL may provoke a 'FAIL' report from CPAN Testers' automated smoke testers. Use C 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) =item libpath a string or an array of strings representing additional paths to search for libraries. =item LIBS a C-style space-seperated list of libraries (each preceded by '-l') and directories (preceded by '-L'). This can also be supplied on the command-line. =item debug If true - emit information during processing that can be used for debugging. =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-style space-seperated list of incpaths, each preceded by '-I'. This can also be supplied on the command-line. =back =head2 check_lib_or_exit This behaves exactly the same as C 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 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}; # 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})) { foreach my $arg (split(' ', $args{LIBS})) { die("LIBS argument badly-formed: $arg\n") unless($arg =~ /^-[lLR]/); push @{$arg =~ /^-l/ ? \@libs : \@libpaths}, substr($arg, 2); } } 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, $ld) = _findcc(); my @missing; my @wrongresult; my @use_headers; # first figure out which headers we can't find ... for my $header (@headers) { push @use_headers, $header; my($ch, $cfile) = File::Temp::tempfile( 'assertlibXXXXXXXX', SUFFIX => '.c' ); my $ofile = $cfile; $ofile =~ s/\.c$/$Config{_o}/; 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), "/link", @$ld ); } elsif($Config{cc} =~ /bcc32(\.exe)?/) { # Borland @sys_cmd = ( @$cc, @$ld, (map { "-I$_" } @incpaths), "-o$exefile", $cfile ); } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ... @sys_cmd = ( @$cc, @$ld, $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 $ofile if -e $ofile; unlink $cfile; } # now do each library in turn with headers my($ch, $cfile) = File::Temp::tempfile( 'assertlibXXXXXXXX', SUFFIX => '.c' ); my $ofile = $cfile; $ofile =~ s/\.c$/$Config{_o}/; print $ch qq{#include <$_>\n} foreach (@headers); print $ch "int main(void) { ".($args{function} || 'return 0;')." }\n"; close($ch); for my $lib ( @libs ) { 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, "${lib}.lib", "/Fe$exefile", (map { '/I'.Win32::GetShortPathName($_) } @incpaths), "/link", @$ld, (map {'/libpath:'.Win32::GetShortPathName($_)} @libpaths), ); } elsif($Config{cc} eq 'CC/DECC') { # VMS } elsif($Config{cc} =~ /bcc32(\.exe)?/) { # Borland @sys_cmd = ( @$cc, @$ld, "-o$exefile", (map { "-I$_" } @incpaths), (map { "-L$_" } @libpaths), "-l$lib", $cfile); } else { # Unix-ish # gcc, Sun, AIX (gcc, cc) @sys_cmd = ( @$cc, @$ld, $cfile, "-o", "$exefile", (map { "-I$_" } @incpaths), (map { "-L$_" } @libpaths), "-l$lib", ); } warn "# @sys_cmd\n" if $args{debug}; my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd); push @missing, $lib if $rv != 0 || ! -x $exefile; my $absexefile = File::Spec->rel2abs($exefile); $absexefile = '"'.$absexefile.'"' if $absexefile =~ m/\s/; push @wrongresult, $lib if $rv == 0 && -x $exefile && system($absexefile) != 0; unlink $ofile if -e $ofile; _cleanup_exe($exefile); } unlink $cfile; my $miss_string = join( q{, }, map { qq{'$_'} } @missing ); die("Can't link/include C library $miss_string, aborting.\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"; if ( $Config{cc} eq 'cl' ) { # MSVC also creates foo.ilk and foo.pdb my $ilkfile = $exefile; $ilkfile =~ s/$Config{_exe}$/.ilk/; my $pdbfile = $exefile; $pdbfile =~ s/$Config{_exe}$/.pdb/; unlink $ilkfile if -f $ilkfile; unlink $pdbfile if -f $pdbfile; } return } # return ($cc, $ld) # where $cc is an array ref of compiler name, compiler flags # where $ld is an array ref of linker flags sub _findcc { # Need to use $keep=1 to work with MSWin32 backslashes and quotes my $Config_ccflags = $Config{ccflags}; # use copy so ASPerl will compile my @Config_ldflags = (); for my $config_val ( @Config{qw(ldflags perllibs)} ){ push @Config_ldflags, $config_val if ( $config_val =~ /\S/ ); } my @ccflags = grep { length } quotewords('\s+', 1, $Config_ccflags||''); my @ldflags = grep { length } quotewords('\s+', 1, @Config_ldflags); my @paths = split(/$Config{path_sep}/, $ENV{PATH}); my @cc = split(/\s+/, $Config{cc}); return ( [ @cc, @ccflags ], \@ldflags ) if -x $cc[0]; foreach my $path (@paths) { my $compiler = File::Spec->catfile($path, $cc[0]) . $Config{_exe}; return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags) 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 or by email. When submitting a bug report, please include the output from running: perl -V perl -MDevel::CheckLib -e0 =head1 SEE ALSO L L =head1 AUTHORS David Cantrell Edavid@cantrell.org.ukE David Golden Edagolden@cpan.orgE Yasuhiro Matsumoto Emattn@cpan.orgE 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; to Tony Cook for help with Microsoft compiler command-line options =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; Devel-CheckLib-1.01/t/000075500000000000000000000000001222430313200143655ustar00rootroot00000000000000Devel-CheckLib-1.01/t/00-load.t000064400000000000000000000003501222430313200157040ustar00rootroot00000000000000use strict; # compatible use warnings BEGIN{ if (not $] < 5.006) { require warnings; warnings->import } } use Test::More tests => 1; eval "use Devel::CheckLib"; ok($@ =~ /Couldn't find your C compiler/ || !$@, "Can load module"); Devel-CheckLib-1.01/t/bad-single-word-compiler.t000064400000000000000000000014601222430313200213410ustar00rootroot00000000000000# $Id: bad-single-word-compiler.t,v 1.2 2008/02/07 14:16:39 drhyde Exp $ use strict; BEGIN{ if (not $] < 5.006) { require warnings; warnings->import } } use Test::More; plan tests => 1; use Config; BEGIN { BEGIN { if (not $] < 5.006 ) { warnings->unimport('redefine') } } unless(defined($ActivePerl::VERSION) && $Config{cc} =~ /\bgcc\b/) { *Config::STORE = sub { $_[0]->{$_[1]} = $_[2] } } } if(defined($ActivePerl::VERSION) && $Config{cc} =~ /\bgcc\b/) { my $obj = tied %Config::Config; $obj->{cc} = "flibbertigibbet"; } else { eval { $Config{cc} = 'flibbertigibbet' }; } SKIP: { skip "Couldn't update %Config", 1 if $@ =~ /%Config::Config is read-only/; eval "use Devel::CheckLib"; ok($@ =~ /^Couldn't find your C compiler/, "Bad single-word compiler is not OK"); } Devel-CheckLib-1.01/t/cmdline-LIBS-INC.t000064400000000000000000000041431222430313200173250ustar00rootroot00000000000000use strict; # compatible use warnings BEGIN{ if (not $] < 5.006) { require warnings; warnings->import } } use lib 't/lib'; use IO::CaptureOutput qw(capture); use Config; use File::Spec; use Test::More; my($debug, $stdout, $stderr) = ($ENV{DEVEL_CHECKLIB_DEBUG} || 0); my $libdir; eval "use Devel::CheckLib"; if($@ =~ /Couldn't find your C compiler/) { #' plan skip_all => "Couldn't find your C compiler"; } eval "use Helper qw(create_testlib)"; if($libdir = create_testlib("bazbam")) { plan tests => 3; } else { plan skip_all => "Couldn't build a library to test against"; }; my $runtime = '-l'.( $^O eq 'MSWin32' # if Win32 (not Cygwin) ... ? ( $Config{cc} =~ /(^|^\w+ )bcc/ ? 'cc3250' # ... Borland : 'msvcrt' # ... otherwise assume Microsoft ) : 'm' # default to Unix-style ); my $rval = undef; my @args = (qq{LIBS=$runtime}); capture( sub { $rval = system( $Config{perlpath}, '-Mblib', '-MDevel::CheckLib', '-e', "print @ARGV;assert_lib(debug => $debug)", @args )}, \$stdout, \$stderr ); ok($stderr eq '' && defined($rval) && $rval == 0, "linked OK: ".join(', ', @args)) || diag("\tSTDOUT: $stdout\n\tSTDERR: $stderr\n"); $rval = undef; @args = map { "LIBS=$_" } ($runtime, '-lbazbam', "-L$libdir"); capture( sub { $rval = system( $Config{perlpath}, '-Mblib', '-MDevel::CheckLib', '-e', "print @ARGV;assert_lib(debug => $debug)", @args )}, \$stdout, \$stderr ); ok($stderr eq '' && defined($rval) && $rval == 0, "linked OK: ".join(', ', @args)) || diag("\tSTDOUT: $stdout\n\tSTDERR: $stderr\n"); $rval = undef; @args = (qq{"LIBS=$runtime -lbazbam -L$libdir"}); capture( sub { $rval = system( $Config{perlpath}, '-Mblib', '-MDevel::CheckLib', '-e', "print @ARGV;assert_lib(debug => $debug)", @args )}, \$stdout, \$stderr ); ok($stderr eq '' && defined($rval) && $rval == 0, "linked OK: ".join(', ', @args)) || diag("\tSTDOUT: $stdout\n\tSTDERR: $stderr\n"); Devel-CheckLib-1.01/t/coverage.sh000075500000000000000000000002101222430313200165100ustar00rootroot00000000000000#!/bin/sh # $Id: coverage.sh,v 1.1 2008/02/26 21:54:55 drhyde Exp $ cover -delete HARNESS_PERL_SWITCHES=-MDevel::Cover make test cover Devel-CheckLib-1.01/t/custom-function.t000064400000000000000000000045761222430313200177230ustar00rootroot00000000000000use strict; # compatible use warnings BEGIN{ if (not $] < 5.006) { require warnings; warnings->import } } use lib 't/lib'; use IO::CaptureOutput qw(capture); use Config; use File::Spec; use Test::More; eval "use Devel::CheckLib"; if($@ =~ /Couldn't find your C compiler/) { plan skip_all => "Couldn't find your C compiler"; } my $libdir; eval "use Helper qw(create_testlib)"; unless($libdir = create_testlib("bazbam")) { plan skip_all => "Couldn't build a library to test against"; }; my($debug, $stdout, $stderr) = ($ENV{DEVEL_CHECKLIB_DEBUG} || 0); # cases are strings to interpolate into the assert_lib call my %failcases = ( qq{ incpath => 't/inc', libpath => '$libdir', lib => 'bazbam', header => 'headerfile.h', # bar() doesn't exist function => 'bar();' } => 'Can\'t link/include', qq{ incpath => 't/inc', libpath => '$libdir', lib => 'bazbam', header => 'headerfile.h', # libversion returns wrong result function => 'foo();if(libversion() < 5) return 0; else return 1;' } => 'wrong result', ); my %passcases = ( qq{ incpath => 't/inc', libpath => '$libdir', lib => 'bazbam', header => 'headerfile.h', functionbody => 'foo(); return 0;' }, "function exists", qq{ incpath => 't/inc', libpath => '$libdir', lib => 'bazbam', header => 'headerfile.h', functionbody => 'if(libversion() > 5) return 0; else return 1;' }, "function returns right value", qq{ incpath => 't/inc', libpath => '$libdir', lib => 'bazbam', header => 'headerfile.h', functionbody => 'foo();if(libversion() > 5) return 0; else return 1;' }, "function exists and other function returns right value", ); plan tests => scalar(keys %failcases) + scalar(keys %passcases); for my $c (keys %failcases) { capture( sub { eval "assert_lib(debug => $debug, $c)"; }, \$stdout, \$stderr ); ok($@ =~ /^$failcases{$c}/, "failed to build: $failcases{$c}") || diag("$c\n$@\n\tSTDOUT: $stdout\n\tSTDERR: $stderr\n"); } for my $c ( keys %passcases ) { capture( sub { eval "assert_lib(debug => $debug, $c)"; }, \$stdout, \$stderr ); is($@, q{}, "$passcases{$c}") || diag("\tSTDOUT: $stdout\n\tSTDERR: $stderr\n"); } Devel-CheckLib-1.01/t/dash-l-libs.t000064400000000000000000000023161222430313200166530ustar00rootroot00000000000000use strict; # compatible use warnings BEGIN{ if (not $] < 5.006) { require warnings; warnings->import } } use lib 't/lib'; use IO::CaptureOutput qw(capture); use Config; use File::Spec; use Test::More; my($debug, $stdout, $stderr) = ($ENV{DEVEL_CHECKLIB_DEBUG} || 0); my $libdir; eval "use Devel::CheckLib"; if($@ =~ /Couldn't find your C compiler/) { plan skip_all => "Couldn't find your C compiler"; } eval "use Helper qw(create_testlib)"; if($libdir = create_testlib("bazbam")) { plan tests => 1; } else { plan skip_all => "Couldn't build a library to test against"; }; my $runtime = '-l'.( $^O eq 'MSWin32' # if Win32 (not Cygwin) ... ? ( $Config{cc} =~ /(^|^\w+ )bcc/ ? 'cc3250' # ... Borland : 'msvcrt' # ... otherwise assume Microsoft ) : 'm' # default to Unix-style ); # my $runtime = $^O eq 'MSWin32' ? '-lmsvcrt' : '-lm'; my $args = qq{LIBS => '$runtime -lbazbam -L$libdir'}; capture( sub { eval "assert_lib(debug => $debug, $args)"; }, \$stdout, \$stderr ); is($@, q{}, "$args") || diag("\tSTDOUT: $stdout\n\tSTDERR: $stderr\n"); Devel-CheckLib-1.01/t/exit_with_message.t000064400000000000000000000010441222430313200202610ustar00rootroot00000000000000use strict; # compatible use warnings BEGIN{ if (not $] < 5.006) { require warnings; warnings->import } } use Test::More; use File::Temp; my $fh = File::Temp->new(); print {$fh} << 'ENDPRINT'; use Devel::CheckLib; check_lib_or_exit( qw/lib hlagh/ ); ENDPRINT $fh->close; my $err = `$^X $fh 2>&1`; if($err =~ /Couldn't find your C compiler/) { plan skip_all => "Couldn't find your C compiler"; } else { plan tests => 1; like ($err, "/^Can't link\\/include C library 'hlagh'/ms", "missing hlagh detected non-fatally" ); } Devel-CheckLib-1.01/t/found.t000064400000000000000000000027051222430313200156710ustar00rootroot00000000000000use strict; # compatible use warnings BEGIN{ if (not $] < 5.006) { require warnings; warnings->import } } use lib 't/lib'; use IO::CaptureOutput qw(capture); use Config; use File::Spec; use Test::More; eval "use Devel::CheckLib"; if($@ =~ /Couldn't find your C compiler/) { plan skip_all => "Couldn't find your C compiler"; } else { eval "use Helper qw/create_testlib/"; } my($debug, $stdout, $stderr) = ($ENV{DEVEL_CHECKLIB_DEBUG} || 0); # compile a test library my $libdir = create_testlib("bazbam"); my @lib = $^O eq 'MSWin32' # if Win32 (not Cygwin) ... ? ( $Config{cc} =~ /(^|^\w+ )bcc/ # FIXME - find a second Borland lib ? ('cc3250', 'cc3250') # ... Borland : ('msvcrt', 'kernel32') # ... otherwise assume Microsoft ) : qw(m c) # default to Unix-style ; # cases are strings to interpolate into the assert_lib call my @cases = ( qq/lib => '$lib[0]'/, qq/lib => '$lib[1]'/, qq/lib => ['$lib[0]', '$lib[1]']/, ); push @cases, qq{lib => 'bazbam', libpath => '$libdir'} if $libdir; plan tests => 2 * scalar @cases; for my $c ( @cases ) { capture( sub { eval "assert_lib(debug => $debug, $c)"; }, \$stdout, \$stderr ); is($@, q{}, "$c") || diag("\tSTDOUT: $stdout\n\tSTDERR: $stderr\n"); ok(check_lib(debug => $debug, eval($c)), "... and check_lib is true"); } Devel-CheckLib-1.01/t/headers.t000064400000000000000000000025171222430313200161720ustar00rootroot00000000000000use strict; # compatible use warnings BEGIN{ if (not $] < 5.006) { require warnings; warnings->import } } use lib 't/lib'; use IO::CaptureOutput qw(capture); use Config; use File::Spec; use Test::More; eval "use Devel::CheckLib"; if($@ =~ /Couldn't find your C compiler/) { plan skip_all => "Couldn't find your C compiler"; } my($debug, $stdout, $stderr) = ($ENV{DEVEL_CHECKLIB_DEBUG} || 0); # cases are strings to interpolate into the assert_lib call my %failcases = ( qq{incpath => '.', header => 'headerfile.h'} => "Can't link/include", qq{INC => '-t/inc', header => 'headerfile.h'} => "INC argument badly-formed" ); my @passcases = ( qq{incpath => '.', header => 't/inc/headerfile.h'}, qq{incpath => [qw(t/inc)], header => 'headerfile.h'}, qq{INC => '-I. -It/inc', header => 'headerfile.h'} ); plan tests => scalar(keys %failcases) + scalar(@passcases); for my $c (keys %failcases) { capture( sub { eval "assert_lib(debug => $debug, $c)"; }, \$stdout, \$stderr ); ok($@ =~ /^$failcases{$c}/, "$c") || diag("$@\n\tSTDOUT: $stdout\n\tSTDERR: $stderr\n"); } for my $c ( @passcases ) { capture( sub { eval "assert_lib(debug => $debug, $c)"; }, \$stdout, \$stderr ); is($@, q{}, "$c") || diag("\tSTDOUT: $stdout\n\tSTDERR: $stderr\n"); } Devel-CheckLib-1.01/t/inc/000075500000000000000000000000001222430313200151365ustar00rootroot00000000000000Devel-CheckLib-1.01/t/inc/headerfile.h000064400000000000000000000000461222430313200173770ustar00rootroot00000000000000int foo(void); int libversion(void); Devel-CheckLib-1.01/t/lib/000075500000000000000000000000001222430313200151335ustar00rootroot00000000000000Devel-CheckLib-1.01/t/lib/Helper.pm000064400000000000000000000066771222430313200167300ustar00rootroot00000000000000package Helper; use strict; # compatible use warnings BEGIN{ if (not $] < 5.006) { require warnings; warnings->import } } use Config; use Cwd; use Exporter; use IO::File; use File::Spec::Functions qw/catfile canonpath splitdir/; use File::Temp qw/tempdir/; use vars qw/@EXPORT @ISA/; @ISA = qw/Exporter/; @EXPORT = qw( create_testlib find_compiler find_binary ); my $orig_wd = cwd; BEGIN { require Devel::CheckLib; } # for _quiet_system() sub _quiet_system { goto &Devel::CheckLib::_quiet_system; } #--------------------------------------------------------------------------# # create_testlib( 'bazbam' ) # # takes a library name and compiles a simple library with two functions, # foo() (which returns 0) and libversion() (which returns 42), in a temp # directory and returns the temp directory. Returns undef if something # went wrong #--------------------------------------------------------------------------# sub create_testlib { my ($libname) = (@_); return unless $libname; my $tempdir = tempdir(CLEANUP => 1, TEMPLATE => "Devel-Assert-testlib-XXXXXXXX"); chdir $tempdir; my $code_fh = IO::File->new("${libname}.c", ">"); print {$code_fh} "int libversion() { return 42; }\nint foo() { return 0; }\n"; $code_fh->close; my $cc = $Config{cc}; my $gccv = $Config{gccversion}; my $rv = $cc eq 'gcc' ? _gcc_lib( $libname ) : $cc eq 'cc' ? _gcc_lib( $libname ) : $cc eq 'cl' ? _cl_lib( $libname ) : $gccv ? _gcc_lib( $libname ) : undef ; chdir $orig_wd; return $rv ? canonpath($tempdir) : undef; } sub _gcc_lib { my ($libname) = @_; my $cc = find_compiler() or return; my $ar = find_binary('ar') or return; my $ranlib = find_binary('ranlib') or return; my $ccflags = $Config{ccflags}; _quiet_system("$cc $ccflags -c ${libname}.c") and return; _quiet_system("$ar rc lib${libname}.a ${libname}.o") and return; _quiet_system("$ranlib lib${libname}.a") and return; return -f "lib${libname}.a" } sub _cl_lib { my ($libname) = @_; my $cc = find_compiler() or return; my $ar = find_binary('lib') or return; _quiet_system($cc, '/c', "${libname}.c") and return; _quiet_system($ar, "${libname}.obj") and return; return -f "${libname}.lib"; } #--------------------------------------------------------------------------# # find_binary, find_compiler # # Returns absolute path to an executable file in $ENV{PATH} or undef # if it can't be found. find_binary() takes a program argument; # find_compiler takes no arguments and just returns the path to $Config{cc} #--------------------------------------------------------------------------# sub find_binary { my ($program) = @_; if ($Config{_exe} && $program !~ /$Config{_exe}$/) { $program .= $Config{_exe}; } return $program if -x $program; my @search_paths = split /$Config{path_sep}/, $ENV{PATH}; my @lib_search_paths = map lib_to_bin($_), split /$Config{path_sep}/, $ENV{LIBRARY_PATH}||''; for my $path ( @search_paths, @lib_search_paths ) { my $binary = catfile( $path, $program ); return $binary if -x $binary; } return; } sub lib_to_bin { my ( $lib_dir ) = @_; my @parts = splitdir $lib_dir; pop @parts; push @parts, 'bin'; my $bin_dir = catfile(@parts); return $bin_dir; } sub find_compiler { return find_binary($Config{cc}); } 1; # must be true Devel-CheckLib-1.01/t/multi-word-compiler.t000064400000000000000000000014411222430313200204650ustar00rootroot00000000000000# $Id: multi-word-compiler.t,v 1.3 2008/02/07 14:16:39 drhyde Exp $ use strict; BEGIN{ if (not $] < 5.006) { require warnings; warnings->import } } use Test::More; plan tests => 1; use Config; BEGIN { BEGIN { if (not $] < 5.006 ) { warnings->unimport('redefine') } } unless(defined($ActivePerl::VERSION) && $Config{cc} =~ /\bgcc\b/) { *Config::STORE = sub { $_[0]->{$_[1]} = $_[2] } } } if(defined($ActivePerl::VERSION) && $Config{cc} =~ /\bgcc\b/) { my $obj = tied %Config::Config; $obj->{cc} = "$^X $Config{cc}"; } else { $Config{cc} = "$^X $Config{cc}"; } eval { $Config{cc} = "$^X $Config{cc}" }; SKIP: { skip "Couldn't update %Config", 1 if $@ =~ /%Config::Config is read-only/; eval "use Devel::CheckLib"; ok(!$@, "Good multi-word compiler is OK"); } Devel-CheckLib-1.01/t/not_found.t000064400000000000000000000026461222430313200165550ustar00rootroot00000000000000use strict; # compatible use warnings BEGIN{ if (not $] < 5.006) { require warnings; warnings->import } } use Test::More; use Config; my $debug = 0; eval "use Devel::CheckLib"; if($@ =~ /Couldn't find your C compiler/) { plan skip_all => "Couldn't find your C compiler"; } my $platform_lib = $^O eq 'MSWin32' # if Win32 (not Cygwin) ... ? ( $Config{cc} =~ /(^|^\w+ )bcc/ ? 'cc3250' # ... Borland : 'msvcrt' # ... otherwise assume Microsoft ) : 'm' # default to Unix-style ; # Cases are AoH: { arg => $string, missing => $string } my @cases = ( { arg => qq{lib => 'foo'}, missing => ['foo'] }, { arg => qq{lib => [qw/$platform_lib foo/]}, missing => ['foo'] }, { arg => qq{lib => [qw/foo $platform_lib/]}, missing => ['foo'] }, { arg => qq{lib => [qw/foo bar/]}, missing => [qw/foo bar/] }, ); plan tests => 3 * @cases; for my $c ( @cases ) { eval "assert_lib(debug => $debug, $c->{arg})"; my $err = $@; ok ( $err, "died on '$c->{arg}'" ); my $miss_string = join(q{, }, map { qq{'$_'} } @{$c->{missing}} ); like ($err, "/^Can't link\/include C library ${miss_string}/ms", "missing $miss_string detected" ); ok(!check_lib(debug => $debug, eval($c->{arg})), "... and check_lib is false"); }