Building GCC for i386

At first, the idea of an i386 "cross" compiler under Linux seems strange. After all, you're already running Linux on a i386 compatible architecture. But the compiler is sometimes tied in misterious ways with the operating system it's running on (see for example this page for some possible symptoms). And after all, you want to use Newlib, not libc, and to customize your development environment as much as possible. This tutorial will show you how to do that.

DISCLAIMER: I'm by no means a specialist in the GCC/newlib/binutils compilation process. I'm sure that there are better ways to accomplish what I'm describing here, however I just wanted a quick and dirty way to build a toolchain, I have no intention in becoming too intimate with the build process. If you think that what I did is wrong, innacurate, or simply outrageously ugly, feel free to contact me and I'll make the necessary corrections. And of course, this tutorial comes without any guarantees whatsoever.

› Prerequisites

To build your toolchain you'll need:

Also, you need some support programs/libraries in order to compile the toolchain. To install them:


$ sudo apt-get install flex bison libgmp3-dev libmpfr-dev autoconf texinfo

Next, decide where you want to install your toolchain. They generally go in /usr/local/, so I'm going to assume /usr/local/cross-i686 for this tutorial. To save yourself some typing, set this path into a shell variable:


$ export TOOLPATH=/usr/local/cross-i686

› Step 1: binutils

This is the easiest step: unpack, configure, build.


$ tar -xvjf binutils-2.17.tar.bz2
$ cd binutils-2.17
$ mkdir build
$ cd build
$ ../configure --target=i686-elf --prefix=$TOOLPATH --with-gnu-as --with-gnu-ld --disable-nls
$ make all
$ sudo make install
$ export PATH=${TOOLPATH}/bin:$PATH

Now you have your i386 "binutils" (assembler, linker, disassembler ...) in your PATH.

› Step 2: basic GCC

In this step we build a "basic" GCC (that is, a GCC without any support libs, which we'll use in order to build all the libraries for our target). But first we need to make a slight modification in the configuration files. Out of the box, the GCC 4.3.1/newlib combo won't compile properly, giving a very weird "Link tests are not allowed after GCC_NO_EXECUTABLES" error. After a bit of googling, I found the solution for this:


$ tar -xvjf gcc-4.3.1.tar.bz2
$ cd gcc-4.3.1/libstdc++-v3
$ joe configure.ac

I'm using "joe" here as it's my favourite Linux text mode editor, you can use any other text editor. Now find the line which says "AC_LIBTOOL_DLOPEN" and comment it out by adding a "#" before it:

  # AC_LIBTOOL_DLOPEN

Save the modified file and exit the text editor


$ autoconf
$ cd ..

Great, now we know it will compile, so let's do it:


$ mkdir build
$ cd build
$ ../configure --target=i686-elf --prefix=$TOOLPATH --enable-languages="c,c++" --with-newlib --without-headers --disable-shared --with-gnu-as --with-gnu-ld
$ make all-gcc
$ sudo make install-gcc

On my system, the last line above (sudo make install-gcc) terminated with errors, because it was unable to find our newly compiled binutils. If this happens for any kind of "make install" command, this is a quick way to solve it:


$ sudo -s -H
  # export PATH=/usr/local/cross-i686/bin:$PATH
# make install-gcc
# exit

› Step 3: Newlib

Once again, Newlib is as easy as unpack, configure, build. But I wanted my library to be as small as possible (as opposed to as fast as possible) and I only wanted to keep what's needed from it in the final executable, so I added the "-ffunction-sections -fdata-sections" flags to allow the linker to perform dead code stripping:


$ tar xvfz newlib-1.16.0.tar.gz
$ cd newlib-1.16.0
$ mkdir build
$ cd build
$ ../configure --target=i686-elf --prefix=$TOOLPATH --disable-newlib-supplied-syscalls --with-gnu-ld --with-gnu-as --disable-shared
$ make CFLAGS_FOR_TARGET="-ffunction-sections -fdata-sections -D__PREFER_SIZE_OVER_SPEED -D__OPTIMIZE_SIZE__ -Os -fomit-frame-pointer -D__BUFSIZ__=256"
$ sudo make install

Some notes about the flags used in the above sequence:

› Step 4: full GCC

Finally, in the last step of our tutorial, we complete the GCC build. In this stage, a number of compiler support libraries are built (most notably libgcc.a). Fortunately this is simpler that the Newlib compilation step:


$ cd gcc-4.3.1/build
$ make all
$ sudo make install

› Step 5: all done!

Now you can finally enjoy your i386 toolchain, and compile eLua with it :) After you do, you'll be able to boot eLua directly on your PC, as described here, but you won't need to download the ELF file from the eLua project page, since you just generated it using your own toolchain! If you need further clarification, or if the above instructions didn't work for you, feel free to contact me.