]> err.no Git - dpkg/commitdiff
dpkg-shlibdeps: add some cases where the lack of dependency information is ignored
authorRaphael Hertzog <hertzog@debian.org>
Fri, 23 Nov 2007 09:46:37 +0000 (10:46 +0100)
committerRaphael Hertzog <hertzog@debian.org>
Fri, 23 Nov 2007 16:16:50 +0000 (17:16 +0100)
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.

ChangeLog
debian/changelog
scripts/Dpkg/Path.pm
scripts/dpkg-shlibdeps.pl

index 74dc96e0049bfc511d5b78d545816b2b71cd2a24..e1b30bf355ac27ff648d4ae5b91f358440efd28f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2007-11-23  Raphael Hertzog  <hertzog@debian.org>
+
+       * 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  <guillem@debian.org>
 
        * configure.ac: Bump version to 1.14.11~.
index 5eefeec7cbfb3886eded8624303d7fa89543671d..670187372be50bcc90a095ca064ab25ba01d0768 100644 (file)
@@ -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 <guillem@debian.org>  Fri, 23 Nov 2007 06:50:02 +0200
 
index 32d57fc9e26604efded64a39a908cceaf46f9982..93518e85d39327cf194d81399a458effe6501592 100644 (file)
@@ -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
index 5930eb788bef5892209e774c5cc07b05f09b5345..7223034987d371270e2a11775f4c32d432c2256c 100755 (executable)
@@ -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);