[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Explicit arch qualifiers in “Depends” field



Hi,

A small set of packages would benefit from explicit arch qualifiers in *-Depends.
Indeed, a cross-compiler, for instance, is meant to run on a certain (build) architecture
and use libs from the foreign (host) architecture.
This isn't actually possible in Debian, since the MultiArch spec only allows the “:any” qualifier,
and dpkg actually reject anything different from “any”.

So, I've played a bit with dpkg and apt.
It turns out dpkg handles cross-arch dependencies perfectly, it only rejects anything else than “any”.
Disabling this test does the trick.

Apt uses implicit “Provides” to satisfy “:any” dependencies and treats the arch qualifier
as part of the package name. One obvious solution would be to add an implicit “Provides”
to each package to satisfy “$package:$arch”. But considering the enormous number of implicit provides
this would add (at least one per “M-A: same” package), I think it's a very bad idea.
Another solution would be to add effective cross-arch dependencies.
It turns out to be fairly easy, but a proper patch would need a bit more work,
and this might have a number of subtle implications I haven't thought of.

Here are patches for dpkg and apt. They need reviewing, and the apt one could probably be cleaned up
a bit. Anyway, there are a few questions left:

1. When parsing the *-Depends fields, should dpkg check whether the arch is known?
     I think it doesn't matter, as a package with a dependency qualified with an unknown arch
     would be uninstallable anyway.
2. Should a package be able to depend on a package regardless of its M-A field?
     I think it only makes sense for a package to depend on a “M-A: same” or “M-A: allowed” package,
     “M-A: foreign” packages providing arch-independent interfaces, and M-A unaware packages
     probably being unwanted.
     On the other hand, explicitly disallowing other packages would probably be unnecessary work.
3. Have I overlooked something?


Regards,
Thibaut.
Description: Add support for explicit cross-arch dependencies

diff -rup apt-0.9.1/apt-pkg/deb/deblistparser.cc apt-0.9.1+nmu1/apt-pkg/deb/deblistparser.cc
--- apt-0.9.1/apt-pkg/deb/deblistparser.cc	2012-04-16 19:23:05.000000000 +0200
+++ apt-0.9.1+nmu1/apt-pkg/deb/deblistparser.cc	2012-04-18 19:48:30.459997929 +0200
@@ -627,14 +627,16 @@ bool debListParser::ParseDepends(pkgCach
 
    string Package;
    string const pkgArch = Ver.Arch();
-   string Version;
+   string Version, Arch;
    unsigned int Op;
+   size_t found;
 
    while (1)
    {
       Start = ParseDepends(Start,Stop,Package,Version,Op,false,!MultiArchEnabled);
       if (Start == 0)
 	 return _error->Error("Problem parsing dependency %s",Tag);
+      found = Package.rfind(":");
 
       if (MultiArchEnabled == true &&
 	  (Type == pkgCache::Dep::Conflicts ||
@@ -646,6 +648,17 @@ bool debListParser::ParseDepends(pkgCach
 	    if (NewDepends(Ver,Package,*a,Version,Op,Type) == false)
 	       return false;
       }
+      else if (MultiArchEnabled == true && found != string::npos
+	       && strcmp(Package.c_str() + found, ":any") != 0)
+      {
+	  if (strcmp(Package.c_str() + found, ":native") == 0)
+	      Arch = _config->Find("APT::Architecture");
+	  else
+	      Arch = Package.substr(found+1, string::npos);
+	  Package = Package.substr(0, found);
+	  if (NewDepends(Ver,Package,Arch,Version,Op,Type) == false)
+	      return false;
+      }
       else if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false)
 	 return false;
       if (Start == Stop)
diff -rup apt-0.9.1/apt-pkg/edsp.cc apt-0.9.1+nmu1/apt-pkg/edsp.cc
--- apt-0.9.1/apt-pkg/edsp.cc	2012-04-16 19:23:05.000000000 +0200
+++ apt-0.9.1+nmu1/apt-pkg/edsp.cc	2012-04-18 17:33:02.019998928 +0200
@@ -119,7 +119,10 @@ void EDSP::WriteScenarioDependency(pkgDe
    for (pkgCache::DepIterator Dep = Ver.DependsList(); Dep.end() == false; ++Dep)
    {
       // Ignore implicit dependencies for multiarch here
-      if (strcmp(Pkg.Arch(), Dep.TargetPkg().Arch()) != 0)
+      if (strcmp(Pkg.Arch(), Dep.TargetPkg().Arch()) != 0
+          && (Dep->Type == pkgCache::Dep::Replaces
+              || Dep->Type == pkgCache::Dep::DpkgBreaks
+              || Dep->Type == pkgCache::Dep::Conflicts))
 	 continue;
       if (orGroup == false)
 	 dependencies[Dep->Type].append(", ");
@@ -160,7 +163,10 @@ void EDSP::WriteScenarioLimitedDependenc
    for (pkgCache::DepIterator Dep = Ver.DependsList(); Dep.end() == false; ++Dep)
    {
       // Ignore implicit dependencies for multiarch here
-      if (strcmp(Pkg.Arch(), Dep.TargetPkg().Arch()) != 0)
+      if (strcmp(Pkg.Arch(), Dep.TargetPkg().Arch()) != 0
+          && (Dep->Type == pkgCache::Dep::Replaces
+              || Dep->Type == pkgCache::Dep::DpkgBreaks
+              || Dep->Type == pkgCache::Dep::Conflicts))
 	 continue;
       if (orGroup == false)
       {
Description: Quick and dirty patch to enable explicit arch qualifiers.
  This seems to be enough for dpkg to resolve dependencies, but apt 0.8.15
  can't resolve such dependencies.

diff --git a/lib/dpkg/fields.c b/lib/dpkg/fields.c
index 9a7974a..091664a 100644
--- a/lib/dpkg/fields.c
+++ b/lib/dpkg/fields.c
@@ -447,8 +447,8 @@ f_dependency(struct pkginfo *pkg, struct pkgbin *pkgbin,
 
         if (dop->arch->type == arch_illegal)
           emsg = dpkg_arch_name_is_illegal(arch.buf);
-        else if (dop->arch->type != arch_wildcard)
-          emsg = _("a value different from 'any' is currently not allowed");
+        /*else if (dop->arch->type != arch_wildcard && dop->arch->type != arch_foreign)
+          emsg = _("a value different from 'any' is currently not allowed");*/
         if (emsg)
           parse_error(ps, _("'%s' field, reference to '%.255s': "
                             "invalid architecture name '%.255s': %s"),
diff --git a/scripts/Dpkg/Deps.pm b/scripts/Dpkg/Deps.pm
index 9635cc2..2fe484f 100644
--- a/scripts/Dpkg/Deps.pm
+++ b/scripts/Dpkg/Deps.pm
@@ -565,7 +565,7 @@ sub parse_string {
               ([a-zA-Z0-9][a-zA-Z0-9+.-]*)  # package name
               (?:                           # start of optional part
                 :                           # colon for architecture
-                (any)                       # architecture name
+                ([a-zA-Z0-9][a-zA-Z0-9-]*)  # architecture name
               )?                            # end of optional part
               (?:                           # start of optional part
                 \s* \(                      # open parenthesis for version part

Attachment: signature.asc
Description: Digital signature


Reply to: