Part of the Fathom-OS Project Log.
This is Part 2 of Chapter 8, the core system build. Part 1 covered the API headers and core libraries through Pcre2. This part builds the toolchain group: the build tools, the testing trio, and the permanent Binutils plus the three math libraries that GCC depends on. Eleven packages, several with critical test suites.
References:
Resuming the Build: A Mount Cleanup
Every Chapter 8 session starts by remounting the virtual kernel filesystems and re-entering the chroot, since the snapshots are taken outside the chroot with everything unmounted. This session that resume hit a snag worth documenting.
After becoming root and confirming $LFS was set, the remount block reported an error on the sysfs mount: mount: /lfs/sys: sysfs already mounted on /sys. That “already mounted” message was the tell. Checking the actual state with findmnt showed the virtual filesystems were already mounted from a prior session, and the remount commands had stacked a second copy on top of most of them. Several mount points were doubled.
Mounting onto an already-mounted point stacks the mounts, which causes confusing failures later. The fix was to fully unmount every layer, verify clean, then remount once. Because things were stacked, some needed unmounting more than once, and the children (dev/pts, dev/shm) had to come off before the parent (dev) would release. Working one at a time and checking with findmnt after each step is what untangled it:
umount /lfs/dev/shm
umount /lfs/dev/pts
umount /lfs/dev
umount /lfs/sys
umount /lfs/proc
umount /lfs/run
findmnt | grep /lfs
Once findmnt showed only the /lfs root partition, a clean single remount and chroot entry worked.
Lesson: if the remount ever reports “already mounted,” stop and check findmnt before proceeding. Do not build on top of stacked mounts. Verify the mount state is clean at the start of every session.
The Build Tools
8.14 M4
A plain native build now, no cross-compilation flags like the Chapter 6 temporary version.
./configure --prefix=/usr
make
make check
make install
8.15 Bc
Bc uses a custom configure, not autotools, with a CC variable and the test target is make test rather than make check.
CC='gcc -std=c99' ./configure --prefix=/usr -G -O3 -r
make
make test
make install
All bc and dc tests passed.
8.16 Flex
Has a test suite, then two symlinks so programs expecting the older lex name find flex.
./configure --prefix=/usr --disable-static --docdir=/usr/share/doc/flex-2.6.4
make
make check
make install
ln -sv flex /usr/bin/lex
ln -sv flex.1 /usr/share/man/man1/lex.1
The Testing Trio
These three are installed specifically to support running the test suites of Binutils, GCC, and other packages. Installing three packages just for testing seems like a lot, but knowing the most important tools are working properly is worth it.
8.17 Tcl
The largest of the three at 2.9 SBU. Builds in the unix subdirectory, then a set of seds rewrite the build-directory paths in the config files to the install locations. The embedded package versions for this release are tdbc1.1.12 and itcl4.3.4 (these differ between Tcl point releases, so they must match the source being built).
SRCDIR=$(pwd)
cd unix
./configure --prefix=/usr --mandir=/usr/share/man --disable-rpath
make
After the config-file seds and unset SRCDIR, the test suite runs with a specific locale:
LC_ALL=C.UTF-8 make test
Result: Total 47153, Passed 43698, Skipped 3455, Failed 0. The skipped tests are for features not applicable here (Windows, big-endian, tests needing a server). Then install, with two library permission fixes so debug symbols can be stripped later, the private headers that Expect needs, the tclsh symlink, and a man page rename to avoid a Perl conflict.
8.18 Expect
Before building Expect, the book has you verify that PTYs work inside the chroot, because the test suites of Bash, Binutils, GCC and others depend on it:
python3 -c 'from pty import spawn; spawn(["echo", "ok"])'
This printed ok, confirming the devpts mount is healthy. Given the mount cleanup at the start of the session, this was a good thing to verify. Then a gcc15 compatibility patch, configure pointing at the Tcl install, build, test, install.
patch -Np1 -i ../expect-5.45.4-gcc15-1.patch
./configure --prefix=/usr --with-tcl=/usr/lib --enable-shared \
--disable-rpath --mandir=/usr/share/man --with-tclinclude=/usr/include
make
make test
make install
ln -svf expect5.45.4/libexpect5.45.4.so /usr/lib
Tests: Total 29, Passed 29, Failed 0.
8.19 DejaGNU
The test framework GCC and Binutils use. Builds in a dedicated directory, generates two doc formats, runs a quick check, installs with docs.
mkdir -v build
cd build
../configure --prefix=/usr
makeinfo --html --no-split -o doc/dejagnu.html ../doc/dejagnu.texi
makeinfo --plaintext -o doc/dejagnu.txt ../doc/dejagnu.texi
make check
make install
install -v -dm755 /usr/share/doc/dejagnu-1.6.3
install -v -m644 doc/dejagnu.{html,txt} /usr/share/doc/dejagnu-1.6.3
8.20 Pkgconf
The successor to pkg-config. Two compatibility symlinks at the end so it works as a drop-in replacement.
./configure --prefix=/usr --disable-static --docdir=/usr/share/doc/pkgconf-2.5.1
make
make install
ln -sv pkgconf /usr/bin/pkg-config
ln -sv pkgconf.1 /usr/share/man/man1/pkg-config.1
The Permanent Toolchain
8.21 Binutils
The final permanent Binutils, 1.7 SBU. Builds in a dedicated directory. The test suite is marked critical, do not skip.
mkdir -v build
cd build
../configure --prefix=/usr --sysconfdir=/etc --enable-ld=default \
--enable-plugins --enable-shared --disable-werror \
--enable-64-bit-bfd --enable-new-dtags --with-system-zlib \
--enable-default-hash-style=gnu
make tooldir=/usr
make -k check
The ld summary showed 3258 expected passes, 59 expected failures (these are intentional, not real failures), 3 untested, 37 unsupported. The book says one gprofng test is known to fail, and verifying by name confirmed exactly that:
grep '^FAIL:' $(find -name '*.log')
Output: a single gprofng/gprofng.log:FAIL: tmpdir/gp-gmon, the known failure. Nothing else. The critical test suite is clean. Then install and remove the static libraries.

