Building a GCC cross-compiler for the Rio Receiver

Jeff Mock
2/6/1

There are a lot of good sources for information about building
GCC cross compilers:

    http://www.inkvine.fluff.org/~chris/arm-tools.html
    http://www.objsw.com/CrossGCC/

There is a chicken-n-egg problem building a GCC and glibc
toolchain as a cross-compiler from scratch.  In order to build the compiler 
you need the include files for target, but you can't build the include files
until you have a compiler.  This gets slightly more complicated
if you are building a cross compiler for a Linux system because
you need the include files for a configured linux kernel as well when
building the compiler.  Aside from this weirdness it's pretty
straight forward.

This is how I build an arm-linux cross compiler and kernel 
from scratch for the Dell Audio Receiver on an RH7 X86 machine. If
you aren't inclined to duplicate the effort you can get a binary 
copy of my toolchain at: 

    ftp://ftp.mock.com/pub/arm-linux/arm-linux-toolchain.tgz (32MB)

This must be placed in /usr/local/arm-linux or it won't work properly.  
It was built to run on a Redhat 7.0 system.  This is GCC 2.95.2 with
some Arm patches, binutils 2.10.1.0.4, and glibc-2.1.3.

Useful defines for my build process:

    BASE=/home/jeff/mercury
    TOOLCHAIN=$BASE/toolchain
    TARGET=arm-linux
    DEST=/usr/local/$TARGET
    KERNEL=/home/jeff/mercury/linux-mercury

Here are some useful files for building the toolchain.  The other 
items can be found in the usual places.

    GCC 2.95.2 mods for Arm
        ftp://ftp.mock.com/pub/arm-linux/gcc-2.95.2-diff-991022.gz (26k)

    2.2.14 kernel with rmk4 patches for Arm with Empeg patches for
    digital audio receiver product.
        ftp://ftp.mock.com/pub/arm-linux/linux-kernel-v1.01.tar.gz (16MB)

    If you prefer you can derive the kernel for the Dell audio
    receiver from source material.  Get a copy of the distribution
    kernel 2.2.14 from kernel.org and apply these patches in order.
    This should produce a tree identical to the above kernel:

    The rmk4 arm patches for 2.2.14:
        ftp://ftp.mock.com/pub/arm-linux/patch-2.2.14-rmk4.gz (454k)

    Patches specific to the Dell Audio Receiver:
        ftp://ftp.mock.com/pub/arm-linux/patch-mercury.gz (85k)

    I had a small problem building this kernel, the solution is 
    described below.

$TOOLCHAIN directory should contain stuff to make tools, empty otherwise
    binutils-2.10.1.0.4.tar.gz
    gcc-2.95.2.tar.gz
    gcc-2.95.2-diff-991022
    glibc-2.1.3.tar.gz
    glibc-linuxthreads-2.1.3.tar.gz

Delete any vestige of old toolkit
    rm -rf $DEST

Build binutils
    tar zxvf binutils-2.10.1.0.4.tar.gz
    rm -rf build-binutils
    mkdir build-binutils
    cd build-binutils
    ../binutils-2.10.1.0.4/configure --target=$TARGET --prefix=$DEST
    make 
    make install

Setup kernel sources for Arm kernel, configure kernel, and do
a "make dep".  This does not need an arm compiler, uses host
compiler.  The kernel includes are necessary to build the compiler.
If you are using the kernel image listed above for the Dell Digital
Audio Receiver, a suitable kernel configuration is 
arch/arm/def-configs/mercury:

    cd $KERNEL
    cp arch/arm/def-configs/mercury .config
    make oldconfig
    make dep

Manually link kernel includes into toolchain includes

    cd $DEST/$TARGET
    mkdir include
    cd include
    ln -s $KERNEL/include/asm-arm asm
    ln -s $KERNEL/include/linux linux

build just C compiler in special way that doesn't require libc
include files.

    # untar and patch compiler sources
    cd $TOOLCHAIN
    tar zxvf gcc-2.95.2.tar.gz
    cd gcc-2.95.2
    patch -p0 < ../gcc-2.95.2-diff-991022

    # Make mod so C compiler will build without libc includes
    Edit file $TOOLCHAIN/gcc-2.95.2/gcc/config/arm/t-linux, change line:
       TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fPIC
    Change to:
       TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fPIC -Dinhibit_libc \
           -D__gthr_posix_h

    # Configure to build only C compiler
    cd $TOOLCHAIN
    rm -rf build-gcc0
    mkdir build-gcc0
    cd build-gcc0
    ../gcc-2.95.2/configure $TARGET --prefix=$DEST --disable-threads \
        --enable-languages="c" --with-cpu=strongarm110
    make
    make install
 
At this point the C compiler and utilties are suitable for building the 
kernel, but there is no libc or includes for building user code.

I had a little problem building the Arm kernel listed above for 
the Dell Audio Receiver.  ld fails during the final link building
the zImage file. I don't know the source of the problem, but the
problem can be fixed by removing the following line near the end
of arch/arm/boot/compressed/vmlinux.lds.in: 

      .comment 0 : { *(.comment) }   (remove this line)

Add /usr/local/arm-linux/bin to your path, the kernel should build 
properly and you should have a zImage suitable for the audio receiver.

Build glibc, this takes the longest...
    # Extract glibc
    cd $TOOLCHAIN
    tar zxvf glibc-2.1.3.tar.gz
    cd glibc-2.1.3
    tar zxvf ../glibc-linuxthreads-2.1.3.tar.gz
 
    # configure libc
    cd $TOOLCHAIN
    rm -rf build-glibc
    mkdir build-glibc
    cd build-glibc
    CC=$TARGET-gcc
    ../glibc-2.1.3/configure $TARGET --build=i686-linux \
        --prefix=$DEST/$TARGET --enable-add-ons --disable-sanity-checks
    make
    make install

Now that libc is built and the includes are installed, go back and rebuild
C and C++ compilers properly.

    # Remove hack used to build temp C compiler
    Edit file $TOOLCHAIN/gcc-2.95.2/gcc/config/arm/t-linux, change line:
       TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fPIC -Dinhibit_libc \
           -D__gthr_posix_h
    Change back to:
       TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fPIC
 
    # Configure to build full C and C++ compilers
    cd $TOOLCHAIN
    rm -rf build-gcc1
    mkdir build-gcc1
    cd build-gcc1
    ../gcc-2.95.2/configure $TARGET --prefix=$DEST --enable-languages="c,c++" \
        --with-cpu=strongarm110
    make
    make install

Rebuild libc with newly built compiler (might not be necessary)

    # configure libc
    cd $TOOLCHAIN
    rm -rf build-glibc1
    mkdir build-glibc1
    cd build-glibc1
    CC=$TARGET-gcc
    ../glibc-2.1.3/configure $TARGET --build=i686-linux \
        --prefix=$DEST/$TARGET --enable-add-ons --disable-sanity-checks
    make
    make install

All done, toolchain for Arm-linux running on x86 linux is in 
/usr/local/arm-linux, add /usr/local/arm-linux/bin to your path.