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