Cross-compilation

Contents:

1. Introduction

About 

This document describes how to setup a cross-compiler for PowerPC on a x86 for use in a distributed compilation system. The system used is Gentoo Linux. Most information will be Gentoo-centric, however, some information can be generally applied to other Linux systems and to non-Linux systems.

Some information comes by examining the Gentoo crossdev script. Unfortunately, I was unable to build successfully a cross-compiler for my system configuration by simply using the script. The approach taken was to read the script and go step by step, fixing a few things for my system. Later, cross-compilation support had been completed in portage and further information was added about this. Finally, I received several contributions from readers that I added, making this documentation more complete.

Note: I took some options from the crossdev script. For some of these, I have no clue if they are (still) necessary.

Note:

To Mac OS X users: I have successfully set up a cross-compiler toolchain on Linux/x86 with target Mac OS X (Darwin)/powerpc by following instructions at http://www.myownlittleworld.com/computers/darwin-cross-distcc.html. I have OS X 10.2.8 and I had to do additional changes to gcc. I will eventually publish these changes.

Also, there is this documentation.

Document History 

2005-04-20: Started reorganizing documentation and using Gentoo doc stylesheets.

2005-04-19: Added info on building minimal toolchain using Gentoo portage.

2005-02-23: Updated documentation.

2. Options

Overview 

Four options are presented. The Gentoo-related options make full use of Gentoo tools such as portage. The non-Gentoo options can be generalized to several systems and require more work. The full toolchain options builds a full cross-compiler toolchain. With a full toolchain, full applications can be cross-compiled on the system provided all the dependencies are cross-compiled. With the minimal toolchain, applications can not entirely be cross-compiled on the system, however, this toolchain is sufficient for distributed cross-compilation with distcc.

The options are:

  1. Gentoo Minimal Toolchain
  2. Gentoo Full Toolchain
  3. General Minimal Toolchain
  4. General Full Toolchain
Option Requires Gentoo Sufficient for distcc? Can cross-compile full applications entirely on host
Gentoo Minimal Toolchain yes yes no
Gentoo Full Toolchain yes yes yes
General Minimal Toolchain no yes no
General Full Toolchain no yes yes

Full Toolchain 

It consists of all the tools with glibc. It is suitable to cross-compile full applications on the cross-compiler host.

Distcc-Only Toolchain 

It consists of the minimal amount of tools required for distributed cross-compilation with distcc. In particular, only the assembler (as) and the compilers (gcc, g++, ...) are required. All preprocessing and linking are done by the distcc client.

Note: Advanced users might want to try out the nolibgcc patch in this section. On a Gentoo system, that patch allow an easy cross-compiler installation in two steps: binutils and then gcc. It might also work on a non-Gentoo system.

3. Cross-Compilation Support in Gentoo

Gentoo Minimal Toolchain 

A reader contributed a patch and some instructions on how to build a minimal cross-compiler toolchain (binutils and gcc only). This toolchain is sufficient for cross-compilation with distcc. He used it for a x86 cross-compiler on an amd64. Following his instructions, I built successfully and easily an x86 cross-compiler on PowerPC as follows:

Code listing 3.1: Installing a Minimal Toolchain

# mkdir -p /usr/local/cross-portage-minimal/cross-i686-pc-linux-gnu
# cd /usr/local/cross-portage-minimal/cross-i686-pc-linux-gnu
# ln -sf /usr/portage/sys-devel/binutils
# cp -ax /usr/portage/sys-devel/gcc .
# PORTDIR_OVERLAY=`pwd`/.. emerge -av cross-i686-pc-linux-gnu/binutils
Add this user-contributed patch to gcc/files/3.4.3
Add an epatch line to the src_unpack() function in the gcc ebuild:
epatch ${FILESDIR}/3.4.3/gcc-3.4.3-nolibgcc.patch
# PORTDIR_OVERLAY=`pwd`/.. emerge -av cross-i686-pc-linux-gnu/gcc

Gentoo Full Toolchain 

Read this HOWTO to build a full toolchain on a Gentoo system.

Note that I was unable to a PowerPC cross-compiler by following directly the instructions from the HOWTO. I had to do these two modifications:

  1. Build the kernel headers before gcc. In order to do this, change make prepare ... for make include/linux/version.h in the headers ebuild.
  2. Add --with-sysroot=/ to the gcc configure options in toolchain.eclass.

