How To Build a Current GNU (Cross) Toolchain

At this moment... build-toolchain works for:

Here are notes and scripts and things related to my efforts to build a cross-toolchain using the latest* released versions of all tools, by which I mean:

* August 27, 2008 GCC 4.3.2 has been released. These instructions have not yet been updated.

GMP and MPFR are new pieces of the GNU toolchain; since they are required in order to build GCC, I think they qualify as components of the toolchain the same way that glibc does.

This is all built using a sysroot approach, as recommended by the GCC developers, and WITHOUT using most of the CLFS toolchain build instructions. "sysroot" means that a directory on the host system, in our case $CLFS, will be set up to contain a subset of the root filesystem of the target system; include files and libraries will be used only from the sysroot location, not from the normal host system locations. That's perfect for us, since we want to ensure that components of the host system are ignored by our cross-tools, whether we're doing a real cross-toolchain or a faux cross-toolchain (like an x86-to-x86 cross).

These instructions are very conservative, and include building the C library in the sysroot as well as everything else. For CLFS, we eventually need to install glibc in the /tools directory, so that we have an entirely self-contained set of utilities under /tools; but we're going to build that separately after the cross-toolchain build is complete.

The patches referred to here are included in the "patches" directory.

Note that we are building our cross-glibc with a "minimum kernel version" of 2.6.25; that means the actual runtime kernel being used to construct the real LFS system using the stuff under /tools will have to be a 2.6.25 kernel. You can adjust the kernel version downward if you are currently using an older kernel and don't want to upgrade it. It isn't really a big deal to build an optimized glibc here; none of the code we are currently building will wind up on the final system.

Flags for building an x86-to-x86 "faux" cross-toolchain -- put these in the building user's .bashrc:

export CLFS=/home/clfs
export LC_ALL=POSIX
export PATH=/cross-tools/bin:/bin:/usr/bin
unset CFLAGS
unset CXXFLAGS
export CLFS_HOST=i686-cross-linux-gnu
export CLFS_TARGET=i686-pc-linux-gnu
export SYSROOT=/cross-tools/sysroot
export KERNEL_VERSION=2.6.25
unset KERNEL_ARCH
export GLIBCFLAG="-march=$(cut -d- -f1 <<< $CLFS_TARGET) -mtune=generic -g -O2"

Flags for building an x86-to-mipsel cross-toolchain:

export CLFS_TARGET=mipsel-unknown-linux-gnu
export KERNEL_VERSION=2.6.23
export GLIBCFLAG="-g -O2"
export KERNEL_ARCH="ARCH=mips"

For uClibc builds, set some more variables (and skip GLIBCFLAG, as far as that goes)...

x86:

export UCLIBC_CONFIG=$CONFIG_DIR/uclibc-config-x86
export UCLIBC_MAKE_PARAM=''

mips:

export UCLIBC_CONFIG=$CONFIG_DIR/uclibc-config-mips
export UCLIBC_MAKE_PARAM="CROSS=${CLFS_TARGET}-"

There's a build script in automation that does all the work for you.

gcc, glibc, and binutils MUST all be built from a separate "build" directory, not the source directory.

The notes here are meant to be read along with the automated script. Gosh, it sure would be cool if the whole thing had been written using literate programming style a la Knuth; then you could read it like a narrative or run it like a program, depending on your personal needs. Maybe someday.

STEP 0 host system dependencies

Build and install gmp and mpfr. I used gmp 4.2.2 and mpfr 2.3.1. You can install them anywhere you want, but I went with /usr. They don't take up much space, and they might come in handy for something later.

The CLFS book says it's also important to have file at least version 2.41, so go ahead and upgrade that if necessary.

Also make sure you have everything else you might need. You know, GNU make and that kind of thing.

STEP 1 linux kernel headers

This one doesn't need a separate build directory.

[On digad: 0:19 azoth: 0:13]

(SEE SCRIPT FOR COMMANDS)

STEP 2 binutils

Apply the posix and branch_update-3 patches, originally from CLFS, that you can find in the patch directory.

You can clean up the source directory for this immediately after the build, if you'd like. You won't use it again in this process.

(SEE SCRIPT FOR COMMANDS)

[On digad: 2:30 azoth 2:00]

STEP 3 glibc headers

Apply the patches: libgcc_eh, localedef_segfault, i586_chk, and fixup_for_gcc43. The first three are from CLFS; the last one corrects the glibc build so it works with GCC 4.3 (and is already in glibc CVS).

After doing this build, get rid of the glibc-build directory but keep the source directory around for now: we will need it again a little later.

(SEE SCRIPT FOR COMMANDS)

