Introduction

I maintain the lsvpd package. The target platform for lsvpd is PPC and recently my PPC build machine stopped rebooting. I decided to get serious about building all the binary packages on my laptop instead of relying on having machines around with a suitably old version of glibc. An old glibc is needed because I build one PPC RPM package that needs to run on various SLES and RHEL releases and one Debian PPC package that should also run on as many versions as possible. I also want to build packages for i386 and x86_64.

Crosstool

Most of the work is done by crosstool, which is excellent. The biggest problem is figuring out how to build a configuration that works. I downloaded crosstool and copied and hacked configuration files until it worked. So what worked?

I copied gcc-4.0.1-glibc-2.2.2-hdrs-2.6.11.2.dat to gcc-martins.dat and edited it to look like this:

    BINUTILS_DIR=binutils-2.16.1
    GCC_CORE_DIR=gcc-2.95.3
    GCC_DIR=gcc-4.0.2
    GLIBC_DIR=glibc-2.2.5
    LINUX_SANITIZED_HEADER_DIR=linux-libc-headers-2.6.12.0
    GLIBCTHREADS_FILENAME=glibc-linuxthreads-2.2.5
    

This meant I would be using the latest tools, with a suitably old C library and some recent kernel headers. I then copied demo-ppc604.sh to demo-martins.sh and edited to make it look like this:

    #!/bin/sh
    set -ex
    TARBALLS_DIR=$HOME/downloads
    RESULT_TOP=/opt/crosstool
    export TARBALLS_DIR RESULT_TOP
    GCC_LANGUAGES="c,c++"
    export GCC_LANGUAGES

    # Really, you should do the mkdir before running this,
    # and chown /opt/crosstool to yourself so you don't need to run as root.
    mkdir -p $RESULT_TOP

    # Build the toolchain.  Takes a couple hours and a couple gigabytes.
    eval `cat powerpc-604.dat gcc-martins.dat`  sh all.sh --notest

    echo Done.
    

This uses a 32-bit PPC configuration, builds the C and C++ compilers, and installs the results somewhere under /opt/crosstool.

The big step was to run ./demo-martins.sh. This caused crosstool to download all the various bits - if I already had them I could have put them into /home/martins/downloads and crosstool would have found them - and compiled and installed everything. Nice!

Problems

Installing Support Libraries

To build lsvpd I was going to need PPC versions of libsysfs.a (from sysfsutils - version 1.30) and and libsgutils.a (from sg3_utils). The right thing to do would probably have been to build Debian packages with weird names and weird file locations. However, I decided to just build the bits I needed and install them into the cross-compiler tree by hand.

libsysfs.a

This one was easy to build. The following commands built the library:

    CC=/opt/crosstool/gcc-4.0.2-glibc-2.2.5/powerpc-604-linux-gnu/bin/powerpc-604-linux-gnu-gcc \
        ./configure --host=powerpc-unknown-linux
    make
    

This left these files, which needed to be installed:

    include/dlist.h
    include/libsysfs.h
    lib/.libs/libsysfs.a
    

I decided to initially install them outside the cross-compiler tree, so I could more easily rebuild the cross-compiler if needed:

    /opt/cross-extras/powerpc-gcc-4.0.2-glibc-2.2.5/
    |-- include
    |   `-- sysfs
    |       |-- dlist.h
    |       `-- libsysfs.h
    `-- lib
        `-- libsysfs.a
    

