Chapters
Chapter 6. Cross Compiling Temporary Tools 6.1. Introduction

Chapter 6. Cross Compiling Temporary Tools 6.1. Introduction

This chapter shows how to cross-compile basic utilities using the just built cross-toolchain. Those utilities are installed into their final location, but cannot be used yet. Basic tasks still rely on the host's tools. Nevertheless, the installed libraries are used when linking.

Using the utilities will be possible in the next chapter after entering the “chroot” environment. But all the packages built in the present chapter need to be built before we do that. Therefore we cannot be independent of the host system yet.

Once again, let us recall that improper setting of LFS together with building as root , may render your computer unusable.

This whole chapter must be done as user lfs , with the environment as described in Section 4.4, “Setting Up the Environment.”

6.2. M4-1.4.20

The M4 package contains a macro processor.

Approximate build time: 0.1 SBU Required disk space: 38 MB (Required disk space: 38 MB)

6.2.1. Installation of M4

Prepare M4 for compilation:

./configure --prefix=/usr   \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)

Compile the package:

make

Install the package:

make DESTDIR=$LFS install

Details on this package are located in Section 8.13.2, “Contents of M4.”

6.3. Ncurses-6.5-20250809

The Ncurses package contains libraries for terminal-independent handling of character screens.

Approximate build time: 0.4 SBU Required disk space: 54 MB (Required disk space: 54 MB)

6.3.1. Installation of Ncurses

First, run the following commands to build the tic program on the build host. We install it in $LFS/tools , so that it is found in the PATH when needed:

mkdir build
pushd build
../configure --prefix=$LFS/tools AWK=gawk
make -C include
make -C progs tic
install progs/tic $LFS/tools/bin
popd

Prepare Ncurses for compilation:

./configure --prefix=/usr                \
--host=$LFS_TGT              \
--build=$(./config.guess)    \
--mandir=/usr/share/man      \
--with-manpage-format=normal \
--with-shared                \
--without-normal             \
--with-cxx-shared            \
--without-debug              \
--without-ada                \
--disable-stripping          \
AWK=gawk

The meaning of the new configure options:

--with-manpage-format=normal

This prevents Ncurses from installing compressed manual pages, which may happen if the host distribution itself has compressed manual pages.

--with-shared

This makes Ncurses build and install shared C libraries.

--without-normal

This prevents Ncurses from building and installing static C libraries.

--without-debug

This prevents Ncurses from building and installing debug libraries.

--with-cxx-shared

This makes Ncurses build and install shared C++ bindings. It also prevents it building and installing static C+ + bindings.

--without-ada

This ensures that Ncurses does not build support for the Ada compiler, which may be present on the host but will not be available once we enter the chroot environment.

--disable-stripping

This switch prevents the building system from using the strip program from the host. Using host tools on cross- compiled programs can cause failure.

AWK=gawk

This switch prevents the building system from using the mawk program from the host. Some versions of mawk can cause this package to fail to build.

Compile the package:

make

Install the package:

make DESTDIR=$LFS install
ln -sv libncursesw.so $LFS/usr/lib/libncurses.so
sed -e 's/^#if.*XOPEN.*$/#if 1/' \
-i $LFS/usr/include/curses.h

The meaning of the install options:

ln -sv libncursesw.so $LFS/usr/lib/libncurses.so

The libncurses.so library is needed by a few packages we will build soon. We create this symlink to use libncursesw.so as a replacement.

sed -e 's/^#if.*XOPEN.*$/#if 1/' ...

The header file curses.h contains the definition of various Ncurses data structures. With different preprocessor macro definitions two different sets of the data structure definition may be used: the 8-bit definition is compatible with libncurses.so and the wide-character definition is compatible with libncursesw.so . Since we are using libncursesw.so as a replacement of libncurses.so , edit the header file so it will always use the wide-character data structure definition compatible with libncursesw.so .

Details on this package are located in Section 8.30.2, “Contents of Ncurses.”

6.4. Bash-5.3

The Bash package contains the Bourne-Again Shell.

Approximate build time: 0.2 SBU Required disk space: 72 MB (Required disk space: 72 MB)

6.4.1. Installation of Bash

Prepare Bash for compilation:

./configure --prefix=/usr                      \
--build=$(sh support/config.guess) \
--host=$LFS_TGT                    \
--without-bash-malloc

The meaning of the configure options:

--without-bash-malloc

