Installing basic system software Introduction In this chapter we enter the building site, and start constructing our LFS system in earnest. That is, we chroot into our temporary mini Linux system, create some auxiliary things, and then start installing all the packages, one by one. The installation of all this software is pretty straightforward, and you will probably think it would be much shorter to give here the generic installation instructions and explain in full only the installation of those packages that require an alternate method. Although we agree with that, we nevertheless choose to give the full instructions for each and every package, simply to minimize the possibilities for mistakes. The key to learning what makes a Linux system work is to know what each package is used for and why the user (or the system) needs it. For this purpose for every installed package a summary of its content is given followed by concise descriptions of each program and library it installed. If you plan to use compiler optimizations in this chapter, take a look at the optimization hint at . Compiler optimizations can make a program run slightly faster, but they may also cause compilation difficulties and even problems when running the program. If a package refuses to compile when using optimization, try to compile it without optimization and see if the problem goes away. Even if the package does compile when using optimization, there is the risk it may have been compiled incorrectly due to complex interactions between the code and build tools. In short, the small potential gains achieved in using compiler optimization are generally outweighed by the risk. First time builders of LFS are encouraged to build without custom optimizations. Your system will still be very fast and very stable at the same time. The order in which packages are installed in this chapter has to be strictly followed, to ensure that no program gets a path referring to /tools hard-wired into it. For the same reason, do not compile packages in parallel. Compiling in parallel may save you some time (especially on dual-CPU machines), but it could result in a program containing a hard-wired path to /tools, which will cause the program to stop working when that directory is removed. Before the installation instructions each installation page gives some information about the package: a concise description of what it contains, how long it will approximately take to build it, how much disk space it needs during this building process, the official download location of the package (in case you just want to update a few of them), and which other packages it needs in order to be built successfully. After the installation instructions follows a list of programs and libraries that the package installs, together with a series of short descriptions of these. If you wish to keep track of which package installs what files, you may want to use a package manager. For a general overview of package managers have a look at . And for a package management method specifically geared towards LFS see . Mounting the proc and devpts file systems In order for certain programs to function properly, the proc and devpts file systems must be available within the chroot environment. The proc file system is the process information pseudo file system through which the kernel provides information about the status of the system. And the devpts file system is nowadays the most common way pseudo terminals (PTYs) are implemented. Since kernel version 2.4, a file system can be mounted as many times and in as many places as you like, thus it's not a problem that these file systems are already mounted on your host system, especially so because they are virtual file systems. First become root, as only root can mount file systems in unusual places. Then check again that the LFS environment variable is set correctly by running echo $LFS and making sure it shows the path to your LFS partition's mount point, which is /mnt/lfs if you followed our example. Now make the mount points for these filesystems: mkdir -p $LFS/{proc,dev/pts} Mount the proc file system with: mount proc $LFS/proc -t proc And mount the devpts file system with: mount devpts $LFS/dev/pts -t devpts This last command might fail with an error like:
filesystem devpts not supported by kernel
The most likely cause for this is that your host system's kernel was compiled without support for the devpts file system (you can check which file systems your kernel supports with cat /proc/filesystems, for example). A few PTYs are needed to be able to run the suites for Binutils and GCC later on. If your kernel does not support devpts, do not worry, there is another way to get them working inside the chroot environment. We'll cover this shortly in the section. Remember that if for any reason you stop working on your LFS, and start again later, it's important to check that these file systems are mounted again before entering the chroot environment, otherwise problems could occur.
Entering the chroot environment It is time to enter the chroot environment in order to begin building and installing your final LFS system. Still as root run the following command to enter the small world that is, at the moment, populated with only the temporary tools: chroot $LFS /tools/bin/env -i \     HOME=/root TERM=$TERM PS1='\u:\w\$ ' \     PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin \     /tools/bin/bash +h The -i option passed to the env command will clear all variables of the chroot environment. After that, only the HOME, TERM, PS1 and PATH variables are set again. The HOME variable is set mainly to prevent several small warnings during the configure runs of Diffutils, Grep and Grub. The TERM variable is set to make programs such as less and vim, that make use of the Ncurses package, operate properly -- the TERM=$TERM construct sets the TERM variable inside chroot to the same value as outside chroot. The main prompt (PS1) is set to "username:working-dir# " (since the "\$" becomes "#" for root). If you need other variables present, such as CFLAGS, CXXFLAGS or LDFLAGS, this is a good place to set them. From this point on there's no need to use the LFS variable anymore, because everything you do will be restricted to the LFS file system -- since what the shell thinks is / is actually the value of $LFS, which was passed to the chroot command. Notice that /tools/bin comes last in the PATH. This means that a temporary tool will not be used any more as soon as its final version is installed. Well, at least when the shell doesn't remember the locations of executed binaries -- for this reason hashing is switched off by passing the +h option to bash. You have to make sure all the commands in the rest of this chapter and in the following chapters are run from within the chroot environment. If you ever leave this environment for any reason (rebooting for example), you must remember to first mount the proc and devpts file systems (discussed in the previous section) and enter chroot again before continuing with the installations. Note that the bash prompt will say "I have no name!" This is normal, as the /etc/passwd file has not been created yet. Changing ownership Right now the /tools directory is owned by the user lfs, a user that exists only on your host system. Although you will probably want to delete the /tools directory once you have finished your LFS system, you may want to keep it around, for example to build more LFS systems. But if you keep the /tools directory as it is, you end up with files owned by a user ID without a corresponding account. This is dangerous because a user account created later on could get this same user ID and would suddenly own the /tools directory and all the files therein, thus exposing these files to possible malicious manipulation. To avoid this issue, you could add the lfs user to your new LFS system later on when creating the /etc/passwd file, taking care to assign it the same user and group IDs as on your host system. Alternatively, you can (and the book assumes you do) assign the contents of the /tools directory to user root by running the following command: chown -R 0:0 /tools The command uses "0:0" instead of "root:root", because chown is unable to resolve the name "root" until the password file has been created. Creating directories Let's now create some structure in our LFS file system. Let's create a directory tree. Issuing the following commands will create a more or less standard tree: mkdir -p /{bin,boot,dev/{pts,shm},etc/opt,home,lib,mnt,proc} mkdir -p /{root,sbin,tmp,usr/local,var,opt} mkdir /usr/{bin,include,lib,sbin,share,src} ln -s share/{man,doc,info} /usr mkdir /usr/share/{doc,info,locale,man} mkdir /usr/share/{misc,terminfo,zoneinfo} mkdir /usr/share/man/man{1,2,3,4,5,6,7,8} mkdir /usr/local/{bin,etc,include,lib,sbin,share,src} ln -s share/{man,doc,info} /usr/local mkdir /usr/local/share/{doc,info,locale,man} mkdir /usr/local/share/{misc,terminfo,zoneinfo} mkdir /usr/local/share/man/man{1,2,3,4,5,6,7,8} mkdir /var/{lock,log,mail,run,spool} mkdir -p /var/{tmp,opt,cache,lib/misc,local} mkdir /opt/{bin,doc,include,info} mkdir -p /opt/{lib,man/man{1,2,3,4,5,6,7,8}} Directories are, by default, created with permission mode 755, but this isn't desirable for all directories. We will make two changes: one to the home directory of root, and another to the directories for temporary files. chmod 0750 /root chmod 1777 /tmp /var/tmp The first mode change ensures that not just anybody can enter the /root directory -- the same as a normal user would do with his or her home directory. The second mode change makes sure that any user can write to the /tmp and /var/tmp directories, but cannot remove other users' files from them. The latter is prohibited by the so-called "sticky bit" -- the highest bit in the 1777 bit mask. FHS compliance note We have based our directory tree on the FHS standard (available at ). Besides the above created tree this standard stipulates the existence of /usr/local/games and /usr/share/games, but we don't much like these for a base system. However, feel free to make your system FHS-compliant. As to the structure of the /usr/local/share subdirectory, the FHS isn't precise, so we created here the directories that we think are needed. Creating essential symlinks Some programs hard-wire paths to programs which don't exist yet. In order to satisfy these programs, we create a number of symbolic links which will be replaced by real files throughout the course of this chapter when we're installing all the software. ln -s /tools/bin/{bash,cat,pwd,stty} /bin ln -s /tools/bin/perl /usr/bin ln -s /tools/lib/libgcc_s.so.1 /usr/lib ln -s bash /bin/sh Creating the passwd, group and log files In order for root to be able to login and for the name "root" to be recognized, there need to be relevant entries in the /etc/passwd and /etc/group files. Create the /etc/passwd file by running the following command: cat > /etc/passwd << "EOF" root:x:0:0:root:/root:/bin/bash EOF The actual password for root (the "x" here is just a placeholder) will be set later. Create the /etc/group file by running the following command: cat > /etc/group << "EOF" root:x:0: bin:x:1: sys:x:2: kmem:x:3: tty:x:4: tape:x:5: daemon:x:6: floppy:x:7: disk:x:8: lp:x:9: dialout:x:10: audio:x:11: EOF The created groups aren't part of any standard -- they are some of the groups that the make_devices script in the next section uses. The LSB (Linux Standard Base) recommends only that, beside the group "root" with a GID of 0, a group "bin" with a GID of 1 be present. All other group names and GIDs can be chosen freely by the system administrator, since well-written packages don't depend on GID numbers but use the group's name. To get rid of the "I have no name!" prompt, we will start a new shell. Since we installed a full Glibc in , and have just created the /etc/passwd and /etc/group files, user name and group name resolution will now work. exec /tools/bin/bash +h Note the use of the +h directive. This tells bash not to use its internal path hashing. Without this directive, bash would remember the paths to binaries it has executed. Since we want to use our newly compiled binaries as soon as they are installed, we turn off this function for the duration of this chapter. The login, agetty and init programs (and some others) use a number of log files to record information such as who was logged into the system and when. These programs, however, won't write to the log files if they don't already exist. Initialize the log files and give them their proper permissions: touch /var/run/utmp /var/log/{btmp,lastlog,wtmp} chmod 644 /var/run/utmp /var/log/{btmp,lastlog,wtmp} The /var/run/utmp file records the users that are currently logged in. The /var/log/wtmp file records all logins and logouts. The /var/log/lastlog file records for each user when he or she last logged in. The /var/log/btmp file records the bad login attempts. &c6-makedev; &c6-kernel-headers; &c6-manpages; &c6-glibc; Re-adjusting the toolchain Now that the new and final C libraries have been installed, it's time to adjust our toolchain again. We'll adjust it so that it will link any newly compiled program against these new libraries. This is in fact the same thing we did in the "Adjusting" phase in the beginning of the previous chapter, even though it looks like the reverse: then we guided the chain from the host's /{,usr/}lib to the new /tools/lib, now we guide it from that same /tools/lib to the LFS's /{,usr/}lib. First we adjust the linker. For this we retained the source and build directories from the second pass over Binutils. Install the adjusted linker by running the following from within the binutils-build directory: make -C ld INSTALL=/tools/bin/install install If you somehow missed the earlier warning to retain the Binutils source and build directories from the second pass in , or otherwise accidentally deleted them or just don't have access to them, don't worry, all is not lost. Just ignore the above command. The result will be that the next package, Binutils, will link against the C libraries in /tools rather than in /{,usr/}lib. This is not ideal, however, our testing has shown that the resulting Binutils program binaries should be identical. From now on every compiled program will link only against the libraries in /usr/lib and /lib. The extra INSTALL=/tools/bin/install is needed because the Makefile created during the second pass still contains the reference to /usr/bin/install, which we obviously haven't installed yet. Some host distributions contain a ginstall symbolic link which takes precedence in the Makefile and thus can cause a problem here. The above command takes care of this also. You must now remove the Binutils source and build directories. (This is important, as you should start the next section with a fresh untarring of the package.) The next thing to do is to amend our GCC specs file so that it points to the new dynamic linker. Just like earlier on, we use a sed to accomplish this: SPECFILE=/tools/lib/gcc-lib/*/*/specs && sed -e 's@ /tools/lib/ld-linux.so.2@ /lib/ld-linux.so.2@g' \     $SPECFILE > newspecfile && mv -f newspecfile $SPECFILE && unset SPECFILE Again, cutting and pasting the above is recommended. And just like before, it is a good idea to visually inspect the specs file to verify the intended change was actually made. If you are working on a platform where the name of the dynamic linker is something other than ld-linux.so.2, you must substitute ld-linux.so.2 with the name of your platform's dynamic linker in the above commands. Refer back to if necessary. It is imperative at this point to stop and ensure that the basic functions (compiling and linking) of the adjusted toolchain are working as expected. For this we are going to perform a simple sanity check: echo 'main(){}' > dummy.c cc dummy.c readelf -l a.out | grep ': /lib' If everything is working correctly, there should be no errors, and the output of the last command will be (allowing for platform specific differences in dynamic linker name):
[Requesting program interpreter: /lib/ld-linux.so.2]
Note especially that /lib is now the prefix of our dynamic linker. If you did not receive the output as shown above, or received no output at all, then something is seriously wrong. You will need to investigate and retrace your steps to find out where the problem is and correct it. There is no point in continuing until this is done. Most likely something went wrong with the specs file amendment above. Once you are satisfied that all is well, clean up the test files: rm dummy.c a.out
&c6-binutils; &c6-gcc; &c6-coreutils; &c6-zlib; &c6-lfs-utils; &c6-findutils; &c6-gawk; &c6-ncurses; &c6-vim; &c6-m4; &c6-bison; &c6-less; &c6-groff; &c6-sed; &c6-flex; &c6-gettext; &c6-nettools; &c6-inetutils; &c6-perl; &c6-texinfo; &c6-autoconf; &c6-automake; &c6-bash; &c6-file; &c6-libtool; &c6-bzip2; &c6-diffutils; &c6-ed; &c6-kbd; &c6-e2fsprogs; &c6-grep; &c6-grub; &c6-gzip; &c6-man; &c6-make; &c6-modutils; &c6-patch; &c6-procinfo; &c6-procps; &c6-psmisc; &c6-shadow; &c6-sysklogd; &c6-sysvinit; &c6-tar; &c6-utillinux; &c6-gcc-2953; About debugging symbols Most programs and libraries are, by default, compiled with debugging symbols included (with gcc's -g option). This means that, when debugging a program or library that was compiled with debugging information included, the debugger can give you not only memory addresses but also the names of the routines and variables. The inclusion of these debugging symbols, however, enlarges a program or library significantly. To get an idea of the amount of space these symbols occupy, have a look at the following: a bash binary with debugging symbols: 1200 KB a bash binary without debugging symbols: 480 KB Glibc and GCC files (/lib and /usr/lib) with debugging symbols: 87 MB Glibc and GCC files without debugging symbols: 16 MB Sizes may vary somewhat, depending on which compiler was used and which C library, but when comparing programs with and without debugging symbols the difference will generally be a factor between 2 and 5. As most people will probably never use a debugger on their system software, a lot of disk space can be regained by removing these symbols. For your convenience, the next section shows how to strip all debugging symbols from all programs and libraries. Information on other ways of optimizing your system can be found in the hint at . Stripping again If you are not a programmer and don't plan to do any debugging on your system software, you can shrink your system by about 200 MB by removing the debugging symbols from binaries and libraries. This causes no inconvenience other than not being able to debug the software fully any more. Most people who use the command mentioned below don't experience any problems. But it is easy to make a typo and render your new system unusable, so before running the strip command it is probably a good idea to make a backup of the current situation. If you are going to perform the stripping, special care is needed to ensure you're not running any of the binaries that are about to be stripped. If you're not sure whether you entered chroot with the command given in , then first exit from chroot: logout Then reenter it with: chroot $LFS /tools/bin/env -i \     HOME=/root TERM=$TERM PS1='\u:\w\$ ' \     PATH=/bin:/usr/bin:/sbin:/usr/sbin \     /tools/bin/bash Now you can safely strip the binaries and libraries: /tools/bin/find /{,usr/}{bin,lib,sbin} -type f \    -exec /tools/bin/strip --strip-debug '{}' ';' A large number of files will be reported as having their file format not recognized. These warnings can be safely ignored, they just mean that those files are scripts instead of binaries, no harm is done. If you are really tight on disk space, you may want to use --strip-all on the binaries in /{,usr/}{bin,sbin} to gain several more megabytes. But do not use this option on libraries: they would be destroyed. Cleaning up From now on, when you exit the chroot environment and wish to reenter it, you should use the following modified chroot command: chroot $LFS /usr/bin/env -i \     HOME=/root TERM=$TERM PS1='\u:\w\$ ' \     PATH=/bin:/usr/bin:/sbin:/usr/sbin \     /bin/bash The reason for this is that, since the programs in /tools are no longer needed, you may want to delete the whole directory and regain the space. Before actually deleting the directory, exit from chroot and reenter it with the above command. Also, before removing /tools, you may want to tar it up and store it in a safe place, in case you want to build another LFS system soon. Removing /tools will also remove the temporary copies of Tcl, Expect and DejaGnu, which were used for running the toolchain tests. If you want to use these programs later on, you will need to recompile and re-install them. The installation instructions are the same as in , apart from changing the prefix from /tools to /usr. The BLFS book discusses a slightly different approach to installing Tcl, see . You may also want to move the packages and patches stored in /sources to a more usual location, such as /usr/src/packages, and remove the directory -- or simply delete the whole directory if you've burned its contents on a CD).