Note: Once you have a toolchain built, you will probably be able to build it (or rebuild it) in the order describe in the HOWTO.

Example of Use 

This document explains how to cross-compile SableVM on a Gentoo system.

4. General Build Information

Overview 

Although this information is Gentoo-centric, it explains how to manually configure and build the various components and it can be applied to several systems. Information on package names and on getting sources is Gentoo-centric. Users of non-Gentoo systems will have to learn how to get the sources for their systems for the packages involved.

Configuration 

Both systems run Gentoo Linux. Distributed compilation is accomplished with distcc.

The host is a AMD Athlon (i686-pc-linux-gnu).

The target is a PowerPC 750FX (G3) (powerpc-unknown-linux-gnu)

The cross-compilation toolchain was built from the following packages and versions:

  • sys-kernel/linux26-headers-2.6.7-r4
  • sys-devel/binutils-2.15.90.0.3-r3
  • sys-libs/glibc-2.3.4.20040808
  • sys-devel/gcc-3.4.1-r2

Space Requirements 

The full toolchain installation takes 190MB. The distcc-only toolchain takes only 12MB after some cleanup.

Note the build requirements are much higher.

Installation - Preparation 

Note: To Gentoo users: You might want to consider using cross-compilation support built in portage.

Throughout this document, I will refer to the following variables:

  • DEST: Destination directory
  • CROSS_CHOST
  • MY_CHOST
  • MY_CFLAGS
  • CROSS_CFLAGS
  • MIN_KV
  • CROSS_GCCLANG: Languages to support.
    export CROSS_GCCLANG="c,c++"
    or
    export CROSS_GCCLANG="c,c++,ada,f77,objc"
  • POWERPC_HOSTNAME: Hostname of your PowerPC machine.

I used these values:

Code listing 4.1: Values Used

export DEST=/home/crossdev/ppc
export CROSS_CHOST=powerpc-unknown-linux-gnu
export MY_CHOST=i686-pc-linux-gnu
export MY_CFLAGS="-O2 -pipe -march=i686 -fomit-frame-pointer"
export CROSS_CFLAGS="-O3 -mcpu=750 -pipe"
export MIN_KV=2.6.7
export CROSS_GCCLANG="c,c++"

export HEADERS_VER=2.6.7-r4
export BINUTILS_VER=2.15.90.0.3-r3
export GLIBC_VER=2.3.4.20040808
export GCC_VER=3.4.1-r2

export POWERPC_HOSTNAME=ibou

export PATH=${DEST}/bin:${PATH}

Step 0 - Preparation 

Create a destination directory:

Code listing 4.2: Creating Directory

# mkdir -p ${DEST}
# chmod a+rx ${DEST}

Note: We refer to this directory as the destination directory ${DEST}

Unpack the linux-headers, binutils, glibc and gcc sources. Note that these should correspond to your target system, in particular the gcc versions should match in you are considering distributed compilation with distcc.

On Gentoo, this can be done with the ebuild command as follows:

Code listing 4.3: Unpacking Sources on Gentoo

(By default, sources are unpacked in /var/tmp/portage/package_name.)
# ebuild /usr/portage/sys-kernel/linux26-headers/linux26-headers-${HEADERS_VER}.ebuild unpack
# ebuild /usr/portage/sys-devel/binutils/binutils-${BINUTILS_VER}.ebuild unpack
# ebuild /usr/portage/sys-libs/glibc/glibc-${GLIBC_VER}.ebuild unpack
# ebuild /usr/portage/sys-devel/gcc/gcc-${GCC_VER}.ebuild unpack

Note: glibc is required only for a full toolchain.

You are now ready to configure/compile/install each component. For each of the next 5 steps, go into the source root directory of the component to build before executing the commands.

Step 1 - Installation of kernel-headers 

Do:

Code listing 4.4: Installing Kernel Headers

# mkdir ${DEST}/include
# make ARCH=ppc CROSS_COMPILE=powerpc-unknown-linux-gnu- mrproper

Optionnally copy the .config from your PowerPC before continuing:

Code listing 4.5: Getting .config from PowerPC

# scp ${POWERPC_HOSTNAME}:/usr/src/linux/.config .

Then, continue the installation:

Code listing 4.6: Finishing Installing Kernel Headers

