From 15fbb138b6af6d5b114f69ae374b896358d8acdf Mon Sep 17 00:00:00 2001 From: Raphael Hertzog Date: Tue, 25 Mar 2008 11:33:06 +0100 Subject: [PATCH] dpkg-shlibdeps: new warning about useless libraries, new --warnings option * 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 | 8 +++++ debian/changelog | 6 ++++ man/dpkg-shlibdeps.1 | 35 ++++++++++++++-------- scripts/dpkg-shlibdeps.pl | 61 +++++++++++++++++++++++++++++++++++---- 4 files changed, 92 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index fc0316f6..06c5ffe6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2008-03-25 Raphael Hertzog + + * 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 * lib/dpkg-db.h (modstatdb_note_ifwrite): New prototype. diff --git a/debian/changelog b/debian/changelog index f28d30f0..0cc4250c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -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= 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 diff --git a/man/dpkg-shlibdeps.1 b/man/dpkg-shlibdeps.1 index 6677abce..38db7d91 100644 --- a/man/dpkg-shlibdeps.1 +++ b/man/dpkg-shlibdeps.1 @@ -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. diff --git a/scripts/dpkg-shlibdeps.pl b/scripts/dpkg-shlibdeps.pl index 8cb9890f..11a72df3 100755 --- a/scripts/dpkg-shlibdeps.pl +++ b/scripts/dpkg-shlibdeps.pl @@ -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 exclude package from the generated dependencies. -S 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= define set of active warnings (see manual page). --admindir= change the administrative directory. -h, --help show this help message. --version show the version. -- 2.39.5