My experience building Linux From Scratch (LFS)
Published: 2020-07-27 | Last Updated: 2022-01-10 | ~23 Minute Read
Table of Contents
- Motivation
- My Setup
- Chapter 1 - Initial Steps
- Chapter 2 - Preparing the Host System
- Chapter 3 - Packages and Patches
- Chapter 4 - Final Preparations
- Chapter 5 - Constructing a Temporary System
- Chapter 6 - Installing Basic System Software
- Chapter 7 - System Configuration
- Chapter 8 - Making the LFS System Bootable
- Chapter 9 - The End
- Conclusion
Motivation
I, probably as many others, have heard about the LFS book that is provided by the LFS project. This magical book provides the recipe to create your very own Linux system. I have been really excited to play around with this but have not had the time. I decided to make the time as this is something that I have looked forward to doing for a long time.
I didn’t really know how to record my progress with this though, at first I wanted to make sort of an ongoing series where I would update here with separate blog posts of my progress, however that seemed like a lot of work. I decided it’s best to simply record my experience as I go and make a single post once I’m done.
I only recorded the sections I found to be relevant, not the entire process package by package, so expect some parts of the book being skipped (mainly compilation sections).
My Setup
I thought about doing this on a VM, but I have a laptop that I’m not currently using for anything else, so I thought it would be good to have actual hardware to run this on and not take up CPU from my main desktop while compiling the packages.
My current build system has the following specs:
- Lenovo Thinkpad T440p
- Intel® Core™ i5-4300M CPU @ 2.60GHz
- 8GB RAM
- 20 GB dedicated LFS partition
- Slackware 14.2
I will be using version 9.1 of the LFS book.
Chapter 1 - Initial Steps
I read through the initial sections of the LFS book and decided to build a 64-bit system. I will be installing the default packages that come in the book as I would like to avoid as many errors as possible.
I will try to track how long this takes me in actual time so that I can have a reference point to share.
Chapter 2 - Preparing the Host System
2.2. Host System Requirements
I made sure to update the host system (Slackware 14.2) to the latest stable version, once that was done I got to work.
I ran the host system requirements script, this was the result:
root@darkstar:~# bash version-check.sh
bash, version 4.3.48(1)-release
/bin/sh -> /bin/bash
Binutils: version 2.26.20160125
bison (GNU Bison) 3.0.4
yacc is bison (GNU Bison) 3.0.4
bzip2, Version 1.0.8, 13-Jul-2019.
Coreutils: 8.25
diff (GNU diffutils) 3.3
find (GNU findutils) 4.4.2
GNU Awk 4.1.3, API: 1.1 (GNU MPFR 3.1.4, GNU MP 6.1.1)
/usr/bin/awk -> /bin/gawk-4.1.3
gcc (GCC) 5.5.0
g++ (GCC) 5.5.0
(GNU libc) 2.23
grep (GNU grep) 2.25
gzip 1.8
Linux version 4.4.227 (root@z-mp.slackware.lan) (gcc version 5.5.0 (GCC) ) #1 SMP Thu Jun 11 15:06:42 CDT 2020
m4 (GNU M4) 1.4.17
GNU Make 4.1
GNU patch 2.7.6
Perl version='5.22.2';
Python 3.6.5
sed (GNU sed) 4.2.2
tar (GNU tar) 1.29
texi2any (GNU texinfo) 6.1
xz (XZ Utils) 5.2.2
g++ compilation OK
According to the documentation on this chapter I have two software packages that do not meet the minimum version requirements for this version of LFS:
gcc (GCC) 5.5.0
grep (GNU grep) 2.25
These versions should be:
GCC-6.2
Grep-2.5.1a
I will continue on with these non-recommended versions keeping in mind that if I have issues while compiling down the road, this may be a factor, let’s keep our fingers crossed.
2.4. Creating a New Partition
I created a 20 GB partition for LFS via fdisk
and made a ext4
file system on it, the end result looks like this:
root@darkstar:~# fdisk -l
Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 209717247 209715200 100G 83 Linux
/dev/sda2 209717248 419432447 209715200 100G 83 Linux
/dev/sda3 419432448 461375487 41943040 20G 83 Linux
root@darkstar:~# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/root 99G 13G 81G 14% /
devtmpfs 3.8G 0 3.8G 0% /dev
tmpfs 3.8G 1.1M 3.8G 1% /run
tmpfs 3.8G 0 3.8G 0% /dev/shm
cgroup_root 3.8G 0 3.8G 0% /sys/fs/cgroup
/dev/sda2 99G 4.4G 89G 5% /home
/dev/sda3 20G 3.9G 15G 21% /mnt/lfs
cgmfs 100K 0 100K 0% /run/cgmanager/fs
root@darkstar:~#
I followed the instructions for creating the ext4
file system and mounting the new partition. I also created the $LFS
shell variable for my root
user.
Chapter 3 - Packages and Patches
3.1. Introduction
I created the wget-list
file and downloaded the sources as instructed. I did the checks with the md5sums
file and everything turned out OK:
root@darkstar:/mnt/lfs/sources# md5sum -c md5sums
acl-2.2.53.tar.gz: OK
attr-2.4.48.tar.gz: OK
autoconf-2.69.tar.xz: OK
automake-1.16.1.tar.xz: OK
bash-5.0.tar.gz: OK
bc-2.5.3.tar.gz: OK
binutils-2.34.tar.xz: OK
bison-3.5.2.tar.xz: OK
bzip2-1.0.8.tar.gz: OK
check-0.14.0.tar.gz: OK
coreutils-8.31.tar.xz: OK
dejagnu-1.6.2.tar.gz: OK
diffutils-3.7.tar.xz: OK
e2fsprogs-1.45.5.tar.gz: OK
elfutils-0.178.tar.bz2: OK
eudev-3.2.9.tar.gz: OK
expat-2.2.9.tar.xz: OK
expect5.45.4.tar.gz: OK
file-5.38.tar.gz: OK
findutils-4.7.0.tar.xz: OK
flex-2.6.4.tar.gz: OK
gawk-5.0.1.tar.xz: OK
gcc-9.2.0.tar.xz: OK
gdbm-1.18.1.tar.gz: OK
gettext-0.20.1.tar.xz: OK
glibc-2.31.tar.xz: OK
gmp-6.2.0.tar.xz: OK
gperf-3.1.tar.gz: OK
grep-3.4.tar.xz: OK
groff-1.22.4.tar.gz: OK
grub-2.04.tar.xz: OK
gzip-1.10.tar.xz: OK
iana-etc-2.30.tar.bz2: OK
inetutils-1.9.4.tar.xz: OK
intltool-0.51.0.tar.gz: OK
iproute2-5.5.0.tar.xz: OK
kbd-2.2.0.tar.xz: OK
kmod-26.tar.xz: OK
less-551.tar.gz: OK
lfs-bootscripts-20191031.tar.xz: OK
libcap-2.31.tar.xz: OK
libffi-3.3.tar.gz: OK
libpipeline-1.5.2.tar.gz: OK
libtool-2.4.6.tar.xz: OK
linux-5.5.3.tar.xz: OK
m4-1.4.18.tar.xz: OK
make-4.3.tar.gz: OK
man-db-2.9.0.tar.xz: OK
man-pages-5.05.tar.xz: OK
meson-0.53.1.tar.gz: OK
mpc-1.1.0.tar.gz: OK
mpfr-4.0.2.tar.xz: OK
ninja-1.10.0.tar.gz: OK
ncurses-6.2.tar.gz: OK
openssl-1.1.1d.tar.gz: OK
patch-2.7.6.tar.xz: OK
perl-5.30.1.tar.xz: OK
pkg-config-0.29.2.tar.gz: OK
procps-ng-3.3.15.tar.xz: OK
psmisc-23.2.tar.xz: OK
Python-3.8.1.tar.xz: OK
python-3.8.1-docs-html.tar.bz2: OK
readline-8.0.tar.gz: OK
sed-4.8.tar.xz: OK
shadow-4.8.1.tar.xz: OK
sysklogd-1.5.1.tar.gz: OK
sysvinit-2.96.tar.xz: OK
tar-1.32.tar.xz: OK
tcl8.6.10-src.tar.gz: OK
texinfo-6.7.tar.xz: OK
tzdata2019c.tar.gz: OK
udev-lfs-20171102.tar.xz: OK
util-linux-2.35.1.tar.xz: OK
vim-8.2.0190.tar.gz: OK
XML-Parser-2.46.tar.gz: OK
xz-5.2.4.tar.xz: OK
zlib-1.2.11.tar.xz: OK
zstd-1.4.4.tar.gz: OK
bash-5.0-upstream_fixes-1.patch: OK
bzip2-1.0.8-install_docs-1.patch: OK
coreutils-8.31-i18n-1.patch: OK
glibc-2.31-fhs-1.patch: OK
kbd-2.2.0-backspace-1.patch: OK
sysvinit-2.96-consolidated-1.patch: OK
Chapter 4 - Final Preparations
I followed the instructions for the addition of the new lfs
user and permission / ownership update of the $LFS/sources
and $LFS/tools
directories.
I also added a line to the lfs
user’s .bashrc
file in order to take full advantage of my CPU. The added line was $MAKEFLAGS='-j 4'
, the final file looks like the following:
lfs:~$ cat .bashrc
set +h
umask 022
LFS=/mnt/lfs
LC_ALL=POSIX
LFS_TGT=$(uname -m)-lfs-linux-gnu
PATH=/tools/bin:/bin:/usr/bin
MAKEFLAGS='-j 4'
export LFS LC_ALL LFS_TGT PATH MAKEFLAGS
Chapter 5 - Constructing a Temporary System
By this point it had been around 60 - 90 minutes since I had started, I wanted to read slowly and carefully but I’m sure that after you have done this about two or three times, 10-15 minutes is a more realistic time frame to get up to this point in the book.
5.4. Binutils-2.34 - Pass 1
I followed the instructions on the book and as suggested, in order to track the time of an SBU for reference, I executed the following:
time { ../configure --prefix=/tools --with-sysroot=$LFS --with-lib-path=/tools/lib --target=$LFS_TGT --disable-nls --disable-werror && make; }
The result was the following:
real 0m52.610s
user 2m27.692s
sys 0m12.757s
So, nearly a minute, I think that was not that bad, we’ll see how it goes as we progress.
5.5. GCC-9.2.0 - Pass 1
This package is supposed to take 10 SBUs, so we’ll test and confirm if that estimation is correct now.
Just out of curiosity during the build process I took a look at the usage of the hardware and confirmed that all 4 threads of my processor were being used successfully:
The final output once built and installed was this:
real 8m17.817s
user 29m34.731s
sys 1m11.821s
So 10 minutes was a good estimation, it finished in just over 8 minutes.
5.7. Glibc-2.31
For this package the time was as follows:
real 4m52.316s
user 13m57.024s
sys 1m41.865s
The expected time for this package was 4.5 SBU, so I suppose we can take it that on my system the estimates are pretty much spot on.
I then ran the commands that are shown in order to test that the installation was successful and got the expected results:
lfs:/mnt/lfs/sources/glibc-2.31/build$ echo 'int main(){}' > dummy.c
lfs:/mnt/lfs/sources/glibc-2.31/build$ $LFS_TGT-gcc dummy.c
lfs:/mnt/lfs/sources/glibc-2.31/build$ readelf -l a.out | grep ': /tools'
[Requesting program interpreter: /tools/lib64/ld-linux-x86-64.so.2]
5.10. GCC-9.2.0 - Pass 2
I’ve reached the point where we’re re-compiling GCC with the full headers so that we can have an independent toolchain for the new LFS system.
Everything was going smooth up until this section, it seems I made a mistake in the way that I built the second pass for GCC, so I took a step back and tried again making sure that I followed the instructions from the LFS book.
After that I was able to see the expected result from the commands below:
lfs:/mnt/lfs/sources/gcc-9.2.0/build$ echo 'int main(){}' > dummy.c
lfs:/mnt/lfs/sources/gcc-9.2.0/build$ cc dummy.c
lfs:/mnt/lfs/sources/gcc-9.2.0/build$ readelf -l a.out | grep ': /tools'
[Requesting program interpreter: /tools/lib64/ld-linux-x86-64.so.2]
Lesson learned was just uncompress the packages from the tarball again, even if you think it doesn’t matter, this was the only thing I did differently. Treat every package as it’s own isolated build even if you reuse them.
5.11. Tcl-8.6.10
This was pretty straight forward, but I ran the test suite so I wanted to share the output.
Test suite results:
Tests ended at Sat Jul 25 16:36:37 UTC 2020
all.tcl: Total 33499 Passed 30389 Skipped 3110 Failed 0
Sourced 150 Test Files.
Number of tests skipped for each constraint:
9 !ieeeFloatingPoint
3 asyncPipeChan
76 bigEndian
5 bug-3057639
49 dde
4 dontCopyLinks
64 emptyTest
5 fullutf
2 hasIsoLocale
1 knownBadTest
42 knownBug
100 localeRegexp
9 localhost_v6
52 longIs32bit
14 macosxFileAttr
82 memory
46 nonPortable
5 notNetworkFilesystem
1 notValgrind
9 nt
4 readonlyAttr
1996 serverNeeded
1 testexprparser && !ieeeFloatingPoint
1 testwinclock
21 testwordend
3 tip389
2 unthreaded
2 wideBiggerThanInt
487 win
4 winVista
lfs:/mnt/lfs/sources/tcl8.6.10/unix$
Although the LFS book says that there might be errors, I was lucky and it seems there wasn’t any.
The rest of the installation for tcl
was pretty uneventful.
5.36. Changing Ownership
Everything went fairly smoothly for the installation of all the rest of the packages from Chapter 5.
At this stage I made a backup as suggested by the LFS book:
tar -czvf /home/root/lfs-initial-toolchain.tar.gz $LFS
Just in case I’d like to build another system later from this same 9.1 version
And so we move on to the actual building of the new LFS system, I’m excited!
Chapter 6 - Installing Basic System Software
6.3. Package Management
I decided against choosing a package management scheme at this point. Since this is my first build, I’ll just take a look at this later as it becomes necessary.
6.10. Adjusting the Toolchain
This seems to be a very important section, as this is where we make the switch from the temp utilities to the final toolchain for the rest of the building process.
This is the output from the instructions in this section:
(lfs chroot) root:/sources/glibc-2.31/build# mv -v /tools/bin/{ld,ld-old}
renamed '/tools/bin/ld' -> '/tools/bin/ld-old'
(lfs chroot) root:/sources/glibc-2.31/build# mv -v /tools/$(uname -m)-pc-linux-gnu/bin/{ld,ld-old}
renamed '/tools/x86_64-pc-linux-gnu/bin/ld' -> '/tools/x86_64-pc-linux-gnu/bin/ld-old'
(lfs chroot) root:/sources/glibc-2.31/build# mv -v /tools/bin/{ld-new,ld}
renamed '/tools/bin/ld-new' -> '/tools/bin/ld'
(lfs chroot) root:/sources/glibc-2.31/build# ln -sv /tools/bin/ld /tools/$(uname -m)-pc-linux-gnu/bin/ld
'/tools/x86_64-pc-linux-gnu/bin/ld' -> '/tools/bin/ld'
(lfs chroot) root:/sources/glibc-2.31/build# gcc -dumpspecs | sed -e 's@/tools@@g' \
> -e '/\*startfile_prefix_spec:/{n;s@.*@/usr/lib/ @}' \
> -e '/\*cpp:/{n;s@$@ -isystem /usr/include@}' > \
> `dirname $(gcc --print-libgcc-file-name)`/specs
(lfs chroot) root:/sources/glibc-2.31/build# echo 'int main(){}' > dummy.c
(lfs chroot) root:/sources/glibc-2.31/build# cc dummy.c -v -Wl,--verbose &> dummy.log
(lfs chroot) root:/sources/glibc-2.31/build# readelf -l a.out | grep ': /lib'
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
(lfs chroot) root:/sources/glibc-2.31/build# grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log
/usr/lib/../lib/crt1.o succeeded
/usr/lib/../lib/crti.o succeeded
/usr/lib/../lib/crtn.o succeeded
(lfs chroot) root:/sources/glibc-2.31/build# grep -B1 '^ /usr/include' dummy.log
#include <...> search starts here:
/usr/include
(lfs chroot) root:/sources/glibc-2.31/build# grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
SEARCH_DIR("=/tools/x86_64-pc-linux-gnu/lib64")
SEARCH_DIR("/usr/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("=/tools/x86_64-pc-linux-gnu/lib");
(lfs chroot) root:/sources/glibc-2.31/build# grep "/lib.*/libc.so.6 " dummy.log
attempt to open /lib/libc.so.6 succeeded
(lfs chroot) root:/sources/glibc-2.31/build# grep found dummy.log
found ld-linux-x86-64.so.2 at /lib/ld-linux-x86-64.so.2
So everything went as expected, now we start building the rest of the packages against the local toolchain.
6.25. GCC-9.2.0
This was a big one as well, I actually left this running overnight, so I’m not entirely sure how long it took for the testing, the compile time was about 15-20 minutes.
The results after the testing were the following on my setup:
(lfs chroot) root:/sources/gcc-9.2.0/build# ../contrib/test_summary | grep -A7 Summ
gawk: cmd. line:36: warning: regexp escape sequence `\=' is not a known regexp operator
=== g++ Summary ===
# of expected passes 134787
# of expected failures 527
# of unsupported tests 5921
/sources/gcc-9.2.0/build/gcc/xg++ version 9.2.0 (GCC)
=== gcc tests ===
--
=== gcc Summary ===
# of expected passes 139439
# of unexpected failures 2
# of expected failures 527
# of unsupported tests 2151
/sources/gcc-9.2.0/build/gcc/xgcc version 9.2.0 (GCC)
--
=== libatomic Summary ===
# of expected passes 54
=== libgomp tests ===
Running target unix
=== libgomp Summary ===
# of expected passes 2316
# of expected failures 2
# of unsupported tests 210
=== libitm tests ===
--
=== libitm Summary ===
# of expected passes 42
# of expected failures 3
# of unsupported tests 1
=== libstdc++ tests ===
--
=== libstdc++ Summary ===
# of expected passes 12892
# of unexpected failures 8
# of expected failures 78
# of unsupported tests 380
Compiler version: 9.2.0 (GCC)
I compared it to the output as suggested and saw a few failed tests as well on there, so I’m going to hope all is well.
The final compiling test for this the new toolchain was successful:
(lfs chroot) root:/sources/gcc-9.2.0/build# echo 'int main(){}' > dummy.c
(lfs chroot) root:/sources/gcc-9.2.0/build# cc dummy.c -v -Wl,--verbose &> dummy.log
(lfs chroot) root:/sources/gcc-9.2.0/build# readelf -l a.out | grep ': /lib'
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
The rest of the tests also showed the expected results:
(lfs chroot) root:/sources/gcc-9.2.0/build# grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log
/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../lib/crt1.o succeeded
/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../lib/crti.o succeeded
/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../lib/crtn.o succeeded
(lfs chroot) root:/sources/gcc-9.2.0/build# grep -B4 '^ /usr/include' dummy.log
#include <...> search starts here:
/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/include
/usr/local/include
/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/include-fixed
/usr/include
(lfs chroot) root:/sources/gcc-9.2.0/build# grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib64")
SEARCH_DIR("/usr/local/lib64")
SEARCH_DIR("/lib64")
SEARCH_DIR("/usr/lib64")
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib")
SEARCH_DIR("/usr/local/lib")
SEARCH_DIR("/lib")
SEARCH_DIR("/usr/lib");
(lfs chroot) root:/sources/gcc-9.2.0/build# grep "/lib.*/libc.so.6 " dummy.log
attempt to open /lib/libc.so.6 succeeded
(lfs chroot) root:/sources/gcc-9.2.0/build# grep found dummy.log
found ld-linux-x86-64.so.2 at /lib/ld-linux-x86-64.so.2
For the rest of the packages in the chapter everything went pretty well, I ran the test suites for all of the packages that had one and got expected results for each one of them.
6.81. Cleaning Up
I followed most of the cleaning up process, I left the /tools
directory present on the system.
Chapter 7 - System Configuration
We have finally reached a point where the system seems to have already been built. It looks from the index like the rest of the steps are more related to configuration of the already installed packages than more installation.
7.1. Introduction
This explains how System V
works, which I’m familiar with from using Slackware, but I learned how it’s installed so that was great. I was actually surprised at how fast it was to compile and install the System V
binary as well as how small it is.
In the rest of this section I set up the basic files that the new LFS system will use, pretty straight forward.
Chapter 8 - Making the LFS System Bootable
I can finally see the light at the end of the tunnel, we’re close to having a working system (I hope).
8.3. Linux-5.5.3
Something that is usually seen as the single hardest thing to set up on a Linux system is the Kernel. Usually most users are intimidated by the thought of compiling or re-compiling the Kernel for their systems (I include myself in that pool of users).
In LFS this is left for the end, which by this point doesn’t really seem all that involved.
I followed the recommendations and did not make any specific tweaks, the compilation went pretty smoothly.
This was my first time doing this, so it took me longer that it may have taken an experienced Kernel hacker to compile the LFS Kernel.
8.4. Using GRUB to Set Up the Boot Process
I use LILO on the Slackware host system as a boot manager, so I decided to just add a new entry in /etc/lilo.conf
for the new LFS system.
I added the following OS block to /etc/lilo.conf
:
# LFS bootable partition config begins
image= /boot/vmlinuz-5.5.3-lfs-9.1
root = /dev/sda3
label = LFS
read-only
# LFS bootable partition config end
The full /etc/lilo.conf
looks like this now:
# LILO configuration file
# generated by 'liloconfig'
#
# Start LILO global section
# Append any additional kernel parameters:
append=" vt.default_utf8=0"
boot = /dev/sda
compact # faster, but won't work on all systems.
# Boot BMP Image.
# Bitmap in BMP format: 640x480x8
bitmap = /boot/slack.bmp
# Menu colors (foreground, background, shadow, highlighted
# foreground, highlighted background, highlighted shadow):
bmp-colors = 255,0,255,0,255,0
# Location of the option table: location x, location y, number of
# columns, lines per column (max 15), "spill" (this is how many
# entries must be in the first column before the next begins to
# be used. We don't specify it here, as there's just one column.
bmp-table = 60,6,1,16
# Timer location x, timer location y, foreground color,
# background color, shadow color.
bmp-timer = 65,27,0,255
# Standard menu.
# Or, you can comment out the bitmap menu above and
# use a boot message with the standard menu:
#message = /boot/boot_message.txt
# Wait until the timeout to boot (if commented out, boot the
# first entry immediately):
# prompt
# Timeout before the first entry boots.
# This is given in tenths of a second, so 600 for every minute:
# timeout = 1200
# Override dangerous defaults that rewrite the partition table:
change-rules
reset
# Normal VGA console
vga = normal
# Ask for video mode at boot (time out to normal in 30s)
#vga = ask
# VESA framebuffer console @ 1024x768x64k
#vga=791
# VESA framebuffer console @ 1024x768x32k
#vga=790
# VESA framebuffer console @ 1024x768x256
#vga=773
# VESA framebuffer console @ 800x600x64k
#vga=788
# VESA framebuffer console @ 800x600x32k
#vga=787
# VESA framebuffer console @ 800x600x256
#vga=771
# VESA framebuffer console @ 640x480x64k
#vga=785
# VESA framebuffer console @ 640x480x32k
#vga=784
# VESA framebuffer console @ 640x480x256
#vga=769
# End LILO global section
# LFS bootable partition config begins
image= /boot/vmlinuz-5.5.3-lfs-9.1
root = /dev/sda3
label = LFS
read-only
# LFS bootable partition config end
# Linux bootable partition config begins
image = /boot/vmlinuz
root = /dev/sda1
label = Linux
read-only
# Linux bootable partition config ends
Chapter 9 - The End
It seems we have finished building LFS, I haven’t tried rebooting the system yet, so we’ll see.
This chapter still has some configuration steps that need to be done, mainly for system personalization.
9.2. Get Counted
I then registered as an LFS user:
9.3. Rebooting the System
Part of this section suggests to add a few more packages before rebooting the system, but at the time it was late so I decided not to do this and do it once I got to the BLFS book.
After that I rebooted the system and..success!…sort of. My editing of the /etc/lilo.conf
on Slackware seems to have made it so that LFS boots, but I’m not given a choice on whether I want to boot LFS or Slackware from LILO, I’m basically locked out of Slackware. Oops!
I booted a Slackware image from a USB drive as if I was going to install Slackware. I then followed this article from the Slackware Documentation Project to mount the already installed Slackware OS.
I executed the following:
mount /dev/sda3 /mnt
mount -o bind /dev /mnt/dev
mount -o bind /proc /mnt/proc
mount -o bind /sys /mnt/sys
chroot /mnt /bin/bash
vim /etc/lilo.conf
I noticed that I had commented out the lines in LILO that allowed the prompt and timeout settings to be applied, and I forgot to revert these changes so that I could choose from any of the two installed systems.
Here are the lines that were changed from the file that I shared earlier:
# prompt
# timeout = 1200
I simply uncommented these lines, ran /sbin/lilo
and rebooted once again. With that everything worked as expected and I was able to choose whether I wanted to boot into the newly built LFS system or the existing Slackware system successfully!
Conclusion
We did it!
That was quite the journey, in total it took me around 18 hours of actual time to build my first LFS system. It went quite smoothly to be honest, I simply followed the steps on the book and everything worked great.
I really enjoyed learning what packages did what exactly and how those packages were installed and configured on the system, I even learned some new commands along the way. I would like to explore BLFS as well, I think it would be nice to install the i3 Window Manager on LFS for example.
I still have to apply the errata patches, which I will take a look at when the time to do BLFS comes.
A big thank you to the whole team that makes LFS possible, the quality of the project is truly amazing.
Additionally, I now have a new kind of respect for all of the people that maintain the different distributions of Linux out there, it is truly an involved process with many intricacies that we get to ignore as users due to their hard work.
The bottom line is if you have some experience with the command line, and around 20 hours of free time along with a desire to learn more about Linux, this is a great experience to have.