Building GCC Cross compiler for Power PC - linux
-----------------------------------------------


Download the latest tars binutils, glibc, glibc-linuxthreads, gcc from the gnu website - ftp://ftp.gnu.org
create a working forlder (say F1) for your build. Inside that (F1), create a source folder and keep all the tars in that folder.
Now untar each of the tars (binutils, gcc and glibc) in the working folder F1. Untar the glibc-linuxthreads in the glibc folder.

tar x{z|j}vf "tar file name"
 
Go into your kernel source directory (usually in /usr/src/linux-version). Go into the include directory and change the asm sym-link to point to asm-ppc (to get the kernel/sys call headers for the ppc). 

ln -s asm-ppc asm


A) Build Binutils:

As most of the sites suggest, start by building the toolchain in separate directories from where you downloaded and unzipped the sources. So, I do build-binutils, build-gcc and so on... Also, you can specify the PATH you want the cross-compiled binaries to go with --prefix option. The most convenient way is to do configure --help to know the oft needed arguments for configuration. The next step is to configure the binutils for powerpc as target.


mkdir build-binutils & cd build-binutils
../binutils-2.14/configure --target=powerpc-linux --prefix=/opt/crossgcc/powerpc-linux
make all install

After binutils is done, add the cross-compiled binaries to your PATH by

export PATH=$PATH:/opt/crossgcc/powerpc-linux/bin


B) Build Minimal GCC:

mkdir build-gcc & cd build-gcc
../gcc-3.3.2/configure --target=powerpc-linux --prefix=/opt/crossgcc/powerpc-linux --disable-shared --disable-threads --enable-languages=c --with-newlib
make all-gcc install-gcc

We faced a error here where the compilation was asking for a header file 'signal.h' which is present in the glibc package but wsa not available as glibc was not yet build. The error was displayed as follows.

===================================
make \
  CFLAGS="-g -O2 -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -pedantic -Wno-long-long  " \
  CONFIG_H="config.h  auto-host.h ../../gcc-3.4.0/gcc/../include/ansidecl.h" \
  MAKEOVERRIDES= \
  -f libgcc.mk all
