Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

update Devel::CheckLib

  • Loading branch information...
commit b3fc8a2da40333d58eecdc5d4b63b777879b4cf8 1 parent 955d718
Tony Cook authored

Showing 1 changed file with 79 additions and 23 deletions. Show diff stats Hide diff stats

  1. +79 23 inc/Devel/CheckLib.pm
102 inc/Devel/CheckLib.pm
... ... @@ -1,19 +1,21 @@
1 1 # $Id: CheckLib.pm,v 1.25 2008/10/27 12:16:23 drhyde Exp $
2 2
3   -package #
  3 +package
4 4 Devel::CheckLib;
5 5
  6 +use 5.00405; #postfix foreach
6 7 use strict;
7 8 use vars qw($VERSION @ISA @EXPORT);
8   -$VERSION = '0.699_001'; # but modified
9   -use Config;
  9 +$VERSION = '0.98';
  10 +use Config qw(%Config);
  11 +use Text::ParseWords 'quotewords';
10 12
11 13 use File::Spec;
12 14 use File::Temp;
13 15
14 16 require Exporter;
15 17 @ISA = qw(Exporter);
16   -@EXPORT = qw(assert_lib check_lib_or_exit);
  18 +@EXPORT = qw(assert_lib check_lib_or_exit check_lib);
17 19
18 20 # localising prevents the warningness leaking out of this module
19 21 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
151 153 result -- which is what you want if an external library dependency is not
152 154 available.
153 155
  156 +=head2 check_lib
  157 +
  158 +This behaves exactly the same as C<assert_lib()> except that it is silent,
  159 +returning false instead of dieing, or true otherwise.
  160 +
154 161 =cut
155 162
156 163 sub check_lib_or_exit {
@@ -161,6 +168,11 @@ sub check_lib_or_exit {
161 168 }
162 169 }
163 170
  171 +sub check_lib {
  172 + eval 'assert_lib(@_)';
  173 + return $@ ? 0 : 1;
  174 +}
  175 +
