From 15b03b6fc3271dcdb3108c8c9ef0bfd4f350106d Mon Sep 17 00:00:00 2001 From: Raphael Hertzog Date: Sun, 9 Dec 2007 15:42:40 +0100 Subject: [PATCH] dpkg-shlibdeps: use the Build-Depends-Package information from symbols files Use this new field to identify the version requirement possibly encoded in the Build-Depends field and make sure that the generated dependency is at least as strict as this one. Updated dpkg-shlibdeps's manual page. --- ChangeLog | 4 +- debian/changelog | 4 ++ man/ChangeLog | 2 + man/dpkg-shlibdeps.1 | 7 +++ scripts/Dpkg/Shlibs/SymbolFile.pm | 13 +++++ scripts/dpkg-shlibdeps.pl | 91 +++++++++++++++++++++++++------ 6 files changed, 103 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1dc85f13..e8ea1bd4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -44,11 +44,13 @@ * scripts/Dpkg/Shlibs/SymbolFile.pm: Parse and dump properly new meta-information fields (on lines starting with an asterisk). Bugfix with alternate dependency handling that were not properly - dumped. + dumped. New functions get_dependencies() and get_field(). * scripts/t/200_Dpkg_Shlibs.t, scripts/t/200_Dpkg_Shlibs/symbols.fake-2: Add a test case to verify that meta-information fields and alternate dependencies are properly parsed and dumped. + * scripts/dpkg-shlibdeps.pl: Take into account the new + Build-Depends-Package field in symbols files. 2007-12-09 Raphael Hertzog diff --git a/debian/changelog b/debian/changelog index c8c9dfc7..e3be2add 100644 --- a/debian/changelog +++ b/debian/changelog @@ -29,6 +29,10 @@ dpkg (1.14.13) UNRELEASED; urgency=low * Tweak the sort algorithm between dependencies so that intervals are displayed as "a (>= 1), a (<< 2)" instead of the opposite. Closes: #455520 + * Extend format of symbols files to support arbitrary fields of + meta-information. First field is Build-Depends-Package used to extract the + version requirement possibly encoded in the Build-Depends field and make + sure that the generated dependency is at least as strict as this one. [ Updated man pages translations ] * Swedish (Peter Karlsson) diff --git a/man/ChangeLog b/man/ChangeLog index 177d0272..214d101f 100644 --- a/man/ChangeLog +++ b/man/ChangeLog @@ -6,6 +6,8 @@ * deb-symbols.5: Describe syntax of meta-information fields and document the Build-Depends-Package field. + * dpkg-shlibdeps.1: Describe how the Build-Depends-Package field + of symbols file is used. 2007-12-09 Raphael Hertzog diff --git a/man/dpkg-shlibdeps.1 b/man/dpkg-shlibdeps.1 index f02d203d..d7ea373f 100644 --- a/man/dpkg-shlibdeps.1 +++ b/man/dpkg-shlibdeps.1 @@ -68,6 +68,13 @@ remembers the (biggest) minimal version needed for each library. At the end of the process, it is able to write out the minimal dependency for every library used (provided that the information of the \fIsymbols\fR files are accurate). +.P +As a safe-guard measure, a symbols file can provide a +\fIBuild-Depends-Package\fR meta-information field and +.B dpkg-shlibdeps +will extract the minimal version required by the corresponding package in +the Build-Depends field and use this version if it's higher than the +minimal version computed by scanning symbols. .SS Shlibs files Shlibs files associate directly a library to a dependency (without looking at the symbols). It's thus often stronger than really needed but very safe diff --git a/scripts/Dpkg/Shlibs/SymbolFile.pm b/scripts/Dpkg/Shlibs/SymbolFile.pm index 8f3dfe58..e3eb483d 100644 --- a/scripts/Dpkg/Shlibs/SymbolFile.pm +++ b/scripts/Dpkg/Shlibs/SymbolFile.pm @@ -273,6 +273,19 @@ sub get_dependency { return $self->{objects}{$soname}{deps}[$dep_id]; } +sub get_dependencies { + my ($self, $soname) = @_; + return @{$self->{objects}{$soname}{deps}}; +} + +sub get_field { + my ($self, $soname, $name) = @_; + if (exists $self->{objects}{$soname}{fields}{$name}) { + return $self->{objects}{$soname}{fields}{$name}; + } + return undef; +} + sub lookup_symbol { my ($self, $name, $sonames, $inc_deprecated) = @_; $inc_deprecated = 0 unless defined($inc_deprecated); diff --git a/scripts/dpkg-shlibdeps.pl b/scripts/dpkg-shlibdeps.pl index c26b7a3b..72b34ae2 100755 --- a/scripts/dpkg-shlibdeps.pl +++ b/scripts/dpkg-shlibdeps.pl @@ -11,12 +11,16 @@ use Dpkg::Gettext; use Dpkg::ErrorHandling qw(warning error failure syserr usageerr); use Dpkg::Path qw(relative_to_pkg_root guess_pkg_root_dir check_files_are_the_same); -use Dpkg::Version qw(vercmp); +use Dpkg::Version qw(compare_versions); use Dpkg::Shlibs qw(find_library); use Dpkg::Shlibs::Objdump; use Dpkg::Shlibs::SymbolFile; use Dpkg::Arch qw(get_host_arch); use Dpkg::Fields qw(capit); +use Dpkg::Deps; + +push(@INC,$dpkglibdir); +require 'controllib.pl'; # By increasing importance my @depfields = qw(Suggests Recommends Depends Pre-Depends); @@ -83,6 +87,12 @@ foreach (@ARGV) { scalar keys %exec || usageerr(_g("need at least one executable")); +our %fi; +parsecontrolfile("debian/control"); +my $build_depends = defined($fi{"C Build-Depends"}) ? + $fi{"C Build-Depends"} : ""; +my $build_deps = Dpkg::Deps::parse($build_depends, reduce_arch => 1); + my %dependencies; my %shlibs; @@ -210,21 +220,9 @@ foreach my $file (keys %exec) { } my $symdep = $symfile->lookup_symbol($name, \@sonames); if (defined($symdep)) { - my ($d, $m) = ($symdep->{depends}, $symdep->{minver}); $used_sonames{$symdep->{soname}}++; - foreach my $subdep (split /\s*,\s*/, $d) { - if (exists $dependencies{$cur_field}{$subdep} and - defined($dependencies{$cur_field}{$subdep})) - { - if ($dependencies{$cur_field}{$subdep} eq '' or - vercmp($m, $dependencies{$cur_field}{$subdep}) > 0) - { - $dependencies{$cur_field}{$subdep} = $m; - } - } else { - $dependencies{$cur_field}{$subdep} = $m; - } - } + update_dependency_version($symdep->{depends}, + $symdep->{minver}); } else { my $syminfo = $dumplibs_wo_symfile->locate_symbol($name); if (not defined($syminfo)) { @@ -252,8 +250,20 @@ foreach my $file (keys %exec) { } warning(_g("%d other similar warnings have been skipped (use -v to see " . "them all)."), $nb_skipped_warnings) if $nb_skipped_warnings; - # Warn about un-NEEDED libraries foreach my $soname (@sonames) { + # Adjust minimal version of dependencies with information + # extracted from build-dependencies + my $dev_pkg = $symfile->get_field($soname, 'Build-Depends-Package'); + if (defined $dev_pkg) { + my $minver = get_min_version_from_deps($build_deps, $dev_pkg); + if (defined $minver) { + foreach my $dep ($symfile->get_dependencies($soname)) { + update_dependency_version($dep, $minver); + } + } + } + + # Warn about un-NEEDED libraries unless ($soname_notfound{$soname} or $used_sonames{$soname}) { # Ignore warning for libm.so.6 if also linked against libstdc++ next if ($soname =~ /^libm\.so\.\d+$/ and @@ -302,7 +312,7 @@ sub filter_deps { # Since dependencies can be versionned, we have to # verify if the dependency is stronger than the # previously seen one - if (vercmp($depseen{$dep}, $dependencies{$field}{$dep}) > 0) { + if (compare_versions($depseen{$dep}, '>>', $dependencies{$field}{$dep})) { return 0; } else { $depseen{$dep} = $dependencies{$field}{$dep}; @@ -384,6 +394,53 @@ Dependency fields recognised are: "), $progname, join("/",@depfields); } +sub get_min_version_from_deps { + my ($dep, $pkg) = @_; + if ($dep->isa('Dpkg::Deps::Simple')) { + if (($dep->{package} eq $pkg) && + defined($dep->{relation}) && + (($dep->{relation} eq ">=") || + ($dep->{relation} eq ">>"))) + { + return $dep->{version}; + } + return undef; + } else { + my $res; + foreach my $subdep ($dep->get_deps()) { + my $minver = get_min_version_from_deps($subdep, $pkg); + next if not defined $minver; + if (defined $res) { + if (compare_versions($minver, '>>', $res)) { + $res = $minver; + } + } else { + $res = $minver; + } + } + return $res; + } +} + +sub update_dependency_version { + my ($dep, $minver) = @_; + return if not defined($minver); + foreach my $subdep (split /\s*,\s*/, $dep) { + if (exists $dependencies{$cur_field}{$subdep} and + defined($dependencies{$cur_field}{$subdep})) + { + if ($dependencies{$cur_field}{$subdep} eq '' or + compare_versions($minver, '>>', + $dependencies{$cur_field}{$subdep})) + { + $dependencies{$cur_field}{$subdep} = $minver; + } + } else { + $dependencies{$cur_field}{$subdep} = $minver; + } + } +} + sub add_shlibs_dep { my ($soname, $pkg) = @_; print "Looking up shlibs dependency of $soname provided by '$pkg'\n" if $debug; -- 2.39.5