Bug#610689: [buildd-tools-devel] Bug#610689: sbuild: cross build support

2011-04-14 Thread Neil Williams
On Sat, 26 Mar 2011 20:06:21 +
Roger Leigh  wrote:

> On Fri, Mar 25, 2011 at 05:06:02PM +, Hector Oron wrote:
> > 2011/3/10 Roger Leigh :
> > > For the cross-packages, you can add these to the core build
> > > dependencies list, so they will be installed along with build-essential
> > > etc.  Or (better) you can add a separate XAPT_DEPENDS variable which can
> > > be appended to CORE_DEPENDS in Build.pm prior to installing the core
> > > dependencies.  Does xapt not bring in these packages directly, or do
> > > they always need installing by hand?
> > 
> > xapt downloads the foreign architecture packages using APT with -o
> > APT::Architecture=$HOST_ARCH into a directory controlled by xapt
> > (/var/lib/xapt/, irrc), then throws dpkg-cross into that directory to
> > convert those packages and installs them.
> 
> This is the part that I think can be significantly improved.

Not until we have Multi-Arch-Cross. Indeed, there's no point making
special changes to sbuild ahead of Multi-Arch as the entire
cross-dependency resolution mechanism will be completely thrown away at
that stage.

What you're trying to create in this bug report is a Multi-Arch-Cross
resolver for sbuild and then hacking it to handle dpkg-cross. That is
the wrong way around. Use the hacks which already work with the
dpkg-cross hacks and then implement a *clean* Multi-Arch-Cross resolver
when that becomes possible.

dpkg-cross is fundamentally broken and is completely alien to
Multi-Arch. Anything based on dpkg-cross will need to be completely
re-written for Multi-Arch-Cross, so use the tools which exist (and
which will disappear alongside dpkg-cross) to retain as much isolation
as possible between the sbuild code and the broken dpkg-cross methods.

> sbuild creates a local APT archive to install dependency packages from.
> We can use the same mechanism to allow the dpkg-cross packages to be
> installed.  It could even be used to cache generated packages between
> builds.  We can quite easily refactor the code to allow multiple
> archives (if required).

The problems in this area are:

0: The setup_apt_archive code uses the Dpkg bindings to resolve the
dependencies but these are inherently native (despite taking an arch,
it is difficult to get this right when there are alternatives and
architecture-specific dependencies). These have been re-written in
embuilddeps but all that code will be completely pointless once
Multi-Arch-Cross arrives. There is no point implementing yet another
broken version of it in an XaptResolver for sbuild.

1: embuilddeps has tried to solve these problems but has a
fundamentally different approach to actually installing the packages.
Sbuild::AptResolver and Sbuild::AptitudeResolver use the dummy-package
method to actually do the work of resolving the dependencies within the
specified constraints. embuilddeps resolves the constraints directly.
e.g. constraints of foo (>= 1.2.3) [armel] | bar [!linux-any] | baz
[i386| amd64] are particularly hard to resolve correctly when running
on i386 to cross-build for armel.

2: Cross-dependency resolution requires re-doing the dpkg deps_parse
calculation with an empty dpkg status file and then chasing the
dependencies all the way down because -cross packages do not exist in
the archives. This is why I'm looking at Multi-Arch being the preferred
solution here.

3: dummy-package methods won't work for cross because we must resolve
all the constraints ahead of passing a list of packages to apt so that
these can be downloaded *ahead* of being installed, then converted
using dpkg-cross and installed as packagename-$arch-cross packages.
libfoo-dev_1.2.3_armel.deb becomes libfoo-dev-armel-cross_1.2.3_all.deb

4: The converted packages do not (indeed cannot) exist in any
network-accessible archive - these are all generated on-the-fly until
Multi-Arch makes the whole conversion avoidable.

5: apt and aptitude consistently treat -$arch-cross packages as "local
or obsolete" and consistently get removal parsing wrong when upgrading
existing packages. This means that the list of -$arch-cross packages to
be removed needs to be carefully managed, especially if the cross
toolchain is not to be removed upon every build.

Much easier is for xapt|embuilddeps to put the downloaded and the
converted packages into a directory which sbuild can manage, or for
sbuild to become aware of the current defaults which
are /var/lib/xapt/output for -cross packages and /var/lib/xapt/archives
for the foreign architecture originals.

This will also solve problems of package removal after the build,
albeit that some extra processing is required to skip certain
-cross packages which would otherwise cause the removal of the
cross-building toolchain. (libc6-dev-$arch-cross is a frequent problem
here.) This list of packages does need to be kept updated to cope with
changes in gcc and in eglibc - e.g. the Squeeze chroots will have a
libc-bin-$ARCH-cross package which doesn't exist in Lenny chroots.

