Glibc2 on Linux: GCC (cross)

Note that this documentation is historic. It may no longer be very relevant. There will be no updates or further releases.

Introduction

This is the fifth step in installing glibc-2. After installing the library and all supporting files, we will now compile the cross-compiler. After finishing this step, we are ready to compile glibc-2 programs.

Preparing for compilation

Even though this is a relative step-by-step guide, it would be wise to read the most important documentation yourself; especially the README and INSTALL files. The newest version as of the writing of this document is gcc-2.8.1; installation of newer versions may differ, and some of the patches may not apply cleanly.

Patches

You should apply at least the first patch; it is needed if you want to follow this step-by-step guide.

For old-time users of these pages: there is no longer any need for patches to enable a target alias and to use the glibc-version of assert.h, as both things are now the default. The C++ include dir can now also be set during configuration, and g++ always calls the correct compiler.

File Description
gcc281-p1.diff Nicer Installation
gcc281-p2.diff Disable strength reduction

You can apply these patches by entering the gcc directory and using the following command:

(bash) patch -p1 -E < filename

Compiling and installing gcc

I will assume you use bash as shell; if not, some commands may slightly differ. I will explain each step.

(bash) ./configure --with-gnu-as --with-gnu-ld --prefix=/usr \
--host=i486-pc-linux-gnulibc1 \
--target=i486-pc-linux-gnu\
--with-gxx-include-dir=/usr/i486-linux-libc6/include/g++

We configure gcc to use the gnu assembler and loader, to live in /usr/... (instead of the default /usr/local/...). Note that we do not have to specify /usr/i486-linux-libc6. We want to create glibc-2 executables, but the binaries will themselves be linked to libc-5. The C++ compiler must look for its files in gxx-include-dir instead of /usr/include/g++ because there may be header-files installed for libc5 which are different or not installed for libc6, and vice versa.

Note that the local prefix is not changed; the cross-compiler will, regrettably, not be able to use anything in the /usr/local hierarchy anyway without explicit flags to set the searchpaths.

(bash) make CFLAGS="-s -O2" target_alias=i486-linux-libc6 \
LIBGCC1=libgcc1.a OLDCC=./xgcc FLOAT_H=float.h-nat

This command compiles the compiler we will install. We want the compiler to be optimized and stripped, so we specify those options in CFLAGS. And we want to call the target as specified by target_alias. The LIBGCC1 and OLDCC arguments are a way of bootstrapping the cross-compiler that makes it unnecessary to compile anything on the target machine to install the compiler. The FLOAT_H argument tells that float.h may be generated from the current machine. See the INSTALL file for more information.

(bash) make install CFLAGS="-s -O2" target_alias=i486-linux-libc6 \
LIBGCC1=libgcc1.a OLDCC=./xgcc FLOAT_H=float.h-nat

Now we can install the compiler. Remember you must be root to do this. If you want to know what will be installed, you can add prefix=/tmp/usr to install the compiler at a temporary location. Do not forget to do a proper installation afterwards!

(bash) ln -sfn gcc /usr/i486-linux-libc6/bin/cc

This link is not vital, but I recommend making it still. Many makefiles call your C-compiler as cc.

Checking the installation

Calling gcc -v should output something like below now:

(bash) PATH=/usr/i486-linux-libc6/bin:$PATH gcc -v
Reading specs from /usr/lib/gcc-lib/i486-linux-libc6/2.8.1/specs
gcc version 2.8.1

Calling gcc -print-search-dirs should output something like this:

(bash) PATH=/usr/i486-linux-libc6/bin:$PATH gcc -print-search-dirs
install: /usr/lib/gcc-lib/i486-linux-libc6/2.8.1/
programs: /usr/lib/gcc-lib/i486-linux-libc6/2.8.1/:/usr/lib/gcc-lib/i486-linux-libc6/:/usr/lib/gcc/i486-linux-libc6/2.8.1/:/usr/lib/gcc/i486-linux-libc6/:/usr/i486-linux-libc6/bin/i486-linux-libc6/2.8.1/:/usr/i486-linux-libc6/bin/
libraries: /usr/lib/gcc-lib/i486-linux-libc6/2.8.1/:/usr/lib/gcc/i486-linux-libc6/2.8.1/:/usr/i486-linux-libc6/lib/i486-linux-libc6/2.8.1/:/usr/i486-linux-libc6/lib/

