From: Raphael Hertzog Date: Fri, 23 Nov 2007 09:46:37 +0000 (+0100) Subject: dpkg-shlibdeps: add some cases where the lack of dependency information is ignored X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=362f81fe83102e65400dcc6f6e9d5f8d17e11b3f;p=dpkg dpkg-shlibdeps: add some cases where the lack of dependency information is ignored Look for libs in the package's build tree even if that package doesn't contain an shlibs file. Then don't complain about missing dependency information if the lib is in the same package than the binary. Also ignore it if the library is not versionned and can't have an shlibs file. --- diff --git a/ChangeLog b/ChangeLog index 74dc96e0..e1b30bf3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2007-11-23 Raphael Hertzog + + * scripts/dpkg-shlibdeps.pl: Look for libs in the package's build + tree even if that package doesn't contain an shlibs file. Then + don't complain about missing dependency information if the lib is in + the same package than the binary. Also ignore it if the library is + not versionned and can't have an shlibs file. + * scripts/Dpkg/Path.pm (guess_pkg_root_dir, + check_files_are_the_same): Add new helper functions. + 2007-11-23 Guillem Jover * configure.ac: Bump version to 1.14.11~. diff --git a/debian/changelog b/debian/changelog index 5eefeec7..67018737 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,9 @@ dpkg (1.14.11) UNRELEASED; urgency=low - * + * dpkg-shlibdeps now ignores the lack of dependency information in some + specific cases (instead of failing): + - when the library is in the same package than the binary analyzed + - when the library is not versionned and can't have a shlibs file -- Guillem Jover Fri, 23 Nov 2007 06:50:02 +0200 diff --git a/scripts/Dpkg/Path.pm b/scripts/Dpkg/Path.pm index 32d57fc9..93518e85 100644 --- a/scripts/Dpkg/Path.pm +++ b/scripts/Dpkg/Path.pm @@ -20,8 +20,10 @@ use strict; use warnings; use Exporter; +use Cwd qw(realpath); our @ISA = qw(Exporter); -our @EXPORT_OK = qw(get_pkg_root_dir relative_to_pkg_root); +our @EXPORT_OK = qw(get_pkg_root_dir relative_to_pkg_root + guess_pkg_root_dir check_files_are_the_same); =head1 NAME @@ -73,6 +75,50 @@ sub relative_to_pkg_root($) { return undef; } +=item guess_pkg_root_dir($file) + +This function tries to guess the root directory of the package build tree. +It will first use get_pkg_root_dir(), but it will fallback to a more +imprecise check: namely it will use the parent directory that is a +sub-directory of the debian directory. + +It can still return undef if a file outside of the debian sub-directory is +provided. + +=cut +sub guess_pkg_root_dir($) { + my $file = shift; + my $root = get_pkg_root_dir($file); + return $root if defined $root; + + $file =~ s{/+$}{}; + $file =~ s{/+[^/]+$}{} if not -d $file; + my $parent = $file; + while ($file) { + $parent =~ s{/+[^/]+$}{}; + last if not -d $parent; + return $file if check_files_are_the_same("debian", $parent); + $file = $parent; + last if $file !~ m{/}; + } + return undef; +} + +=item check_files_are_the_same($file1, $file2) + +This function verifies that both files are the same by checking that the device +numbers and the inode numbers returned by lstat() are the same. + +=cut +sub check_files_are_the_same($$) { + my ($file1, $file2) = @_; + return 0 if ((! -e $file1) || (! -e $file2)); + my @stat1 = lstat($file1); + my @stat2 = lstat($file2); + my $result = ($stat1[0] == $stat2[0]) && ($stat1[1] == $stat2[1]); + return $result; +} + =back =head1 AUTHOR diff --git a/scripts/dpkg-shlibdeps.pl b/scripts/dpkg-shlibdeps.pl index 5930eb78..72230349 100755 --- a/scripts/dpkg-shlibdeps.pl +++ b/scripts/dpkg-shlibdeps.pl @@ -9,7 +9,8 @@ use Cwd qw(realpath); use Dpkg; use Dpkg::Gettext; use Dpkg::ErrorHandling qw(warning error failure syserr usageerr); -use Dpkg::Path qw(relative_to_pkg_root); +use Dpkg::Path qw(relative_to_pkg_root guess_pkg_root_dir + check_files_are_the_same); use Dpkg::Version qw(vercmp); use Dpkg::Shlibs qw(find_library); use Dpkg::Shlibs::Objdump; @@ -158,9 +159,23 @@ foreach my $file (keys %exec) { my $libobj = $dumplibs_wo_symfile->get_object($id); # Only try to generate a dependency for libraries with a SONAME if ($libobj->is_public_library() and not add_shlibs_dep($soname, $pkg)) { + # This failure is fairly new, try to be kind by + # ignoring as many cases that can be safely ignored + my $ignore = 0; + # 1/ when the lib and the binary are in the same + # package + my $root_file = guess_pkg_root_dir($file); + my $root_lib = guess_pkg_root_dir($lib); + $ignore++ if defined $root_file and defined $root_lib + and check_files_are_the_same($root_file, $root_lib); + # 2/ when the lib is not versioned and can't be + # handled by shlibs + $ignore++ unless scalar(split_soname($soname)); + # 3/ when we have been asked to do so + $ignore++ if $ignore_missing_info; failure(_g("No dependency information found for %s " . "(used by %s)."), $soname, $file) - unless $ignore_missing_info; + unless $ignore; } } } @@ -361,15 +376,22 @@ sub add_shlibs_dep { return 0; } +sub split_soname { + my $soname = shift; + if ($soname =~ /^(.*)\.so\.(.*)$/) { + return wantarray ? ($1, $2) : 1; + } elsif ($soname =~ /^(.*)-(\d.*)\.so$/) { + return wantarray ? ($1, $2) : 1; + } else { + return wantarray ? () : 0; + } +} + sub extract_from_shlibs { my ($soname, $shlibfile) = @_; - my ($libname, $libversion); # Split soname in name/version - if ($soname =~ /^(.*)\.so\.(.*)$/) { - $libname = $1; $libversion = $2; - } elsif ($soname =~ /^(.*)-(.*)\.so$/) { - $libname = $1; $libversion = $2; - } else { + my ($libname, $libversion) = split_soname($soname); + unless (defined $libname) { warning(_g("Can't extract name and version from library name \`%s'"), $soname); return; @@ -466,10 +488,13 @@ sub my_find_library { } # Look into the packages we're currently building (but only those - # that provides shlibs file...) + # that provides shlibs file and the one that contains the binary being + # anlyzed...) # TODO: we should probably replace that by a cleaner way to look into # the various temporary build directories... my @copy = (@pkg_shlibs); + my $pkg_root = guess_pkg_root_dir($execfile); + unshift @copy, $pkg_root if defined $pkg_root; foreach my $builddir (map { s{/DEBIAN/shlibs$}{}; $_ } @copy) { $file = find_library($lib, \@RPATH, $format, $builddir); return $file if defined($file);