make[2]: Entering directory `/root/ppc_crossgcc/gcc/build-gcc/gcc'
for d in libgcc nof libgcc/nof; do \
  if [ -d $d ]; then true; else /bin/sh ../../gcc-3.4.0/gcc/mkinstalldirs $d; fi; \
done
mkdir -p -- libgcc
mkdir -p -- nof
mkdir -p -- libgcc/nof
if [ -f stmp-dirs ]; then true; else touch stmp-dirs; fi
/root/ppc_crossgcc/gcc/build-gcc/gcc/xgcc -B/root/ppc_crossgcc/gcc/build-gcc/gcc/ -B/opt/crossgcc/powerpc-linux/powerpc-linux/bin/ -B/opt/crossgcc/powerpc-linux/powerpc-linux/lib/ -isystem /opt/crossgcc/powerpc-linux/powerpc-linux/include -isystem /opt/crossgcc/powerpc-linux/powerpc-linux/sys-include -O2  -DIN_GCC -DCROSS_COMPILE   -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition  -isystem ./include  -fPIC -g -DHAVE_GTHR_DEFAULT -DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED -Dinhibit_libc -I. -I -I../../gcc-3.4.0/gcc -I../../gcc-3.4.0/gcc/ -I../../gcc-3.4.0/gcc/../include   -fPIC -mstrict-align -DL_muldi3 -c ../../gcc-3.4.0/gcc/libgcc2.c -o libgcc/./_muldi3.o
In file included from ./tm.h:10,
                 from ../../gcc-3.4.0/gcc/libgcc2.c:43:
../../gcc-3.4.0/gcc/config/rs6000/linux.h:100:20: signal.h: No such file or directory
In file included from ./tm.h:10,
                 from ../../gcc-3.4.0/gcc/libgcc2.c:43:
../../gcc-3.4.0/gcc/config/rs6000/linux.h:109: error: parse error before "stack_t"
../../gcc-3.4.0/gcc/config/rs6000/linux.h:109: warning: no semicolon at end of struct or union
../../gcc-3.4.0/gcc/config/rs6000/linux.h:111: error: parse error before "uc_sigmask"
../../gcc-3.4.0/gcc/config/rs6000/linux.h:111: warning: type defaults to `int' in declaration of `uc_sigmask'
../../gcc-3.4.0/gcc/config/rs6000/linux.h:111: warning: data definition has no type or storage class
../../gcc-3.4.0/gcc/config/rs6000/linux.h:110: error: storage size of `uc_mcontext' isn't known
make[2]: *** [libgcc/./_muldi3.o] Error 1
make[2]: Leaving directory `/root/ppc_crossgcc/gcc/build-gcc/gcc'
make[1]: *** [stmp-multilib] Error 2
make[1]: Leaving directory `/root/ppc_crossgcc/gcc/build-gcc/gcc'
make: *** [all-gcc] Error 2

=========================================

To get rid of this error, applied the following patch .

=========================================

--- gcc-3.4.0/gcc/config/rs6000/linux.h.orig    2004-10-03 05:43:56.000000000 +0200
+++ gcc-3.4.0/gcc/config/rs6000/linux.h 2005-02-09 14:36:33.000000000 +0100
@@ -104,6 +104,8 @@
 /* Do code reading to identify a signal frame, and set the frame
    state data appropriately.  See unwind-dw2.c for the structs.  */

+#ifndef inhibit_libc
+
 #ifdef IN_LIBGCC2
 #include <signal.h>

@@ -187,3 +189,5 @@ enum { SIGNAL_FRAMESIZE = 64 };
     (FS)->retaddr_column = CR0_REGNO;                                  \
     goto SUCCESS;                                                      \
   } while (0)
+
+#endif /* inhibit_libc */

=========================================


After this, the compilation should proceed without any problems.

You can very well cross-compile Linux kernel with this minimal gcc, though may not be able to compile other applications.



C) Build Glibc

After the minimal gcc is done; the next major step is to cross-compile glibc. I have had troubles compiling glibc in the past what with some of the patches not being applied to the glibc tree. But after some help from googling, I was able to put the right combination of arguments in place. Be sure to download glibc-linuxthreads and unzip it in the glibc source directory. I found out that glibc needs linuxthreads to compile correctly. It might not be this way but I could not compile it otherwise. So, here is what to do

If compiled as is, glibc would give a compile error for glibc-2.3.2/stdio-common/sscanf.c ... you have to change the parameter declaration for sscaf function in sscanf.c. In glibc-2.3.2/stdio-common/sscanf.c change the parameter declaration for the sscanf function to 
"int sscanf (const char *s, const char *format, ...)"; 
delete the former declaration which should be 
"int sscanf(s, f) const char*s; const char* format;" (or something similar to that). 

In the build-glibc directory run...

mkdir build-glibc & cd build-glibc
../glibc-2.3.2/configure --prefix=/opt/crossgcc/powerpc-linux --target=powerpc-linux --host=powerpc-linux --enable-add-ons=linuxthreads --with-headers=/usr/src/linux-"version"/include/ --with-binutils=/opt/crossgcc/powerpc-linux/powerpc-linux/bin
make all install

It should be a breeze after that.
It was worth noting that --target option does not work with glibc, you have to use --host={target-platform}-linux for glibc to work. 



D) Build complete GCC
After glibc is compiled, you can reconfigure gcc as

../gcc-3.4.0/configure --target=powerpc-linux --prefix=/opt/crossgcc/powerpc-linux --enable-shared --enable-threads --enable-languages=c --with-cpu=405 --without-fp --with-libs=/opt/crossgcc/powerpc-linux/lib
make all install



Now you should have a complete working version of gcc.