This option turns off the use of Bash's memory allocation ( malloc ) function which is known to cause segmentation faults. By turning this option off, Bash will use the malloc functions from Glibc which are more stable.

Compile the package:

make

Install the package:

make DESTDIR=$LFS install

Make a link for the programs that use sh for a shell:

ln -sv bash $LFS/bin/sh

Details on this package are located in Section 8.36.2, “Contents of Bash.”

6.5. Coreutils-9.7

The Coreutils package contains the basic utility programs needed by every operating system.

Approximate build time: 0.3 SBU Required disk space: 181 MB (Required disk space: 181 MB)

6.5.1. Installation of Coreutils

Prepare Coreutils for compilation:

./configure --prefix=/usr                     \
--host=$LFS_TGT                   \
--build=$(build-aux/config.guess) \
--enable-install-program=hostname \
--enable-no-install-program=kill,uptime

The meaning of the configure options:

--enable-install-program=hostname

This enables the hostname binary to be built and installed – it is disabled by default but is required by the Perl test suite.

Compile the package:

make

Install the package:

make DESTDIR=$LFS install

Move programs to their final expected locations. Although this is not necessary in this temporary environment, we must do so because some programs hardcode executable locations:

mv -v $LFS/usr/bin/chroot              $LFS/usr/sbin
mkdir -pv $LFS/usr/share/man/man8
mv -v $LFS/usr/share/man/man1/chroot.1 $LFS/usr/share/man/man8/chroot.8
sed -i 's/"1"/"8"/'                    $LFS/usr/share/man/man8/chroot.8

Details on this package are located in Section 8.59.2, “Contents of Coreutils.”

6.6. Diffutils-3.12

The Diffutils package contains programs that show the differences between files or directories.

Approximate build time: 0.1 SBU Required disk space: 35 MB (Required disk space: 35 MB)

6.6.1. Installation of Diffutils

Prepare Diffutils for compilation:

./configure --prefix=/usr   \
--host=$LFS_TGT \
gl_cv_func_strcasecmp_works=y \
--build=$(./build-aux/config.guess)

The meaning of the configure options:

gl_cv_func_strcasecmp_works=y

This option specify the result of a check for the strcasecmp . The check requires running a compiled C program, and this is impossible during cross-compilation because in general a cross-compiled program cannot run on the host distro. Normally for such a check the configure script would use a fall-back value for cross-compilation, but the fall-back value for this check is absent and the configure script would have no value to use and error out. The upstream has already fixed the issue, but to apply the fix we'd need to run autoconf that the host distro may lack.

So we just specify the check result ( y as we know the strcasecmp function in Glibc-2.42 works fine) instead, then configure will just use the specified value and skip the check.
Compile the package:

make

Install the package:

make DESTDIR=$LFS install

Details on this package are located in Section 8.60.2, “Contents of Diffutils.”

6.7. File-5.46

The File package contains a utility for determining the type of a given file or files.

Approximate build time: 0.1 SBU Required disk space: 42 MB (Required disk space: 42 MB)

6.7.1. Installation of File

The file command on the build host needs to be the same version as the one we are building in order to create the signature file. Run the following commands to make a temporary copy of the file command:

mkdir build
pushd build
../configure --disable-bzlib      \
--disable-libseccomp \
--disable-xzlib      \
--disable-zlib
make
popd

The meaning of the new configure option:

--disable-*

The configuration script attempts to use some packages from the host distribution if the corresponding library files exist. It may cause compilation failure if a library file exists, but the corresponding header files do not. These options prevent using these unneeded capabilities from the host.

Prepare File for compilation:

./configure --prefix=/usr --host=$LFS_TGT --build=$(./config.guess)

Compile the package:

make FILE_COMPILE=$(pwd)/build/src/file

Install the package:

make DESTDIR=$LFS install

Remove the libtool archive file because it is harmful for cross compilation:

rm -v $LFS/usr/lib/libmagic.la

Details on this package are located in Section 8.11.2, “Contents of File.”

6.8. Findutils-4.10.0

The Findutils package contains programs to find files. Programs are provided to search through all the files in a directory tree and to create, maintain, and search a database (often faster than the recursive find, but unreliable unless the database has been updated recently). Findutils also supplies the xargs program, which can be used to run a specified command on each file selected by a search.

Approximate build time: 0.2 SBU Required disk space: 48 MB (Required disk space: 48 MB)

6.8.1. Installation of Findutils

Prepare Findutils for compilation:

./configure --prefix=/usr                   \
--localstatedir=/var/lib/locate \
--host=$LFS_TGT                 \
--build=$(build-aux/config.guess)

