]> err.no Git - dpkg/commitdiff
dpkg-shlibdeps: new warning about useless libraries, new --warnings option
authorRaphael Hertzog <hertzog@debian.org>
Tue, 25 Mar 2008 10:33:06 +0000 (11:33 +0100)
committerRaphael Hertzog <hertzog@debian.org>
Tue, 25 Mar 2008 10:33:06 +0000 (11:33 +0100)
* scripts/dpkg-shlibdeps.pl: Let the user configure the set of
warnings that he wants. Add a new warning for useless libraries
on all binaries analyzed. Disable by default the warning that
does the same but individually, for each binary analyzed.
* man/dpkg-shlibdeps.1: Update manual page accordingly.

ChangeLog
debian/changelog
man/dpkg-shlibdeps.1
scripts/dpkg-shlibdeps.pl

index fc0316f65ef8808b0d071e19d777ea63b0b6080e..06c5ffe6a1f6eb3d3beee7db9fb4c82b2d2b893b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2008-03-25  Raphael Hertzog  <hertzog@debian.org>
+
+       * scripts/dpkg-shlibdeps.pl: Let the user configure the set of
+       warnings that he wants. Add a new warning for useless libraries
+       on all binaries analyzed. Disable by default the warning that
+       does the same but individually, for each binary analyzed.
+       * man/dpkg-shlibdeps.1: Update manual page accordingly.
+
 2008-03-25  Ian Jackson  <ian@davenant.greenend.org.uk>
 
        * lib/dpkg-db.h (modstatdb_note_ifwrite): New prototype.
index f28d30f0cec50d702b0c3bf139f30915cee4b971..0cc4250c223fa6202d076753cd5bba4cb3a16ddb 100644 (file)
@@ -80,6 +80,12 @@ dpkg (1.14.17) UNRELEASED; urgency=low
     discarded one. Added a test case for this.
   * dpkg-shlibdeps properly accounts usage of symbols provided by private
     libraries without SONAME. Closes: #469838
