linux_dist
Markdown

Part 04 Cross Toolchain Build

Part 4: Building the Cross-Compilation Toolchain

Overview

The cross-compilation toolchain allows you to build programs for your LFS system from your host system. This chapter builds the initial compiler and libraries in $LFS/tools.

Prerequisites

  • Completed Part 1-3
  • Logged in as lfs user
  • $LFS variable set
  • All packages downloaded to $LFS/sources

Build Order

  1. Binutils-2.45 (Pass 1)
  2. GCC-15.2.0 (Pass 1)
  3. Linux-6.16.1 API Headers
  4. Glibc-2.42
  5. Libstdc++ from GCC-15.2.0

General Build Instructions

For each package:

# Extract package
cd $LFS/sources
tar -xf <package>.tar.xz
cd <package-directory>

# Create build directory (if recommended)
mkdir -v build
cd build

# Configure, build, install
../ configure <options>
make
make install

# Clean up
cd $LFS/sources
rm -rf <package-directory>

1. Binutils-2.45 - Pass 1

Purpose: Cross-linker and assembler

Build Time: 1 SBU Disk Space: 700 MB

cd $LFS/sources
tar -xf binutils-2.45.tar.xz
cd binutils-2.45

# Create dedicated build directory
mkdir -v build
cd build

# Configure
../configure --prefix=$LFS/tools \
             --with-sysroot=$LFS \
             --target=$LFS_TGT \
             --disable-nls \
             --enable-gprofng=no \
             --disable-werror \
             --enable-new-dtags \
             --enable-default-hash-style=gnu

# Build
make

# Install
make install

# Cleanup
cd $LFS/sources
rm -rf binutils-2.45

Configure Options Explained:

  • --prefix=$LFS/tools - Install to tools directory
  • --with-sysroot=$LFS - Tell linker where to find libraries
  • --target=$LFS_TGT - Cross-compile for LFS target
  • --disable-nls - Disable internationalization (not needed)
  • --enable-gprofng=no - Don't build gprofng (not needed)
  • --disable-werror - Don't stop on warnings
  • --enable-new-dtags - Use modern RPATH tag
  • --enable-default-hash-style=gnu - Use GNU hash style

2. GCC-15.2.0 - Pass 1

Purpose: Cross-compiler

Build Time: 11 SBU Disk Space: 4.2 GB

cd $LFS/sources
tar -xf gcc-15.2.0.tar.xz
cd gcc-15.2.0

# Extract required dependencies
tar -xf ../mpfr-4.2.2.tar.xz
mv -v mpfr-4.2.2 mpfr
tar -xf ../gmp-6.3.0.tar.xz
mv -v gmp-6.3.0 gmp
tar -xf ../mpc-1.3.1.tar.gz
mv -v mpc-1.3.1 mpc

# For x86_64, set default directory to lib (not lib64)
case $(uname -m) in
  x86_64)
    sed -e '/m64=/s/lib64/lib/' \
        -i.orig gcc/config/i386/t-linux64
 ;;
esac

# Create build directory
mkdir -v build
cd build

# Configure
../configure \
    --target=$LFS_TGT \
    --prefix=$LFS/tools \
    --with-glibc-version=2.42 \
    --with-sysroot=$LFS \
    --with-newlib \
    --without-headers \
    --enable-default-pie \
    --enable-default-ssp \
    --disable-nls \
    --disable-shared \
    --disable-multilib \
    --disable-threads \
    --disable-libatomic \
    --disable-libgomp \
    --disable-libquadmath \
    --disable-libssp \
    --disable-libvtv \
    --disable-libstdcxx \
    --enable-languages=c,c++

# Build
make

# Install
make install

# Create limits.h header
cd ..
cat gcc/limitx.h gcc/glimits.h gcc/limity.h > \
  `dirname $($LFS_TGT-gcc -print-libgcc-file-name)`/include/limits.h

# Cleanup
cd $LFS/sources
rm -rf gcc-15.2.0

Configure Options Explained:

  • --target=$LFS_TGT - Cross-compile for LFS target
  • --with-glibc-version=2.42 - Specify glibc version
  • --with-newlib - No C library available yet
  • --without-headers - No C headers available yet
  • --enable-default-pie - Position Independent Executables
  • --enable-default-ssp - Stack Smashing Protector
  • --disable-shared - Build static libraries only
  • --disable-multilib - Disable multi-arch support
  • --enable-languages=c,c++ - Only C and C++

3. Linux-6.16.1 API Headers

Purpose: Kernel headers for glibc

