7 my @alt_transfer = qw/altname incsuffix libbase/;
10 my ($class, $req) = @_;
12 $req->{verbose} ||= $ENV{IM_VERBOSE};
14 my $name = $req->{name};
17 $result = _probe_code($req);
19 if (!$result && $req->{pkg}) {
20 $result = _probe_pkg($req);
22 if (!$result && $req->{inccheck} && ($req->{libcheck} || $req->{libbase})) {
23 $req->{altname} ||= "main";
24 $result = _probe_check($req);
27 if ($result && $req->{testcode}) {
28 $result = _probe_test($req, $result);
31 if (!$result && $req->{alternatives}) {
34 for my $alt (@{$req->{alternatives}}) {
35 $req->{altname} = $alt->{altname} || "alt $index";
37 and print "$req->{name}: Trying alternative $index\n";
39 for my $key (@alt_transfer) {
40 exists $alt->{$key} and $work{$key} = $alt->{$key};
42 $result = _probe_check(\%work);
44 if ($result && $req->{testcode}) {
45 $result = _probe_test(\%work, $result);
55 if (!$result && $req->{testcode}) {
56 $result = _probe_fake($req);
60 $result = _probe_test($req, $result);
71 my $code = $req->{code};
72 my @probes = ref $code eq "ARRAY" ? @$code : $code;
75 for my $probe (@probes) {
76 $result = $probe->($req)
86 my @exe_suffix = $Config{_exe};
87 if ($^O eq 'MSWin32') {
88 push @exe_suffix, qw/.bat .cmd/;
91 for my $dir (File::Spec->path) {
92 for my $suffix (@exe_suffix) {
93 -x File::Spec->catfile($dir, "$name$suffix")
104 # Setup pkg-config's environment variable to search non-standard paths
105 # which may be provided by --libdirs.
106 my @pkgcfg_paths = map { "$_/pkgconfig" } _lib_paths( $req );
107 push @pkgcfg_paths, $ENV{ 'PKG_CONFIG_PATH' } if $ENV{ 'PKG_CONFIG_PATH' };
109 local $ENV{ 'PKG_CONFIG_PATH' } = join $Config{path_sep}, @pkgcfg_paths;
111 is_exe('pkg-config') or return;
112 my $redir = $^O eq 'MSWin32' ? '' : '2>/dev/null';
114 my @pkgs = @{$req->{pkg}};
115 for my $pkg (@pkgs) {
116 if (!system("pkg-config $pkg --exists $redir")) {
117 # if we find it, but the following fail, then pkg-config is too
118 # broken to be useful
119 my $cflags = `pkg-config $pkg --cflags`
122 my $lflags = `pkg-config $pkg --libs`
126 $cflags =~ s/(-D\S+)/$defines .= " $1"; ''/ge;
130 print "$req->{name}: Found via pkg-config $pkg\n";
131 print <<EOS if $req->{verbose};
137 # if Win32 doesn't provide this information, too bad
138 if (!grep(/^-L/, split " ", $lflags)
139 && $^O ne 'MSWin32') {
140 # pkg-config told us about the library, make sure it's
141 # somewhere EU::MM can find it
142 print "Checking if EU::MM can find $lflags\n" if $req->{verbose};
143 my ($extra, $bs_load, $ld_load, $ld_run_path) =
144 ExtUtils::Liblist->ext($lflags, $req->{verbose});
145 unless ($ld_run_path) {
146 # search our standard places
147 $lflags = _resolve_libs($req, $lflags);
160 print "$req->{name}: Not found via pkg-config\n";
166 return $Config{cc} eq "cl";
184 return $base . $Config{_a};
194 return $opt =~ /\s/ ? qq("$opt") : $opt;
202 if ($req->{libcheck}) {
203 if (ref $req->{libcheck} eq "ARRAY") {
204 push @libcheck, @{$req->{libcheck}};
207 push @libcheck, $req->{libcheck};
210 elsif ($req->{libbase}) {
211 @libbase = ref $req->{libbase} ? @{$req->{libbase}} : $req->{libbase};
213 my $lext=$Config{'so'}; # Get extensions of libraries
214 my $aext=$Config{'_a'};
216 for my $libbase (@libbase) {
217 my $basename = _lib_basename($libbase);
218 push @libcheck, sub {
219 -e File::Spec->catfile($_[0], "$basename$aext")
220 || -e File::Spec->catfile($_[0], "$basename.$lext")
225 print "$req->{name}: No libcheck or libbase, nothing to search for\n"
231 my @lib_search = _lib_paths($req);
232 print "$req->{name}: Searching directories for libraries:\n"
234 for my $libcheck (@libcheck) {
235 for my $path (@lib_search) {
236 print "$req->{name}: $path\n" if $req->{verbose};
237 if ($libcheck->($path)) {
238 print "$req->{name}: Found!\n" if $req->{verbose};
239 push @found_libpath, $path;
246 my $inccheck = $req->{inccheck};
247 my @inc_search = _inc_paths($req);
248 print "$req->{name}: Searching directories for headers:\n"
250 for my $path (@inc_search) {
251 print "$req->{name}: $path\n" if $req->{verbose};
252 if ($inccheck->($path)) {
253 print "$req->{name}: Found!\n" if $req->{verbose};
254 $found_incpath = $path;
260 if ($req->{altname}) {
261 $alt = " $req->{altname}:";
263 print "$req->{name}:$alt includes ", $found_incpath ? "" : "not ",
264 "found - libraries ", @found_libpath == @libcheck ? "" : "not ", "found\n";
266 @found_libpath == @libcheck && $found_incpath
269 my @libs = map "-L$_", @found_libpath;
270 if ($req->{libopts}) {
271 push @libs, $req->{libopts};
274 push @libs, map _lib_option($_), @libbase;
277 die "$req->{altname}: inccheck but no libbase or libopts";
282 INC => _quotearg("-I$found_incpath"),
283 LIBS => join(" ", map _quotearg($_), @libs),
291 # the caller provided test code, and the compiler may look in
292 # places we don't, see Imager-Screenshot ticket 56793,
293 # so fake up a result so the test code can
295 if ($req->{libopts}) {
296 $lopts = $req->{libopts};
298 elsif (defined $req->{libbase}) {
299 # might not need extra libraries, eg. Win32 perl already links
301 $lopts = $req->{libbase} ? "-l$req->{libbase}" : "";
303 if (defined $lopts) {
304 print "$req->{name}: Checking if the compiler can find them on its own\n";
313 print "$req->{name}: Can't fake it - no libbase or libopts\n"
320 my ($req, $result) = @_;
322 require Devel::CheckLib;
323 # setup LD_RUN_PATH to match link time
324 print "Asking liblist for LD_RUN_PATH:\n" if $req->{verbose};
325 my ($extra, $bs_load, $ld_load, $ld_run_path) =
326 ExtUtils::Liblist->ext($result->{LIBS}, $req->{verbose});
327 local $ENV{LD_RUN_PATH};
330 print "Setting LD_RUN_PATH=$ld_run_path for $req->{name} probe\n"
332 $ENV{LD_RUN_PATH} = $ld_run_path;
333 if ($Config{lddlflags} =~ /([^ ]*-(?:rpath|R)[,=]?)([^ ]+)/
336 # LD_RUN_PATH is ignored when there's already an -rpath option
339 $result->{LDDLFLAGS} = $Config{lddlflags} . " " .
340 join " ", map "$prefix$_", split $Config{path_sep}, $ld_run_path;
344 Devel::CheckLib::check_lib
346 debug => $req->{verbose},
347 LIBS => [ $result->{LIBS} ],
348 INC => $result->{INC},
349 header => $req->{testcodeheaders},
350 function => $req->{testcode},
351 prologue => $req->{testcodeprologue},
354 print "$req->{name}: Test code failed: $@";
358 print "$req->{name}: Passed code check\n";
363 my ($req, $lflags) = @_;
365 my @libs = grep /^-l/, split ' ', $lflags;
367 my @paths = _lib_paths($req);
368 my $so = $Config{so};
369 my $libext = $Config{_a};
370 for my $lib (@libs) {
373 for my $path (@paths) {
374 if (-e "$path/$lib.$so" || -e "$path/$lib$libext") {
380 return join(" ", ( map "-L$_", keys %paths ), $lflags );
393 @Config{qw/loclibpth libpth libspath/}
395 $^O eq "MSWin32" ? $ENV{LIB} : "",
396 $^O eq "cygwin" ? "/usr/lib/w32api" : "",
407 my ($base_version) = $Config{gccversion} =~ /^([0-9]+)/
413 my ($lib_line) = grep /^libraries:/, `$Config{cc} -print-search-dirs`
415 $lib_line =~ s/^libraries: =//;
418 return grep !/gcc/ && -d, split /:/, $lib_line;
428 $^O eq "MSWin32" ? $ENV{INCLUDE} : "",
429 $^O eq "cygwin" ? "/usr/include/w32api" : "",
433 @Config{qw/locincpth incpath/}
436 "/usr/local/include",
439 if ($req->{incsuffix}) {
440 @paths = map File::Spec->catdir($_, $req->{incsuffix}), @paths;
451 # expand any array refs
452 @in = map { ref() ? @$_ : $_ } @in;
456 $path = _tilde_expand($path);
458 push @out, grep -d $_, split /\Q$Config{path_sep}/, $path;
461 @out = map Cwd::realpath($_), @out;
464 @out = grep !$seen{$_}++, @out;
473 if ($path =~ m!^~[/\\]!) {
474 defined $home or $home = $ENV{HOME};
475 if (!defined $home && $^O eq 'MSWin32'
476 && defined $ENV{HOMEDRIVE} && defined $ENV{HOMEPATH}) {
477 $home = $ENV{HOMEDRIVE} . $ENV{HOMEPATH};
479 unless (defined $home) {
480 $home = eval { (getpwuid($<))[7] };
482 defined $home or die "You supplied $path, but I can't find your home directory\n";
484 $path = File::Spec->catdir($home, $path);
496 Imager::Probe - hot needle of inquiry for libraries
500 require Imager::Probe;
504 # short name of what we're looking for (displayed to user)
507 pkg => [ qw/name1 name2 name3/ ],
508 # perl subs that probe for the library
509 code => [ \&foo_probe1, \&foo_probe2 ],
510 # or just: code => \&foo_probe,
511 inccheck => sub { ... },
512 libcheck => sub { ... },
513 # search for this library if libcheck not supplied
515 # library link time options, uses libbase to build options otherwise
517 # C code to check the library is sane
519 # header files needed
520 testcodeheaders => [ "stdio.h", "foo.h" ],
522 my $result = Imager::Probe->probe(\%probe)
523 or print "Foo library not found: ",Imager::Probe->error;
527 Does the probes that were hidden in Imager's F<Makefile.PL>, pulled
528 out so the file format libraries can be externalized.
530 The return value is either nothing if the probe fails, or a hash
537 C<INC> - C<-I> and other C options
541 C<LIBS> - C<-L>, C<-l> and other link-time options
545 C<DEFINE> - C<-D> options, if any.
549 The possible values for the hash supplied to the probe() method are:
555 C<pkg> - an array of F<pkg-config> names to probe for. If the
556 F<pkg-config> checks pass, C<inccheck> and C<libcheck> aren't used.
560 C<inccheck> - a code reference that checks if the supplied include
561 directory contains the required header files.
565 C<libcheck> - a code reference that checks if the supplied library
566 directory contains the required library files. Note: the
567 F<Makefile.PL> version of this was supplied all of the library file
568 names instead. C<libcheck> can also be an arrayref of library check
569 code references, all of which must find a match for the library to be
574 C<libbase> - if C<inccheck> is supplied, but C<libcheck> isn't, then a
575 C<libcheck> that checks for C<lib>I<libbase>I<$Config{_a}> and
576 C<lib>I<libbase>.I<$Config{so}> is created. If C<libopts> isn't
577 supplied then that can be synthesized as C<< -lI<libbase>
578 >>. C<libbase> can also be an arrayref of library base names to search
579 for, in which case all of the libraries mentioned must be found for
580 the probe to succeed.
584 C<libopts> - if the libraries are found via C<inccheck>/C<libcheck>,
585 these are the C<-l> options to supply during the link phase.
589 C<code> - a code reference to perform custom checks. Returns the
590 probe result directly. Can also be an array ref of functions to call.
594 C<testcode> - test C code that is run with Devel::CheckLib. You also
595 need to set C<testcodeheaders>.
599 C<testcodeprologue> - C code to insert between the headers and the
604 C<incpath> - C<$Config{path_sep}> separated list of header file
605 directories to check, or a reference to an array of such.
609 C<libpath> - C<$Config{path_sep}> separated list of library file
610 directories to check, or a reference to an array of such.
614 C<alternatives> - an optional array reference of alternate
615 configurations (as hash references) to test if the primary
616 configuration isn't successful. Each alternative should include an
617 C<altname> key describing the alternative. Any key not mentioned in
618 an alternative defaults to the value from the main configuration.