# make ARCH=ppc CROSS_COMPILE=powerpc-unknown-linux-gnu- oldconfig
# make include/linux/version.h
# cp -axf include/linux ${DEST}/include
# cp -axf include/asm-ppc ${DEST}/include/asm-ppc
# cp -axf include/asm-generic ${DEST}/include/asm-generic
# ln -sf ${DEST}/include/asm-ppc ${DEST}/include/asm

Step 2 - Installation of binutils 

Configure binutils:

Code listing 4.7: Configuring binutils

# CFLAGS=${MY_CFLAGS} \
./configure \
  --target=${CROSS_CHOST} \
  --host=${MY_CHOST} \
  --prefix=${DEST} \
  --enable-shared

Note: Add --enable-64-bit-bfd to add support for 64-bit targets on 32-bit hosts.

Note: --disable-static could be useful to avoid installing the static libs for the distcc-only toolchain.

Build it:

Code listing 4.8: Building binutils

# make

Install it in one of two ways:

  1. For distcc-only toolchain, install only the assembler and its libraries:

    Code listing 9: Build binutils - Minimal Toolchain

    # (cd gas && make install)
    # (cd opcodes && make install)
    # (cd bfd && make install)
    
  2. For a full toolchain:

    Code listing 10: Build binutils - Full Toolchain

    # make install
    

Update your path to use the binutils just built:

Code listing 4.11: Updating PATH

# export PATH=${DEST}/bin:$PATH

Step 3 - Installation of gcc (bootstrap) 

For some reasons, headers are installed in ${DEST}/include, however, gcc does not include that directory but it does look in the non-existing ${DEST}/powerpc-unknown-linux-gnu/include directory. To fix this, I do the following symlink:

Code listing 4.12: Make Symlink

# ln -s ../include ${DEST}/powerpc-unknown-linux-gnu/include

Prepare, configure, build, and install by doing one of these two alternatives:

  1. For a distcc-only installation:

    Code listing 13: Building gcc (Bootstrap) - Minimal Toolchain

    # mkdir buildfullhere-ppc
    # cd buildfullhere-ppc
    
    # CFLAGS="${MY_CFLAGS}" \
    ../configure \
      --prefix=${DEST} \
      --host=${MY_CHOST} \
      --target=${CROSS_CHOST} \
      --disable-multilib \
      --disable-nls \
      --enable-shared \
      --enable-languages="${CROSS_GCCLANG}" \
      --without-included-gettext \
      --with-system-zlib \
      --enable-threads=posix \
      --enable-long-long \
      --enable-symvers=gnu \
      --disable-checking \
      --enable-cstdio=stdio \
      --enable-clocale=generic \
      --enable-__cxa_atexit \
      --enable-c99 \
      --enable-version-specific-runtime-libs \
      --with-local-prefix=${DEST}/local \
      --with-sysroot=/
    
    # make CFLAGS_FOR_TARGET="${CROSS_CFLAGS} -DHAVE_SYS_ERRLIST" CXXFLAGS_FOR_TARGET="${CFLAGS_FOR_TARGET}"
    

    Since powerpc-unknown-linux-gnu-ar was not built, this build error should occur:

    Code listing 14: Build Error

    make[2]: powerpc-unknown-linux-gnu-ar: Command not found
    make[2]: *** [libgcc.a] Error 127
    make[2]: Leaving directory `/var/tmp/portage/gcc-3.4.1-r2/work/gcc-3.4.1/buildfullhere-ppc/gcc'
    make[1]: *** [stmp-multilib] Error 2
    make[1]: Leaving directory `/var/tmp/portage/gcc-3.4.1-r2/work/gcc-3.4.1/buildfullhere-ppc/gcc'
    make: *** [all-gcc] Error 2
    

    It is not required to build any PowerPC libraries (such as libgcc, etc.). Simply force the compilation of the remaining components with the -k option:

    Code listing 15: Finishing Build with make -k

    # make -k CFLAGS_FOR_TARGET="${CROSS_CFLAGS} -DHAVE_SYS_ERRLIST" CXXFLAGS_FOR_TARGET="${CFLAGS_FOR_TARGET}"
    
    (...)
    
    make[1]: Target `all' not remade because of errors.
    rm gcc.pod
    make[1]: Leaving directory `/var/tmp/portage/gcc-3.4.1-r2/work/gcc-3.4.1/buildfullhere-ppc/gcc'
    make: *** [all-gcc] Error 2
    make: Target `all' not remade because of errors.
    

    Not everything was built. It is okay, simply install the compiler files:

    Code listing 16: Installing Compiler

    # (cd gcc && make -k install)
    

    More errors but the compiler should have been installed:

    Code listing 17: More Errors

    make: Target `install' not remade because of errors.
    

    Congratulations! At this point you should have a working cross-compiler toolchain that is sufficient for distcc use. Go to Testing the Cross-compiler Toolchain.

  2. For a full installation:

    Code listing 18: Configuring gcc (Bootstrap) - Full Toolchain

    # mkdir buildboothere-ppc
    # cd buildboothere-ppc
    
    # CFLAGS="${MY_CFLAGS} -Dinhibit_libc -static-libgcc" \
    ../configure \
    --prefix=${DEST} \
    --host=${MY_CHOST} \
    --target=${CROSS_CHOST} \
    --with-newlib \
    --disable-shared \
    --disable-threads \
    --enable-languages="c" \
    --disable-multilib \
    --disable-nls \
    --enable-symvers=gnu \
    --enable-__cxa_atexit \
    --with-sysroot=/ \
    --enable-static
    

    Note: We use the --with-sysroot / option rather than the deprecate --with-headers /usr/include option. Unlike the --with-headers /usr/include, the --with-sysroot option does not copy the system headers to ${DEST}/powerpc-unknown-linux-gnu/sys-include.

    Build and install:

    Code listing 19: Building and Installing gcc (Bootstrap) - Full Toolchain

    # make CFLAGS_FOR_TARGET="${CROSS_CFLAGS}" CXXFLAGS_FOR_TARGET="${CFLAGS_FOR_TARGET}"
    # make install
    