164 176 sub assert_lib {
165 177 my %args = @_;
166 178 my (@libs, @libpaths, @headers, @incpaths);
@@ -178,7 +190,7 @@ sub assert_lib {
178 190 # work-a-like for Makefile.PL's LIBS and INC arguments
179 191 # if given as command-line argument, append to %args
180 192 for my $arg (@ARGV) {
181   - for my $mm_attr_key qw(LIBS INC) {
  193 + for my $mm_attr_key (qw(LIBS INC)) {
182 194 if (my ($mm_attr_value) = $arg =~ /\A $mm_attr_key = (.*)/x) {
183 195 # it is tempting to put some \s* into the expression, but the
184 196 # MM command-line parser only accepts LIBS etc. followed by =,
@@ -202,16 +214,21 @@ sub assert_lib {
202 214 }
203 215 }
204 216
205   - my @cc = _findcc();
  217 + my ($cc, $ld) = _findcc();
206 218 my @missing;
207 219 my @wrongresult;
  220 + my @use_headers;
208 221
209 222 # first figure out which headers we can't find ...
210 223 for my $header (@headers) {
  224 + push @use_headers, $header;
211 225 my($ch, $cfile) = File::Temp::tempfile(
212 226 'assertlibXXXXXXXX', SUFFIX => '.c'
213 227 );
214   - print $ch qq{#include <$header>\nint main(void) { return 0; }\n};
  228 + my $ofile = $cfile;
  229 + $ofile =~ s/\.c$/$Config{_o}/;
  230 + print $ch qq{#include <$_>\n} for @use_headers;
  231 + print $ch qq{int main(void) { return 0; }\n};
215 232 close($ch);
216 233 my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
217 234 my @sys_cmd;
@@ -219,21 +236,25 @@ sub assert_lib {
219 236 if ( $Config{cc} eq 'cl' ) { # Microsoft compiler
220 237 require Win32;
221 238 @sys_cmd = (
222   - @cc,
  239 + @$cc,
223 240 $cfile,
224 241 "/Fe$exefile",
225   - (map { '/I'.Win32::GetShortPathName($_) } @incpaths)
  242 + (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
  243 + "/link",
  244 + @$ld
226 245 );
227 246 } elsif($Config{cc} =~ /bcc32(\.exe)?/) { # Borland
228 247 @sys_cmd = (
229   - @cc,
  248 + @$cc,
  249 + @$ld,
230 250 (map { "-I$_" } @incpaths),
231 251 "-o$exefile",
232 252 $cfile
233 253 );
234 254 } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
235 255 @sys_cmd = (
236   - @cc,
  256 + @$cc,
  257 + @$ld,
237 258 $cfile,
238 259 (map { "-I$_" } @incpaths),
239 260 "-o", "$exefile"
@@ -241,8 +262,9 @@ sub assert_lib {
241 262 }
242 263 warn "# @sys_cmd\n" if $args{debug};
243 264 my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
244   - push @missing, $header if $rv != 0 || ! -x $exefile;
  265 + push @missing, $header if $rv != 0 || ! -x $exefile;
245 266 _cleanup_exe($exefile);
  267 + unlink $ofile if -e $ofile;
246 268 unlink $cfile;
247 269 }
248 270
@@ -250,6 +272,8 @@ sub assert_lib {
250 272 my($ch, $cfile) = File::Temp::tempfile(
251 273 'assertlibXXXXXXXX', SUFFIX => '.c'
252 274 );
  275 + my $ofile = $cfile;
  276 + $ofile =~ s/\.c$/$Config{_o}/;
253 277 print $ch qq{#include <$_>\n} foreach (@headers);
254 278 print $ch "int main(void) { ".($args{function} || 'return 0;')." }\n";
255 279 close($ch);
@@ -261,45 +285,52 @@ sub assert_lib {
261 285 my @libpath = map {
262 286 q{/libpath:} . Win32::GetShortPathName($_)
263 287 } @libpaths;
  288 + # this is horribly sensitive to the order of arguments
264 289 @sys_cmd = (
265   - @cc,
  290 + @$cc,
266 291 $cfile,
267 292 "${lib}.lib",
268 293 "/Fe$exefile",
269 294 (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
270 295 "/link",
  296 + @$ld,
271 297 (map {'/libpath:'.Win32::GetShortPathName($_)} @libpaths),
272 298 );
273 299 } elsif($Config{cc} eq 'CC/DECC') { # VMS
274 300 } elsif($Config{cc} =~ /bcc32(\.exe)?/) { # Borland
275 301 @sys_cmd = (
276   - @cc,
  302 + @$cc,
  303 + @$ld,
277 304 "-o$exefile",
278   - "-l$lib",
279 305 (map { "-I$_" } @incpaths),
280 306 (map { "-L$_" } @libpaths),
  307 + "-l$lib",
281 308 $cfile);
282 309 } else { # Unix-ish
283 310 # gcc, Sun, AIX (gcc, cc)
284 311 @sys_cmd = (
285   - @cc,
  312 + @$cc,
  313 + @$ld,
286 314 $cfile,
287 315 "-o", "$exefile",
288   - "-l$lib",
289 316 (map { "-I$_" } @incpaths),
290   - (map { "-L$_" } @libpaths)
  317 + (map { "-L$_" } @libpaths),
  318 + "-l$lib",
291 319 );
292 320 }
293 321 warn "# @sys_cmd\n" if $args{debug};
294 322 my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
295 323 push @missing, $lib if $rv != 0 || ! -x $exefile;
296   - push @wrongresult, $lib if $rv == 0 && -x $exefile && system(File::Spec->rel2abs($exefile)) != 0;
  324 + my $absexefile = File::Spec->rel2abs($exefile);
  325 + $absexefile = '"'.$absexefile.'"' if $absexefile =~ m/\s/;
  326 + push @wrongresult, $lib if $rv == 0 && -x $exefile && system($absexefile) != 0;
  327 + unlink $ofile if -e $ofile;
297 328 _cleanup_exe($exefile);
298 329 }
299 330 unlink $cfile;
300 331
301 332 my $miss_string = join( q{, }, map { qq{'$_'} } @missing );
302   - die("Can't link/include $miss_string\n") if @missing;
  333 + die("Can't link/include C library $miss_string, aborting.\n") if @missing;
303 334 my $wrong_string = join( q{, }, map { qq{'$_'} } @wrongresult);
304 335 die("wrong result: $wrong_string\n") if @wrongresult;
305 336 }
@@ -311,16 +342,37 @@ sub _cleanup_exe {
311 342 unlink $exefile if -f $exefile;
312 343 unlink $ofile if -f $ofile;
313 344 unlink "$exefile\.manifest" if -f "$exefile\.manifest";
  345 + if ( $Config{cc} eq 'cl' ) {
  346 + # MSVC also creates foo.ilk and foo.pdb
  347 + my $ilkfile = $exefile;
  348 + $ilkfile =~ s/$Config{_exe}$/.ilk/;
  349 + my $pdbfile = $exefile;
  350 + $pdbfile =~ s/$Config{_exe}$/.pdb/;
  351 + unlink $ilkfile if -f $ilkfile;
  352 + unlink $pdbfile if -f $pdbfile;
  353 + }
314 354 return
315 355 }
316 356
  357 +# return ($cc, $ld)
  358 +# where $cc is an array ref of compiler name, compiler flags
  359 +# where $ld is an array ref of linker flags
317 360 sub _findcc {
  361 + # Need to use $keep=1 to work with MSWin32 backslashes and quotes
  362 + my $Config_ccflags = $Config{ccflags}; # use copy so ASPerl will compile
  363 + my @Config_ldflags = ();
  364 + for my $config_val ( @Config{qw(ldflags perllibs)} ){
  365 + push @Config_ldflags, $config_val if ( $config_val =~ /\S/ );
  366 + }
  367 + my @ccflags = grep { length } quotewords('\s+', 1, $Config_ccflags||'');
  368 + my @ldflags = grep { length } quotewords('\s+', 1, @Config_ldflags);
318 369 my @paths = split(/$Config{path_sep}/, $ENV{PATH});
319 370 my @cc = split(/\s+/, $Config{cc});
320   - return @cc if -x $cc[0];
  371 + return ( [ @cc, @ccflags ], \@ldflags ) if -x $cc[0];
321 372 foreach my $path (@paths) {
322 373 my $compiler = File::Spec->catfile($path, $cc[0]) . $Config{_exe};
323   - return ($compiler, @cc[1 .. $#cc]) if -x $compiler;
  374 + return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags)
  375 + if -x $compiler;
324 376 }
325 377 die("Couldn't find your C compiler\n");
326 378 }
@@ -409,10 +461,14 @@ David Cantrell E<lt>david@cantrell.org.ukE<gt>
409 461
410 462 David Golden E<lt>dagolden@cpan.orgE<gt>
411 463
  464 +Yasuhiro Matsumoto E<lt>mattn@cpan.orgE<gt>
  465 +
412 466 Thanks to the cpan-testers-discuss mailing list for prompting us to write it
413 467 in the first place;
414 468
415   -to Chris Williams for help with Borland support.
  469 +to Chris Williams for help with Borland support;
  470 +
  471 +to Tony Cook for help with Microsoft compiler command-line options
416 472
417 473 =head1 COPYRIGHT and LICENCE
418 474

0 comments on commit b3fc8a2

Please sign in to comment.
Something went wrong with that request. Please try again.