Tag Archives: GCC

LFS 6.8 (Part 8): Temporary Toolchain Second Pass and Sanity Check

The LFS temporary toolchain is going to take a while to cover completely, so I’m breaking it up into several parts for readability.

Binutils (Pass 2)

To review:

Binutils contains some of the closest “to the metal” utilities that Linux needs, providing low-level translation of programmer intent into machine-readable binary code. Binutils gets built first as GCC and Glibc will need these lower-level utilities in order to function properly themselves.

The first pass of Binutils was a cross-compile, and this second pass uses a few extra options to use only the first pass (cross-compiled) Binutil’s tools and libraries. This removes any traces of library or settings contamination from the build environment (I’m using the LFS live CD). The second pass of Binutils is installed to the /tools directory (in the temporary toolchain, /mnt/lfs/tools), overwriting the first pass version of Binutils.

I estimated Pass #2 of Binutils to take 1 hour and 4 minutes to build, and Pressie breezed through in only 58 minutes.

Not quite everything is right yet: the library linker (ld) I just compiled would incorrectly look in /tools for libraries to build against. To remove the contamination of the temporary toolchain itself, I cleaned out the ld subdirectory and recompiled ld to point to /usr/lib and /lib (which is where libraries will be on my final LFS system). Then I copied the new ld to /tools/bin (in the temporary toolchain, /mnt/lfs/tools/bin).

GCC (Pass 2)

To review again:

GCC is the GNU Compiler Collection, and it is the main utility on a Linux box for compiling programs written in C and C++ (and a host of others that are irrelevant to LFS for now).

The first pass of GCC was a cross-compile, and the second pass of GCC will be an uncontaminated build. GCC required a patch and several tweaks to prepare it for building the final LFS system, mostly by changing various build scripts to use the /tools Glibc libraries rather than the live CD Glibc libraries. These tweaks took quite a bit of typing, so be sure to check several times for any typos before hitting that last Enter. Since Pressie is based on a i586 CPU, I skipped a step that is intended to prevent GCC from linking to x86_64 libraries on a 64-bit host environment. Next, I extracted GMP, MPFR, and MPC into GCC’s source directory for the build process. I needed both the C and C++ compilers to be built, so there are some extra C++-specific configure options that were unnecessary in the first pass. The second pass of GCC installed to /tools (/mnt/lfs/tools in the temporary toolchain), overwriting the first pass version.

I expected GCC to build in 7 hours and 21 minutes, but it took 8 hours and 12 minutes.

Finally, since many programs link to cc (a generic C compiler) instead of to gcc specifically, I created a cc symlink to gcc.

Sanity Check!

LFS recommends doing a basic sanity check on the temporary toolchain before going further. Essentially, I compiled an empty C program and made sure I was using the correct program linker (the new one in /tools, and not the one from the live CD environment), then deleted the test output. At this point, everything is A-OK to-the-letter perfect. Now I’m ready to build the rest of the utilities in the temporary toolchain!

LFS 6.8 (Part 7): Temporary Toolchain First Pass and Adjustments

The LFS temporary toolchain is going to take a while to cover completely, so I’m breaking it up into several parts for readability.

Binutils (Pass 1)

Binutils contains some of the closest “to the metal” utilities that Linux needs, providing low-level translation of programmer intent into machine-readable binary code. Binutils gets built first as GCC and Glibc will need these lower-level utilities in order to function properly themselves.

This first pass of Binutils is a cross-compile, making it refer specifically to the hardware it is being built on, rather than to the hardware the current build environment (I’m using the LFS live CD) was built for. Binutils is installed to the /tools directory (in the temporary toolchain, /mnt/lfs/tools) because right now / (root) refers to the live CD environment.

I put the configure and make commands for Binutils into a time{} container to measure an SBU (Standard Build Unit) so I could then reliably guess build times for other packages. It turns out an SBU on Pressie is 49 minutes and 8 seconds.

GCC (Pass 1)

GCC is the GNU Compiler Collection, and it is the main utility on a Linux box for compiling programs written in C and C++ (and a host of others that are irrelevant to LFS for now).

The first pass of GCC is also a cross-compile. It requires GMP, MPFR, and MPC, so I extracted their sources into GCC’s source directory so they could be used during the build process. GCC is installed to /tools (/mnt/lfs/tools in the temporary toolchain). Only the C compiler is required for now, so that’s all I built.

