use strict;
use File::Spec;
use Config;
+use Cwd ();
+
+my @alt_transfer = qw/altname incsuffix libbase/;
sub probe {
my ($class, $req) = @_;
$result = _probe_pkg($req);
}
if (!$result && $req->{inccheck} && ($req->{libcheck} || $req->{libbase})) {
+ $req->{altname} ||= "main";
$result = _probe_check($req);
}
+ if (!$result && $req->{alternatives}) {
+ ALTCHECK:
+ my $index = 1;
+ for my $alt (@{$req->{alternatives}}) {
+ $req->{altname} = $alt->{altname} || "alt $index";
+ $req->{verbose}
+ and print "$req->{name}: Trying alternative $index\n";
+ my %work = %$req;
+ for my $key (@alt_transfer) {
+ exists $alt->{$key} and $work{$key} = $alt->{$key};
+ }
+ $result = _probe_check(\%work)
+ and last;
+ ++$index;
+ }
+ }
if (!$result && $req->{testcode}) {
$result = _probe_fake($req);
my $lflags = `pkg-config $pkg --libs`
and !$? or return;
+ my $defines = '';
+ $cflags =~ s/(-D\S+)/$defines .= " $1"; ''/ge;
+
chomp $cflags;
chomp $lflags;
print "$req->{name}: Found via pkg-config $pkg\n";
{
INC => $cflags,
LIBS => $lflags,
+ DEFINE => $defines,
};
}
}
return;
}
+sub _is_msvc {
+ return $Config{cc} eq "cl";
+}
+
+sub _lib_basename {
+ my ($base) = @_;
+
+ if (_is_msvc()) {
+ return $base;
+ }
+ else {
+ return "lib$base";
+ }
+}
+
+sub _lib_option {
+ my ($base) = @_;
+
+ if (_is_msvc()) {
+ return $base . $Config{_a};
+ }
+ else {
+ return "-l$base";
+ }
+}
+
+sub _quotearg {
+ my ($opt) = @_;
+
+ return $opt =~ /\s/ ? qq("$opt") : $opt;
+}
+
sub _probe_check {
my ($req) = @_;
# synthesize a libcheck
my $lext=$Config{'so'}; # Get extensions of libraries
my $aext=$Config{'_a'};
+ my $basename = _lib_basename($libbase);
$libcheck = sub {
- -e File::Spec->catfile($_[0], "lib$libbase$aext")
- || -e File::Spec->catfile($_[0], "lib$libbase.$lext")
+ -e File::Spec->catfile($_[0], "$basename$aext")
+ || -e File::Spec->catfile($_[0], "$basename.$lext")
};
}
}
}
- print "$req->{name}: includes ", $found_incpath ? "" : "not ",
+ my $alt = "";
+ if ($req->{altname}) {
+ $alt = " $req->{altname}:";
+ }
+ print "$req->{name}:$alt includes ", $found_incpath ? "" : "not ",
"found - libraries ", $found_libpath ? "" : "not ", "found\n";
$found_libpath && $found_incpath
push @libs, $req->{libopts};
}
elsif ($libbase) {
- push @libs, "-l$libbase";
+ push @libs, _lib_option($libbase);
}
else {
- die "$req->{name}: inccheck but no libbase or libopts";
+ die "$req->{altname}: inccheck but no libbase or libopts";
}
return
{
- INC => "-I$found_incpath",
- LIBS => "@libs",
+ INC => _quotearg("-I$found_incpath"),
+ LIBS => join(" ", map _quotearg($_), @libs),
+ DEFINE => "",
};
}
$lopts = $req->{libbase} ? "-l$req->{libbase}" : "";
}
if (defined $lopts) {
- print "$req->{name}: Checking if the compiler can find them on it's own\n";
+ print "$req->{name}: Checking if the compiler can find them on its own\n";
return
{
INC => "",
LIBS => $lopts,
+ DEFINE => "",
};
}
else {
print "Setting LD_RUN_PATH=$ld_run_path for $req->{name} probe\n"
if $req->{verbose};
$ENV{LD_RUN_PATH} = $ld_run_path;
+ if ($Config{lddlflags} =~ /([^ ]*-(?:rpath|R)[,=]?)([^ ]+)/
+ && -d $2) {
+ # hackety, hackety
+ # LD_RUN_PATH is ignored when there's already an -rpath option
+ # so provide one
+ my $prefix = $1;
+ $result->{LDDLFLAGS} = $Config{lddlflags} . " " .
+ join " ", map "$prefix$_", split $Config{path_sep}, $ld_run_path;
+ }
}
my $good =
Devel::CheckLib::check_lib
INC => $result->{INC},
header => $req->{testcodeheaders},
function => $req->{testcode},
+ prologue => $req->{testcodeprologue},
);
unless ($good) {
print "$req->{name}: Test code failed: $@";
(
map { split ' ' }
grep $_,
- @Config{qw/loclibpath libpth libspath/}
+ @Config{qw/loclibpth libpth libspath/}
),
$^O eq "MSWin32" ? $ENV{LIB} : "",
$^O eq "cygwin" ? "/usr/lib/w32api" : "",
+ "/usr/lib",
+ "/usr/local/lib",
+ _gcc_lib_paths(),
);
}
+sub _gcc_lib_paths {
+ $Config{gccversion}
+ or return;
+
+ my ($base_version) = $Config{gccversion} =~ /^([0-9]+)/
+ or return;
+
+ $base_version >= 4
+ or return;
+
+ my ($lib_line) = grep /^libraries:/, `$Config{cc} -print-search-dirs`
+ or return;
+ $lib_line =~ s/^libraries: =//;
+ chomp $lib_line;
+
+ return grep !/gcc/ && -d, split /:/, $lib_line;
+}
+
sub _inc_paths {
my ($req) = @_;
- return _paths
+ my @paths = _paths
(
$ENV{IM_INCPATH},
$req->{incpath},
(
map { split ' ' }
grep $_,
- @Config{qw/locincpath incpath/}
+ @Config{qw/locincpth incpath/}
),
"/usr/include",
"/usr/local/include",
);
+
+ if ($req->{incsuffix}) {
+ @paths = map File::Spec->catdir($_, $req->{incsuffix}), @paths;
+ }
+
+ return @paths;
}
sub _paths {
my @out;
+ # expand any array refs
+ @in = map { ref() ? @$_ : $_ } @in;
+
for my $path (@in) {
$path or next;
$path = _tilde_expand($path);
push @out, grep -d $_, split /\Q$Config{path_sep}/, $path;
}
+ @out = map Cwd::realpath($_), @out;
+
+ my %seen;
+ @out = grep !$seen{$_}++, @out;
+
return @out;
}
C<LIBS> - C<-L>, C<-l> and other link-time options
+=item *
+
+C<DEFINE> - C<-D> options, if any.
+
=back
The possible values for the hash supplied to the probe() method are:
=item *
+C<testcodeprologue> - C code to insert between the headers and the
+main function.
+
+=item *
+
C<incpath> - C<$Config{path_sep}> separated list of header file
-directories to check.
+directories to check, or a reference to an array of such.
=item *
C<libpath> - C<$Config{path_sep}> separated list of library file
-directories to check.
+directories to check, or a reference to an array of such.
=back