Building gcc as a cross compiler

June 8, 2013

The Gnu C compiler (gcc) is the foundation upon which all other open source software is built. For that matter it is the tool with which all kinds of commerical software is built. This discussion covers the things you need to know to build a cross compiler version of gcc hosted on a linux system.

Happily, gcc has been set up to make it possible (if not simple) to build as a cross compiler for a multitude of different processor targets. The good news ends there however. The process is not well documented, and in many cases the only thing to do is to resort to trial and error. This is what I have done, and I am trying to pass on some of the hard learned lessons that I have learned here. The gcc/binutils maintainers are in the unfortunate position of being unable to see the forest for the trees, and have no clue what it is like to be someone outside of their group coming to gcc as an end user.

Here are some sources from which I have gleaned valuable bits of information:

A major problem with the official Gnu install document that they keep on the web is that it is not connected to any particular compiler version. You can assume that they are keeping the document up to date and that it applies to the current gcc release, but that is exercising a lot of faith given the ragged nature of their documentation. What really ought to be done is to include documentation with each gcc version.

How to do it

You need to pick a version of both binutils and gcc, download the source distribution, then configure and build them both. You will need to specify your target system, decide where the collection of tools will live, and ensure that they don't interfere with your native compiler. In any event, you must build binutils first, then gcc.

Hot tip

Do NOT do the usual thing of running ./configure in the distribution directory. Yes this is a total violation of the standard practice for virtually every open source package in the known universe and trips up all kinds of people. The Gnu people are above doing things like anyone else, so you may as well get over it and get with their program. It very well may seem to work (at least the first time), but you will run into trouble later if you want to build a different target. In particular the configure and build process will leave dregs laying around in the source tree that "make distclean" will not eradicate and you will be pulling your hair out. I imagine things are set up this way to support builds for multiple targets while keeping the source tree pristine. Read the install document. You want to do something like this:
tar xjvf gcc.tar.bz2
mkdir gcc-build
cd gcc-build
../gcc/configure --target=xxx, etc. etc.

Another tip

Since these compiles have to build a lot of stuff, and it takes a long time anyway, and since these days most people have multi-core CPU's sitting in front of them, it only makes sense to use those cores. If you have an 8-core CPU like a Pentium i7, you should use:
make -j 8
This speeds things up a lot, BUT if you get an error, the information you need may not be the last thing in the output on the screen, which is less than convenient, so I tend to avoid the nice parallel make feature when playing at the cross compiler casino.

Picking a version

It seems to me that you can mix and match binutils and gcc versions with some abandon. No doubt there are limitations, but I am not aware of any compatibility table. As binutils has moved along, support for some older object file formats (such as coff and perhaps a.out) has been dropped, at least for certain processors. At least the claim has been made that versions of binutils after 2.16.1 no longer support m68k-coff if that is important to you.

Here are some combinations that are known or claimed to work:

You should at least ponder the fact that the native compiler you are using to build gcc is yet another variable that plays a part. Just because somebody claims that they successfully built a certain version of gcc as a cross compiler, does not mean that you will be successful doing so using a different native compiler.

To build gcc version 4.3 and later, you will need the GMP library (as well as several others) on your system. GMP is the Gnu multiple precision library. I thought this was going to be some herculean chore, but it was absolutely simple. All that was needed was to install the development packages of these libraries (see below).

Note that binutils 2.23 is a more recent version than 2.7 or 2.8.

Specifying your target (and other things)

Now that we know the secret about not building in the source tree, the general outline of how to build binutils and/or gcc is: The usual drill is:

Given the above general scheme, the trick is setting the options for configure. I have always had to specify the following switches to configure: The syntax for the target specification is a dark secret. There are half hearted attempts to document it here and there, and the basic approach is to pick something that looks likely and see if you get lucky. There are lots of shorthand targets if you really feel lucky. The general approach is to use something like m68k-linux-elf. Here "m68k" specifies the CPU, "linux" specifies the target operating system, and "elf" specifies the binary file format.