Step 4 - Installation of glibc 

Note: This step is not required for a distcc-only toolchain.

Note: You can optionally enable ccache at this point.

Apply the following patch:

Code listing 4.20: glibc Patch

--- Makeconfig  2004-09-08 02:03:53.755231360 -0400
+++ Makeconfig  2004-09-08 02:23:03.817395336 -0400
@@ -522,16 +522,16 @@
 
 ifndef gnulib
 ifneq ($(have-as-needed),yes)
- libgcc_eh := -lgcc_eh
+ libgcc_eh :=
 else
  libgcc_eh := -Wl,--as-needed -lgcc_s$(libgcc_s_suffix) -Wl,--no-as-needed
 endif
 ifneq ($(have-cc-with-libunwind),yes)
  gnulib := -lgcc $(libgcc_eh)
- static-gnulib := -lgcc -lgcc_eh
+ static-gnulib := -lgcc
 else
  gnulib := -lgcc $(libgcc_eh) -lunwind
- static-gnulib := -lgcc -lgcc_eh -lunwind
+ static-gnulib := -lgcc -lunwind
 endif
 endif
 ifeq ($(elf),yes)

Note: The glibc manual recommends using a separate build directory and always building from new empty directory.

Note: I tested it only with linuxthreads. The nptl instructions were contributed by a reader.

Configure, build and install glibc by using one of these alternatives.

  1. For linuxthreads, do:

    Code listing 21: Building glibc - with linuxthreads

    # mkdir buildppc
    # cd buildppc
    
    # BUILD_CC="gcc" \
    CC="${CROSS_CHOST}-gcc ${CROSS_CFLAGS}" \
    AR="${CROSS_CHOST}-ar" \
    RANLIB="${CROSS_CHOST}-ranlib" \
    ../configure \
      --prefix=${DEST} \
      --host=powerpc-unknown-linux-gnu \
      --build=${MY_CHOST} \
      --without-tls \
      --without-__thread \
      --enable-add-ons=linuxthreads \
      --enable-clocale=gnu \
      --enable-kernel=${MIN_KV} \
      --without-gd \
      --without-cvs \
      --disable-profile \
      --disable-debug \
      --with-headers="${DEST}/include"
    
    # make
    # make install
    
  2. For nptl, do:

    Code listing 22: Building glibc - with nptl

    # mkdir buildppc
    # cd buildppc
    
    # cp ../nptl/sysdeps/pthread/pthread.h ${DEST}/include
    # mkdir ${DEST}/include/bits
    # cp ../nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h ${DEST}/include/bits
    
    # echo "libc_cv_forced_unwind=yes" > config.cache
    # echo "libc_cv_c_cleanup=yes" >> config.cache
    
    # BUILD_CC="gcc" \
    CC="${CROSS_CHOST}-gcc ${CROSS_CFLAGS}" \
    AR="${CROSS_CHOST}-ar" \
    RANLIB="${CROSS_CHOST}-ranlib" \
    ../configure \
      --prefix=${DEST} \
      --host=powerpc-unknown-linux-gnu \
      --build=${MY_CHOST} \
      --with-tls \
      --with-__thread \
      --enable-add-ons=nptl \
      --enable-clocale=gnu \
      --enable-kernel=${MIN_KV} \
      --without-gd \
      --disable-profile \
      --disable-debug \
      --with-headers="${DEST}/include" \
      --cache-file=config.cache
    
    # make
    # make install
    

    Note: The differences from linuxthreads are shown in italic.

