File Coverage

blib/lib/Devel/CheckLib.pm
Criterion Covered Total %
statement 159 208 76.4
branch 76 130 58.4
condition 15 28 53.5
subroutine 15 16 93.7
pod 3 4 75.0
total 268 386 69.4


line stmt bran cond sub pod time code
1             # $Id: CheckLib.pm,v 1.25 2008/10/27 12:16:23 drhyde Exp $
2              
3             package Devel::CheckLib;
4              
5 11     11   7565 use 5.00405; #postfix foreach
  11         31  
6 11     11   46 use strict;
  11         17  
  11         228  
7 11     11   45 use vars qw($VERSION @ISA @EXPORT);
  11         18  
  11         626  
8             $VERSION = '1.14';
9 11     11   63 use Config qw(%Config);
  11         22  
  11         393  
10 11     11   4464 use Text::ParseWords 'quotewords';
  11         12302  
  11         520  
11              
12 11     11   63 use File::Spec;
  11         18  
  11         252  
13 11     11   2291 use File::Temp;
  11         55557  
  11         1929  
14              
15             require Exporter;
16             @ISA = qw(Exporter);
17             @EXPORT = qw(assert_lib check_lib_or_exit check_lib);
18              
19             # localising prevents the warningness leaking out of this module
20             local $^W = 1; # use warnings is a 5.6-ism
21              
22             _findcc(); # bomb out early if there's no compiler
23              
24             =head1 NAME
25              
26             Devel::CheckLib - check that a library is available
27              
28             =head1 DESCRIPTION
29              
30             Devel::CheckLib is a perl module that checks whether a particular C
31             library and its headers are available.
32              
33             =head1 SYNOPSIS
34              
35             use Devel::CheckLib;
36              
37             check_lib_or_exit( lib => 'jpeg', header => 'jpeglib.h' );
38             check_lib_or_exit( lib => [ 'iconv', 'jpeg' ] );
39            
40             # or prompt for path to library and then do this:
41             check_lib_or_exit( lib => 'jpeg', libpath => $additional_path );
42              
43             =head1 USING IT IN Makefile.PL or Build.PL
44              
45             If you want to use this from Makefile.PL or Build.PL, do
46             not simply copy the module into your distribution as this may cause
47             problems when PAUSE and search.cpan.org index the distro. Instead, use
48             the use-devel-checklib script.
49              
50             =head1 HOW IT WORKS
51              
52             You pass named parameters to a function, describing to it how to build
53             and link to the libraries.
54              
55             It works by trying to compile some code - which defaults to this:
56              
57             int main(int argc, char *argv[]) { return 0; }
58              
59             and linking it to the specified libraries. If something pops out the end
60             which looks executable, it gets executed, and if main() returns 0 we know
61             that it worked. That tiny program is
62             built once for each library that you specify, and (without linking) once
63             for each header file.
64              
65             If you want to check for the presence of particular functions in a
66             library, or even that those functions return particular results, then
67             you can pass your own function body for main() thus:
68              
69             check_lib_or_exit(
70             function => 'foo();if(libversion() > 5) return 0; else return 1;'
71             incpath => ...
72             libpath => ...
73             lib => ...
74             header => ...
75             );
76              
77             In that case, it will fail to build if either foo() or libversion() don't
78             exist, and main() will return the wrong value if libversion()'s return
79             value isn't what you want.
80              
81             =head1 FUNCTIONS
82              
83             All of these take the same named parameters and are exported by default.
84             To avoid exporting them, C<use Devel::CheckLib ()>.
85              
86             =head2 assert_lib
87              
88             This takes several named parameters, all of which are optional, and dies
89             with an error message if any of the libraries listed can
90             not be found. B<Note>: dying in a Makefile.PL or Build.PL may provoke
91             a 'FAIL' report from CPAN Testers' automated smoke testers. Use
92             C<check_lib_or_exit> instead.
93              
94             The named parameters are:
95              
96             =over
97              
98             =item lib
99              
100             Must be either a string with the name of a single
101             library or a reference to an array of strings of library names. Depending
102             on the compiler found, library names will be fed to the compiler either as
103             C<-l> arguments or as C<.lib> file names. (E.g. C<-ljpeg> or C<jpeg.lib>)
104              
105             =item libpath
106              
107             a string or an array of strings
108             representing additional paths to search for libraries.
109              
110             =item LIBS
111              
112             a C<ExtUtils::MakeMaker>-style space-separated list of
113             libraries (each preceded by '-l') and directories (preceded by '-L').
114              
115             This can also be supplied on the command-line.
116              
117             =item debug
118              
119             If true - emit information during processing that can be used for
120             debugging.
121              
122             =back
123              
124             And libraries are no use without header files, so ...
125              
126             =over
127              
128             =item header
129              
130             Must be either a string with the name of a single
131             header file or a reference to an array of strings of header file names.
132              
133             =item incpath
134              
135             a string or an array of strings
136             representing additional paths to search for headers.
137              
138             =item INC
139              
140             a C<ExtUtils::MakeMaker>-style space-separated list of
141             incpaths, each preceded by '-I'.
142              
143             This can also be supplied on the command-line.
144              
145             =item ccflags
146              
147             Extra flags to pass to the compiler.
148              
149             =item ldflags
150              
151             Extra flags to pass to the linker.
152              
153             =item analyze_binary
154              
155             a callback function that will be invoked in order to perform custom
156             analysis of the generated binary. The callback arguments are the
157             library name and the path to the binary just compiled.
158              
159             It is possible to use this callback, for instance, to inspect the
160             binary for further dependencies.
161              
162             =item not_execute
163              
164             Do not try to execute generated binary. Only check that compilation has not failed.
165              
166             =back
167              
168             =head2 check_lib_or_exit
169              
170             This behaves exactly the same as C<assert_lib()> except that instead of
171             dieing, it warns (with exactly the same error message) and exits.
172             This is intended for use in Makefile.PL / Build.PL
173             when you might want to prompt the user for various paths and
174             things before checking that what they've told you is sane.
175              
176             If any library or header is missing, it exits with an exit value of 0 to avoid
177             causing a CPAN Testers 'FAIL' report. CPAN Testers should ignore this
178             result -- which is what you want if an external library dependency is not
179             available.
180              
181             =head2 check_lib
182              
183             This behaves exactly the same as C<assert_lib()> except that it is silent,
184             returning false instead of dieing, or true otherwise.
185              
186             =cut
187              
188             sub check_lib_or_exit {
189 0     0 1 0 eval 'assert_lib(@_)';
190 0 0       0 if($@) {
191 0         0 warn $@;
192 0         0 exit;
193             }
194             }
195              
196             sub check_lib {
197 8     8 1 19923 eval 'assert_lib(@_)';
198 8 100       333 return $@ ? 0 : 1;
199             }
200              
201             # borrowed from Text::ParseWords
202             sub _parse_line {
203 31     31   178 my($delimiter, $keep, $line) = @_;
204 31         95 my($word, @pieces);
205              
206 11     11   82 no warnings 'uninitialized'; # we will be testing undef strings
  11         27  
  11         26550  
207              
208 31         157 while (length($line)) {
209             # This pattern is optimised to be stack conservative on older perls.
210             # Do not refactor without being careful and testing it on very long strings.
211             # See Perl bug #42980 for an example of a stack busting input.
212 0 0       0 $line =~ s/^
213             (?:
214             # double quoted string
215             (") # $quote
216             ((?>[^\\"]*(?:\\.[^\\"]*)*))" # $quoted
217             | # --OR--
218             # singe quoted string
219             (') # $quote
220             ((?>[^\\']*(?:\\.[^\\']*)*))' # $quoted
221             | # --OR--
222             # unquoted string
223             ( # $unquoted
224             (?:\\.|[^\\"'])*?
225             )
226             # followed by
227             ( # $delim
228             \Z(?!\n) # EOL
229             | # --OR--
230             (?-x:$delimiter) # delimiter
231             | # --OR--
232             (?!^)(?=["']) # a quote
233             )
234             )//xs or return; # extended layout
235 0 0       0 my ($quote, $quoted, $unquoted, $delim) = (($1 ? ($1,$2) : ($3,$4)), $5, $6);
236              
237 0 0 0     0 return() unless( defined($quote) || length($unquoted) || length($delim));
      0        
238              
239 0 0       0 if ($keep) {
240 0         0 $quoted = "$quote$quoted$quote";
241             }
242             else {
243 0         0 $unquoted =~ s/\\(.)/$1/sg;
244 0 0       0 if (defined $quote) {
245 0 0       0 $quoted =~ s/\\(.)/$1/sg if ($quote eq '"');
246             }
247             }
248 0         0 $word .= substr($line, 0, 0); # leave results tainted
249 0 0       0 $word .= defined $quote ? $quoted : $unquoted;
250              
251 0 0       0 if (length($delim)) {
252 0         0 push(@pieces, $word);
253 0 0       0 push(@pieces, $delim) if ($keep eq 'delimiters');
254 0         0 undef $word;
255             }
256 0 0       0 if (!length($line)) {
257 0         0 push(@pieces, $word);
258             }
259             }
260 31         95 return(@pieces);
261             }
262              
263             sub assert_lib {
264 31     31 1 97674 my %args = @_;
265 31         93 my (@libs, @libpaths, @headers, @incpaths);
266              
267             # FIXME: these four just SCREAM "refactor" at me
268 8         43 @libs = (ref($args{lib}) ? @{$args{lib}} : $args{lib})
269 31 100       229 if $args{lib};
    100          
270 0         0 @libpaths = (ref($args{libpath}) ? @{$args{libpath}} : $args{libpath})
271 31 50       158 if $args{libpath};
    100          
272 0         0 @headers = (ref($args{header}) ? @{$args{header}} : $args{header})
273 31 50       160 if $args{header};
    100          
274 1         3 @incpaths = (ref($args{incpath}) ? @{$args{incpath}} : $args{incpath})
275 31 100       238 if $args{incpath};
    100          
276 31         347 my $analyze_binary = $args{analyze_binary};
277 31         68 my $not_execute = $args{not_execute};
278              
279 31         86 my @argv = @ARGV;
280 31   50     430 push @argv, _parse_line('\s+', 0, $ENV{PERL_MM_OPT}||'');
281              
282             # work-a-like for Makefile.PL's LIBS and INC arguments
283             # if given as command-line argument, append to %args
284 31         97 for my $arg (@argv) {
285 0         0 for my $mm_attr_key (qw(LIBS INC)) {
286 0 0       0 if (my ($mm_attr_value) = $arg =~ /\A $mm_attr_key = (.*)/x) {
287             # it is tempting to put some \s* into the expression, but the
288             # MM command-line parser only accepts LIBS etc. followed by =,
289             # so we should not be any more lenient with whitespace than that
290 0         0 $args{$mm_attr_key} .= " $mm_attr_value";
291             }
292             }
293             }
294              
295             # using special form of split to trim whitespace
296 31 100       118 if(defined($args{LIBS})) {
297 1         4 foreach my $arg (split(' ', $args{LIBS})) {
298 3 50       18 die("LIBS argument badly-formed: $arg\n") unless($arg =~ /^-[lLR]/);
299 3 100       5 push @{$arg =~ /^-l/ ? \@libs : \@libpaths}, substr($arg, 2);
  3         13  
300             }
301             }
302 31 100       99 if(defined($args{INC})) {
303 2         8 foreach my $arg (split(' ', $args{INC})) {
304 3 100       29 die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
305 2         15 push @incpaths, substr($arg, 2);
306             }
307             }
308              
309 30         202 my ($cc, $ld) = _findcc($args{debug}, $args{ccflags}, $args{ldflags});
310 30         160 my @missing;
311             my @wrongresult;
312 30         0 my @wronganalysis;
313 30         0 my @use_headers;
314              
315             # first figure out which headers we can't find ...
316 30         80 for my $header (@headers) {
317 13         27 push @use_headers, $header;
318 13         48 my($ch, $cfile) = File::Temp::tempfile(
319             'assertlibXXXXXXXX', SUFFIX => '.c'
320             );
321 13         4387 my $ofile = $cfile;
322 13         319 $ofile =~ s/\.c$/$Config{_o}/;
323 13         196 print $ch qq{#include <$_>\n} for @use_headers;
324 13         39 print $ch qq{int main(void) { return 0; }\n};
325 13         432 close($ch);
326 13         105 my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
327 13         1797 my @sys_cmd;
328             # FIXME: re-factor - almost identical code later when linking
329 13 50       111 if ( $Config{cc} eq 'cl' ) { # Microsoft compiler
    50          
330 0         0 require Win32;
331             @sys_cmd = (
332             @$cc,
333             $cfile,
334             "/Fe$exefile",
335 0         0 (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
336             "/link",
337             @$ld,
338 0         0 split(' ', $Config{libs}),
339             );
340             } elsif($Config{cc} =~ /bcc32(\.exe)?/) { # Borland
341             @sys_cmd = (
342             @$cc,
343             @$ld,
344 0         0 (map { "-I$_" } @incpaths),
  0         0  
345             "-o$exefile",
346             $cfile
347             );
348             } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
349             @sys_cmd = (
350             @$cc,
351 13         43 (map { "-I$_" } @incpaths),
  14         91  
352             $cfile,
353             @$ld,
354             "-o", "$exefile"
355             );
356             }
357 13 50       51 warn "# @sys_cmd\n" if $args{debug};
358 13 50       71 my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
359 13 100 66     553 push @missing, $header if $rv != 0 || ! -f $exefile;
360 13         179 _cleanup_exe($exefile);
361 13         755 unlink $cfile;
362             }
363              
364             # now do each library in turn with headers
365 30         662 my($ch, $cfile) = File::Temp::tempfile(
366             'assertlibXXXXXXXX', SUFFIX => '.c'
367             );
368 30         15733 my $ofile = $cfile;
369 30         569 $ofile =~ s/\.c$/$Config{_o}/;
370 30         389 print $ch qq{#include <$_>\n} foreach (@headers);
371 30   100     520 print $ch "int main(int argc, char *argv[]) { ".($args{function} || 'return 0;')." }\n";
372 30         1083 close($ch);
373 30         242 for my $lib ( @libs ) {
374 35         463 my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
375 35         8070 my @sys_cmd;
376 35 50       503 if ( $Config{cc} eq 'cl' ) { # Microsoft compiler
    50          
    50          
377 0         0 require Win32;
378             my @libpath = map {
379 0         0 q{/libpath:} . Win32::GetShortPathName($_)
  0         0  
380             } @libpaths;
381             # this is horribly sensitive to the order of arguments
382             @sys_cmd = (
383             @$cc,
384             $cfile,
385             "${lib}.lib",
386             "/Fe$exefile",
387 0         0 (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
388             "/link",
389             @$ld,
390             split(' ', $Config{libs}),
391 0         0 (map {'/libpath:'.Win32::GetShortPathName($_)} @libpaths),
  0         0  
392             );
393             } elsif($Config{cc} eq 'CC/DECC') { # VMS
394             } elsif($Config{cc} =~ /bcc32(\.exe)?/) { # Borland
395             @sys_cmd = (
396             @$cc,
397             @$ld,
398             "-o$exefile",
399 0         0 (map { "-I$_" } @incpaths),
400 0         0 (map { "-L$_" } @libpaths),
  0         0  
401             "-l$lib",
402             $cfile);
403             } else { # Unix-ish
404             # gcc, Sun, AIX (gcc, cc)
405             @sys_cmd = (
406             @$cc,
407 9         57 (map { "-I$_" } @incpaths),
408             $cfile,
409 35         218 (map { "-L$_" } @libpaths),
  13         217  
410             "-l$lib",
411             @$ld,
412             "-o", "$exefile",
413             );
414             }
415 35 50       309 warn "# @sys_cmd\n" if $args{debug};
416 35 50       605 local $ENV{LD_RUN_PATH} = join(":", grep $_, @libpaths, $ENV{LD_RUN_PATH}) unless $^O eq 'MSWin32';
417 35 50       141 local $ENV{PATH} = join(";", @libpaths).";".$ENV{PATH} if $^O eq 'MSWin32';
418 35 50       162 my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
419 35 100 66     1203 if ($rv != 0 || ! -f $exefile) {
420 11         58 push @missing, $lib;
421             }
422             else {
423 24         596 chmod 0755, $exefile;
424 24         3180 my $absexefile = File::Spec->rel2abs($exefile);
425 24 50       512 $absexefile = '"'.$absexefile.'"' if $absexefile =~ m/\s/;
426 24 100 66     130728 if (!$not_execute && system($absexefile) != 0) {
427 2         109 push @wrongresult, $lib;
428             }
429             else {
430 22 100       319 if ($analyze_binary) {
431 2 100       63 push @wronganalysis, $lib if !$analyze_binary->($lib, $exefile)
432             }
433             }
434             }
435 35         4007 _cleanup_exe($exefile);
436             }
437 30         1198 unlink $cfile;
438              
439 30         296 my $miss_string = join( q{, }, map { qq{'$_'} } @missing );
  12         234  
440 30 100       964 die("Can't link/include C library $miss_string, aborting.\n") if @missing;
441 20         137 my $wrong_string = join( q{, }, map { qq{'$_'} } @wrongresult);
  2         26  
442 20 100       271 die("wrong result: $wrong_string\n") if @wrongresult;
443 18         127 my $analysis_string = join(q{, }, map { qq{'$_'} } @wronganalysis );
  1         19  
444 18 100       1499 die("wrong analysis: $analysis_string") if @wronganalysis;
445             }
446              
447             sub _cleanup_exe {
448 48     48   420 my ($exefile) = @_;
449 48         322 my $ofile = $exefile;
450 48         4387 $ofile =~ s/$Config{_exe}$/$Config{_o}/;
451             # List of files to remove
452 48         215 my @rmfiles;
453 48         452 push @rmfiles, $exefile, $ofile, "$exefile\.manifest";
454 48 50       695 if ( $Config{cc} eq 'cl' ) {
455             # MSVC also creates foo.ilk and foo.pdb
456 0         0 my $ilkfile = $exefile;
457 0         0 $ilkfile =~ s/$Config{_exe}$/.ilk/;
458 0         0 my $pdbfile = $exefile;
459 0         0 $pdbfile =~ s/$Config{_exe}$/.pdb/;
460 0         0 push @rmfiles, $ilkfile, $pdbfile;
461             }
462 48         387 foreach (@rmfiles) {
463 144 100       2225 if ( -f $_ ) {
464 36 50       2310 unlink $_ or warn "Could not remove $_: $!";
465             }
466             }
467             return
468 48         1394 }
469            
470             # return ($cc, $ld)
471             # where $cc is an array ref of compiler name, compiler flags
472             # where $ld is an array ref of linker flags
473             sub _findcc {
474 41     41   213 my ($debug, $user_ccflags, $user_ldflags) = @_;
475             # Need to use $keep=1 to work with MSWin32 backslashes and quotes
476 41         985 my $Config_ccflags = $Config{ccflags}; # use copy so ASPerl will compile
477 41         143 my @Config_ldflags = ();
478 41         220 for my $config_val ( @Config{qw(ldflags)} ){
479 41 50       1052 push @Config_ldflags, $config_val if ( $config_val =~ /\S/ );
480             }
481 41   50     1329 my @ccflags = grep { length } quotewords('\s+', 1, $Config_ccflags||'', $user_ccflags||'');
  288   100     11541  
482 41 100 50     486 my @ldflags = grep { length && $_ !~ m/^-Wl/ } quotewords('\s+', 1, @Config_ldflags, $user_ldflags||'');
  123         4742  
483 41         767 my @paths = split(/$Config{path_sep}/, $ENV{PATH});
484 41         334 my @cc = split(/\s+/, $Config{cc});
485 41 100       209 if (check_compiler ($cc[0], $debug)) {
486 1         5 return ( [ @cc, @ccflags ], \@ldflags );
487             }
488             # Find the extension for executables.
489 40         644 my $exe = $Config{_exe};
490 40 50       295 if ($^O eq 'cygwin') {
491 0         0 $exe = '';
492             }
493 40         99 foreach my $path (@paths) {
494             # Look for "$path/$cc[0].exe"
495 243         1674 my $compiler = File::Spec->catfile($path, $cc[0]) . $exe;
496 243 100       522 if (check_compiler ($compiler, $debug)) {
497 39         344 return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags)
498             }
499 204 50       457 next if ! $exe;
500             # Look for "$path/$cc[0]" without the .exe, if necessary.
501 0         0 $compiler = File::Spec->catfile($path, $cc[0]);
502 0 0       0 if (check_compiler ($compiler, $debug)) {
503 0         0 return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags)
504             }
505             }
506 1         29 die("Couldn't find your C compiler.\n");
507             }
508              
509             sub check_compiler
510             {
511 284     284 0 478 my ($compiler, $debug) = @_;
512 284 100 66     3820 if (-f $compiler && -x $compiler) {
513 40 50       122 if ($debug) {
514 0         0 warn("# Compiler seems to be $compiler\n");
515             }
516 40         119 return 1;
517             }
518 244         749 return '';
519             }
520              
521              
522             # code substantially borrowed from IPC::Run3
523             sub _quiet_system {
524 66     66   82780 my (@cmd) = @_;
525              
526             # save handles
527 66         285 local *STDOUT_SAVE;
528 66         370 local *STDERR_SAVE;
529 66 50       2158 open STDOUT_SAVE, ">&STDOUT" or die "CheckLib: $! saving STDOUT";
530 66 50       1647 open STDERR_SAVE, ">&STDERR" or die "CheckLib: $! saving STDERR";
531            
532             # redirect to nowhere
533 66         294 local *DEV_NULL;
534 66 50       3184 open DEV_NULL, ">" . File::Spec->devnull
535             or die "CheckLib: $! opening handle to null device";
536 66 50       2023 open STDOUT, ">&" . fileno DEV_NULL
537             or die "CheckLib: $! redirecting STDOUT to null handle";
538 66 50       1622 open STDERR, ">&" . fileno DEV_NULL
539             or die "CheckLib: $! redirecting STDERR to null handle";
540              
541             # run system command
542 66         3546345 my $rv = system(@cmd);
543              
544             # restore handles
545 66 50       5859 open STDOUT, ">&" . fileno STDOUT_SAVE
546             or die "CheckLib: $! restoring STDOUT handle";
547 66 50       1509 open STDERR, ">&" . fileno STDERR_SAVE
548             or die "CheckLib: $! restoring STDERR handle";
549              
550 66         5297 return $rv;
551             }
552              
553             =head1 PLATFORMS SUPPORTED
554              
555             You must have a C compiler installed. We check for C<$Config{cc}>,
556             both literally as it is in Config.pm and also in the $PATH.
557              
558             It has been tested with varying degrees of rigorousness on:
559              
560             =over
561              
562             =item gcc (on Linux, *BSD, Mac OS X, Solaris, Cygwin)
563              
564             =item Sun's compiler tools on Solaris
565              
566             =item IBM's tools on AIX
567              
568             =item SGI's tools on Irix 6.5
569              
570             =item Microsoft's tools on Windows
571              
572             =item MinGW on Windows (with Strawberry Perl)
573              
574             =item Borland's tools on Windows
575              
576             =item QNX
577              
578             =back
579              
580             =head1 WARNINGS, BUGS and FEEDBACK
581              
582             This is a very early release intended primarily for feedback from
583             people who have discussed it. The interface may change and it has
584             not been adequately tested.
585              
586             Feedback is most welcome, including constructive criticism.
587             Bug reports should be made using L<http://rt.cpan.org/> or by email.
588              
589             When submitting a bug report, please include the output from running:
590              
591             perl -V
592             perl -MDevel::CheckLib -e0
593              
594             =head1 SEE ALSO
595              
596             L<Devel::CheckOS>
597              
598             L<Probe::Perl>
599              
600             =head1 AUTHORS
601              
602             David Cantrell E<lt>david@cantrell.org.ukE<gt>
603              
604             David Golden E<lt>dagolden@cpan.orgE<gt>
605              
606             Yasuhiro Matsumoto E<lt>mattn@cpan.orgE<gt>
607              
608             Thanks to the cpan-testers-discuss mailing list for prompting us to write it
609             in the first place;
610              
611             to Chris Williams for help with Borland support;
612              
613             to Tony Cook for help with Microsoft compiler command-line options
614              
615             =head1 COPYRIGHT and LICENCE
616              
617             Copyright 2007 David Cantrell. Portions copyright 2007 David Golden.
618              
619             This module is free-as-in-speech software, and may be used, distributed,
620             and modified under the same conditions as perl itself.
621              
622             =head1 CONSPIRACY
623              
624             This module is also free-as-in-mason software.
625              
626             =cut
627              
628             1;