You can find a manifest of all installed files here.

Compiling a very small program

If you have followed all steps until now, you are ready to compile programs and link them against glibc-2. We will use a small hello.c program, like below:

#include <stdio.h>
int main ()
{
  printf("Hello world!\n");
}

If you compile it, it should run correctly and ldd hello should show the links to glibc-2. Note the use of the -v option, which shows exactly what happens:

(bash) PATH=/usr/i486-linux-libc6/bin gcc -v hello.c -o hello
Reading specs from /usr/lib/gcc-lib/i486-linux-libc6/2.8.1/specs
gcc version 2.8.1
 /usr/lib/gcc-lib/i486-linux-libc6/2.8.1/cpp -lang-c -v -undef -D__GNUC__=2 -D__GNUC_MINOR__=8 -D__ELF__ -Dunix -Dlinux -D__ELF__ -D__unix__ -D__linux__ -D__unix -D__linux -Asystem(posix) -Di386 -Di486 -Asystem(unix) -Acpu(i386) -Amachine(i386) -D__i386__ -D__i486__ -Asystem(unix) -Acpu(i386) -Amachine(i386) hello.c /tmp/cca00925.i
GNU CPP version 2.8.1 (i386 GNU/Linux with ELF)
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc-lib/i486-linux-libc6/2.8.1/include
 /usr/i486-linux-libc6/include
End of search list.
 /usr/lib/gcc-lib/i486-linux-libc6/2.8.1/cc1 /tmp/cca00925.i -quiet -dumpbase hello.c -version -o /tmp/cca00925.s
GNU C version 2.8.1 (i486-linux-libc6) compiled by GNU C version 2.8.1.
 /usr/i486-linux-libc6/bin/as -V -Qy -o /tmp/cca009251.o /tmp/cca00925.s
GNU assembler version 970731 (i486-linux-libc6), using BFD version linux-2.8.1.0.15
 /usr/i486-linux-libc6/bin/ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o
hello /usr/i486-linux-libc6/lib/crt1.o /usr/i486-linux-libc6/lib/crti.o /usr/lib/gcc-lib/i486-linux-libc6/2.8.1/crtbegin.o -L/usr/lib/gcc-lib/i486-linux-libc6/2.8.1 -L/usr/i486-linux-libc6/lib /tmp/cca009251.o -lgcc -lc -lgcc /usr/lib/gcc-lib/i486-linux-libc6/2.8.1/crtend.o /usr/i486-linux-libc6/lib/crtn.o
(bash) ldd hello
    libc.so.6 => /usr/i486-linux-libc6/lib/libc.so.6 (0x4000e000)
    /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
(bash) ./hello
Hello world!

An alternate way to call the compiler:

(bash) gcc -b i486-linux-libc6 hello.c -o hello
(bash) ldd hello
    libc.so.6 => /usr/i486-linux-libc6/lib/libc.so.6 (0x4000e000)
    /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
(bash) ./hello
Hello world!

You should check whether the correct subprograms are called (the i486-linux-libc6 variants) and whether all search-paths are correct (only subdirectories of /usr/i486-linux-libc6 should be used).

What to do if everything fails

If the above example program does not compile cleanly, something has gone wrong in this step or in one of the steps before. If calling gcc fails, something went probably wrong in the installation of the compiler. If you can't run hello, something went probably wrong in the installation of either glibc-2 itself or the binary utilities. If the last is the case, check what ldd reports. It may be you forgot to create some links, or you may have to edit /etc/ld.so.conf and run ldconfig again as root.