Note: BUILD_CC is the compiler on the platform we are building the cross-compiler on.

Note: The CC="${CROSS_CHOST}-gcc -O2 -nostdlib -nostartfiles ${CROSS_CFLAGS}" from the crossdev script leads to the __fixdfdi error that some might have previously encountered.

Note: This seems no longer necessary:

Code listing 23: Unnessary Steps

# make sysdeps/gnu/errlist.c
# mkdir -p stdio-common
# touch stdio-common/errlist-compat.c
These used to be done before make.

Step 5 - Installation of gcc (full) 

Note: This step is not required for a distcc-only toolchain.

Build and install gcc (full):

Code listing 4.24: Installation of gcc (Full)

# mkdir buildfullhere-ppc
# cd buildfullhere-ppc
# CFLAGS="${MY_CFLAGS}" \
../configure \
  --prefix=${DEST} \
  --target=${CROSS_CHOST} \
  --host=${MY_CHOST} \
  --disable-multilib \
  --disable-nls \
  --enable-shared \
  --enable-languages="${CROSS_GCCLANG}" \
  --without-included-gettext \
  --with-system-zlib \
  --enable-threads=posix \
  --enable-long-long \
  --enable-symvers=gnu \
  --disable-checking \
  --enable-cstdio=stdio \
  --enable-clocale=generic \
  --enable-__cxa_atexit \
  --enable-c99 \
  --enable-version-specific-runtime-libs \
  --with-local-prefix=${DEST}/local \
  --with-libs="${DEST}/lib" \
  --with-headers="${DEST}/include"

# make CFLAGS_FOR_TARGET="${CROSS_CFLAGS} -DHAVE_SYS_ERRLIST" CXXFLAGS_FOR_TARGET="${CFLAGS_FOR_TARGET}"

# make install

Congratulations! At this point you should have a working cross-compiler toolchain.

Note: (to myself) If --with-sysroot used, the suffix /usr is automatically added. If --with-headers is used, a sys-include directory is added, though it is maybe not necessary. Maybe a symlink will do: ln -s /usr/include ${DEST}/powerpc-unknown-linux-gnu/sys-include.

5. Testing the Cross-compiler Toolchain

Setup 

We use the hello world program as an example:

Code listing 5.1: Creating Test Program

curly root # cat > /tmp/hello.c

#include <stdio.h>

int main(void) {
  printf("allo!\n");
}

We are compiling on a x86:

Code listing 5.2: Compiling Host

curly root # uname -a
Linux curly 2.6.7-rc3 #1 Tue Jun 15 02:26:52 EDT 2004 i686 AMD Athlon(tm) Processor AuthenticAMD GNU/Linux
curly root #

Full Toolchain 

We cross-compile the HelloWorld program and we get a PowerPC executable:

Code listing 5.3: Cross-Compiling the Test Program

curly root # ${DEST}/bin/powerpc-unknown-linux-gnu-gcc hello.c
curly root # file a.out
a.out: ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV), for GNU/Linux 2.6.5, dynamically linked (uses shared libs), not stripped
curly root # 

We can send the executable to the PowerPC and execute it:

Code listing 5.4: Transfering Executable to Target Machine

root@curly ~ # ssh ibou 'uname -a ; cd /tmp ; cat > hello ; chmod a+x hello; ./hello' < a.out
Linux ibou 2.6.7-gentoo-r14 #1 Sat Sep 4 18:51:22 EDT 2004 ppc 750FX PowerBook4,3 GNU/Linux
allo!
root@curly ~ # 