+  * Add a new warning to dpkg-shlibdeps when a library NEEDED is in fact
+    not used by any of the binaries analyzed. Closes: #472332
+  * Add a new --warnings=<value> option to select the set of warnings to
+    activate. By default, do not activate the warning about useless
+    libraries at the binary level (instead the new warning above is activated
+    by default: it's less strict and more useful).
 
   [ Frank Lichtenheld ]
   * Add a warning in dpkg-buildpackage if the build-dependencies are not
index 6677abce1e526284bb1c956066e6d52086772014..38db7d9160811a356cde3ce5dd03ea542ab45764 100644 (file)
@@ -1,4 +1,4 @@
-.TH dpkg\-shlibdeps 1 "2007-07-16" "Debian Project" "dpkg utilities"
+.TH dpkg\-shlibdeps 1 "2008-03-25" "Debian Project" "dpkg utilities"
 .SH NAME
 dpkg\-shlibdeps \- generate shared library substvar dependencies
 .
@@ -199,6 +199,17 @@ Usage of this option is discouraged, all libraries should provide
 dependency information (either with shlibs files, or with symbols files)
 even if they are not yet used by other packages.  
 .TP
+.BI \-\-warnings= value
+\fIvalue\fP is a bit field defining the set of warnings that
+can be emitted by \fBdpkg-\-shlibdeps\fP.
+Bit 0 (value=1) enables the warning "symbol \fIsym\fP used by \fIbinary\fP
+found in none of the libraries", bit 1 (value=2) enables the warning
+"dependency on \fIlibrary\fP could be avoided" and bit 2 (value=4)
+enables the warning "\fIbinary\fP shouldn't be linked with \fIlibrary\fP".
+The default \fIvalue\fP is 3: the first two warnings are active by
+default, the last one is not. Set \fIvalue\fP to 7 if you want all
+warnings to be active.
+.TP
 .BI \-\-admindir= dir
 Change the location of the \fBdpkg\fR database. The default location is
 \fI/var/lib/dpkg\fP.
@@ -224,18 +235,18 @@ binary. The \fIbinary\fR is most likely a library and it needs to be linked
 with an additional library during the build process (option \fB-l\fR\fIlibrary\fR
 of the linker).
 .TP
+.BI "dependency on " library " could be avoided if " binaries " were not uselessly linked against it (they use none of its symbols)."
+None of the \fIbinaries\fP that are linked with \fPlibrary\fP use any of the
+symbols provided by the library. By fixing all the binaries, you would avoid
+the dependency associated to this library (unless the same dependency is
+also generated by another library that is really used).
+.TP
 .IB binary " shouldn't be linked with " library " (it uses none of its symbols)."
 The \fIbinary\fR is linked to a library that it doesn't need. It's not a
-problem but some small performance improvements in binary load time
-can be obtained by not linking this library to this binary. 
-
-Furthermore, in some cases, this will lead to a non-versioned dependency
-on the library that could have been avoided if the binary was only linked
-against libraries that it really uses. The exception to this rule is
-when several binaries are linked against the same set of libraries but
-each binary only uses a subset of those. You will have warnings on
-individual binaries, but the set of libraries needed at the package level
-is the same whether you fix the binaries or not.
+problem but some small performance improvements in binary load time can be
+obtained by not linking this library to this binary. This warning checks
+the same information than the previous one but does it for each binary
+instead of doing the check globally on all binaries analyzed.
 .SH ERRORS
 .B dpkg\-shlibdeps
 will fail if it can't find a public library used by a binary or if this
@@ -310,7 +321,7 @@ Copyright (C) 2000 Wichert Akkerman
 .br
 Copyright (C) 2006 Frank Lichtenheld
 .br
-Copyright (C) 2007 Rapha\[:e]l Hertzog
+Copyright (C) 2007-2008 Rapha\[:e]l Hertzog
 .sp
 This is free software; see the GNU General Public Licence version 2 or later
 for copying conditions. There is NO WARRANTY.
index 8cb9890f5c5264c1826f3ee32664874889ea2c6c..11a72df3dc9aec5427ead42f53d712f0e2a80760 100755 (executable)
@@ -20,6 +20,12 @@ use Dpkg::Fields qw(capit);
 use Dpkg::Deps;
 use Dpkg::Control;
 
+use constant {
+    WARN_SYM_NOT_FOUND => 1,
+    WARN_DEP_AVOIDABLE => 2,
+    WARN_NOT_NEEDED => 4,
+};
+
 # By increasing importance
 my @depfields = qw(Suggests Recommends Depends Pre-Depends);
 my $i = 0; my %depstrength = map { $_ => $i++ } @depfields;
@@ -34,6 +40,7 @@ my $dependencyfield = 'Depends';
 my $varlistfile = 'debian/substvars';
 my $varnameprefix = 'shlibs';
 my $ignore_missing_info = 0;
+my $warnings = 3;
 my $debug = 0;
 my @exclude = ();
 my @pkg_dir_to_search = ();
@@ -82,6 +89,8 @@ foreach (@ARGV) {
        }
     } elsif (m/^--ignore-missing-info$/) {
        $ignore_missing_info = 1;
+    } elsif (m/^--warnings=(\d+)$/) {
+       $warnings = $1;
     } elsif (m/^-t(.*)$/) {
        $packagetype = $1;
     } elsif (m/^-v$/) {
@@ -113,6 +122,12 @@ my $build_deps = Dpkg::Deps::parse($build_depends, reduce_arch => 1);
 my %dependencies;
 my %shlibs;
 
+# Statictics on soname seen in the whole run (with multiple analysis of
+# binaries)
+my %global_soname_notfound;
+my %global_soname_used;
+my %global_soname_needed;
+
 my $cur_field;
 foreach my $file (keys %exec) {
     $cur_field = $exec{$file};
@@ -130,6 +145,7 @@ foreach my $file (keys %exec) {
        my $lib = my_find_library($soname, $obj->{RPATH}, $obj->{format}, $file);
        unless (defined $lib) {
            $soname_notfound{$soname} = 1;
+           $global_soname_notfound{$soname} = 1;
            my $msg = _g("couldn't find library %s needed by %s (its RPATH is '%s').\n" .
                         "Note: libraries are not searched in other binary packages " .
                         "that do not have any shlibs or symbols file.\nTo help dpkg-shlibdeps " .
@@ -228,7 +244,17 @@ foreach my $file (keys %exec) {
 
     # Scan all undefined symbols of the binary and resolve to a
     # dependency
-    my %used_sonames = map { $_ => 0 } @sonames;
+    my %soname_used;
+    foreach (@sonames) {
+        # Initialize statistics
+        $soname_used{$_} = 0;
+        $global_soname_used{$_} = 0 unless exists $global_soname_used{$_};
+        if (exists $global_soname_needed{$_}) {
+            push @{$global_soname_needed{$_}}, $file;
+        } else {
+            $global_soname_needed{$_} = [ $file ];
+        }
+    }
     my $nb_warnings = 0;
     my $nb_skipped_warnings = 0;
     # Disable warnings about missing symbols when we have not been able to
@@ -245,10 +271,12 @@ foreach my $file (keys %exec) {
        my $symdep = $symfile->lookup_symbol($name, \@sonames);
        if (defined($symdep)) {
             print " Found in symbols file of $symdep->{soname}\n" if $debug > 1;
-           $used_sonames{$symdep->{soname}}++;
+           $soname_used{$symdep->{soname}}++;
+           $global_soname_used{$symdep->{soname}}++;
             if (exists $alt_soname{$symdep->{soname}}) {
                 # Also count usage on alternate soname
-                $used_sonames{$alt_soname{$symdep->{soname}}}++;
+                $soname_used{$alt_soname{$symdep->{soname}}}++;
+                $global_soname_used{$alt_soname{$symdep->{soname}}}++;
             }
            update_dependency_version($symdep->{depends},
                                      $symdep->{minver});
@@ -256,6 +284,7 @@ foreach my $file (keys %exec) {
            my $syminfo = $dumplibs_wo_symfile->locate_symbol($name);
            if (not defined($syminfo)) {
                 print " Not found\n" if $debug > 1;
+                next unless ($warnings & WARN_SYM_NOT_FOUND);
                next if $disable_warnings;
                # Complain about missing symbols only for executables
                # and public libraries
@@ -277,9 +306,11 @@ foreach my $file (keys %exec) {
                 print " Found in $syminfo->{soname} ($syminfo->{objid})\n" if $debug > 1;
                if (exists $alt_soname{$syminfo->{soname}}) {
                    # Also count usage on alternate soname
-                   $used_sonames{$alt_soname{$syminfo->{soname}}}++;
+                   $soname_used{$alt_soname{$syminfo->{soname}}}++;
+                   $global_soname_used{$alt_soname{$syminfo->{soname}}}++;
                }
-               $used_sonames{$syminfo->{soname}}++;
+               $soname_used{$syminfo->{soname}}++;
+               $global_soname_used{$syminfo->{soname}}++;
            }
        }
     }
@@ -299,16 +330,31 @@ foreach my $file (keys %exec) {
        }
 
        # Warn about un-NEEDED libraries
-       unless ($soname_notfound{$soname} or $used_sonames{$soname}) {
+       unless ($soname_notfound{$soname} or $soname_used{$soname}) {
            # Ignore warning for libm.so.6 if also linked against libstdc++
            next if ($soname =~ /^libm\.so\.\d+$/ and
                     scalar grep(/^libstdc\+\+\.so\.\d+/, @sonames));
+            next unless ($warnings & WARN_NOT_NEEDED);
            warning(_g("%s shouldn't be linked with %s (it uses none of its " .
                       "symbols)."), $file, $soname);
        }
     }
 }
 
+# Warn of unneeded libraries at the "package" level (i.e. over all
+# binaries that we have inspected)
+foreach my $soname (keys %global_soname_needed) {
+    unless ($global_soname_notfound{$soname} or $global_soname_used{$soname}) {
+        next if ($soname =~ /^libm\.so\.\d+$/ and scalar(
+                 grep(/^libstdc\+\+\.so\.\d+/, keys %global_soname_needed)));
+        next unless ($warnings & WARN_DEP_AVOIDABLE);
+        warning(_g("dependency on %s could be avoided if \"%s\" were not " .
+                   "uselessly linked against it (they use none of its " .
+                   "symbols)."), $soname,
+                   join(" ", @{$global_soname_needed{$soname}}));
+    }
+}
+
 # Open substvars file
 my $fh;
 if ($stdout) {
@@ -435,6 +481,9 @@ Options:
   -x<package>              exclude package from the generated dependencies.
   -S<pkgbuilddir>          search needed libraries in the given
                            package build directory first.
+  -v                       enable verbose mode (can be used multiple times).
+  --ignore-missing-info    don't fail if dependency information can't be found.
+  --warnings=<value>       define set of active warnings (see manual page).
   --admindir=<directory>   change the administrative directory.
   -h, --help               show this help message.
       --version            show the version.