Fathom-OS Build Series: Chapter 4 - Final Preparations

Part of the Fathom-OS Project Log.


Chapter 4 sets up the environment that Chapters 5 and 6 depend on entirely. This includes creating the directory layout inside the LFS partition, adding a dedicated unprivileged build user, and configuring a clean isolated shell environment for that user. Nothing from the host system bleeds into the build after this point.

References:


Section 4.2: Creating the Directory Layout

The first step is creating a minimal directory structure inside $LFS. The temporary tools built in Chapters 5 and 6 install here, and they get overwritten by the real versions in Chapter 8. The layout needs to exist first so those installs have somewhere to go.

These commands run as dayotte with sudo:

sudo mkdir -pv $LFS/{etc,var} $LFS/usr/{bin,lib,sbin}

for i in bin lib sbin; do
  sudo ln -sv usr/$i $LFS/$i
done

case $(uname -m) in
  x86_64) sudo mkdir -pv $LFS/lib64 ;;
esac

sudo mkdir -pv $LFS/tools

Output:

mkdir: created directory '/lfs/etc'
mkdir: created directory '/lfs/var'
mkdir: created directory '/lfs/usr'
mkdir: created directory '/lfs/usr/bin'
mkdir: created directory '/lfs/usr/lib'
mkdir: created directory '/lfs/usr/sbin'
'/lfs/bin' -> 'usr/bin'
'/lfs/lib' -> 'usr/lib'
'/lfs/sbin' -> 'usr/sbin'
mkdir: created directory '/lfs/lib64'
mkdir: created directory '/lfs/tools'

The bin, lib, and sbin entries under $LFS are symlinks pointing to their counterparts under $LFS/usr. The lib64 directory is created because this is an x86_64 build. The book specifically warns never to create a /usr/lib64 directory. If it appears for any reason it will break the system.

The tools directory is where the cross-compiler and temporary tools will live during Chapters 5 and 6.


Section 4.3: Adding the LFS User

The book requires all packages in Chapters 5 and 6 to be built as an unprivileged user. Running as root during compilation means a single mistake could damage the host system. The dedicated lfs user contains that risk.

sudo groupadd lfs
sudo useradd -s /bin/bash -g lfs -m -k /dev/null lfs
sudo passwd lfs

The lfs group and user already existed from a previous build attempt. The password was reset and everything proceeded normally.

Give the lfs user ownership of the directories it needs to write to:

sudo chown -v lfs $LFS/{usr{,/*},var,etc,tools}
case $(uname -m) in
  x86_64) sudo chown -v lfs $LFS/lib64 ;;
esac

Output:

changed ownership of '/lfs/usr' from root to lfs
changed ownership of '/lfs/usr/bin' from root to lfs
changed ownership of '/lfs/usr/lib' from root to lfs
changed ownership of '/lfs/usr/sbin' from root to lfs
changed ownership of '/lfs/var' from root to lfs
changed ownership of '/lfs/etc' from root to lfs
changed ownership of '/lfs/tools' from root to lfs
changed ownership of '/lfs/lib64' from root to lfs


Section 4.4: Setting Up the Environment

This section runs partly as dayotte and partly as lfs. The order matters.

Neutralize /etc/bash.bashrc (run as dayotte)

Some distributions add an /etc/bash.bashrc file that can silently modify the lfs user’s environment and interfere with the build. The book requires moving it out of the way before switching to the lfs user. This is easy to miss as it is buried in an Important callout in the middle of Section 4.4.

sudo bash -c '[ ! -e /etc/bash.bashrc ] || mv -v /etc/bash.bashrc /etc/bash.bashrc.NOUSE'

Output:

renamed '/etc/bash.bashrc' -> '/etc/bash.bashrc.NOUSE'

The file existed and was moved. It can be restored after the build is complete if needed.

Switch to the lfs User

su - lfs

The - flag starts a login shell, which is required for the .bash_profile to be read correctly.

Create .bash_profile

cat > ~/.bash_profile << "EOF"
exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash
EOF

This replaces the running shell with a completely clean environment, keeping only HOME, TERM, and PS1. Nothing from the host environment carries over.

Create .bashrc

cat > ~/.bashrc << "EOF"
set +h
umask 022
LFS=/lfs
LC_ALL=POSIX
LFS_TGT=$(uname -m)-lfs-linux-gnu
PATH=/usr/bin
if [ ! -L /bin ]; then PATH=/bin:$PATH; fi
PATH=$LFS/tools/bin:$PATH
CONFIG_SITE=$LFS/usr/share/config.site
export LFS LC_ALL LFS_TGT PATH CONFIG_SITE
EOF

Note: LFS=/lfs is used here instead of the book’s example of /mnt/lfs to match the actual mount point on this build host.

set +h disables bash’s hash function so the shell always finds the newly built tools in $LFS/tools/bin rather than caching the path to older host versions.

LFS_TGT sets the cross-compilation target triplet to x86_64-lfs-linux-gnu.

CONFIG_SITE prevents configure scripts from pulling in host-specific configuration during the cross-compilation chapters.

Add MAKEFLAGS

cat >> ~/.bashrc << "EOF"
export MAKEFLAGS=-j$(nproc)
EOF

This tells make to use all available logical cores. The build host has 10 vCPUs so $(nproc) returns 10. Never pass -j without a number, the book specifically warns this will cause make to spawn infinite jobs and destabilize the system.

Source the Profile

source ~/.bash_profile

Verify the Environment

echo $LFS
echo $LFS_TGT
echo $MAKEFLAGS
umask

Output:

/lfs
x86_64-lfs-linux-gnu
-j10
0022

All four confirmed correct.


What Is Next

Chapter 4 is complete. The build environment is isolated, the lfs user is in place, and the directory structure is ready. The next step is Chapter 5, which begins the cross-compilation toolchain.


More updates to follow as each build phase completes.

Previous: Chapter 3: Packages and Patches | Next: Chapter 5: Compiling a Cross-Toolchain


All session notes and build logs are committed to the private repository at github.com/QuietWireDev/fathom-os.