Build Time: <0.1 SBU Disk Space: 1.6 GB

cd $LFS/sources
tar -xf linux-6.16.1.tar.xz
cd linux-6.16.1

# Ensure tree is clean
make mrproper

# Extract headers
make headers

# Install to temporary location
find usr/include -type f ! -name '*.h' -delete
cp -rv usr/include $LFS/usr

# Cleanup
cd $LFS/sources
rm -rf linux-6.16.1

4. Glibc-2.42

Purpose: GNU C Library

Build Time: 4.5 SBU Disk Space: 850 MB

cd $LFS/sources
tar -xf glibc-2.42.tar.xz
cd glibc-2.42

# Create symlink for LSB compliance
case $(uname -m) in
    i?86)   ln -sfv ld-linux.so.2 $LFS/lib/ld-lsb.so.3
    ;;
    x86_64) ln -sfv ../lib/ld-linux-x86-64.so.2 $LFS/lib64
            ln -sfv ../lib/ld-linux-x86-64.so.2 $LFS/lib64/ld-lsb-x86-64.so.3
    ;;
esac

# Apply patch (if needed - check LFS docs)
# patch -Np1 -i ../glibc-2.42-fhs-1.patch

# Create build directory
mkdir -v build
cd build

# Ensure proper tools are used
echo "rootsbindir=/usr/sbin" > configparms

# Configure
../configure \
      --prefix=/usr \
      --host=$LFS_TGT \
      --build=$(../scripts/config.guess) \
      --enable-kernel=5.4 \
      --with-headers=$LFS/usr/include \
      --disable-nscd \
      libc_cv_slibdir=/usr/lib

# Build
make

# Install
make DESTDIR=$LFS install

# Fix hardcoded path
sed '/RTLDLIST=/s@/usr@@g' -i $LFS/usr/bin/ldd

# Sanity check
echo 'int main(){}' | $LFS_TGT-gcc -xc -
readelf -l a.out | grep ld-linux
# Should show: [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
# or [Requesting program interpreter: /lib/ld-linux.so.2] for 32-bit

rm -v a.out

# Cleanup
cd $LFS/sources
rm -rf glibc-2.42

Configure Options Explained:

  • --host=$LFS_TGT - Cross-compile for LFS
  • --build=$(../scripts/config.guess) - Auto-detect build system
  • --enable-kernel=5.4 - Minimum kernel version
  • --with-headers=$LFS/usr/include - Use Linux headers
  • --disable-nscd - Don't build name service cache daemon
  • libc_cv_slibdir=/usr/lib - Install shared libraries to /usr/lib

5. Libstdc++ from GCC-15.2.0

Purpose: C++ standard library

Build Time: 0.4 SBU Disk Space: 1.1 GB

cd $LFS/sources
tar -xf gcc-15.2.0.tar.xz
cd gcc-15.2.0

# Create build directory
mkdir -v build
cd build

# Configure
../libstdc++-v3/configure \
    --host=$LFS_TGT \
    --build=$(../config.guess) \
    --prefix=/usr \
    --disable-multilib \
    --disable-nls \
    --disable-libstdcxx-pch \
    --with-gxx-include-dir=/tools/$LFS_TGT/include/c++/15.2.0

# Build
make

# Install
make DESTDIR=$LFS install

# Remove libtool archive files
rm -v $LFS/usr/lib/lib{stdc++{,exp,fs},supc++}.la

# Cleanup
cd $LFS/sources
rm -rf gcc-15.2.0

Verification

After completing the cross-toolchain, verify it works:

# Test compiler
echo 'int main(){}' | $LFS_TGT-gcc -xc -
readelf -l a.out | grep ld-linux
rm a.out

# Expected output:
# [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
# or
# [Requesting program interpreter: /lib/ld-linux.so.2]

Troubleshooting

Issue: configure fails with "C compiler cannot create executables"

Solution: Verify $LFS and $LFS_TGT are set:

echo $LFS
echo $LFS_TGT

Issue: make fails with permission errors

Solution: Ensure you're the lfs user and directories have correct ownership:

whoami  # Should be: lfs
ls -ld $LFS/tools

Issue: Cannot find headers

Solution: Verify Linux headers installed:

ls $LFS/usr/include/linux

Next Steps

Cross-toolchain complete! Proceed to:

  • Part 5: Build temporary tools using cross-compiler
  • Part 6: Enter chroot environment
  • Part 7: Build final LFS system

Important Notes

  • Never skip sanity checks
  • Save build logs for troubleshooting
  • Each package should be built in the order shown
  • Clean up source directories after each build to save space

References