[On digad: 0:49 azoth: 0:30]

STEP 3b uclibc headers

uClibc is a small C library designed expressly for situations in which glibc is too large. That's the case when building tools for a resource-constrained environment like the flash EPROM on the WL-700gE.

uClibc needs a patch in order to build MIPS pthreads: without it, there are multiple declarations of two functions (testandset and __compare_and_swap). The patch is fix-pthread-mips-build.

After this step, keep the uClibc directory around -- the same configuration will be used in a later step.

(SEE SCRIPT FOR COMMANDS)

STEP 4 gcc (bare compiler)

Apply only the posix patch -- originally from CLFS.

It seems as though it should be unnecessary to mess around with the GCC specs here. It is a cross-compiler; if the wrong libraries are linked in, presumably the thing will simply not work at all, and this compiler is only going to be used to build glibc anyway. (We're going to rebuild GCC after we have a glibc.)

After doing this build, don't get rid of ANYTHING -- we will use the same build directory later on after we use the bare compiler from here to create the startup files that are needed to get libgcc compiled. (If you do delete the gcc-build directory, don't panic, it will just take a few minutes to rebuild the bare compiler before the libgcc build happens.)

GCC can't create programs unless it has access to a support library called libgcc. (There are other support libraries as well, like libgcc_eh; I don't know what they are for.) We can't build libgcc, because it has to be linked against some C runtime startup files (crti.o and a couple others) from the C library. I'm not sure why; it's not a program, just a library. But nevertheless, they are. So all we can do at this point is build a "bare" compiler: just the gcc program per se. We can use that bare compiler to produce the C startup files.

After we build the crt?.o files, we can then build libgcc; and then we'll be able to build glibc. After that, we'll build the full gcc.

With the x86 to x86 toolchain, I did not have to specify host. With the x86 to mips toolchain, I did. It's OK to specify it for the faux-cross toolchain as well.

The LDFLAGS_FOR_TARGET and CPPFLAGS_FOR_TARGET are from gcc bug #35532 -- they are mentioned by Carlos O'Donell as the way to use all of the sysroot framework. How exactly they function is beyond me.

(SEE SCRIPT FOR COMMANDS)

[On digad: 6:36 azoth: 4:28]

STEP 5 glibc (startup files)

If you kept around the source directory from step 3, just use it again here. If not, remember to apply the patches: libgcc_eh, localedef_segfault, i586_chk, and fixup_for_gcc43.

The build commands here just build the startup files we need. We'll build the rest of glibc after we build libgcc.

Again, when this step is complete, delete the glibc-build directory but keep the source directory around.

(SEE SCRIPT FOR COMMANDS)

[On digad: 0:12 azoth: 0:20]

NEW STEP 5b uclibc (startup files)

Brett remembers being able to build uClibc without having a libgcc.a around; but, as of August 2008, he can't manage it any more. So we need to build the same crt?.o files as with glibc, so that we can build libgcc, in order to build the full uClibc.

(SEE SCRIPT FOR COMMANDS)

STEP 6 gcc (libgcc)

If you deleted the gcc and/or gcc-build directories from step 4, reconstruct them now by doing that step again. After this, trash the gcc-build directory; but we will want the gcc source directory one more time.

After we build and install libgcc, we can get rid of the crt* object files we just built in the previous step. They're going to be rebuilt anyway when we do the full glibc build.

(SEE SCRIPT FOR COMMANDS)

[On digad: 0:49 azoth: 0:48]

STEP 7 glibc

Now we have a usable GCC, complete with libgcc, and we can build glibc at last! Use the same glibc source directory as before, or re-apply all the patches that were used previously; but use a fresh glibc-build directory.

(SEE SCRIPT FOR COMMANDS)

[On digad: 14:07 azoth: 11:00]

STEP 7b uclibc

There is something wrong with the uClibc installation -- or, more likely, the flaw is with these instructions and I simply don't know enough to correct the real problem. In either case, a header file "fenv.h" that should be produced is not; the only fenv.h provided is in the "bits" subdirectory and has a guard clause that prevents it from being included directly. The bits/fenv.h file comes from glibc, and the original glibc version gets most of its content from math/fenv.h before including bits/fenv.h. uClibc doesn't have the top-level fenv.h or math/fenv.h. To get around the downstream build failure (when building the full gcc), we simply synthesize a very basic fenv.h that just gets bits/fenv.h included.

fenv.h is a header file related to ISO C99 floating-point arithmetic (it means "floating-point environment"). If problems occur when using the uClibc-based toolchain to compile or run programs that use floating-point math, this is probably the reason.

(SEE SCRIPT FOR COMMANDS)