Whilst it 

Bug#610689: [buildd-tools-devel] Bug#610689: sbuild: cross build support

2011-03-26 Thread Roger Leigh
On Fri, Mar 25, 2011 at 05:06:02PM +, Hector Oron wrote:
> 2011/3/10 Roger Leigh :
> 
> > This part can be done by the xapt resolver directly, without any
> > special user setup required.
> 
> True.
> 
> > For the cross-packages, you can add these to the core build
> > dependencies list, so they will be installed along with build-essential
> > etc.  Or (better) you can add a separate XAPT_DEPENDS variable which can
> > be appended to CORE_DEPENDS in Build.pm prior to installing the core
> > dependencies.  Does xapt not bring in these packages directly, or do
> > they always need installing by hand?
> 
> xapt downloads the foreign architecture packages using APT with -o
> APT::Architecture=$HOST_ARCH into a directory controlled by xapt
> (/var/lib/xapt/, irrc), then throws dpkg-cross into that directory to
> convert those packages and installs them.

This is the part that I think can be significantly improved.

sbuild creates a local APT archive to install dependency packages from.
We can use the same mechanism to allow the dpkg-cross packages to be
installed.  It could even be used to cache generated packages between
builds.  We can quite easily refactor the code to allow multiple
archives (if required).

> > Well, when we install the build dependencies the package isn't yet
> > unpacked.  The unpacking is done in the build() function.  But there's
> > no reason we can't reorder it if we need to.  The unpacking could
> > be split out of build() into a separate unpack_source() function,
> > which could be run earlier if xapt/embuilddeps is in use.
> >
> > What information does embuilddeps require from the unpacked source
> > package?  Is this information also available in the .dsc? (We do
> > have the .dsc information directly to hand).
> 
> It is possible to use .dsc information, but embuilddeps does not know
> how (yet). :-)

OK.  For the purpose of actually implementing this, I would like to
have a description of exactly which fields we need for cross building
from which files in the source or DSC, and what they do and why.  Is
this all documented somewhere?

> > xapt is doing two jobs it seems:
> > 1) from the package list, make a list containing all the cross packages
> >   needed
> 
> That is given with simulation option (-n).

This is with embuilddeps, not xapt?

This option appears to give a package list, prefixed with
"/usr/bin/apt-get -y".  This just isn't suitable.
- it's omitted packages which were already installed; this is not
  necessary and involves poking around under /var/lib/dpkg.
- we need to strip off the "/usr/bin/apt-get -y" which might be subject
  to change and then cause breakage, at some point in the future.
All we want is the /complete/ package list, without any removal of
packages or addition of other bits.

> > 2) install them (but it doesn't list them in the list of packages to
> >   install, which makes removal harder potentially)
> >
> > From the resolver POV, what would be really good if it could just do
> > (1).  This way, we can just give the expanded list back to the
> > resolver for it to install.  Because we need to clean up after
> > ourselves, the apt and aptitude resolvers build a dummy
> > "dependency package" from the dependency list, and then get apt/
> > aptitude to install it.
> 
> This is how old pbuilder used to do it, but it does not work with
> cross packages as adding dependencies on
> $foreign_package-$HOST_ARCH-cross won't work, as those packages are
> output from dpkg-cross and not available from repositories.

Right.  But with sbuild, as I mentioned above, we can install the
dpkg-cross-generated packages into a local archive, which *is*
accessible to apt-get/aptitude, and hence you will then be able to
use cross packages in the dependencies /directly/.  This will permit
proper cleanup after a build using the normal mechanisms sbuild uses
for all builds.

This is to say the resolver can do the following:
- get the cross dependencies from the dsc or unpacked source
- download the debs
- run dpkg-cross
- install the dpkg-cross-generated debs into the local archive
- add the cross-dependencies to the package build dependencies
...
- run dpkg-buildpackage with the necessary options to cross build
...

We already allow various things to add to the package build deps,
and so adding cross-deps will be trivial.  All we really need is the
necessary information for what to parse from the dsc or source package,
and then how to use dpkg-cross.

Just to be clear: none of the above uses xapt/embuilddeps, because
sbuild can, I think, do a better job with its local archive and which
will integrate much better with our existing cleanup code when it comes
to removing build deps.

> > We then reverse the process to clean up
> > after the build.  So ideally, we don't really want xapt to do any
> > installation: we just want it to give us the package list.  If
> > this is possible, it might not even be require to have a separate
> > XaptResolver--we just expand the cros