Chapter 2. Building the Cross Tools

2.1. Introduction

For our purposes a compiler is a black box; a program which accepts ASCII text as input and generates binary data as output. In most cases a compiler running on a given platform will generate code for that same platform. The purpose of this section is to create a program which will generate code for an entirely different platform than the one on which it is running -- this is called a cross compiler. We want to build a compiler on one architecture that will create code for another architecture, from sources.

Note

It is also possible to create a compiler on architecture A, that will generate code for architecture B, which runs, not on the architecture it was created on, but on an entirely different architecture C! In other words: compile a program on this machine that will run on another machine which will generate code for an entirely different machine. None of the three of which are the same architecture.

This is called a Canadian Cross. In this document we will only be creating a cross-compiler, not doing a Canadian Cross. In other words, we will create a compiler on this machine, that runs on this machine, and generates code for another machine.

Creating a cross-compiler involves a chicken-and-egg problem: the compiler needs to know things about the code it is generating as output, but that information comes from the C library. But if we don't have a compiler how can we compile the C library before the compiler? The GCC people have solved this problem by cleverly using stages: in our first pass we don't try to compile a complete and entire cross-compiler, we only generate a small, static cross-compiler. We then use this small cross-compiler to generate a simple C library for the new architecture. Now that we have just enough of a C library for the new architecture, we can now go ahead and create a full and complete cross-compiler. Using this full compiler we are now able to create a full C library for the new architecture.

Compiling a cross compiler is a bit of a touchy procedure; the exact sequence of steps varies depending on which version of the source files you are using. If you aren't starting from the exact same source version numbers that are listed below, the instructions have less chance of succeeding for you. Another variable to consider which affects your success rate is the base system from which you are performing you cross-compile. In general it is more difficult for older compilers to generate newer compilers. All of the following procedures were carried out on a machine running Fedora Core 2.

My first step, before compiling any of the following, was to start by updating my build tools (binutils and gcc) to their latest versions, the versions I used below to create my cross-development environment. Make sure the installation directory of your new tools precedes that of your system's installed tools in your ${PATH} variable.