Package: cli-common-dev
Severity: wishlist
Tags: patch

It would be nice if dh_clideps would fail the build when it can't
resolve shared library dependencies due to a genuine problem, such as
when libgnome-desktop-2 bumps its SONAME *again*.

To this end, the first attached patch adds a function to resolve
modulerefs against private shlibs, by first searching the current binary
package, and if that fails the other binary packages built from the same
source.  If the private library is found in a binary package other than
the one containing the assembly, a strong versioned dependency is added
against the binary package containing the shlib.

If a moduleref cannot be resolved, either by shlibs or to a private
library, dh_clideps fails with an error.

The second patch adds an -X option to exclude paths from the search for
assemblies.  This may not want to be applied, or may want to be
re-worked into a patch to make unresolved references in the excluded
paths not a fatal error.  This patch was written because the
gnome-sharp2-examples package ships some assemblies with unresolved
references to glib-2.0.

This has been tested against most of the reverse build dependencies of
cli-common-dev.  With the exception of gnome-sharp2 it doesn't break
any existing builds.


From 1b56f72feb6dc3b69643aa83921a1935d94f3c7d Mon Sep 17 00:00:00 2001
From: Christopher James Halse Rogers <r...@ubuntu.com>
Date: Tue, 9 Feb 2010 15:33:38 +1100
Subject: [PATCH 1/2] Add resolvePrivateLibrary function and use it to make dh_clideps error rather than warn when shlib refs can't be resolved

---
 dh_clideps |   66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 62 insertions(+), 4 deletions(-)

diff --git a/dh_clideps b/dh_clideps
index e349f2f..d748f96 100755
--- a/dh_clideps
+++ b/dh_clideps
@@ -576,14 +576,24 @@ sub resolveShlibRefs {
        next;
      }
      my $target = $dllmapdata{$name};
+     my $fullTarget = $target;
      
      if (defined($target)) {
        $target = basename($target);
        verbose_print("Resolved moduleref via DLL map: $name to: $target");
      } elsif (defined($shlibdata{$name})) {
        verbose_print("Resolved moduleref via direct match in shlibs");
+     } elsif (resolvePrivateLibrary($package, $name, $package)) {
+       # There is no DllMap, but the package ships the private library alongside the assembly
+       verbose_print("Resolved moduleref to private library $name");
+       next;
+     } elsif (resolvePrivateLibrary($package, "lib" . $name . ".so", $package)) {
+       # There is no DllMap, the assembly is relying on Mono's "foo" -> "libfoo.so"
+       # translation, and is shipping libfoo.so alongside the assembly
+       verbose_print("Resolved moduleref to private library lib" . $name . ".so");
+       next;
      } else {
-       warning("Warning: Could not resolve moduleref: $name for: $assembly_filename!");
+       error("Could not resolve moduleref: $name for: $assembly_filename!");
        next;
      }
  
@@ -596,8 +606,24 @@ sub resolveShlibRefs {
        # for DLL maps that have an unversioned library as target
        $pkgref = $shlibdata{$target.".0"};
      } else {
-       warning("Warning: Missing shlibs entry: $target or $name for: $assembly_filename!");
-       next;
+	 if(!resolvePrivateLibrary($package, $fullTarget, $package)) {
+	     # Private library can't be found in the current package.  Try to resolve it
+	     # in the other binary packages, and add a strong dependency if we find it.
+	     foreach my $binary_package (@{$dh{DOPACKAGES}}) {
+		 if(resolvePrivateLibrary($package, $fullTarget, $binary_package)) {
+		     verbose_print("Found private library in $binary_package");
+		     $pkgref = $binary_package . " (= \${binary:Version})";
+		     verbose_print("pkgref is $pkgref");
+		     last;
+		 }
+	     }
+	     if (!defined($pkgref)) {
+		 error("Missing shlibs entry: $target or $name for: $assembly_filename!");
+	     }
+	 } else {
+	     verbose_print("Found private library $target for $name");
+	     next;
+	 }
      }
 
      my %overriddenRef = resolveOverride($package, $pkgref);
