Building IA32 compatibility

On x86-64, gcc and binutils are both capable of building both i686 and x86-64 binaries, but a i686-compatible glibc is needed. Cross-compiling glibc directly is difficult, so we will cross-compile a whole i686 toolchain and use that to build glibc.

There are problems with cross-compiling the gcc and glibc versions used in LFS, so instead we use gcc-3.2.3 and glibc-2.3.1.

After building the cross-compiler, we use it to build a native toolchain, this time using gcc-3.3.1 and glibc-2.3.2. We then build the native toolchain again, so that it is self-hosting. Thus the 32-but glibc is built in three stages:

After this, we build gcc-3.3.1 for x86-64 again, this time with multilib enabled.

Now, remove any exiting /lib softlink, and create a new one.

rm /lib

Now, save the PATH variable, and temporarily set it to use the first two stages of the ia32 toolchain build. Also, create a new /lib softlink into the first stage.

export ORIG_PATH=$PATH
export PATH=/tc-stage1/bin:/tc-stage0/bin:$ORIG_PATH
ln -s /tc-stage0/lib /lib
set +h

binutils-2.14, stage 0

mkdir ../binutils-build
cd ../binutils-build
../binutils-2.14/configure --prefix=/tc-stage0 \
    --target=i686-pc-linux-gnu \
    --with-lib-path=/tc-stage0/lib 
make -j4 
make install

make -C ld clean
make -C ld LIB_PATH=/tc-stage0/i686-pc-linux-gnu/lib:/tc-stage0/lib
(do not remove binutils-build)

gcc-3.2.3, stage 0

mkdir ../gcc-build
cd ../gcc-build
export CFLAGS='-Dinhibit_libc' 
../gcc-3.2.3/configure --prefix=/tc-stage0 \
    --target=i686-pc-linux-gnu \
    --enable-languages=c \
    --disable-shared \
    --enable-threads=single \
    --host=i686-pc-linux-gnu
make -j4 
make install
unset CFLAGS

linux-2.4.24 headers, stage 0

make mrproper
make include/linux/version.h

mkdir -p /tc-stage0/include
cp -r include/linux/ include/asm-i386/ /tc-stage0/include 
ln -s asm-i386 /tc-stage0/include/asm

glibc-2.3.1, stage 0

patch -p1 -i../glibc-2.3.2-sscanf-1.patch 
tar xjvf ../glibc-linuxthreads-2.3.1.tar.bz2
mkdir ../glibc-build
cd ../glibc-build
../glibc-2.3.1/configure --prefix=/tc-stage0 \
    --with-headers=/tc-stage0/include \
    --without-cvs --enable-kernel=2.4 --enable-add-ons \
    --disable-profile --libdir=/tc-stage0/lib \
    --host=i686-pc-linux-gnu --build=x86_64-unknown-linux
make -j4
make install
make localedata/install-locales

Adjusting ld to use the new glibc

Change to the existing binutils-build directory, and

make -C ld install

SPECFILE=/tc-stage0/lib/gcc-lib/*/*/specs &&
sed -e 's@ /lib/ld-linux.so.2@ /tc-stage0/lib/ld-linux.so.2@g' \
    $SPECFILE > tempspecfile &&
mv -f tempspecfile $SPECFILE &&
unset SPECFILE
rm -f /tc-stage0/lib/gcc-lib/*/*/include/{pthread.h,bits/sigthread.h}

now remove binutils-build.

We have now completed the i686 cross-compiling toolchain. We use the cross-compiler to build a native i686 toolchain.

gcc-3.3.1, stage 1

mkdir ../gcc-build
cd ../gcc-build
../gcc-3.3.1/configure --prefix=/tc-stage1 \
    --with-local-prefix=/tc-stage0 \
    --disable-nls --enable-shared \
    --enable-languages=c \
    --host=i686-pc-linux-gnu \
    --target=i686-pc-linux-gnu
make BOOT_LDFLAGS="-static" bootstrap
make install

linux-2.4.24 headers, stage 1

make mrproper
make include/linux/version.h