STEP 8 gcc (full compiler)

Now we are going to build the full gcc cross-compiler. The point of this compiler is to build the temporary tools (under /tools) that will allow us to build the final LFS system. When we're using those tools to build the final system, we want to do a native build of everything, including glibc, so we want those tools to be independent of any filesystem locations that will still be present in the final system. In particular, this includes /lib.

When the standard GNU toolchain builds an executable, it always links it against the dynamic link library (which is something like /lib/ld-linux.so.2 or /lib/ld.so.1). That's normally fine, but we want the programs we build under /tools to be entirely independent of /lib. So we need to adjust our cross-toolchain so that the programs it builds look in /tools/lib for their libraries. Alternatively, we could build everything under /tools as a static executable, so they would be self-contained and not need any shared libraries at all; but that option isn't well-supported by glibc. (Maybe if we changed the cross-toolchain to be uClibc-based, instead of glibc-based, we could get that to work.)

The CLFS approach has been to modify the specs up front by patching gcc. We're instead going to adjust things after the build, instead of applying additional patches now. Use the same posix patch as earlier, but no others.

(SEE SCRIPT FOR COMMANDS)

[On digad: 11:28 azoth: 9:04]

How about that, it worked! But there are a couple more steps to set things up for the linux from scratch build, as previously noted: we need to build a glibc into /tools that KNOWS it is installed into /tools (as opposed to the normal /usr). We might as well make the kernel headers available there as well. So:

STEP 9 kernel headers (in /tools)

This is just like the earlier kernel headers installation, except they go in a different spot.

Hey! We could just install the kernel headers in /tools to begin with, couldn't we? Yes, of course we could. But it only takes about a third of a minute to install them, so why sweat it?

(SEE SCRIPT FOR COMMANDS)

STEP 9b uclibc utilities

As mentioned earlier, some uclibc utility programs (ldd and ldconfig, and possibly others) weren't built earlier. Build them now.

(SEE SCRIPT FOR COMMANDS)

STEP 10 glibc (in /tools)

This is just like the earlier glibc build except that we don't need to mess around with building part of gcc and then part of glibc and so on -- we already have a perfectly good cross-toolchain built and ready to use. It still takes a while, unfortunately.

(SEE SCRIPT FOR COMMANDS)

STEP 11 Adjusting The Toolchain

Spec file editing is a dark art. You can read all about it in gcc.info, though, so it's not as intractably dark an art as, say, building a cross-toolchain from source.

There are specs built into gcc these days (rather than present as an actual file called specs); you can display them with "gcc -dumpspecs". If you put a modified specs file in the same directory as libgcc.a, then that overrides the built-in specs.

The spec we want to change is the "dynamic-linker" spec, which normally links against the dynamic loader in /lib, but we want it to link against the one we just built in /tools.

(SEE SCRIPT FOR COMMANDS)


Urls

For your wget script:

http://www.freesa.org/toolchain/automation/build-toolchain

http://ftp.gnu.org/gnu/binutils/binutils-2.18.tar.bz2
http://ftp.gnu.org/gnu/gcc/gcc-4.3.1/gcc-4.3.1.tar.bz2
http://ftp.gnu.org/gnu/glibc/glibc-2.7.tar.bz2
http://www.uclibc.org/downloads/uClibc-0.9.29.tar.bz2
ftp://ftp.gnu.org/gnu/gmp/gmp-4.2.2.tar.bz2
http://www.mpfr.org/mpfr-current/mpfr-2.3.1.tar.bz2
http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.25.10.tar.bz2

http://www.freesa.org/toolchain/patches/binutils-2.18-branch_update-3.patch
http://www.freesa.org/toolchain/patches/binutils-2.18-posix-1.patch
http://www.freesa.org/toolchain/patches/gcc-4.3.1-posix-1.patch
http://www.freesa.org/toolchain/patches/glibc-2.7-fixup_for_gcc43-1.patch
http://www.freesa.org/toolchain/patches/glibc-2.7-i586_chk-1.patch
http://www.freesa.org/toolchain/patches/glibc-2.7-libgcc_eh-1.patch
http://www.freesa.org/toolchain/patches/glibc-2.7-localedef_segfault-1.patch
http://www.freesa.org/toolchain/patches/uclibc-0.9.29-fix-pthread-mips-build-1.patch

http://www.freesa.org/toolchain/config/uclibc-config-mips
http://www.freesa.org/toolchain/config/uclibc-config-x86

To Do:


Majority of this text was written by Brett Neumeier with minor contributions from Eric Herman, feel free to send suggestions to: eric@freesa.org   Valid XHTML 1.1