Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Updated included Devel::CheckLib to resolve issues with v5.17.x perls #1

Closed
wants to merge 1 commit into from

2 participants

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 78 additions and 22 deletions.
  1. +78 −22 inc/Devel/CheckLib.pm
View
100 inc/Devel/CheckLib.pm
@@ -3,17 +3,19 @@
package #
Devel::CheckLib;
+use 5.00405; #postfix foreach
use strict;
use vars qw($VERSION @ISA @EXPORT);
-$VERSION = '0.699_001'; # but modified
-use Config;
+$VERSION = '0.98';
+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);
+@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
@@ -151,6 +153,11 @@ 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 {
@@ -161,6 +168,11 @@ sub check_lib_or_exit {
}
}
+sub check_lib {
+ eval 'assert_lib(@_)';
+ return $@ ? 0 : 1;
+}
+
sub assert_lib {
my %args = @_;
my (@libs, @libpaths, @headers, @incpaths);
@@ -178,7 +190,7 @@ sub assert_lib {
# 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) {
+ 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 =,
@@ -202,16 +214,21 @@ sub assert_lib {
}
}
- my @cc = _findcc();
+ 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'
);
- print $ch qq{#include <$header>\nint main(void) { return 0; }\n};
+ 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;
@@ -219,21 +236,25 @@ sub assert_lib {
if ( $Config{cc} eq 'cl' ) { # Microsoft compiler
require Win32;
@sys_cmd = (
- @cc,
+ @$cc,
$cfile,
"/Fe$exefile",
- (map { '/I'.Win32::GetShortPathName($_) } @incpaths)
+ (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
+ "/link",
+ @$ld
);
} elsif($Config{cc} =~ /bcc32(\.exe)?/) { # Borland
@sys_cmd = (
- @cc,
+ @$cc,
+ @$ld,
(map { "-I$_" } @incpaths),
"-o$exefile",
$cfile
);
} else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
@sys_cmd = (
- @cc,
+ @$cc,
+ @$ld,
$cfile,
(map { "-I$_" } @incpaths),
"-o", "$exefile"
@@ -241,8 +262,9 @@ sub assert_lib {
}
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;
+ push @missing, $header if $rv != 0 || ! -x $exefile;
_cleanup_exe($exefile);
+ unlink $ofile if -e $ofile;
unlink $cfile;
}
@@ -250,6 +272,8 @@ sub assert_lib {
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);
@@ -261,45 +285,52 @@ sub assert_lib {
my @libpath = map {
q{/libpath:} . Win32::GetShortPathName($_)
} @libpaths;
+ # this is horribly sensitive to the order of arguments
@sys_cmd = (
- @cc,
+ @$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,
+ @$cc,
+ @$ld,
"-o$exefile",
- "-l$lib",
(map { "-I$_" } @incpaths),
(map { "-L$_" } @libpaths),
+ "-l$lib",
$cfile);
} else { # Unix-ish
# gcc, Sun, AIX (gcc, cc)
@sys_cmd = (
- @cc,
+ @$cc,
+ @$ld,
$cfile,
"-o", "$exefile",
- "-l$lib",
(map { "-I$_" } @incpaths),
- (map { "-L$_" } @libpaths)
+ (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;
- push @wrongresult, $lib if $rv == 0 && -x $exefile && system(File::Spec->rel2abs($exefile)) != 0;
+ 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 $miss_string\n") if @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;
}
@@ -311,16 +342,37 @@ sub _cleanup_exe {
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 if -x $cc[0];
+ 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]) if -x $compiler;
+ return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags)
+ if -x $compiler;
}
die("Couldn't find your C compiler\n");
}
@@ -409,10 +461,14 @@ David Cantrell E<lt>david@cantrell.org.ukE<gt>
David Golden E<lt>dagolden@cpan.orgE<gt>
+Yasuhiro Matsumoto E<lt>mattn@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.
+to Chris Williams for help with Borland support;
+
+to Tony Cook for help with Microsoft compiler command-line options
=head1 COPYRIGHT and LICENCE
Something went wrong with that request. Please try again.