Building Linux from Scratch
Master Recipe

If you really want to learn about Linux, build it from scratch.
Linux from Scratch (LFS) [1] and Beyond Linux from Scratch (BLFS) [2] are online tutorials that provide step-by-step instructions for how to compile and assemble your own Linux system from freely available sources. The abbreviation LFS refers to both the documentation and the resulting Linux system.
If you've been around Linux long enough, you have probably come across the need to compile software – either from a homegrown application or possibly from source code available at an open source project website. You might think that compiling an operating system is similar, and in some ways it is, but building a complete operating system is vastly more complicated than compiling your average desktop application.
Keep in mind that the modern distro you are using to build that desktop app already has a complete toolchain that has been tested and approved for compatibility. Imagine that this build environment doesn't exist yet and you have to create it. That includes a compiler and also important libraries such as glibc and libstdc++. The Linux from Scratch instructions (sometimes call the book) contain 11 chapters that are divided into five major parts. The authors break the process of building a Linux system into three stages (Figure 1):
- configure a build host (Part II, Chapters 2 to 4)
- build a cross toolchain and temporarily required tools (Part III, Chapters 5 to 7)
- create the actual LFS system (Part IV, Chapters 8 to 11).
Gerard Beekmans, the author of LFS, started working with Linux in 1998. After using various distributions, he realized that he could not find a "one size fits all" solution, and he would need to build his own system. When he started compiling, he quickly discovered that he had unleashed an onslaught of compile-time errors and circular dependencies. The experience he gained, which he shared with the Linux community, met with such widespread interest that the LFS project was born.
LFS is one of several distribution kits that focus on letting the user build their own system. Many of these projects specialize in the embedded area, including BitBake from the Yocto project [3]. Other options include Linux Target Image Builder [4], OpenWrt [5], and Scratchbox [6].
LFS makes an effort to follow common standards, including POSIX.1-2008 [7], which defines an operating system interface, including an environment for portability purposes, the Filesystem Hierarchy Standard FHS 3.0 [8], and the Linux Standard Base LSB 5.0 [9]. The Linux Standard Base defines four standards for core, desktop, runtime languages and imaging, that are hotly debated. LFS can implement them only partially due to its minimal software equipment.
If you follow the instructions, you will end up with a minimal Linux system that includes an Ext4 filesystem, Grub 2.04, Kernel 5.10.17, Bash 5.1, GCC 10.2, Perl 5.32.1, Python 3.9.2, and Vim 8.2. (This article uses LFS v10.1 from March 2021.) You have the choice between LFS with SysVinit [10] and LFS with Systemd and D-Bus [11]. I'll cover the Systemd variant, which includes DHCP and NTP clients, as well as other bits and pieces that are not included in the SysVinit variant of LFS, although BLFS offers some additional SysVinit options.
The build takes a good deal of time: Using the test VM described in this article with KVM on a machine with Core i7 10th Gen and NVMe SSD, the build takes several hours even with the tests turned off.
Cross-Compilating
To minimize the influence of the build host's operating system, you need to make sure that the LFS system is independent of it. Chapters 5 and 6 help you create the software tools you'll need to build Linux from Scratch. You then deploy these tools in an isolated chroot environment only for the purpose of building LFS.
The build process is based on the principle of cross-compiling: A cross-compiler is typically used to compile code for other system architectures. On your build machine, a cross-comiler is theoretically not necessary because you are most likely building on x86_64 for x86_64. However, you will want LFS to be free of inlinked software from the build host, which a cross-compiler guarantees.
The LFS documentation assumes you have three hosts, each with a different architecture. Host A has a compiler for its own architecture. The host is slow and its capacity is limited. Host B does not have a compiler initially, but it is fast and well equipped. It will be producing the software for Host C. Host C, with yet another architecture, also has no compiler and is small and slow.
This scenario requires two cross compilers: Cross-Compiler A and Cross-Compiler B. On Host A, the compiler builds Cross-Compiler A, which in turn builds Cross-Compiler B. Cross-Compiler B is used on Host B to build Compiler C and all programs for Host C. However, they cannot be tested on Host B. Therefore, Compiler C rebuilds and tests itself on Host C.
For LFS to succeed with cross-compiling on the same host, you need to gently adjust the well-known vendor triplet x86_64-pc-linux-gnu
(which always contains four components today) in LFS_TGT
to fool the compiler into thinking it has different architectures. Then, on the build host, the compiler build host first builds the cross-compiler build host, which in turn builds the compiler for LFS. In the LFS chroot on the build host, the compiler LFS then rebuilds and tests itself and is then ready for deployment.
For LFS, you need to use the cross-compiler to compile not only the C compiler but also the glibc and libstdc++ libraries. The problem is that, to be built, the C compiler relies internally on libgcc, which in turn has to be linked against glibc – which doesn't exist yet.
To work around these circular dependencies, first build a minimal version of the cross-compiler build host that is just about good enough to compile a full-fledged glibc, as well as a minimally functional libstdc++. The libstdc++ library will be built again later in the chroot environment, this time completely. Further details are given in the LFS documentation.
Hardware
The LFS build process will not work unless your build host is working perfectly. The tutorial in this article assumes an unused virtual machine based on a fully patched, current CentOS 8.3 minimal install with BIOS boot. If you're using a different Linux variant, you might need to modify some of the steps, but the process is similar.
The C compiler GCC benefits from a fast core. The documentation discusses a multi-thread build distributed over several cores, but this configuration is not recommended in practice because of occasional race conditions.
For the build server, two cores, 2GB RAM, an SSD-based hypervisor, and an Intel e1000 NIC are all you need. For mass storage, you need a 10GB disk (VirtIO, /dev/vda/
) for the system and a 20GB disk (SATA or SCSI, /dev/sda/
) for LFS.
Avoid VirtIO for the LFS disk and network card because the instructions in the LFS manual do not compile VirtIO support into the kernel. LFS is happy with a virtual SATA or SCSI disk that it identifies as /dev/sda/
and a classic Intel e1000 network card with 1 Gbps. The disk name is important when it comes to making LFS bootable. The name of the network card (such as enp1s0
) matters if you want to use Predictable Network Interface Names [12].
Getting Started
After CentOS is installed, you need to set up the packages required for the first build processes. You can retrieve the required makeinfo
from the texinfo package in the PowerTools repository, starting with CentOS 8.3. The packages required for the build are quickly installed (Listing 1).
Listing 1
Installing the Required Packages
$ dnf -y install yum-utils $ yum config-manager --set-enabled powertools dnf -y install bison byacc bzip2 gcc-c++ patch perl python3 tar texinfo wget
You then need to check the versions installed by CentOS with the help of a small script: LFS v10.0 requires a GCC version of 6.2 or higher and a GNU Make version of 4.0 or higher, which an earlier Linux distribution such as CentOS 7 will not give you.
If everything is fine so far, split the second disk of the build host into the partitions /
, swap
and /home
, create the Ext4 filesystem, and define the $LFS
environment variable, which is essential for all subsequent shell calls and resolves the root mount point. The variable must therefore work under all circumstances. You will want to complete the locale settings in CentOS 8 and mount the second disk.
Make the /dev/sda/
disk bootable via BIOS/MBR and add various partitions. To give Grub's own core.img
enough space, the first partition for /
with a size of 10GB starts at 1MB. After that, create a /swap
of 2GB, leaving the rest of the disk reserved for /home
.
In this setup, /boot
does not need its own partition but contains the kernel plus the boot loader configuration as an ordinary directory. You only need a separate partition if you want to support multiboot with other distributions, or if the boot loader can no longer access the root file system. Lack of access to the filesystem can happen as a result of missing drivers, disk encryption, software RAID, or LVM.
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Direct Download
Read full article as PDF:
Price $2.95
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Find SysAdmin Jobs
News
-
Escuelas Linux 8.0 is Now Available
Just in time for its 25th anniversary, the developers of Escuelas Linux have released the latest version.
-
LibreOffice 7.5 has Arrived Loaded with New Features and Improvements
The favorite office suite of the Linux community has a new release that includes some visual refreshing and new features across all modules.
-
The Next Major Release of Elementary OS Has Arrived
It's been over a year since the developers of elementary OS released version 6.1 (Jólnir) but they've finally made their latest release (Horus) available with a renewed focus on the user.
-
KDE Plasma 5.27 Beta Is Ready for Testing
The latest beta iteration of the KDE Plasma desktop is now available and includes some important additions and fixes.
-
Netrunner OS 23 Is Now Available
The latest version of this Linux distribution is now based on Debian Bullseye and is ready for installation and finally hits the KDE 5.20 branch of the desktop.
-
New Linux Distribution Built for Gamers
With a Gnome desktop that offers different layouts and a custom kernel, PikaOS is a great option for gamers of all types.
-
System76 Beefs Up Popular Pangolin Laptop
The darling of open-source-powered laptops and desktops will soon drop a new AMD Ryzen 7-powered version of their popular Pangolin laptop.
-
Nobara Project Is a Modified Version of Fedora with User-Friendly Fixes
If you're looking for a version of Fedora that includes third-party and proprietary packages, look no further than the Nobara Project.
-
Gnome 44 Now Has a Release Date
Gnome 44 will be officially released on March 22, 2023.
-
Nitrux 2.6 Available with Kernel 6.1 and a Major Change
The developers of Nitrux have officially released version 2.6 of their Linux distribution with plenty of new features to excite users.