I expected GCC to build in 4 hours and 5 minutes, but in reality it took 4 hours and 44 minutes.

As a final touch, I fake out the soon-to-be-built Glibc by symlinking libgcc.a to libgcc_eh.a, since apparently libgcc.a has all the things Glibc wants from libgcc_eh.a. Ours not to reason why….

Linux API Headers

Now this part took me a short while to figure out: to compile the Linux API headers I had to extract the entire Linux kernel source, but only compile the headers with some special commands.

The Linux API headers expose the Linux API to Glibc when I build Glibc; that way, Glibc knows what the kernel can and can’t do, and it compiles accordingly. The headers are installed to /tools/include (/mnt/lfs/tools/include for in the temporary toolchain)

It actually took longer to extract the sources than to build this one: Pressie shattered through the predicted build time of 5 minutes and build in only 3 minutes.

Glibc (not EGlibc)

Glibc is the main C library. Basically, it is a standardized collection of basic functionality for the C language (like memory allocation, file reading, etc.).

I needed to apply a patch to Glibc that fixes a bug preventing it from compiling with the version of GCC I built earlier. I made Glibc a dedicated build directory, as recommended, and then ran a command to compile it as compatible for i486 (i386 is no longer supported by Glibc). I’m not sure why Glibc’s authors didn’t make it i486 by default, but I’m sure it made sense at the time.

Glibc is also cross-compiled, using the first pass builds of Binutils and GCC to configure itself according to the capabilities of Pressie’s hardware. After adjusting the toolchain settings, I will compile Binutils and GCC against the new and Pressie-specific Glibc, so they will be free of any polluting influences of the live CD environment. Glibc is installed to /tools (/mnt/lfs/tools in the temporary toolchain) as well.

A predicted 5 hours and 38 minutes was really 6 hours and 7 minutes.

Adjusting the Toolchain

With the temporary C libraries in place, it is time to adjust things to point toward these new libraries instead of the libraries provided by the live CD environment. I ran a sed script that removed all references in GCC’s specs file to /lib (libraries on the live CD) and pointed them instead to /tools (temporary toolchain libraries on the hard drive).

Finally, I ran a sanity check like the book recommended, and everything worked perfectly! Next I will compile the second passes of Binutils and GCC, together with twenty-odd smaller packages that I’ll need for the rest of the temporary toolchain.

LFS 6.8 (Part 6): Temporary Toolchain Overview

The LFS temporary toolchain is going to take a while to cover completely, so I’m breaking it up into several parts for readability.

The first part of actually building LFS is building a temporary toolchain to prevent contamination from the host environment (in my case, the LFS live CD).

I will build Binutils and GCC twice during the beginning of this process: first to tune them for the hardware I’m using; and second to allow them to refer only to themselves, and not to the liveCD versions. This was the trickiest part of the build for me to understand, but it made sense the more I thought about it. Next, I will build a minimal set of tools that will let me build (and test) my final LFS system.

At several points in this process, I must adjust the temporary toolchain to be more self-referential, until finally I chroot into the final build environment and discard the temporary toolchain.

Before I actually begin building the temporary toolchain, I am going to explain my process for actually building the toolchain, and most of the rest of LFS, so it can be assumed in later entries for brevity’s sake:

  • Since my sources are in /sources (/mnt/lfs/sources during the temporary toolchain build), I will be there to begin with each program build.
  • I will then use tar -zxf on .tar.gz sources and tar -jxf on .tar.bz2 sources to decompress them into their own directory (usually <package-name>-<version>).
  • I will the cd into the newly extracted directories and follow the instructions as given in the book.
  • I will, where possible, use a time { ./configure && make && make install } template so I can give an accurate account of the length of each build (this is slightly deviant from the book, other than the first time I build Binutils for the temporary toolchain).
  • I will then cd back into /sources (again, /mnt/lfs/sources during the temporary toolchain build) and rm -rf the extracted source files and any dedicated build directories. This keeps down the amount of hard disk space needed, especially for a very constrained system like Pressie, and it will ensure a completely clean build for software that I have to build multiple times.

And with these preliminaries, I am ready to build the temporary toolchain.