Minimal Toolchain 

If a full toolchain was not build, a full executable cannot be built. Although the code can be compiled, it cannot be linked. If the preprecessor installed for the cross-compiler, we can compile the program to assembly code or to object file. If the preprocessor was not installed, the source will need to be processed on the PowerPC first. It can then be transfered to the x86 and it can be used instead of the C source to perform the tests:

Code listing 5.5: Preprocessing the Source

# gcc -E hello.c > hello.i

To compile to assembly, do:

Code listing 5.6: Cross-Compiling the Test Program

root@curly /tmp # powerpc-unknown-linux-gnu-gcc -S hello.c

The output file hello.s should contain PowerPC assembly code:

Code listing 5.7: Content of hello.s

        .file   "hello.c"
        .section        .rodata
        .align 2
.LC0:
        .string "allo!\n"
        .section        ".text"
        .align 2
        .globl main
        .type   main, @function
main:
        stwu 1,-32(1)
        mflr 0
        stw 31,28(1)
        stw 0,36(1)
        mr 31,1
        lis 9,.LC0@ha
        la 3,.LC0@l(9)
        bl printf
        mr 3,0
        lwz 11,0(1)
        lwz 0,4(11)
        mtlr 0
        lwz 31,-4(11)
        mr 1,11
        blr
        .size   main, .-main
        .section        .note.GNU-stack,"",@progbits
        .ident  "GCC: (GNU) 3.4.1 20040803 (Gentoo Linux 3.4.1-r2, ssp-3.4-2, pie-8.7.6.5)"

To compile to an object file:

Code listing 5.8: Cross-Compiling and Cross-Assembling Test Program

root@curly /tmp # powerpc-unknown-linux-gnu-gcc -c hello.c
root@curly /tmp # file hello.o
hello.o: ELF 32-bit MSB relocatable, PowerPC or cisco 4500, version 1 (SYSV), not stripped

The object file can be linked and tested on the PowerPC:

Code listing 5.9: Linked Cross-Compiled Object File

root@curly /tmp # ssh ibou 'uname -a ; cd /tmp ; cat > hello.o ; gcc -o hello hello.o; ./hello' < hello.o
Linux ibou 2.6.7-gentoo-r14 #1 Sat Sep 4 18:51:22 EDT 2004 ppc 750FX PowerBook4,3 GNU/Linux
allo!
root@curly /tmp # 

6. Extra Cleanup for Distcc-Only Toolchain

If a minimal toolchain has been manually installed (i.e. not through portage), unnecessary files can be removed.

The distcc-only toolchain takes 28MB. With some cleanup, I reduced it to only 12MB. A full toolchain (without any cleanup) is 190MB.

We can remove: include files, unneeded executables, unneeded static libs, unused libs, documentation files (info and man pages), and locales.

Warning: Make sure that ${DEST} is properly set before executing the following commands.

Code listing 6.1: Removing Unnecessary Files

# rm -rf ${DEST}/include \
  ${DEST}/powerpc-unknown-linux-gnu/include \
  ${DEST}/i686-pc-linux-gnu/powerpc-unknown-linux-gnu/include

# rm ${DEST}/bin/powerpc-unknown-linux-gnu-{cpp,gcc-3.4.1,gccbug,gcov}

# rm -f ${DEST}/i686-pc-linux-gnu/powerpc-unknown-linux-gnu/lib/*.{a,la}

# rm -rf ${DEST}/lib

# rm -rf ${DEST}/info ${DEST}/man

# rm -rf ${DEST}/share

We removed the preprocessor... To do a test, use preprocessed input:

Code listing 6.2: Testing Without a Preprocessor

root@curly /home/crossdev/ppc # gcc -E -o /tmp/hello.i /tmp/hello.c

root@curly /home/crossdev/ppc # powerpc-unknown-linux-gnu-gcc -o /tmp/hello.o -c /tmp/hello.i ; file /tmp/hello.o
/tmp/hello.o: ELF 32-bit MSB relocatable, PowerPC or cisco 4500, version 1 (SYSV), not stripped
root@curly /home/crossdev/ppc # 

7. Cross-compiling with distcc

Install distcc 

Install distcc. On Gentoo it can be done as follows:

Code listing 7.1: Installing distcc on Gentoo

emerge distcc
(Follow the setup instructions.)

Configuration for cross-compilation 

Note: Some of these instructions might be deprecated for Gentoo if the cross-compiler has been installed via portage.

Note: If you want to setup distccd for compilation on more that one architecture on Gentoo, read this thread in the Gentoo Forums.

Add ${DEST}/bin (and optionnally ${DEST}/powerpc-unknown-linux-gnu/bin) to the distcc daemon path configuration. This is done by modifying /etc/init.d/distccd:

Code listing 7.2: Modifying /etc/init.d/distcc

start() {
        rm -f ${DISTCCD_PIDFILE}
        ebegin "Starting distccd"
        TMPDIR="${TMPDIR}" \
        PATH="/home/crossdev/ppc/bin:/home/crossdev/ppc/powerpc-unknown-linux-gnu/bin" \
        /sbin/start-stop-daemon --start --quiet --startas ${DISTCCD_EXEC} \
        --pidfile ${DISTCCD_PIDFILE} -- \
        --pid-file ${DISTCCD_PIDFILE} -N ${DISTCCD_NICE} --user distcc \
        ${DISTCCD_OPTS}

        eend $?
}

Note: The directory ${DEST}/powerpc-unknown-linux-gnu/bin contains binaries not prefixed by powerpc-unknown-linux-gnu-. If you do this, you might as well create the following symlink:

Code listing 3: Creating cc Symlink

# ln -s gcc ${DEST}/powerpc-unknown-linux-gnu/bin/cc

Note: If you add /usr/powerpc-unknown-linux-gnu/gcc-bin/3.4 to the distccd PATH, you will get both the powerpc-unknown-linux-gnu-x and x binaries.

If you do not add this directory to the path, you might encounter some problems for some packages that do not respect the $CC and $CXX variables. If you add this directory however, you will run into problems if you do distributed compilation for the host architecture (x86 in our case) as distcc will use the cross-compiler instead of the native compiler.

Note: If the daemon is already started, to not forget to restart it to have the new configuration:

Code listing 4: Restarting the Daemon

# /etc/init.d/distccd restart

Note: The daemon logs messages in the syslog.

Compiling 

If you added ${DEST}/powerpc-unknown-linux-gnu/bin to the distccd path, you can compile as usual:

Code listing 7.5: Emerging

# emerge vi

Otherwise, you need to set the CC and CXX environment variables to specify the compiler to use. For example:

Code listing 7.6: Emerging

# CC=powerpc-unknown-linux-gnu CXX=powerpc-unknown-linux-gnu emerge vi

Note: The approach with the CC and CXX variables does not work for all software packages.

An approach suggested here can be used to select the appropriate compiler without manually setting CC and CXX before emerge. It consists of setting these variables to the full ${CHOST}-gcc and ${CHOST}-g++ names in the compiler configuration files located in /etc/env.d/gcc. This is especially useful when the same distccd servers are used for multiple architectures.

8. Adding ccache Support

Note that with distributed compilation, the code is cached on the client side. If you intend to cross-compile code directly on the host with the cross-compiler, you can add ccache support with the command:

Code listing 8.1: Adding ccache Support

# ccache-config --install-links powerpc-unknown-linux-gnu

Note: If you configure ccache after the installation of glibc and before the installation of gcc (full), you will need to reconfigure it for for C++ and other languages.

9. Resources

This section will contain various links to web pages and forums that discuss cross-compilation for a variety of operating systems and architectures.

10. About this Document

Note that several code segments are coming from the crossdev script. The crossdev script is licensed under GPL-2.

This document uses a modified XSL stylesheet from the Gentoo project: guide.xsl.

Send your comments, suggestions, or corrections to:

dbelan2 (at) cs (dot) mcgill (dot) ca
The contents of this document are licensed under the Creative Commons - Attribution / Share Alike license.
line
Updated 2005-04-20
line
David Bélanger
Author

line
Summary:  This guide shows you how to setup a cross-compiler on a Gentoo system. Configuring ccache and distcc for cross-compilation is also covered. This guide also contain general information that can be applied to non-Gentoo systems as well.
line
Copyright 2004-2005 David Bélanger. Questions, Comments, Corrections? Email dbelan2_at_cs_dot_mcgill_dot_ca.