7 our $VERSION = "1.003";
9 my @alt_transfer = qw/altname incsuffix libbase/;
12 my ($class, $req) = @_;
14 $req->{verbose} ||= $ENV{IM_VERBOSE};
16 my $name = $req->{name};
19 $result = _probe_code($req);
21 if (!$result && $req->{pkg}) {
22 $result = _probe_pkg($req);
24 if (!$result && $req->{inccheck} && ($req->{libcheck} || $req->{libbase})) {
25 $req->{altname} ||= "main";
26 $result = _probe_check($req);
29 if ($result && $req->{testcode}) {
30 $result = _probe_test($req, $result);
33 if (!$result && $req->{alternatives}) {
36 for my $alt (@{$req->{alternatives}}) {
37 $req->{altname} = $alt->{altname} || "alt $index";
39 and print "$req->{name}: Trying alternative $index\n";
41 for my $key (@alt_transfer) {
42 exists $alt->{$key} and $work{$key} = $alt->{$key};
44 $result = _probe_check(\%work);
46 if ($result && $req->{testcode}) {
47 $result = _probe_test(\%work, $result);
57 if (!$result && $req->{testcode}) {
58 $result = _probe_fake($req);
62 $result = _probe_test($req, $result);
73 my $code = $req->{code};
74 my @probes = ref $code eq "ARRAY" ? @$code : $code;
77 for my $probe (@probes) {
78 $result = $probe->($req)
88 my @exe_suffix = $Config{_exe};
89 if ($^O eq 'MSWin32') {
90 push @exe_suffix, qw/.bat .cmd/;
93 for my $dir (File::Spec->path) {
94 for my $suffix (@exe_suffix) {
95 -x File::Spec->catfile($dir, "$name$suffix")
106 # Setup pkg-config's environment variable to search non-standard paths
107 # which may be provided by --libdirs.
108 my @pkgcfg_paths = map { "$_/pkgconfig" } _lib_paths( $req );
109 push @pkgcfg_paths, $ENV{ 'PKG_CONFIG_PATH' } if $ENV{ 'PKG_CONFIG_PATH' };
111 local $ENV{ 'PKG_CONFIG_PATH' } = join $Config{path_sep}, @pkgcfg_paths;
113 is_exe('pkg-config') or return;
114 my $redir = $^O eq 'MSWin32' ? '' : '2>/dev/null';
116 my @pkgs = @{$req->{pkg}};
117 for my $pkg (@pkgs) {
118 if (!system("pkg-config $pkg --exists $redir")) {
119 # if we find it, but the following fail, then pkg-config is too
120 # broken to be useful
121 my $cflags = `pkg-config $pkg --cflags`
124 my $lflags = `pkg-config $pkg --libs`
128 $cflags =~ s/(-D\S+)/$defines .= " $1"; ''/ge;
132 print "$req->{name}: Found via pkg-config $pkg\n";
133 print <<EOS if $req->{verbose};
139 # if Win32 doesn't provide this information, too bad
140 if (!grep(/^-L/, split " ", $lflags)
141 && $^O ne 'MSWin32') {
142 # pkg-config told us about the library, make sure it's
143 # somewhere EU::MM can find it
144 print "Checking if EU::MM can find $lflags\n" if $req->{verbose};
145 my ($extra, $bs_load, $ld_load, $ld_run_path) =
146 ExtUtils::Liblist->ext($lflags, $req->{verbose});
147 unless ($ld_run_path) {
148 # search our standard places
149 $lflags = _resolve_libs($req, $lflags);
162 print "$req->{name}: Not found via pkg-config\n";
168 return $Config{cc} eq "cl";
186 return $base . $Config{_a};
196 return $opt =~ /\s/ ? qq("$opt") : $opt;
204 if ($req->{libcheck}) {
205 if (ref $req->{libcheck} eq "ARRAY") {
206 push @libcheck, @{$req->{libcheck}};
209 push @libcheck, $req->{libcheck};
212 elsif ($req->{libbase}) {
213 @libbase = ref $req->{libbase} ? @{$req->{libbase}} : $req->{libbase};
215 my $lext=$Config{'so'}; # Get extensions of libraries
216 my $aext=$Config{'_a'};
218 for my $libbase (@libbase) {
219 my $basename = _lib_basename($libbase);
220 push @libcheck, sub {
221 -e File::Spec->catfile($_[0], "$basename$aext")
222 || -e File::Spec->catfile($_[0], "$basename.$lext")
227 print "$req->{name}: No libcheck or libbase, nothing to search for\n"
233 my @lib_search = _lib_paths($req);
234 print "$req->{name}: Searching directories for libraries:\n"
236 for my $libcheck (@libcheck) {
237 for my $path (@lib_search) {
238 print "$req->{name}: $path\n" if $req->{verbose};
239 if ($libcheck->($path)) {
240 print "$req->{name}: Found!\n" if $req->{verbose};
241 push @found_libpath, $path;
248 my $inccheck = $req->{inccheck};
249 my @inc_search = _inc_paths($req);
250 print "$req->{name}: Searching directories for headers:\n"
252 for my $path (@inc_search) {
253 print "$req->{name}: $path\n" if $req->{verbose};
254 if ($inccheck->($path)) {
255 print "$req->{name}: Found!\n" if $req->{verbose};
256 $found_incpath = $path;
262 if ($req->{altname}) {
263 $alt = " $req->{altname}:";
265 print "$req->{name}:$alt includes ", $found_incpath ? "" : "not ",
266 "found - libraries ", @found_libpath == @libcheck ? "" : "not ", "found\n";
268 @found_libpath == @libcheck && $found_incpath
271 my @libs = map "-L$_", @found_libpath;
272 if ($req->{libopts}) {
273 push @libs, $req->{libopts};
276 push @libs, map _lib_option($_), @libbase;
279 die "$req->{altname}: inccheck but no libbase or libopts";
284 INC => _quotearg("-I$found_incpath"),
285 LIBS => join(" ", map _quotearg($_), @libs),
293 # the caller provided test code, and the compiler may look in
294 # places we don't, see Imager-Screenshot ticket 56793,
295 # so fake up a result so the test code can
297 if ($req->{libopts}) {
298 $lopts = $req->{libopts};
300 elsif (defined $req->{libbase}) {
301 # might not need extra libraries, eg. Win32 perl already links
303 $lopts = $req->{libbase} ? "-l$req->{libbase}" : "";
305 if (defined $lopts) {
306 print "$req->{name}: Checking if the compiler can find them on its own\n";
315 print "$req->{name}: Can't fake it - no libbase or libopts\n"
322 my ($req, $result) = @_;
324 require Devel::CheckLib;
325 # setup LD_RUN_PATH to match link time
326 print "Asking liblist for LD_RUN_PATH:\n" if $req->{verbose};
327 my ($extra, $bs_load, $ld_load, $ld_run_path) =
328 ExtUtils::Liblist->ext($result->{LIBS}, $req->{verbose});
329 local $ENV{LD_RUN_PATH};
332 print "Setting LD_RUN_PATH=$ld_run_path for $req->{name} probe\n"
334 $ENV{LD_RUN_PATH} = $ld_run_path;
335 if ($Config{lddlflags} =~ /([^ ]*-(?:rpath|R)[,=]?)([^ ]+)/
338 # LD_RUN_PATH is ignored when there's already an -rpath option
341 $result->{LDDLFLAGS} = $Config{lddlflags} . " " .
342 join " ", map "$prefix$_", split $Config{path_sep}, $ld_run_path;
346 Devel::CheckLib::check_lib
348 debug => $req->{verbose},
349 LIBS => [ $result->{LIBS} ],
350 INC => $result->{INC},
351 header => $req->{testcodeheaders},
352 function => $req->{testcode},
353 prologue => $req->{testcodeprologue},
356 print "$req->{name}: Test code failed: $@";
360 print "$req->{name}: Passed code check\n";
365 my ($req, $lflags) = @_;
367 my @libs = grep /^-l/, split ' ', $lflags;
369 my @paths = _lib_paths($req);
370 my $so = $Config{so};
371 my $libext = $Config{_a};
372 for my $lib (@libs) {
375 for my $path (@paths) {
376 if (-e "$path/$lib.$so" || -e "$path/$lib$libext") {
382 return join(" ", ( map "-L$_", keys %paths ), $lflags );
395 @Config{qw/loclibpth libpth libspath/}
397 $^O eq "MSWin32" ? $ENV{LIB} : "",
398 $^O eq "cygwin" ? "/usr/lib/w32api" : "",
410 my ($base_version) = $Config{gccversion} =~ /^([0-9]+)/
416 local $ENV{LANG} = "C";
417 local $ENV{LC_ALL} = "C";
418 my ($lib_line) = grep /^libraries:/, `$Config{cc} -print-search-dirs`
420 $lib_line =~ s/^libraries: =//;
423 return grep !/gcc/ && -d, split /:/, $lib_line;
427 return map { defined() ? split /\Q$Config{path_sep}/ : () }
429 qw(LD_RUN_PATH LD_LIBRARY_PATH DYLD_LIBRARY_PATH LIBRARY_PATH);
439 $^O eq "MSWin32" ? $ENV{INCLUDE} : "",
440 $^O eq "cygwin" ? "/usr/include/w32api" : "",
444 @Config{qw/locincpth incpath/}
447 "/usr/local/include",
451 if ($req->{incsuffix}) {
452 @paths = map File::Spec->catdir($_, $req->{incsuffix}), @paths;
461 $tmp =~ s/\blib$/include/ ? $tmp : ()
470 # expand any array refs
471 @in = map { ref() ? @$_ : $_ } @in;
475 $path = _tilde_expand($path);
477 push @out, grep -d $_, split /\Q$Config{path_sep}/, $path;
480 @out = map Cwd::realpath($_), @out;
483 @out = grep !$seen{$_}++, @out;
492 if ($path =~ m!^~[/\\]!) {
493 defined $home or $home = $ENV{HOME};
494 if (!defined $home && $^O eq 'MSWin32'
495 && defined $ENV{HOMEDRIVE} && defined $ENV{HOMEPATH}) {
496 $home = $ENV{HOMEDRIVE} . $ENV{HOMEPATH};
498 unless (defined $home) {
499 $home = eval { (getpwuid($<))[7] };
501 defined $home or die "You supplied $path, but I can't find your home directory\n";
503 $path = File::Spec->catdir($home, $path);
515 Imager::Probe - hot needle of inquiry for libraries
519 require Imager::Probe;
523 # short name of what we're looking for (displayed to user)
526 pkg => [ qw/name1 name2 name3/ ],
527 # perl subs that probe for the library
528 code => [ \&foo_probe1, \&foo_probe2 ],
529 # or just: code => \&foo_probe,
530 inccheck => sub { ... },
531 libcheck => sub { ... },
532 # search for this library if libcheck not supplied
534 # library link time options, uses libbase to build options otherwise
536 # C code to check the library is sane
538 # header files needed
539 testcodeheaders => [ "stdio.h", "foo.h" ],
541 my $result = Imager::Probe->probe(\%probe)
542 or print "Foo library not found: ",Imager::Probe->error;
546 Does the probes that were hidden in Imager's F<Makefile.PL>, pulled
547 out so the file format libraries can be externalized.
549 The return value is either nothing if the probe fails, or a hash
556 C<INC> - C<-I> and other C options
560 C<LIBS> - C<-L>, C<-l> and other link-time options
564 C<DEFINE> - C<-D> options, if any.
568 The possible values for the hash supplied to the probe() method are:
574 C<pkg> - an array of F<pkg-config> names to probe for. If the
575 F<pkg-config> checks pass, C<inccheck> and C<libcheck> aren't used.
579 C<inccheck> - a code reference that checks if the supplied include
580 directory contains the required header files.
584 C<libcheck> - a code reference that checks if the supplied library
585 directory contains the required library files. Note: the
586 F<Makefile.PL> version of this was supplied all of the library file
587 names instead. C<libcheck> can also be an arrayref of library check
588 code references, all of which must find a match for the library to be
593 C<libbase> - if C<inccheck> is supplied, but C<libcheck> isn't, then a
594 C<libcheck> that checks for C<lib>I<libbase>I<$Config{_a}> and
595 C<lib>I<libbase>.I<$Config{so}> is created. If C<libopts> isn't
596 supplied then that can be synthesized as C<< -lI<libbase>
597 >>. C<libbase> can also be an arrayref of library base names to search
598 for, in which case all of the libraries mentioned must be found for
599 the probe to succeed.
603 C<libopts> - if the libraries are found via C<inccheck>/C<libcheck>,
604 these are the C<-l> options to supply during the link phase.
608 C<code> - a code reference to perform custom checks. Returns the
609 probe result directly. Can also be an array ref of functions to call.
613 C<testcode> - test C code that is run with Devel::CheckLib. You also
614 need to set C<testcodeheaders>.
618 C<testcodeprologue> - C code to insert between the headers and the
623 C<incpath> - C<$Config{path_sep}> separated list of header file
624 directories to check, or a reference to an array of such.
628 C<libpath> - C<$Config{path_sep}> separated list of library file
629 directories to check, or a reference to an array of such.
633 C<alternatives> - an optional array reference of alternate
634 configurations (as hash references) to test if the primary
635 configuration isn't successful. Each alternative should include an
636 C<altname> key describing the alternative. Any key not mentioned in
637 an alternative defaults to the value from the main configuration.
643 Tony Cook <tonyc@cpan.org>, Arnar M. Hrafnkelsson