@@ -606,10 +632,42 @@ sub resolveShlibRefs {
      push(@{$ret{suggests}},   $overriddenRef{suggests});
    } 
    close(F);
-   
+
    return %ret;
 }
 
+sub resolvePrivateLibrary {
+    my $package = shift;
+    my $target = shift;
+    my $resolveIn = shift;
+    my $library_file;
+
+    use File::Spec;
+    if (File::Spec->file_name_is_absolute($target)) {
+	# If the DLLMap target is absolute, we should check that the target
+	# exists in that location.  Since we're currently in the directory
+	# with the assembly, we need to back out first.
+	my @targetDirs = File::Spec->splitdir($target);
+	my @cwdComponents = File::Spec->splitdir(File::Spec->rel2abs(File::Spec->curdir()));
+	my @upDirs = ("../", "../");
+
+	# Find where the last occurance of tmpdir is in $curdir, and add enough
+	# updirs to get there from cwd.
+	while(join("/", ($cwdComponents[-2], $cwdComponents[-1])) ne tmpdir($package)) {
+	    pop(@cwdComponents);
+	    push(@upDirs, "../");
+	}
+
+	$library_file = File::Spec->rel2abs(File::Spec->catdir((File::Spec->curdir(), @upDirs, tmpdir($resolveIn), @targetDirs)));
+    } else {
+	# If the DLLMap target is not absolute, look in the same directory
+	# as the assembly.
+	$library_file = basename($target);
+    }
+    verbose_print("Looking for $target at $library_file");
+    return 1 if -f $library_file || -s $library_file;
+}
+
 =head1 SEE ALSO
 
 L<debhelper(7)>
-- 
1.6.6.1

From 224cb1db7244e406e523d17c147230d3022b09e0 Mon Sep 17 00:00:00 2001
From: Christopher James Halse Rogers <r...@ubuntu.com>
Date: Tue, 9 Feb 2010 15:50:31 +1100
Subject: [PATCH 2/2] Add -X handling to exclude directories from the assembly search

---
 dh_clideps |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/dh_clideps b/dh_clideps
index d748f96..df3f345 100755
--- a/dh_clideps
+++ b/dh_clideps
@@ -65,6 +65,12 @@ paths will be made absolute for the benefit of monodis.
 Note that the directory given should be the complete or relative path to a directory that contains
 the library. See example below.
 
+=item B<-X>path B<--exclude=>path
+
+Paths to exclude from the .dll/.exe search.  Assemblies in these paths or their subdirectories
+will not be searched for dependencies, and assemblies missing references will not cause dh_clideps 
+to fail.
+
 =item B<internal-mono>                             
 
 Uses the mono runtime in . (used for bootstrapping mono packages)  
@@ -84,6 +90,10 @@ or
   (MONO_GAC_PREFIX example)
   dh_clideps -l debian/tmp/usr
 
+Suppose your source package libquux1.0-cil also ships some examples in /usr/share, and you don't
+want to pull in those dependencies.
+  dh_clideps -X/usr/share
+
 =cut
 
 # gar, debhelper 7.1 defines -d for all scripts already :(
@@ -228,6 +238,12 @@ foreach my $package (@{$dh{DOPACKAGES}}) {
                recommends => [],
                suggests => [] );
   my $found_exe = 0;
+
+  use File::Spec;
+  my @exclude_dirs = ();
+  foreach(@{$dh{EXCLUDE}}) {
+      push(@exclude_dirs, File::Spec->catdir($tmp, $_));
+  }
   $needs_net_1_0 = 0;
   $needs_net_2_0 = 0;
   $needs_net_2_1 = 0;
@@ -245,6 +261,12 @@ foreach my $package (@{$dh{DOPACKAGES}}) {
       $found_exe = 1;
     }
 
+    foreach(@exclude_dirs) {
+	if($File::Find::dir =~ m/^$_/) {
+	    verbose_print("Excluding module $file from dir $File::Find::dir");
+	    return;
+	}
+    }
     verbose_print("Package: $package Assembly: $file");
         
     my %shlibRefs = resolveShlibRefs($package, $file);
-- 
1.6.6.1

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to