Also, it pays to indicate that you only want the C language. Otherwise the build process will try to generate compilers for C++ and Objective-C and fortran and ada and so on. Apart from wasting time, sometimes there are show stopping issues building libraries for these languages we don't want.

You used to limit the languages you obtained by setting an environment variable like so:

These days (i.e. with "recent" versions of gcc), things are better and if you are building a recent enough version you have a switch:

A concrete example

Lets try to build binutils-2.23 along with gcc-3.4.6 for a m68k-linux-elf target.
mkdir binutils-build
cd binutils-build
../binutils-2.23/configure --target=m68k-linux-elf --prefix=/opt/m68k-linux-elf --exec-prefix=/opt/m68k-linux-elf
make
make install

mkdir gcc-build
cd gcc-build
../gcc-3.4.6/configure --target=m68k-linux-elf --prefix=/opt/m68k-linux-elf --exec-prefix=/opt/m68k-linux-elf --enable-languages=c
make
make install
Binutils builds cleanly.

Gcc configures with one warning about something obscure. Gcc compiles with zillions of warnings, most about enum type mismatches or something that somebody ought to clean up. The build finally dies with:

m68k-linux-elf-ar: Command not found
A reasonable fix for this might be to put /opt/m68k-linux-elf/bin on my path, which I do using the command export PATH=$PATH:/opt/m68k-linux-elf/bin. Continuing the make gets me this:
/u1/tom/GCC/gcc-build/gcc/xgcc -B/u1/tom/GCC/gcc-build/gcc/ -B/opt/m68k-linux-elf/m68k-linux-elf/bin/ -B/opt/m68k-linux-elf/m68k-linux-elf/lib/ -isystem /opt/m68k-linux-elf/m68k-linux-elf/include -isystem /opt/m68k-linux-elf/m68k-linux-elf/sys-include -O2  -DIN_GCC -DCROSS_COMPILE   -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition  -isystem ./include   -g  -DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED -Dinhibit_libc -I. -I. -I../../gcc-3.4.6/gcc -I../../gcc-3.4.6/gcc/. -I../../gcc-3.4.6/gcc/../include   -m68000 -DL_fixdfdi -c ../../gcc-3.4.6/gcc/libgcc2.c -o libgcc/m68000/_fixdfdi.o
../../gcc-3.4.6/gcc/libgcc2.c: In function `__fixdfdi':
../../gcc-3.4.6/gcc/libgcc2.c:1277: internal compiler error: in do_SUBST, at combine.c:447
Please submit a full bug report,
with preprocessed source if appropriate.
See  for instructions.
make[2]: *** [libgcc/m68000/_fixdfdi.o] Error 1
make[2]: Leaving directory `/u1/tom/GCC/gcc-build/gcc'
make[1]: *** [stmp-multilib] Error 2
make[1]: Leaving directory `/u1/tom/GCC/gcc-build/gcc'
make: *** [all-gcc] Error 2
Heaven only knows what this error is all about, but it is not the kind of thing I should be debugging. Maybe if we try 4.7.2 and see what happens (this business of building a cross compiler is a lot like playing games at a casino -- you shove in your coin, pull the handle, and maybe you get lucky. If you ever do, you save the compiler you get forever like a precious jewel. Well, 4.7.2 gets into the nonsense with the gmp, mpfr, and mpc libraries (groan!).

On my fedora system, I need to install the following packages:

yum install gmp-devel mpfr-devel libmpc-devel
Who knows why "lib" is prefixed to mpc and not the other two, but that is how it is. After doing this, the "config" command succeeds. Note that I already had the gmp-devel package installed, but not the other two. One error message covers the case where any or all is missing. After getting these packages in place, I try make again, and it goes along busy as a beaver till it hits this:
make[3]: Entering directory `/u1/tom/GCC/gcc-build/m68k-linux-elf/libssp'
/bin/sh ./libtool --tag=CC   --mode=compile /u1/tom/GCC/gcc-build/./gcc/xgcc -B/u1/tom/GCC/gcc-build/./gcc/ -B/opt/m68k-linux-elf/m68k-linux-elf/bin/ -B/opt/m68k-linux-elf/m68k-linux-elf/lib/ -isystem /opt/m68k-linux-elf/m68k-linux-elf/include -isystem /opt/m68k-linux-elf/m68k-linux-elf/sys-include    -DHAVE_CONFIG_H -I. -I../../../gcc-4.7.2/libssp    -Wall -g -O2 -MT ssp.lo -MD -MP -MF .deps/ssp.Tpo -c -o ssp.lo ../../../gcc-4.7.2/libssp/ssp.c
libtool: compile:  /u1/tom/GCC/gcc-build/./gcc/xgcc -B/u1/tom/GCC/gcc-build/./gcc/ -B/opt/m68k-linux-elf/m68k-linux-elf/bin/ -B/opt/m68k-linux-elf/m68k-linux-elf/lib/ -isystem /opt/m68k-linux-elf/m68k-linux-elf/include -isystem /opt/m68k-linux-elf/m68k-linux-elf/sys-include -DHAVE_CONFIG_H -I. -I../../../gcc-4.7.2/libssp -Wall -g -O2 -MT ssp.lo -MD -MP -MF .deps/ssp.Tpo -c ../../../gcc-4.7.2/libssp/ssp.c -o ssp.o
../../../gcc-4.7.2/libssp/ssp.c: In function ‘__guard_setup’:
../../../gcc-4.7.2/libssp/ssp.c:78:3: warning: implicit declaration of function ‘open’ [-Wimplicit-function-declaration]
../../../gcc-4.7.2/libssp/ssp.c:78:30: error: ‘O_RDONLY’ undeclared (first use in this function)
../../../gcc-4.7.2/libssp/ssp.c:78:30: note: each undeclared identifier is reported only once for each function it appears in
../../../gcc-4.7.2/libssp/ssp.c:81:7: error: unknown type name ‘ssize_t’
../../../gcc-4.7.2/libssp/ssp.c:81:7: warning: implicit declaration of function ‘read’ [-Wimplicit-function-declaration]
../../../gcc-4.7.2/libssp/ssp.c:83:7: warning: implicit declaration of function ‘close’ [-Wimplicit-function-declaration]
../../../gcc-4.7.2/libssp/ssp.c: At top level:
../../../gcc-4.7.2/libssp/ssp.c:97:25: error: unknown type name ‘size_t’
../../../gcc-4.7.2/libssp/ssp.c: In function ‘__stack_chk_fail’:
../../../gcc-4.7.2/libssp/ssp.c:169:3: warning: implicit declaration of function ‘fail’ [-Wimplicit-function-declaration]
../../../gcc-4.7.2/libssp/ssp.c:169:3: warning: implicit declaration of function ‘strlen’ [-Wimplicit-function-declaration]
../../../gcc-4.7.2/libssp/ssp.c:169:14: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default]
../../../gcc-4.7.2/libssp/ssp.c: In function ‘__chk_fail’:
../../../gcc-4.7.2/libssp/ssp.c:176:14: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default]
make[3]: *** [ssp.lo] Error 1
make[3]: Leaving directory `/u1/tom/GCC/gcc-build/m68k-linux-elf/libssp'
make[2]: *** [all] Error 2
make[2]: Leaving directory `/u1/tom/GCC/gcc-build/m68k-linux-elf/libssp'
make[1]: *** [all-target-libssp] Error 2
make[1]: Leaving directory `/u1/tom/GCC/gcc-build'
make: *** [all] Error 2
One of the guys I linked to mentioned that he uses the switch --disable-libssp when building gcc-4.3.3 "because libssp won't build". It looks like that issue has yet to be fixed. He also suggests using --enable-multilib, so I will will take his advice and add both of these options to my config line and try again. This time the build dies much sooner with:
make[4]: Entering directory `/u1/tom/GCC/gcc-build/32/zlib'
make[4]: *** No rule to make target `all'.  Stop.
Just on a hunch, I drop the --enable-multilib option and try again. And I hit the jackpot, looks like this one is a winner!! At least the build doesn't crash and burn, and it seems to build proper code also. It only took a day of frustration and head banging to get there.
Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org