#!/bin/bash export LINUX_VERSION="6.12.1" # Function to handle errors error_handler() { local exit_code=$? local line_number=$1 local file_name=$2 echo "Error in file: $file_name, line: $line_number, reason: Command exited with status $exit_code" } # Set the trap to catch errors trap 'error_handler $LINENO $0' ERR set -eo pipefail if [ ! -d "./sources" ]; then echo "Run this script from the right directory" exit 1 fi export BASE_DIR=$(pwd) if [ -z "$ARCH" ]; then echo "You must set a target architecture among supported ones:" echo "i386" echo "x86_64" echo "armv5" exit 1 fi if [ -z "$LFS_TGT" ]; then export LFS_TGT="$ARCH-lfs-linux-gnu" echo "Target triplet set to '$LFS_TGT'. You can specify another one with the LFS_TGT env var." fi if [ ! -d "$LFS_TGT" ]; then export LFS="$(pwd)/out/$LFS_TGT/rootfs" echo "Target rootfs set to '$LFS_TGT'. You can override this by setting the LFS_TGT env var." fi # test bash bash --version echo "" # test rsync rsync --version echo "" # test clang clang --version echo "" # test lld ld --version echo "" make --version echo "" # Create the target directory mkdir -p "$LFS" export STEPS_DIR="$LFS/../steps/" mkdir -vp "$STEPS_DIR" export LFS_TOOLS="$LFS/tools" mkdir -vp "$LFS_TOOLS" export PATH="$LFS_TOOLS/bin/:$PATH" export LFS_BUILD="$LFS/../" unset CFLAGS # Create a directory layout if [ ! -d "$LFS/etc" ]; then mkdir -pv $LFS/{etc,var} $LFS/usr/{bin,lib,sbin} for i in bin lib sbin; do ln -sv usr/$i $LFS/$i done case $ARCH in x86_64) mkdir -pv $LFS/lib64 ;; esac fi # Build binutils if [ ! -f "$STEPS_DIR/binutils" ]; then if [ ! -d "$LFS_BUILD/binutils" ]; then tar -xf "$BASE_DIR/sources/binutils-2.43.tar.zst" mv "binutils-2.43" "$LFS_BUILD/binutils" fi cd "$LFS_BUILD/binutils" mkdir -vp build cd build "../configure" \ --prefix=$LFS_TOOLS \ --with-sysroot=$LFS \ --target=$LFS_TGT \ --disable-nls \ --enable-gprofng=no \ --disable-werror \ --enable-new-dtags \ --disable-multilib \ --enable-default-hash-style=gnu make configure-host make -j 32 make install cd "$BASE_DIR" rm -rf binutils-2.43 touch "$STEPS_DIR/binutils" fi # Build gcc if [ ! -f "$STEPS_DIR/gcc" ]; then if [ ! -d "$LFS_BUILD/gcc" ]; then tar -xzf "$BASE_DIR/sources/gcc-14.2.0.tar.gz" mv "gcc-14.2.0" "$LFS_BUILD/gcc" fi cd "$LFS_BUILD/gcc/" tar -xf "$BASE_DIR/sources/mpfr-4.2.1.tar.xz" mv -v mpfr-4.2.1 mpfr tar -xf "$BASE_DIR/sources/gmp-6.3.0.tar.xz" mv -v gmp-6.3.0 gmp tar -xf "$BASE_DIR/sources/mpc-1.3.1.tar.gz" mv -v mpc-1.3.1 mpc # On x86_64 hosts, set the default directory name for 64-bit libraries to “lib” case $(uname -m) in x86_64) sed -e '/m64=/s/lib64/lib/' \ -i.orig gcc/config/i386/t-linux64 ;; esac mkdir -vp build cd build "../configure" \ --target=$LFS_TGT \ --prefix=$LFS_TOOLS \ --with-glibc-version=2.40 \ --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 \ --disable-decimal-float \ --disable-multilib \ --enable-languages=c,c++ make -j 32 # if build fails add --disable-libsanitizer make install cd "$BASE_DIR" rm -rf "$LFS_BUILD/gcc/build" # Do not remove the whole gcc directory: we need it for libstdc++ touch "$STEPS_DIR/gcc" fi # Install kernel headers if [ ! -f "$STEPS_DIR/linux-headers" ]; then if [ ! -d "$LFS_BUILD/linux" ]; then tar -xzf "$BASE_DIR/sources/linux-$LINUX_VERSION.tar.gz" mv "linux-$LINUX_VERSION" "$LFS_BUILD/linux" fi cd "$LFS_BUILD/linux" make mrproper LD="$LFS_TGT-ld" CC="$LFS_TGT-gcc" CXX="$LFS_TGT-g++" AR="$LFS_TGT-ar" RANLIB="$LFS_TGT-ranlib" make headers_install ARCH="$ARCH" INSTALL_HDR_PATH="$LFS/usr" cd "$BASE_DIR" rm -rf "$LFS_BUILD/linux" touch "$STEPS_DIR/linux-headers" fi # build glibc if [ ! -f "$STEPS_DIR/glibc" ]; then if [ ! -d "$LFS_BUILD/glibc" ]; then tar -xzf "$BASE_DIR/sources/glibc-2.40.tar.gz" mv "glibc-2.40" "$LFS_BUILD/glibc" fi cd "$LFS_BUILD/glibc" mkdir -vp build cd build echo "rootsbindir=/usr/sbin" > configparms "../configure" \ --prefix=/usr \ --host=$LFS_TGT \ --build=$(../scripts/config.guess) \ --enable-kernel=4.19 \ --with-headers=$LFS/usr/include \ --disable-debug \ --without-selinux \ --disable-nscd \ libc_cv_slibdir=/usr/lib make -j 32 make DESTDIR=$LFS install sed '/RTLDLIST=/s@/usr@@g' -i $LFS/usr/bin/ldd cd "$BASE_DIR" rm -rf "$LFS_BUILD/glibc" touch "$STEPS_DIR/glibc" fi # test the cross toolchain which -- $LFS_TGT-as || echo $LFS_TGT-as is not in the PATH echo 'int main(){}' | "$LFS_TGT-gcc" -xc - "$LFS_TGT-readelf" -l a.out > test_compiler cat test_compiler | grep ld-linux rm -v a.out test_compiler # build libstdc++ if [ ! -f "$STEPS_DIR/libstdcxx" ]; then bash unpack-gcc.sh cd "$LFS_BUILD/gcc" mkdir -vp build_libstdcxx cd build_libstdcxx #PATH="$PATH:$LFS_TOOLS/bin" RANLIB="$LFS_TOOLS/bin/$LFS_TGT-ranlib" AR="$LFS_TOOLS/bin/$LFS_TGT-ar" LD="$LFS_TOOLS/bin/$LFS_TGT-ld" CC="$LFS_TOOLS/bin/$LFS_TGT-gcc" CXX="$LFS_TOOLS/bin/$LFS_TGT-g++" bash \ ../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++/14.2.0 make -j 32 make DESTDIR=$LFS install # Remove the libtool archive files because they are harmful for cross-compilation rm -v $LFS/usr/lib/lib{stdc++{,exp,fs},supc++}.la cd "$BASE_DIR" rm -rf "$LFS_BUILD/gcc" touch "$STEPS_DIR/libstdcxx" fi # build m4 if [ ! -f "$STEPS_DIR/m4" ]; then if [ ! -d "$LFS_BUILD/m4" ]; then tar -xzf "$BASE_DIR/sources/m4-1.4.19.tar.gz" mv "m4-1.4.19" "$LFS_BUILD/m4" fi cd "$LFS_BUILD/m4" #mkdir -vp build #cd build echo "rootsbindir=/usr/sbin" > configparms "./configure" \ --prefix=/usr \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) \ make -j 32 make DESTDIR=$LFS install cd "$BASE_DIR" rm -rf "$LFS_BUILD/m4" touch "$STEPS_DIR/m4" fi