Przeglądaj źródła

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.
Raphael Hertzog 18 lat temu
rodzic
commit
15b03b6fc3

+ 3 - 1
ChangeLog

@@ -44,11 +44,13 @@
 	* scripts/Dpkg/Shlibs/SymbolFile.pm: Parse and dump properly
 	* scripts/Dpkg/Shlibs/SymbolFile.pm: Parse and dump properly
 	new meta-information fields (on lines starting with an asterisk).
 	new meta-information fields (on lines starting with an asterisk).
 	Bugfix with alternate dependency handling that were not properly
 	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.t,
 	scripts/t/200_Dpkg_Shlibs/symbols.fake-2: Add a test case to
 	scripts/t/200_Dpkg_Shlibs/symbols.fake-2: Add a test case to
 	verify that meta-information fields and alternate dependencies are
 	verify that meta-information fields and alternate dependencies are
 	properly parsed and dumped.
 	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  <hertzog@debian.org>
 2007-12-09  Raphael Hertzog  <hertzog@debian.org>
 
 

+ 4 - 0
debian/changelog

@@ -29,6 +29,10 @@ dpkg (1.14.13) UNRELEASED; urgency=low
   * Tweak the sort algorithm between dependencies so that intervals
   * Tweak the sort algorithm between dependencies so that intervals
     are displayed as "a (>= 1), a (<< 2)" instead of the opposite.
     are displayed as "a (>= 1), a (<< 2)" instead of the opposite.
     Closes: #455520
     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 ]
   [ Updated man pages translations ]
   * Swedish (Peter Karlsson)
   * Swedish (Peter Karlsson)

+ 2 - 0
man/ChangeLog

@@ -6,6 +6,8 @@
 
 
 	* deb-symbols.5: Describe syntax of meta-information
 	* deb-symbols.5: Describe syntax of meta-information
 	fields and document the Build-Depends-Package field.
 	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  <hertzog@debian.org>
 2007-12-09  Raphael Hertzog  <hertzog@debian.org>
 
 

+ 7 - 0
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
 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
 library used (provided that the information of the \fIsymbols\fR files are
 accurate).
 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
 .SS Shlibs files
 Shlibs files associate directly a library to a dependency (without looking
 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
 at the symbols). It's thus often stronger than really needed but very safe

+ 13 - 0
scripts/Dpkg/Shlibs/SymbolFile.pm

@@ -273,6 +273,19 @@ sub get_dependency {
     return $self->{objects}{$soname}{deps}[$dep_id];
     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 {
 sub lookup_symbol {
     my ($self, $name, $sonames, $inc_deprecated) = @_;
     my ($self, $name, $sonames, $inc_deprecated) = @_;
     $inc_deprecated = 0 unless defined($inc_deprecated);
     $inc_deprecated = 0 unless defined($inc_deprecated);

+ 74 - 17
scripts/dpkg-shlibdeps.pl

@@ -11,12 +11,16 @@ use Dpkg::Gettext;
 use Dpkg::ErrorHandling qw(warning error failure syserr usageerr);
 use Dpkg::ErrorHandling qw(warning error failure syserr usageerr);
 use Dpkg::Path qw(relative_to_pkg_root guess_pkg_root_dir
 use Dpkg::Path qw(relative_to_pkg_root guess_pkg_root_dir
 		  check_files_are_the_same);
 		  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 qw(find_library);
 use Dpkg::Shlibs::Objdump;
 use Dpkg::Shlibs::Objdump;
 use Dpkg::Shlibs::SymbolFile;
 use Dpkg::Shlibs::SymbolFile;
 use Dpkg::Arch qw(get_host_arch);
 use Dpkg::Arch qw(get_host_arch);
 use Dpkg::Fields qw(capit);
 use Dpkg::Fields qw(capit);
+use Dpkg::Deps;
+
+push(@INC,$dpkglibdir);
+require 'controllib.pl';
 
 
 # By increasing importance
 # By increasing importance
 my @depfields = qw(Suggests Recommends Depends Pre-Depends);
 my @depfields = qw(Suggests Recommends Depends Pre-Depends);
@@ -83,6 +87,12 @@ foreach (@ARGV) {
 
 
 scalar keys %exec || usageerr(_g("need at least one executable"));
 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 %dependencies;
 my %shlibs;
 my %shlibs;
 
 
@@ -210,21 +220,9 @@ foreach my $file (keys %exec) {
 	}
 	}
 	my $symdep = $symfile->lookup_symbol($name, \@sonames);
 	my $symdep = $symfile->lookup_symbol($name, \@sonames);
 	if (defined($symdep)) {
 	if (defined($symdep)) {
-	    my ($d, $m) = ($symdep->{depends}, $symdep->{minver});
 	    $used_sonames{$symdep->{soname}}++;
 	    $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 {
 	} else {
 	    my $syminfo = $dumplibs_wo_symfile->locate_symbol($name);
 	    my $syminfo = $dumplibs_wo_symfile->locate_symbol($name);
 	    if (not defined($syminfo)) {
 	    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 " .
     warning(_g("%d other similar warnings have been skipped (use -v to see " .
 	    "them all)."), $nb_skipped_warnings) if $nb_skipped_warnings;
 	    "them all)."), $nb_skipped_warnings) if $nb_skipped_warnings;
-    # Warn about un-NEEDED libraries
     foreach my $soname (@sonames) {
     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}) {
 	unless ($soname_notfound{$soname} or $used_sonames{$soname}) {
 	    # Ignore warning for libm.so.6 if also linked against libstdc++
 	    # Ignore warning for libm.so.6 if also linked against libstdc++
 	    next if ($soname =~ /^libm\.so\.\d+$/ and
 	    next if ($soname =~ /^libm\.so\.\d+$/ and
@@ -302,7 +312,7 @@ sub filter_deps {
 	# Since dependencies can be versionned, we have to
 	# Since dependencies can be versionned, we have to
 	# verify if the dependency is stronger than the
 	# verify if the dependency is stronger than the
 	# previously seen one
 	# previously seen one
-	if (vercmp($depseen{$dep}, $dependencies{$field}{$dep}) > 0) {
+	if (compare_versions($depseen{$dep}, '>>', $dependencies{$field}{$dep})) {
 	    return 0;
 	    return 0;
 	} else {
 	} else {
 	    $depseen{$dep} = $dependencies{$field}{$dep};
 	    $depseen{$dep} = $dependencies{$field}{$dep};
@@ -384,6 +394,53 @@ Dependency fields recognised are:
 "), $progname, join("/",@depfields);
 "), $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 {
 sub add_shlibs_dep {
     my ($soname, $pkg) = @_;
     my ($soname, $pkg) = @_;
     print "Looking up shlibs dependency of $soname provided by '$pkg'\n" if $debug;
     print "Looking up shlibs dependency of $soname provided by '$pkg'\n" if $debug;