Compile the package:

make

Install the package:

make DESTDIR=$LFS install

Details on this package are located in Section 8.62.2, “Contents of Findutils.”

6.9. Gawk-5.3.2

The Gawk package contains programs for manipulating text files.

Approximate build time: 0.1 SBU Required disk space: 49 MB (Required disk space: 49 MB)

6.9.1. Installation of Gawk

First, ensure some unneeded files are not installed:

sed -i 's/extras//' Makefile.in

Prepare Gawk for compilation:

./configure --prefix=/usr   \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)

Compile the package:

make

Install the package:

make DESTDIR=$LFS install

Details on this package are located in Section 8.61.2, “Contents of Gawk.”

6.10. Grep-3.12

The Grep package contains programs for searching through the contents of files.

Approximate build time: 0.1 SBU Required disk space: 32 MB (Required disk space: 32 MB)

6.10.1. Installation of Grep

Prepare Grep for compilation:

./configure --prefix=/usr   \
--host=$LFS_TGT \
--build=$(./build-aux/config.guess)

Compile the package:

make

Install the package:

make DESTDIR=$LFS install

Details on this package are located in Section 8.35.2, “Contents of Grep.”

6.11. Gzip-1.14

The Gzip package contains programs for compressing and decompressing files.

Approximate build time: 0.1 SBU Required disk space: 12 MB (Required disk space: 12 MB)

6.11.1. Installation of Gzip

Prepare Gzip for compilation:

./configure --prefix=/usr --host=$LFS_TGT

Compile the package:

make

Install the package:

make DESTDIR=$LFS install

Details on this package are located in Section 8.65.2, “Contents of Gzip.”

6.12. Make-4.4.1

The Make package contains a program for controlling the generation of executables and other non-source files of a package from source files.

Approximate build time: less than 0.1 SBU Required disk space: 15 MB (Required disk space: 15 MB)

6.12.1. Installation of Make

Prepare Make for compilation:

./configure --prefix=/usr   \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)

Compile the package:

make

Install the package:

make DESTDIR=$LFS install

Details on this package are located in Section 8.69.2, “Contents of Make.”

6.13. Patch-2.8

The Patch package contains a program for modifying or creating files by applying a “patch” file typically created by the diff program.

Approximate build time: 0.1 SBU Required disk space: 14 MB (Required disk space: 14 MB)

6.13.1. Installation of Patch

Prepare Patch for compilation:

./configure --prefix=/usr   \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)

Compile the package:

make

Install the package:

make DESTDIR=$LFS install

Details on this package are located in Section 8.70.2, “Contents of Patch.”

6.14. Sed-4.9

The Sed package contains a stream editor.

Approximate build time: 0.1 SBU Required disk space: 21 MB (Required disk space: 21 MB)

6.14.1. Installation of Sed

Prepare Sed for compilation:

./configure --prefix=/usr   \
--host=$LFS_TGT \
--build=$(./build-aux/config.guess)

Compile the package:

make

Install the package:

make DESTDIR=$LFS install

Details on this package are located in Section 8.31.2, “Contents of Sed.”

6.15. Tar-1.35

The Tar package provides the ability to create tar archives as well as perform various other kinds of archive manipulation. Tar can be used on previously created archives to extract files, to store additional files, or to update or list files which were already stored.

Approximate build time: 0.1 SBU Required disk space: 42 MB (Required disk space: 42 MB)

6.15.1. Installation of Tar

Prepare Tar for compilation:

./configure --prefix=/usr   \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)

Compile the package:

make

Install the package:

make DESTDIR=$LFS install

Details on this package are located in Section 8.71.2, “Contents of Tar.”

6.16. Xz-5.8.1

The Xz package contains programs for compressing and decompressing files. It provides capabilities for the lzma and the newer xz compression formats. Compressing text files with xz yields a better compression percentage than with the traditional gzip or bzip2 commands.

Approximate build time: 0.1 SBU Required disk space: 23 MB (Required disk space: 23 MB)

6.16.1. Installation of Xz

Prepare Xz for compilation:

./configure --prefix=/usr                     \
--host=$LFS_TGT                   \
--build=$(build-aux/config.guess) \
--disable-static                  \
--docdir=/usr/share/doc/xz-5.8.1

Compile the package:

make

Install the package:

make DESTDIR=$LFS install

Remove the libtool archive file because it is harmful for cross compilation:

