8 our $VERSION = "1.007";
10 my @alt_transfer = qw/altname incsuffix libbase/;
13 my ($class, $req) = @_;
15 $req->{verbose} ||= $ENV{IM_VERBOSE};
17 my $name = $req->{name};
20 $result = _probe_code($req);
22 if (!$result && $req->{pkg}) {
23 $result = _probe_pkg($req);
25 if (!$result && $req->{inccheck} && ($req->{libcheck} || $req->{libbase})) {
26 $req->{altname} ||= "main";
27 $result = _probe_check($req);
30 if ($result && $req->{testcode}) {
31 $result = _probe_test($req, $result);
34 if (!$result && $req->{alternatives}) {
37 for my $alt (@{$req->{alternatives}}) {
38 $req->{altname} = $alt->{altname} || "alt $index";
40 and print "$req->{name}: Trying alternative $index\n";
42 for my $key (@alt_transfer) {
43 exists $alt->{$key} and $work{$key} = $alt->{$key};
45 $result = _probe_check(\%work);
47 if ($result && $req->{testcode}) {
48 $result = _probe_test(\%work, $result);
58 if (!$result && $req->{testcode}) {
59 $result = _probe_fake($req);
63 $result = _probe_test($req, $result);
74 my $code = $req->{code};
75 my @probes = ref $code eq "ARRAY" ? @$code : $code;
78 for my $probe (@probes) {
79 $result = $probe->($req)
89 my @exe_suffix = $Config{_exe};
90 if ($^O eq 'MSWin32') {
91 push @exe_suffix, qw/.bat .cmd/;
93 elsif ($^O eq 'cygwin') {
97 for my $dir (File::Spec->path) {
98 for my $suffix (@exe_suffix) {
99 -x File::Spec->catfile($dir, "$name$suffix")
110 # Setup pkg-config's environment variable to search non-standard paths
111 # which may be provided by --libdirs.
112 my @pkgcfg_paths = map { "$_/pkgconfig" } _lib_paths( $req );
113 push @pkgcfg_paths, $ENV{ 'PKG_CONFIG_PATH' } if $ENV{ 'PKG_CONFIG_PATH' };
115 local $ENV{ 'PKG_CONFIG_PATH' } = join $Config{path_sep}, @pkgcfg_paths;
117 is_exe('pkg-config') or return;
118 my $redir = $^O eq 'MSWin32' ? '' : '2>/dev/null';
120 my @pkgs = @{$req->{pkg}};
121 for my $pkg (@pkgs) {
122 if (!system("pkg-config $pkg --exists $redir")) {
123 # if we find it, but the following fail, then pkg-config is too
124 # broken to be useful
125 my $cflags = `pkg-config $pkg --cflags`
128 my $lflags = `pkg-config $pkg --libs`
132 $cflags =~ s/(-D\S+)/$defines .= " $1"; ''/ge;
136 print "$req->{name}: Found via pkg-config $pkg\n";
137 print <<EOS if $req->{verbose};
143 # if Win32 doesn't provide this information, too bad
144 if (!grep(/^-L/, split " ", $lflags)
145 && $^O ne 'MSWin32') {
146 # pkg-config told us about the library, make sure it's
147 # somewhere EU::MM can find it
148 print "Checking if EU::MM can find $lflags\n" if $req->{verbose};
149 my ($extra, $bs_load, $ld_load, $ld_run_path) =
150 ExtUtils::Liblist->ext($lflags, $req->{verbose});
151 unless ($ld_run_path) {
152 # search our standard places
153 $lflags = _resolve_libs($req, $lflags);
166 print "$req->{name}: Not found via pkg-config\n";
172 return $Config{cc} eq "cl";
190 return $base . $Config{_a};
200 return $opt =~ /\s/ ? qq("$opt") : $opt;
208 if ($req->{libcheck}) {
209 if (ref $req->{libcheck} eq "ARRAY") {
210 push @libcheck, @{$req->{libcheck}};
213 push @libcheck, $req->{libcheck};
216 elsif ($req->{libbase}) {
217 @libbase = ref $req->{libbase} ? @{$req->{libbase}} : $req->{libbase};
219 my $lext=$Config{'so'}; # Get extensions of libraries
220 my $aext=$Config{'_a'};
222 for my $libbase (@libbase) {
223 my $basename = _lib_basename($libbase);
224 push @libcheck, sub {
225 -e File::Spec->catfile($_[0], "$basename$aext")
226 || -e File::Spec->catfile($_[0], "$basename.$lext")
231 print "$req->{name}: No libcheck or libbase, nothing to search for\n"
237 my @lib_search = _lib_paths($req);
238 print "$req->{name}: Searching directories for libraries:\n"
240 for my $libcheck (@libcheck) {
241 for my $path (@lib_search) {
242 print "$req->{name}: $path\n" if $req->{verbose};
243 if ($libcheck->($path)) {
244 print "$req->{name}: Found!\n" if $req->{verbose};
245 push @found_libpath, $path;
252 my $inccheck = $req->{inccheck};
253 my @inc_search = _inc_paths($req);
254 print "$req->{name}: Searching directories for headers:\n"
256 for my $path (@inc_search) {
257 print "$req->{name}: $path\n" if $req->{verbose};
258 if ($inccheck->($path)) {
259 print "$req->{name}: Found!\n" if $req->{verbose};
260 $found_incpath = $path;
266 if ($req->{altname}) {
267 $alt = " $req->{altname}:";
269 print "$req->{name}:$alt includes ", $found_incpath ? "" : "not ",
270 "found - libraries ", @found_libpath == @libcheck ? "" : "not ", "found\n";
272 @found_libpath == @libcheck && $found_incpath
275 my @libs = map "-L$_", @found_libpath;
276 if ($req->{libopts}) {
277 push @libs, $req->{libopts};
280 push @libs, map _lib_option($_), @libbase;
283 die "$req->{altname}: inccheck but no libbase or libopts";
288 INC => _quotearg("-I$found_incpath"),
289 LIBS => join(" ", map _quotearg($_), @libs),
297 # the caller provided test code, and the compiler may look in
298 # places we don't, see Imager-Screenshot ticket 56793,
299 # so fake up a result so the test code can
301 if ($req->{libopts}) {
302 $lopts = $req->{libopts};
304 elsif (defined $req->{libbase}) {
305 # might not need extra libraries, eg. Win32 perl already links
307 my @libs = $req->{libbase}
308 ? ( ref $req->{libbase} ? @{$req->{libbase}} : $req->{libbase} )
310 $lopts = join " ", map _lib_option($_), @libs;
312 if (defined $lopts) {
313 print "$req->{name}: Checking if the compiler can find them on its own\n";
322 print "$req->{name}: Can't fake it - no libbase or libopts\n"
329 my ($req, $result) = @_;
331 require Devel::CheckLib;
332 # setup LD_RUN_PATH to match link time
333 print "Asking liblist for LD_RUN_PATH:\n" if $req->{verbose};
334 my ($extra, $bs_load, $ld_load, $ld_run_path) =
335 ExtUtils::Liblist->ext($result->{LIBS}, $req->{verbose});
336 local $ENV{LD_RUN_PATH};
339 print "Setting LD_RUN_PATH=$ld_run_path for $req->{name} probe\n"
341 $ENV{LD_RUN_PATH} = $ld_run_path;
342 if ($Config{lddlflags} =~ /([^ ]*-(?:rpath|R)[,=]?)([^ ]+)/
345 # LD_RUN_PATH is ignored when there's already an -rpath option
348 $result->{LDDLFLAGS} = $Config{lddlflags} . " " .
349 join " ", map "$prefix$_", split $Config{path_sep}, $ld_run_path;
353 Devel::CheckLib::check_lib
355 debug => $req->{verbose},
356 LIBS => [ $result->{LIBS} ],
357 INC => $result->{INC},
358 header => $req->{testcodeheaders},
359 function => $req->{testcode},
360 prologue => $req->{testcodeprologue},
363 print "$req->{name}: Test code failed: $@";
367 print "$req->{name}: Passed code check\n";
372 my ($req, $lflags) = @_;
374 my @libs = grep /^-l/, split ' ', $lflags;
376 my @paths = _lib_paths($req);
377 my $so = $Config{so};
378 my $libext = $Config{_a};
379 for my $lib (@libs) {
382 for my $path (@paths) {
383 if (-e "$path/$lib.$so" || -e "$path/$lib$libext") {
389 return join(" ", ( map "-L$_", keys %paths ), $lflags );
395 print "$req->{name} IM_LIBPATH: $ENV{IM_LIBPATH}\n"
396 if $req->{verbose} && defined $ENV{IM_LIBPATH};
397 print "$req->{name} LIB: $ENV{IM_LIBPATH}\n"
398 if $req->{verbose} && defined $ENV{LIB} && $^O eq "MSWin32";
399 my $lp = $req->{libpath};
400 print "$req->{name} libpath: ", ref $lp ? join($Config{path_sep}, @$lp) : $lp, "\n"
401 if $req->{verbose} && defined $lp;
410 @Config{qw/loclibpth libpth libspath/}
412 $^O eq "MSWin32" ? $ENV{LIB} : "",
413 $^O eq "cygwin" ? "/usr/lib/w32api" : "",
425 my ($base_version) = $Config{gccversion} =~ /^([0-9]+)/
431 local $ENV{LANG} = "C";
432 local $ENV{LC_ALL} = "C";
433 my ($lib_line) = grep /^libraries:/, `$Config{cc} -print-search-dirs`
435 $lib_line =~ s/^libraries: =//;
438 return grep !/gcc/ && -d, split /:/, $lib_line;
442 return map { defined() ? split /\Q$Config{path_sep}/ : () }
444 qw(LD_RUN_PATH LD_LIBRARY_PATH DYLD_LIBRARY_PATH LIBRARY_PATH);
450 print "$req->{name} IM_INCPATH: $ENV{IM_INCPATH}\n"
451 if $req->{verbose} && defined $ENV{IM_INCPATH};
452 print "$req->{name} INCLUDE: $ENV{INCLUDE}\n"
453 if $req->{verbose} && defined $ENV{INCLUDE} && $^O eq "MSWin32";
454 my $ip = $req->{incpath};
455 print "$req->{name} incpath: ", ref $ip ? join($Config{path_sep}, @$ip) : $ip, "\n"
456 if $req->{verbose} && defined $req->{incpath};
462 $^O eq "MSWin32" ? $ENV{INCLUDE} : "",
463 $^O eq "cygwin" ? "/usr/include/w32api" : "",
467 @Config{qw/locincpth incpath/}
470 "/usr/local/include",
475 if ($req->{incsuffix}) {
476 @paths = map File::Spec->catdir($_, $req->{incsuffix}), @paths;
486 my ($base_version) = $Config{gccversion} =~ /^([0-9]+)/
492 local $ENV{LANG} = "C";
493 local $ENV{LC_ALL} = "C";
494 my $devnull = File::Spec->devnull;
495 my @spam = `$Config{cc} -E -v - <$devnull 2>&1`;
496 # output includes lines like:
498 # ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../x86_64-linux-gnu/include"
499 # #include "..." search starts here:
500 # #include <...> search starts here:
501 # /usr/lib/gcc/x86_64-linux-gnu/4.9/include
503 # /usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed
504 # /usr/include/x86_64-linux-gnu
506 # End of search list.
511 while (@spam && $spam[0] !~ /^#include /) {
515 while (@spam && $spam[0] !~ /^End of search/) {
516 my $line = shift @spam;
518 next if $line =~ /^#include /;
519 next unless $line =~ s/^\s+//;
528 $tmp =~ s/\blib$/include/ ? $tmp : ()
537 # expand any array refs
538 @in = map { ref() ? @$_ : $_ } @in;
542 $path = _tilde_expand($path);
544 push @out, grep -d $_, split /\Q$Config{path_sep}/, $path;
547 @out = map Cwd::realpath($_), @out;
550 @out = grep !$seen{$_}++, @out;
559 if ($path =~ m!^~[/\\]!) {
560 defined $home or $home = $ENV{HOME};
561 if (!defined $home && $^O eq 'MSWin32'
562 && defined $ENV{HOMEDRIVE} && defined $ENV{HOMEPATH}) {
563 $home = $ENV{HOMEDRIVE} . $ENV{HOMEPATH};
565 unless (defined $home) {
566 $home = eval { (getpwuid($<))[7] };
568 defined $home or die "You supplied $path, but I can't find your home directory\n";
570 $path = File::Spec->catdir($home, $path);
582 Imager::Probe - hot needle of inquiry for libraries
586 require Imager::Probe;
590 # short name of what we're looking for (displayed to user)
593 pkg => [ qw/name1 name2 name3/ ],
594 # perl subs that probe for the library
595 code => [ \&foo_probe1, \&foo_probe2 ],
596 # or just: code => \&foo_probe,
597 inccheck => sub { ... },
598 libcheck => sub { ... },
599 # search for this library if libcheck not supplied
601 # library link time options, uses libbase to build options otherwise
603 # C code to check the library is sane
605 # header files needed
606 testcodeheaders => [ "stdio.h", "foo.h" ],
608 my $result = Imager::Probe->probe(\%probe)
609 or print "Foo library not found: ",Imager::Probe->error;
613 Does the probes that were hidden in Imager's F<Makefile.PL>, pulled
614 out so the file format libraries can be externalized.
616 The return value is either nothing if the probe fails, or a hash
623 C<INC> - C<-I> and other C options
627 C<LIBS> - C<-L>, C<-l> and other link-time options
631 C<DEFINE> - C<-D> options, if any.
635 The possible values for the hash supplied to the probe() method are:
641 C<pkg> - an array of F<pkg-config> names to probe for. If the
642 F<pkg-config> checks pass, C<inccheck> and C<libcheck> aren't used.
646 C<inccheck> - a code reference that checks if the supplied include
647 directory contains the required header files.
651 C<libcheck> - a code reference that checks if the supplied library
652 directory contains the required library files. Note: the
653 F<Makefile.PL> version of this was supplied all of the library file
654 names instead. C<libcheck> can also be an arrayref of library check
655 code references, all of which must find a match for the library to be
660 C<libbase> - if C<inccheck> is supplied, but C<libcheck> isn't, then a
661 C<libcheck> that checks for C<lib>I<libbase>I<$Config{_a}> and
662 C<lib>I<libbase>.I<$Config{so}> is created. If C<libopts> isn't
663 supplied then that can be synthesized as C<< -lI<libbase>
664 >>. C<libbase> can also be an arrayref of library base names to search
665 for, in which case all of the libraries mentioned must be found for
666 the probe to succeed.
670 C<libopts> - if the libraries are found via C<inccheck>/C<libcheck>,
671 these are the C<-l> options to supply during the link phase.
675 C<code> - a code reference to perform custom checks. Returns the
676 probe result directly. Can also be an array ref of functions to call.
680 C<testcode> - test C code that is run with Devel::CheckLib. You also
681 need to set C<testcodeheaders>.
685 C<testcodeprologue> - C code to insert between the headers and the
690 C<incpath> - C<$Config{path_sep}> separated list of header file
691 directories to check, or a reference to an array of such.
695 C<libpath> - C<$Config{path_sep}> separated list of library file
696 directories to check, or a reference to an array of such.
700 C<alternatives> - an optional array reference of alternate
701 configurations (as hash references) to test if the primary
702 configuration isn't successful. Each alternative should include an
703 C<altname> key describing the alternative. Any key not mentioned in
704 an alternative defaults to the value from the main configuration.
710 Tony Cook <tonyc@cpan.org>, Arnar M. Hrafnkelsson