On Wed, Jul 30, 2014 at 11:30:39PM +0200, Václav Ovsík wrote:
> Hi Peter,
> thanks you for your attention on the ustr packaging. My work on ustr is
> a bit stuck for some time. One reason is that upstream has no activity
> for some time (great work of James Antill without bugs fortunately), the
> other is I tried to prepare cross-build chroot (sbuild) without much
> success. I'm not educated on cross-building yet :(. Can you direct me
> how you are cross-building ustr please? Is it possible without Ubuntu
> packages on current Debian Unstable?
> Thanks for all patches. I will look at these after some brain restoration
> :). I forgot almost everything...

Sure, no problem, it happens :)  (I've had this happen quite a few times
with both Debian and FreeBSD packages that I'm supposed to maintain, but
haven't touched in years)

Now, about the cross-build environment: the truth is, this was my first
serious foray into cross-building, too :)  However, the task was made
much, much easier than usual by Helmut Grohne's rebootstrap tool - its
very purpose is to, well, bootstrap the Debian archive on a new
architecture, starting from scratch, zero host packages, building
several cross-compilers, libc packages and other supporting packages
first, and then building "normal" packages, one by one, in the order
necessary to satisfy build dependencies, applying local patches as
necessary.  I'd recommend that you try it that way, too.  The easiest
way to install it does involve Ubuntu-related packages, but they are all
in the Debian archive now, so this shouldn't be a problem.

1. Install the schroot, sbuild, and ubuntu-dev-tools packages.

2. Set up an 'sbuild' group and make your account a member; log out and
   then back in again if necessary for this to take effect.

3. Create a ~/.sbuildrc file from the example template at
   /usr/share/doc/sbuild/examples/example.sbuildrc
   I've attached mine, just as an example.

4. Run 'mk-sbuild' to create the master chroot which will be used for
   rebootstrap runs.  The mk-sbuild defaults are fine, you mostly need
   to provide a name for the chroot (I use "rebootstrap" for mine) and,
   if necessary, the URL of the Debian mirror to use for the initial
   debootstrap run.  I usually do something like:

   mk-sbuild --name=rebootstrap-demo 
--debootstrap-mirror=http://127.0.0.1:9999/debian/ unstable

   This points at my local approx instance as a Debian mirror.

5. Edit the schroot definition to allow members of the sbuild group to
   log in to the source chroot, not just create temp ones from it:

   sudo vim /etc/schroot/chroot.d/sbuild-rebootstrap-demo-amd64

   Uncomment the source-root-users and source-root-groups lines.

6. Log into the source chroot to set it up for rebootstrap runs:

   schroot -c source:rebootstrap-demo-amd64 -u root

7. Set Apt up to skip recommended packages:

   echo 'APT { Install-Recommends: "false"; };' > /etc/apt/apt.conf.d/99local

8. Either install Git and then check out rebootstrap, or check out
   rebootstrap in a directory outside the master chroot and then copy it
   inside the chroot.

   If you choose to install Git inside the chroot:

   apt-get install git
   git clone git.debian.org:/git/users/helmutg/rebootstrap.git

   If you choose to clone rebootstrap outside the chroot, then you need
   to copy it inside the chroot afterwards; something like:

   sudo rsync -av rebootstrap/ 
/var/lib/schroot/mount/rebootstrap-demo-amd64-de4ba356-103e-4d9b-9ad4-49a85de1dc1e/root/rebootstrap/

   Of course, your schroot session ID (the directory under
   /var/lib/schroot/mount/) will almost certainly be different; you can
   look it up inside the chroot by:

   printenv SCHROOT_SESSION_ID
   or printenv | fgrep SCHROOT

   Any way you choose (Git checkout inside the chroot or rsync/copy from
   outside), you should now have a /root/rebootstrap/ directory inside
   your current source chroot session.

9. Log out of the source chroot; your changes should be saved.

   exit

10. Create a temporary chroot from this template to actually run
    rebootstrap and cross-build something:

    schroot -c rebootstrap-demo-amd64 -u root
    cd rebootstrap

11. Pick an architecture that you want to cross-build for, pick a Debian
    mirror for rebootstrap to use, and, well, let it rip :)
    
    sh bootstrap.sh HOST_ARCH=armel MIRROR=http://127.0.0.1:9999/debian/ 2>&1 | 
tee /tmp/bootstrap.log

12. Now sit back and relax, or (from outside the chroot) monitor
    rebootstrap's progress by something like the attached script that
    extracts some of the info from the in-chroot /tmp/bootstrap.log:

    watch -n5 sh check-progress.sh 
rebootstrap-demo-amd64-c9563936-cd8a-41a3-9400-6ca1f92afca2

The result of the rebootstrap script will be twofold: there is a
/tmp/result directory in the chroot that holds the built packages, and
there is a reprepro Debian package repository in /tmp/repo (again, in
the chroot) that, well, holds the built packages in an easier-to-use
format :)  The way I use those packages is to wait for something to show
up in the repository, then rsync it (from outside the chroot) to a
similar location in another chroot, then install packages from it.
There are two types of packages there: native ones (pretty much only the
cross-compiler) and host ones (the actual cross-built ones for your
target architecture).

Note that to install host packages for cross-building and keep a clean
environment you may need to do something similar to what rebootstrap
does with dpkg and the sources.list file:

