Cross-compiling

From gc-linux

Jump to: navigation, search

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 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 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 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] 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.

Personal tools