mkdir -p /tc-stage1/include
cp -r include/linux/ include/asm-i386/ /tc-stage1/include 
ln -s asm-i386 /tc-stage1/include/asm
touch /tc-stage1/include/linux/autoconf.h

glibc-2.3.2, stage 1

patch -Np1 -i ../glibc-2.3.2-sscanf-1.patch
tar xjvf ../glibc-linuxthreads-2.3.2.tar.bz2
mkdir ../glibc-build
cd ../glibc-build
../glibc-2.3.2/configure --prefix=/tc-stage1 \
    --disable-profile --enable-add-ons \
    --with-headers=/tools/include \
    --with-binutils=/tools/bin \
    --without-gd \
    --build=i686-pc-linux-gnu \
    --target=i686-pc-linux-gnu
make
make check
make install
make localedata/install-locales

locking-in glibc, stage 1

Change to the binutils-build directory.

make -C ld install

SPECFILE=/tc-stage1/lib/gcc-lib/*/*/specs &&
sed -e 's@ /lib/ld-linux.so.2@ /tc-stage1/lib/ld-linux.so.2@g' \
    $SPECFILE > tempspecfile &&
mv -f tempspecfile $SPECFILE &&
unset SPECFILE

rm -f /tc-stage1/lib/gcc-lib/*/*/include/{pthread.h,bits/sigthread.h}

We have now completed the native toolchain, and use it to build the self-hosted toolchain.

gcc-3.3.1, stage 2

patch -Np1 -i ../gcc-3.3.1-no_fixincludes-2.patch
patch -Np1 -i ../gcc-3.3.1-specs-tc-stage1.patch

mkdir ../gcc-build
cd ../gcc-build
../gcc-3.3.1/configure --prefix=/tc-stage1 \
    --with-local-prefix=/tc-stage1 \
    --enable-clocale=gnu --enable-shared \
    --enable-threads=posix --enable-__cxa_atexit \
    --enable-languages=c \
    --host=i686-pc-linux-gnu \
    --target=i686-pc-linux-gnu
make
make install

binutils-2.14, stage 2

mkdir ../binutils-build
cd ../binutils-build
../binutils-2.14/configure --prefix=/tc-stage1 \
    --enable-shared --with-lib-path=/tc-stage1/lib
make 
make install
For once, the binutils-build directory can be deleted immediately.

glibc-2.3.2, stage 2

The normal configuration for glibc on GNU/Linux is to install some libraries to /lib, and some to /usr/lib. This is done automatically on GNU/Linux systems if --prefix=/usr is passed to the configure script, but we can not use --prefix=/usr because we do not want to install anything but libraries to /usr. To accomplish our goal, installing libraries to /lib and /usr/lib and everything else to a dummy location, we need a configparms file indicating what we want to do.

patch -p1 -i../glibc-2.3.2-sscanf-1.patch 
tar xjvf ../glibc-linuxthreads-2.3.2.tar.bz2
mkdir ../glibc-build
cd ../glibc-build

cat >>configparms <<__END__
libdir=/usr/lib
slibdir=/lib
sysconfdir=/etc
__END__

../glibc-2.3.2/configure --prefix=/tc-stage1 \
    --with-headers=/tc-stage1/include \
    --without-cvs --enable-kernel=2.4 --enable-add-ons \
    --disable-profile \
    --target=i686-pc-linux-gnu \
    --build=i686-pc-linux-gnu
make -j4
rm /lib
mkdir /lib
chmod 755 /lib
make install

multilib-capable gcc-3.3.1

mkdir ../gcc-build
cd ../gcc-build
../gcc-3.3.1/configure --prefix=/usr \
    --enable-shared --enable-threads=posix \
    --enable-__cxa_atexit --enable-clocale=gnu 
make
make install

This builds all the languages gcc supports. If desired, --enable-languages can be used to specify a subset of these languages, which will build more quickly and use less space. For example, --enable-languages=c,c++ will build only C and C++, which is likely to be the minimal set of languages needed by most LFS builders.

At this point, the temporary toolchain builds at /tc-stage0 and /tc-stage1 can be deleted to recover disk space if desired.

Next: building grub