8.22 GMP
The arbitrary-precision math library. Critical test suite. A gcc15 compatibility sed first, then build, html docs, test, and a check that at least 199 tests passed.
sed -i '/long long t1;/,+1s/()/(...)/' configure
./configure --prefix=/usr --enable-cxx --disable-static --docdir=/usr/share/doc/gmp-6.3.0
make
make html
make check 2>&1 | tee gmp-check-log
awk '/# PASS:/{total+=$3} ; END{print total}' gmp-check-log
The pass count came back 199, meeting the book’s threshold.
8.23 MPFR
Multiple-precision floating point. Critical test suite, book expects all 198 to pass.
./configure --prefix=/usr --disable-static --enable-thread-safe --docdir=/usr/share/doc/mpfr-4.2.2
make
make html
make check
Result: TOTAL 198, PASS 198, FAIL 0. The test output also confirmed the toolchain lining up correctly: GCC 15.2.0, Glibc 2.43, GMP 6.3.0, with the build host’s processor detected.
8.24 MPC
Complex-number math. The last of the three math libraries.
./configure --prefix=/usr --disable-static --docdir=/usr/share/doc/mpc-1.3.1
make
make html
make check
make install
make install-html
A Note on Following the Right Book
One process note worth recording. The LFS site hosts several versions: the stable release tree at /lfs/view/13.0-systemd/ and a rolling development tree at /lfs/view/systemd/. They drift apart. The development tree had already moved to Tcl 8.6.18 with different embedded package versions, and it had reordered packages. Building against the wrong tree means version mismatches in the seds and commands.
The fix is to always build the package versions you downloaded and verified, from the stable book matching your release. Bookmark the stable URL with the version in the path, confirm the page header reads the plain version with no development suffix, and follow the book’s own Next links in order rather than jumping ahead. Checking the package number and version against the book before running each block catches any mismatch before it matters.
Snapshot
With the toolchain group complete, this is the checkpoint before the long run of system packages that follows. Exit the chroot, unmount the virtual filesystems one at a time, verify clean with findmnt (only the /lfs root partition should remain), then snapshot.
What Is Next
The next stretch is the long middle run of Chapter 8: the system libraries and utilities starting with Attr, Acl, Libcap, Libxcrypt, and Shadow, then the final permanent GCC with its full test suite, and onward through the bulk of the userland. That run is large enough that it will span more than one post.
More updates to follow as each build phase completes.
Previous: Chapter 8 Part 1: API and Core Libraries | Next: Chapter 8 Part 3: System Libraries and the Final GCC
All session notes and build logs are committed to the private repository at github.com/QuietWireDev/fathom-os.

