cross-toolchain-build 12.9 KB
At this works for:

* x86 glibc
* x86 uclibc
* mipsel glibc
* mipsel uclibc
* mips glibc
* mips uclibc

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

binutils 2.19
gcc 4.3.2
glibc 2.9 or uClibc 0.9.30
gmp 4.2.4
linux (or, for mips,
mpfr 2.3.2

It's arguable whether GMP and MPFR are actual toolchain components or not.
I think they qualify, since they are needed in order to build the GCC C

This is all built using a sysroot approach, as recommended by the GCC
developers.  I started with the instructions from CLFS, but wound up
heavily modifying those instructions because they didn't work very well for
me when using the latest stable versions of the components.  "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"
configuration directgive; that means the actual runtime kernel being used
to construct the final system using the stuff under /tools will have to be
at least the specified version.  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 PATH=/cross-tools/bin:/bin:/usr/bin
unset CFLAGS
export CLFS_HOST=i686-cross-linux-gnu
export CLFS_TARGET=i686-pc-linux-gnu
export SYSROOT=/cross-tools/sysroot
export KERNEL_VERSION=2.6.27
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)...


export CLFS_TARGET=mipsel-unknown-linux-uclibc
export UCLIBC_CONFIG=$CONFIG_DIR/uclibc-config-x86


export CLFS_TARGET=mipsel-unknown-linux-uclibc
export UCLIBC_CONFIG=$CONFIG_DIR/uclibc-config-mips

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.  Linux and uClibc don't have that

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

STEP 2 binutils

Apply the posix patch, originally from CLFS, that you can find in the patch
directory, and the latest branch-update patch from the binutils project.

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.


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

STEP 3 glibc headers

Apply the patches: libgcc_eh and localedef_segfault.  These are from CLFS;
libgcc_eh causes the GCC exception-handling library to be linked into glibc
only if it exists (which it won't, until after the final gcc build in step
8), and the second corrects a segmentation fault on architectures that
we're probably not using.  (Maybe sometime we'll try without the patch to
determine whether the fault exists on MIPS?)

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.


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

The UCLIBC_EXTRA_CFLAGS in the .config file need to specify
an -isystem directive using the correct include-fixed directory
for the GCC cross-compiler, which will be
/cross-tools/lib/gcc/$TARGET/$GCC_VERSION/include-fixed.  Make
sure it has the right contents.

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

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.


[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,
and localedef_segfault.

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.


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


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

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.


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


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

STEP 7b uclibc

The former problems with the fenv.h header are resolved by
enabling the C99 floating-point environment.

There is a problem when compiling a MIPS library, because a
function in the linuxthreads.old implementation (_test_and_set)
is declared static and then used in a non-static context. The
mips-linuxthreads-1 patch corrects the problem by removing the
static function definition and explicitly using the definition
provided in a separate header (sys/tas.h) instead.

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

When the standard GNU toolchain builds an executable, it always links it
against the dynamic link library (which is something like
/lib/ or /lib/  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


[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?


STEP 9b uclibc utilities

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

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.  We
also have a libgcc_eh to link against now, for whatever that's worth.  It
still takes a while, unfortunately.


STEP 11 Adjusting The Toolchain

Spec file editing is a dark art.  You can read all about it in,
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.