Cross-compiling
From GamecubeLinux Wiki
| Table of contents |
Cross Compiling
Since this seems to be a topic that many people, who are new to cross compiling, have troubles with, this section will give some tips, and how-to's. This will be split up into several smaller categories since there are many ways of setting up the cross compiler chain. There will also be a section on how to use the cross compiler in a native environment in addition to using it in a distcc environment.
Building the Cross Compiler
Crosstool
Crosstool (http://kegel.com/crosstool/) is a well tested set of shell scripts for building a Glibc based cross compiler. Typically you can just run:
./demo-powerpc-750.sh
to build the Gamecube cross compiler with crosstool.
Buildroot
Buildroot (http://buildroot.uclibc.org/) is another excellent choice if you not only want a uClibc compiler but also a small working base system that you can boot into. Typically you'll just need to download Buildroot from svn and run:
make menuconfig
and set it up to be a powerpc build.
BuildCross
BuildCross (http://losinggeneration.oddmint.com/) is my build script which has the ability to build both Glibc and uClibc toolchains. Like Crosstool it's written as a shell script. It also supports some other targets that aren't Linux based (such as sh-elf for Dreamcast/KOS development.) The Linux compiler support is fairly new to the script and so there maybe bugs yet. Crosstool and this are about the best when it comes to making a customized cross compiler. with BuildCross you can run:
./buildcross.sh -gcl
which will install the cross compiler to /usr/local/gc-linux
Gentoo Overlays
I've played with this only a bit, but it seemed to work alright in a Gentoo chrooted environment. This section is a modified version of [1] (http://dev.gentoo.org/~vapier/CROSS-COMPILE-HOWTO) to be Gamecube (powerpc) centric.
Howto Build a Cross Compiler With Emerge!
Before you read any further, you should try using 'crossdev' in portage. You're less likely to screw something up that way. Simply do `emerge '>=crossdev-0.9'` and then execute `crossdev --help`.
The instructions below are for those who wish to learn more about the details of how crossdev works wrt portage. Most would care less, in which case use crossdev!
PACKAGE NOTES
- binutils
Only binutils versions that 'inherit toolchain-binutils' will work. The host system should also being using one of these versions or you'll probably break your system.
- linux-headers
Any version that has 'inherit kernel-2' should work.
- gcc
Only gcc versions that 'inherit toolchain' will work.
Supported versions:
3.3.6+
3.4.6+
4.0.3+
4.1.1+
Anything else you're on your own.
- glibc
Supported versions:
2.3.6-r4+
2.4-r3+
Anything else you're on your own.
General Notes
- ARCH / USE
sometimes you may have to pass ARCH / USE to the emerge process for things to work properly. For example, glibc will only apply hppa patches if 'hppa' is in ARCH / USE. This is a bug and I am working on fixing it :).
- CFLAGS
All packages should be built with your HOST's CFLAGS except for glibc. When building glibc, change your CFLAGS to something for the target host.
Building with Portage
(1) Pick your target. Any valid 'CHOST' will do. I will be using 'powerpc-unknown-linux-gnu'.
(2) Setup 'categories'.
mkdir -p /etc/portage echo cross-powerpc-unknown-linux-gnu >> /etc/portage/categories
(3) Setup PORTDIR_OVERLAY. For more info, see make.conf(5) manpage. My overlay is /usr/local/portage.
mkdir -p /usr/local/portage/cross-powerpc-unknown-linux-gnu cd /usr/local/portage/cross-powerpc-unknown-linux-gnu ln -s /usr/portage/sys-devel/binutils binutils ln -s /usr/portage/sys-devel/gcc gcc ln -s /usr/portage/sys-kernel/linux-headers linux-headers ln -s /usr/portage/sys-libs/glibc glibc
(4) Emerge binutils.
emerge cross-powerpc-unknown-linux-gnu/binutils
(5) Emerge gcc [C compiler only].
USE=nocxx emerge cross-powerpc-unknown-linux-gnu/gcc gcc-config powerpc-unknown-linux-gnu-4.1.2
(6) Emerge linux headers.
emerge cross-powerpc-unknown-linux-gnu/linux-headers
(7) Emerge glibc.
USE=powerpc emerge cross-powerpc-unknown-linux-gnu/glibc
(8) Emerge gcc [C and C++ compiler].
emerge cross-powerpc-unknown-linux-gnu/gcc
(9) Build stuff ! When you go to emerge packages, you should just need to do: ROOT=/gclinux-root/ CHOST=powerpc-unknown-linux-gnu emerge cpio
- you should also set CBUILD to your building machine for completeness sake ... most of the time you won't need it, but sometimes you will :)
- CTARGET is no longer needed so don't set it !
If you want to cross compile a kernel, do this:
make ARCH=powerpc CROSS_COMPILE=powerpc-unknown-linux-gnu-
Building Your Own
This is typically not needed since the above methods should be more than enough to get a sane working compiler, but I'll give a crash course here for all those who might be crazy like me and want to try it without having to figure out what's going on with the scripts above.
Typically you'll want to have a directory structure like this: Build directories
~/gamecubebuild/binutils-version ~/gamecubebuild/buildbinutils ~/gamecubebuild/gcc-version ~/gamecubebuild/buildinitialgcc ~/gamecubebuild/buildfinalgcc ~/gamecubebuild/glibc-version ~/gamecubebuild/buildglibc
Install directories
/usr/local/gc-linux /usr/local/gc-linux/sys-root /usr/local/gc-linux/sys-root/lib /usr/local/gc-linux/sys-root/usr /usr/local/gc-linux/sys-root/usr/lib
Before you start building the cross compiler you should make sure to add /usr/local/gc-linux/bin to the path.
export PATH=$PATH:/usr/local/gc-linux/bin
First you should build Binutils for your target.
cd buildbinutils ../binutils-version/configure --target=powerpc-linux-gnu --enable-shared \ --enable-sysroot=/usr/local/gc-linux/sys-root --prefix=/usr/local/gc-linux make make install cd ..
Next you need to install the Linux headers
cd linux-2.6.20 make ARCH=ppc CROSS_COMPILE=powerpc-linux-gnu- \ INSTALL_HDR_PATH=/usr/local/gc-linux/sys-root/usr headers_install cd ..
- NOTE: If you're building a non-Gamecube cross compiler change ARCH to powerpc. Also, you should patch the kernel with the Gamecube Linux patches.
Building the minimal Gcc needs the headers from Glibc
cd buildglibc CC=gcc ../glibc-version/configure --target=powerpc-linux-gnu --with-elf \ --enable-shared --disable-sanity-checks --prefix=/usr \ --build=i686-build_pc-linux-gnu make cross-compiling=yes install_root=/usr/local/gc-linux/sys-root \ install-headers mkdir -p /usr/local/gc-linux/sys-root/usr/include/gnu/ touch /usr/local/gc-linux/sys-root/usr/include/gnu/stubs.h cp ../glibc-version/include/features.h /home/harley/gc-linux/sys-root/usr/include/features.h cp bits/stdio_lim.h /home/harley/gc-linux/sys-root/usr/include/bits/stdio_lim.h cd ..
- NOTE: You should have build set with the second portion changed from the actual system.
Now build the minimal Gcc
cd buildinitialgcc ../gcc-version/configure --target=powerpc-linux-gnu --enable-multilib \ --with-sysroot=/usr/local/gc-linux/sys-root --prefix=/usr/local/gc-linux \ --disable-nls --disable-threads --disable-shared --enable-__cxa_atexit \ --with-local-prefix=/usr/local/gc-linux/sys-root \ --enable-clocale=gnu --enable-languages=c make all-gcc make install-gcc cd ..
Minimal Gcc built, so go to Glibc
cd buildglibc libc_cv_forced_unwind=yes libc_cv_c_cleanup=yes export libc_cv_forced_unwind libc_cv_c_cleanup BUILD_CC=gcc CC=powerpc-linux-gnu-gcc AR=powerpc-linux-gnu-ar \ RANLIB=powerpc-linux-gnu-ranlib ../glibc-version/configure \ --host=powerpc-linux-gnu --build=i686-build_pc-linux-gnu --without-cvs \ --with-headers=/usr/local/gc-linux/sys-root/usr/include --disable-profile \ --disable-debug --without-gd --with-elf --enable-shared \ --prefix=/usr --target=powerpc-linux-gnu
- NOTE: --build should be set your compiler if it's not i686-pc-linux-gnu. Also, again, change the second portion. You'll hit problems IIRC if you don't set build.
make LD=powerpc-linux-gnu-ld RANLIB=powerpc-linux-gnu-ranlib all make install_root=/usr/local/gc-linux/sys-root install
Glibc build fine? Then build the last Gcc
cd ../buildfinalgcc ../gcc-version/configure --target=powerpc-linux-gnu \ --disable-multilib --with-sysroot=/usr/local/gc-linux/sys-root \ --with-local-prefix=/usr/local/gc-linux/sys-root --enable-threads=posix \ --enable-shared --enable-__cxa_atexit --enable-clocale=gnu \ --enable-languages=c,c++ --prefix=/usr/local/gc-linux make make install
As you can see, it's a pretty involved process. I haven't tested these steps as written, so please correct this section. If I have more time, I may do this myself though.
Using Your New Cross Compiler
Cross Compiling
This can be an alright choice for many cases. It does have some problems though. For example, some older programs that don't have an updated automake/autoconf may not recognize that it's supposed to cross compile. Other configure problems occur such as finding the wrong libraries during configure. So this can potentially be problematic in some cases.
To use the cross compiler is fairly straight forward with most projects that use configure. You'll typically just need to do:
./configure --build=i686-unknown-linux-gnu --host=powerpc-unknown-linux-gnu \
--target=powerpc-unknown-linux-gnu
make
This should work on a good amount of projects, but as mentioned above, can be problematic.
Using the Cross Compile with Distcc
[Cross-compiling_using_distcc] has how to set it up. This way you can avoid the problems of using the cross compiler on a non-PowerPC platform. In a nutshell you'll do:
./configure make -j2 CC="distcc powerpc-unknown-linux-gnu-gcc"
Tips
When building the cross compiler you'll want to make it the same as the target's distro for the most part. So, with Arch Linux PPC, for example, you use powerpc-unknown-linux-gnu. If you setup a small distro with Buildroot the cross compile will be powerpc-unknown-linux-uclibc on both the Gamecube and as the cross compiler. This is very important if you're using distcc, and less important otherwise.

