Jump to Navigation

Gcc (cross compiler)

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.

  • Nicer installation
    This patch makes make install run more cleanly. It also disables the installation of versions of binaries that start with the target alias name (we put them in a separate directory instead).
  • (Optional) Disable strength reduction
    There have been some reports that this flag (enabled by default by -O2) may be harmful. Other reports deny it, but say that strength reduction is not very useful on Intel processors anyway (due to a lack of general registers). With this patch -O2 does not enable strength reduction (-fstrength-reduce still enables it). This patch is probably not needed for gcc-2.8.1, but it will do no actual harm.

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

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.

./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 search paths.

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.

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!

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:

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:

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

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:

PATH=/usr/i486-linux-libc6/bin gcc -v hello.c -o hello

This will output something like:

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

Next try 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)

Finally, you can run ./hello and get Hello world! as output.

An alternate way to call the compiler:

gcc -b i486-linux-libc6 hello.c -o hello

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.



Historic_content | by Dr. Radut