After some experimentation to find the right include and lib subdirectories, I settled upon these symbolic links:

    /opt/crosstool/gcc-4.0.2-glibc-2.2.5/powerpc-604-linux-gnu/powerpc-604-linux-gnu/
    |-- include
    |   `-- sysfs -> /opt/cross-extras/powerpc-gcc-4.0.2-glibc-2.2.5/include/sysfs
    `-- lib
        `-- libsysfs.a -> /opt/cross-extras/powerpc-gcc-4.0.2-glibc-2.2.5/lib/libsysfs.a
    

libsgutils

Due to a lack of a suitable libtool and a lack of interest on my part to try and build one, I had to hack things a little. There's a special make file that builds the commands in the package without building a separate library, so I used it to build 2 object files and then built the library by hand:

    make \
        CC=/opt/crosstool/gcc-4.0.2-glibc-2.2.5/powerpc-604-linux-gnu/bin/powerpc-604-linux-gnu-gcc \
        -f lib_no_lib/Makefile.no_lib \
        sg_cmds.o sg_lib.o
    ar crv libsgutils.a sg_cmds.o sg_lib.o
    

Installation details:

    libsgutils.a
    sg_cmds.h
    sg_lib.h

    /opt/cross-extras/powerpc-gcc-4.0.2-glibc-2.2.5/
    |-- include
    |   `-- scsi
    |   |   |-- sg_cmds.h
    |   |   `-- sg_lib.h
    `-- lib
        `-- libsgutils.a

    /opt/crosstool/gcc-4.0.2-glibc-2.2.5/powerpc-604-linux-gnu/powerpc-604-linux-gnu/
    |-- include
    |   `-- scsi
    |       |-- sg_cmds.h -> /opt/cross-extras/powerpc-gcc-4.0.2-glibc-2.2.5/include/scsi/sg_cmds.h
    |       `-- sg_lib.h -> /opt/cross-extras/powerpc-gcc-4.0.2-glibc-2.2.5/include/scsi/sg_lib.h
    `-- lib
        `- libsgutils.a -> /opt/cross-extras/powerpc-gcc-4.0.2-glibc-2.2.5/lib/libsgutils.a
    

Building RPM packages

This was surprisingly simple. I put these lines into ~/.rpmmacros:

    %_topdir     /home/martins/tmp/rpm
    %__cc        /opt/cross-extras/rpm-bin/%{_target}-gcc
    
Then I populated the relevant directories:
    /home/martins/tmp/rpm/
    |-- BUILD
    |-- RPMS
    |-- SOURCES
    |-- SPECS
    `-- SRPMS

    /opt/cross-extras/rpm-bin
    `-- ppc-linux-gcc -> /opt/crosstool/gcc-4.0.2-glibc-2.2.5/powerpc-604-linux-gnu/bin/powerpc-604-linux-gnu-gcc
    

I had to update lsvpd.spec to say:

    make CC=%__cc
    

This also works when not cross-building.

Now an RPM package can be built by running:

    rpmbuild --target ppc-unknown-linux -tb --clean lsvpd-0.14.1.99.tar.gz
    

Building Debian packages

This was surprisingly difficult! I installed dpkg-cross, which came with slightly dodgy documentation. This package wraps the dpkg-buildpackage command so you can do fancy cross-building things. First I had to change a line in /etc/dpkg-cross/cross-compile to move the world to a sensible place:

    crossbase = /opt/cross-extras/dpkg-cross
    
Then I populated this directory:
    /opt/cross-extras/dpkg-cross/
    `-- powerpc-linux-gnu
        `-- bin
            `-- powerpc-linux-gnu-gcc -> /opt/crosstool/gcc-4.0.2-glibc-2.2.5/powerpc-604-linux-gnu/bin/powerpc-604-linux-gnu-gcc
    

This changed subtly under version 1.26: having -gnu in the paths is a new thing.

In theory, the package could now be built with:

    dpkg-buildpackage -apowerpc -rfakeroot -us -uc -b
    

Notice how there's no space between -a and powerpc? If you have a space you're told:

    dpkg-buildpackage: Architecture is not specified.
      
I've seen more helpful error messages!

Reality was a little more exciting than theory. After hacking my debian/rules file so that it no longer used the deprecated debstd command but used all the funky little debhelper commands instead (a feat not worth documenting here) I noticed these things.

Other than that, cross-building Debian packages isn't too hard.

Conclusions

crosstool made most of the job easy, with rpm and dpkg-cross providing good support. I also managed to build a cross-compiler for i386 (again with an old libc) - the process was exactly the same as for PPC. I'm yet to succeed in building a x86_64 cross-compiler.