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