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.
Entering the chroot environment
It is time to enter the chroot environment in order to begin installing
the packages we need. Before you can chroot, however, you need to become
root, since only root
can execute the chroot command.
Just like earlier, ensure the LFS environment variable is set up properly
by running echo $LFS and ensuring it shows the path to
your LFS partition's mount point, which is
/mnt/lfs if you followed our
example.
Become root and run the following command
to enter the chroot environment:
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 --login +h
The -i option given 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 TERM=$TERM construct will set the TERM variable inside chroot
to the same value as outside chroot; this variable is needed for programs
like vim and less to operate
properly. If you need other variables present, such as CFLAGS or CXXFLAGS,
this is a good place to set them again.
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 again enter chroot and mount the proc and devpts
filesystems (discussed later) 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}
for dirname in /usr /usr/local
do
mkdir $dirname/{bin,etc,include,lib,sbin,share,src}
ln -s share/{man,doc,info} $dirname
mkdir $dirname/share/{doc,info,locale,man}
mkdir $dirname/share/{misc,terminfo,zoneinfo}
mkdir $dirname/share/man/man{1,2,3,4,5,6,7,8}
done
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.
&c6-mountproc;
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 and group 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 the groups
that the MAKEDEV script in the next section uses. Besides the group "root", the
LSB () recommends only a group "bin",
with a GID of 1, be present. All other group names and GIDs can be chosen
freely by the user, as well-written packages don't depend on GID numbers but
use the group's name.
Lastly, we re-login to the chroot environment. User name and group name
resolution will start working immediately after the
/etc/passwd and /etc/group files are
created, because we installed a full Glibc in Chapter 5. This will get rid of
the I have no name!
prompt.
exec /tools/bin/bash --login +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.
&c6-makedev;
&c6-kernel;
&c6-manpages;
&c6-glibc;
Re-adjusting the toolchain
Now that the new C libraries have been installed, it's time to re-adjust
our toolchain. We'll adjust it so that it will link any newly compiled program
against the new C libraries. Basically, this is the reverse of what we did
in the "locking in" stage in the beginning of the previous chapter.
The first thing to do is to 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 Chapter 5 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 Glibc libraries in
/tools rather than
/usr. 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 can now remove the Binutils source and build directories.
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 check the specs file to ensure the intended
changes were 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
gcc 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:
[Requesting program interpreter: /lib/ld-linux.so.2]
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. Note especially that /lib now appears
as the prefix of our dynamic linker. Of course, if you are working on a platform
where the name of the dynamic linker is something other than
ld-linux.so.2, then the output will be slightly
different.
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-shadowpwd;
&c6-sysklogd;
&c6-sysvinit;
&c6-tar;
&c6-utillinux;
&c6-gcc-2953;
Revised chroot command
From now on when you exit the chroot environment and wish to re-enter
it, you should run 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 --login
The reason being there is no longer any need to use programs from the
/tools directory. However, we don't
want to remove the /tools directory
just yet. There is still some use for it towards the end of the book.
&c6-bootscripts;
&c6-aboutdebug;