rm -v $LFS/usr/lib/liblzma.la

Details on this package are located in Section 8.8.2, “Contents of Xz.”

6.17. Binutils-2.45 - Pass 2

The Binutils package contains a linker, an assembler, and other tools for handling object files.

Approximate build time: 0.4 SBU Required disk space: 548 MB (Required disk space: 548 MB)

6.17.1. Installation of Binutils

Binutils building system relies on an shipped libtool copy to link against internal static libraries, but the libiberty and zlib copies shipped in the package do not use libtool. This inconsistency may cause produced binaries mistakenly linked against libraries from the host distro. Work around this issue:

sed '6031s/$add_dir//' -i ltmain.sh

Create a separate build directory again:

mkdir -v build
cd       build

Prepare Binutils for compilation:

../configure                   \
--prefix=/usr              \
--build=$(../config.guess) \
--host=$LFS_TGT            \
--disable-nls              \
--enable-shared            \
--enable-gprofng=no        \
--disable-werror           \
--enable-64-bit-bfd        \
--enable-new-dtags         \
--enable-default-hash-style=gnu

The meaning of the new configure options:

--enable-shared

Builds libbfd as a shared library.

--enable-64-bit-bfd

Enables 64-bit support (on hosts with smaller word sizes). This may not be needed on 64-bit systems, but it does no harm.

Compile the package:

make

Install the package:

make DESTDIR=$LFS install

Remove the libtool archive files because they are harmful for cross compilation, and remove unnecessary static libraries:

rm -v $LFS/usr/lib/lib{bfd,ctf,ctf-nobfd,opcodes,sframe}.{a,la}

Details on this package are located in Section 8.20.2, “Contents of Binutils.”

6.18. GCC-15.2.0 - Pass 2

The GCC package contains the GNU compiler collection, which includes the C and C++ compilers.

Approximate build time: 4.5 SBU Required disk space: 6.0 GB (Required disk space: 6.0 GB)

6.18.1. Installation of GCC

As in the first build of GCC, the GMP, MPFR, and MPC packages are required. Unpack the tarballs and move them into the required directories:

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

If you are building on x86_64, change 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

Override the build rules of the libgcc and libstdc++ headers to allow building these libraries with POSIX threads support:

sed '/thread_header =/s/@.*@/gthr-posix.h/' \
-i libgcc/Makefile.in libstdc++-v3/include/Makefile.in

Create a separate build directory again:

mkdir -v build
cd       build

Before starting to build GCC, remember to unset any environment variables that override the default optimization flags.

Now prepare GCC for compilation:

../configure                   \
--build=$(../config.guess) \
--host=$LFS_TGT            \
--target=$LFS_TGT          \
--prefix=/usr              \
--with-build-sysroot=$LFS  \
--enable-default-pie       \
--enable-default-ssp       \
--disable-nls              \
--disable-multilib         \

The meaning of the new configure options:

--with-build-sysroot=$LFS

Normally, using --host ensures that a cross-compiler is used for building GCC, and that compiler knows that it has to look for headers and libraries in $LFS .

However, the build system for GCC uses additional tools which are not aware of this location. This switch is needed so those tools will find the needed files in $LFS , and not on the host.

--target=$LFS_TGT

We are cross-compiling GCC, so it's impossible to build target libraries ( libgcc and libstdc++ ) with the GCC binaries compiled in this pass—those binaries won't run on the host. The GCC build system will attempt to use the host's C and C++ compilers as a workaround by default. Building the GCC target libraries with a different version of GCC is not supported, so using the host's compilers may cause the build to fail. This parameter ensures the libraries are built by GCC pass 1.

LDFLAGS_FOR_TARGET=...

Allow libstdc++ to use the libgcc being built in this pass, instead of the previous version built in gcc-pass1. The previous version cannot properly support C++ exception handling because it was built without libc support.

--disable-libsanitizer

Disable GCC sanitizer runtime libraries. They are not needed for the temporary installation. In gcc-pass1 it was implied by --disable-libstdcxx , and now we can explicitly pass it.

Compile the package:

make

Install the package:

make DESTDIR=$LFS install

As a finishing touch, create a utility symlink. Many programs and scripts run cc instead of gcc , which is used to keep programs generic and therefore usable on all kinds of UNIX systems where the GNU C compiler is not always installed.

Running cc leaves the system administrator free to decide which C compiler to install:

ln -sv gcc $LFS/usr/bin/cc

Details on this package are located in Section 8.29.2, “Contents of GCC.”