1. Let dpkg know you're interested in the host architecture, too:

   dpkg --add-architecture armel

2. Edit /etc/apt/sources.list and, well, pretty much all of your
   /etc/apt/ources.list.d/* files and add the "[ arch-=armel ]" notation
   after each "deb" line, so that apt never tries to fetch host packages
   from the Debian archive; they may not be there at all (if the
   architecutre has not been properly bootstrapped yet, or if it is only
   in debian-ports, or if something is wrong and you're trying to
   diagnose it by doing the cross-building yourself) or, in theory, they
   might not be completely compatible with the rebootstrap-built ones.

3. Edit /etc/apt/sources.list or add an /etc/apt/sources.list.d/ file
   pointing at the rsynced /tmp/repo reprepro repository, so that apt
   knows it can fetch packages for the host architecture from it.

4. Install the cross-compiler:

   apt-cache search -n gcc-4.9-arm
   apt-get install gcc-4.9-arm-linux-gnueabi

   (you may have to answer 'yes' to the unauthenticated packages prompt,
   unless you've taken the trouble to actually sign the packages built
   by rebootstrap)

   Then go into /usr/bin/ and, well, create some missing symlinks:

   cd /usr/bin
   for src in *-4.9; do dst="${src%-4.9}"; if [ -f "$src" ] && [ ! -f "$dst" ]; 
then ln -sv "$src" "$dst"; fi; done

5. Get the source and the build dependencies of the package that you
   intend to cross-build (in this case, ustr):

   mkdir /tmp/build
   cd /tmp/build
   apt-get source ustr
   cd ustr*/

   apt-get build-dep ustr
   apt-get build-dep -aarmel --arch-only ustr

   In the case of ustr, the last command will do nothing, since ustr
   does not have any arch-dependent build dependencies - it only
   build-depends on debhelper and cdbs, and those are both
   arch-independent, so the native versions (installed by the simple
   "apt-get build-dep ustr") will serve just fine.

6. Try to cross-build the package, specifying the host architecture:

   dpkg-buildpackage -aarmel -uc -us
   
   Now, in the unpatched ustr case, this will actually almost succeed -
   right up to the point at the end where dh_strip tries to run the
   armel "strip" cross-tool on the just-built ustr binaries.  It will
   fail with a "File format not recognized" error, because... well,
   beccause ustr's upstream Makefile hard-codes the C compiler name to
   "cc", it doesn't listen to the debian/rules file, which can supply
   a cross-compiler name, so even though we pass "-aarmel" to
   dpkg-buildpackage, it doesn't affect the ustr build at all! :)

   So...

7. Apply the patches and try to cross-build ustr again :)

   (copy the patches from outside the chroot into the chroot's /tmp/build/ )

   debian/rules clean
   export QUILT_PATCHES=debian/patches
   qiult pop -a
   quilt push -a
   quilt import -p1 -Pdebian/config-compile.diff ../config-compile.diff
   quilt import -p1 -Pdebian/cross-build.diff ../cross-build.diff
   quilt pop -a

   And now try it again:

   debian/rules clean
   dpkg-buildpackage -aarmel -uc -us

   Right, this one will fail again, since we forgot one of the basic
   rules of cross-building: "no running host programs" usually implies
   "disable the test suite, please!"  But we can already check that
   something good happened:

   file libustr-1.0.so.1.0.4
   libustr-1.0.so.1.0.4: ELF 32-bit LSB shared object, ARM, EABI5 version 1 
(SYSV), dynamically linked, 
BuildID[sha1]=117fbf898f5d5c50b6a6902ceac037eff880c399, not stripped

   So here we go again:

   debian/rules clean
   env DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -aarmel -uc -us

   And there you go :)

OK, so it wasn't quite simple, but, well, I do believe this is still one
of the simplest ways to create a cross-build environment from scratch on
a recent Debian system.  Here's hoping that this didn't scare you too
much, and here's hoping that it actually helped :)

G'luck,
Peter

-- 
Peter Pentchev  [email protected] [email protected] [email protected]
PGP key:        http://people.FreeBSD.org/~roam/roam.key.asc
Key fingerprint 2EE7 A7A5 17FC 124C F115  C354 651E EFB0 2527 DF13
# *** VERIFY AND UPDATE $mailto and $maintainer_name BELOW ***

# Mail address where logs are sent to (mandatory, no default!)
$mailto = 'roam';

# Name to use as override in .changes files for the Maintainer: field
#$maintainer_name='roam <roam@localhost>';

# Directory for chroot symlinks and sbuild logs.  Defaults to the
# current directory if unspecified.
#$build_dir='/home/roam/ubuntu/build';

# Directory for writing build logs to
$log_dir="/var/lib/sbuild/logs";

# APT_DISTUPGRADE
# Type: BOOL
# APT distupgrade.  1 to enable running "apt-get dist-upgrade" at the start
# of each build, or 0 to disable.
$apt_distupgrade = 0;

# APT_UPDATE
# Type: BOOL
# APT update.  1 to enable running "apt-get update" at the start of each
# build, or 0 to disable.
$apt_update = 0;

# CHROOT
# Type: STRING
# Default chroot (defaults to distribution[-arch][-sbuild])
$chroot = 'unstable-amd64';

# don't remove this, Perl needs it:
1;

Attachment: check-progress.sh
Description: Bourne shell script

Attachment: signature.asc
Description: Digital signature

Reply via email to