TITLE: Keeping chapter 5 and chapter 6 separate (v1.1) LFS VERSION: 3.1 (may need small changes for later versions) AUTHOR: Matthias S. Benkmann SYNOPSIS: The way LFS is built now, the static programs from chapter 5 are overwritten in chapter 6. So when you begin building your chapter 6 system, your $LFS filesystem is populated by hundreds of files you don't want to keep. During the chapter 6 process there is a confusing mix of chapter 5 and chapter 6 files and in the end you can't be sure whether your LFS system is really "clean" or retains some "dirt" from the host distro. When I built my first LFS, my host system was very different from the LFS target (libc5 vs libc6). I ended up with a whole /usr/lib/gcc-lib/ directory tree remaining and several unreplaced header files. I've had an uneasy feeling regarding the current building method ever since. But this is over now. With a few changes to the book, you can build chapter 5 and chapter 6 completely separate. HINT: ############################################################################## Changelog ############################################################################## 2002-01-30 -added Changelog -create awk symlink in chapter 5 because gcc needs it -submitted v0.8 2002-02-06 -added findutils patch instruction -submitted v0.9 2002-03-16 -added remark that "mv chroot ../sbin" needs to be skipped when installing sh-utils in chapter 5 -submitted 1.0 2002-02-19 -changed LFS VERSION header so that I don't have to keep things up-to-date ;-) -submitted v1.1 ############################################################################## Introduction ############################################################################## The idea behind this hint is simple: Chapter 5 gets built in $LFS/static rather than $LFS. By setting the PATH correctly in chroot, the binaries are still accessible, although they don't "pollute" the main directory tree. The advantages of this approach are the following: - no stale files from chapter 5 remain in the LFS system - you can use the same chapter 5 static tree to build multiple LFS systems - if you forgot a package from chapter 5 you can safely install it to the static tree later, without the risk of overwriting chapter 6 files - you can restart chapter 6 after something went wrong without having to redo chapter 5 - you can build the chapter 5 system on a different partition or mount it from a CD-ROM, etc. to use less disk space on the target LFS partition - it just feels better ############################################################################## How to do it ############################################################################## Chapter 4: 1. You _DON'T_ create the Unix directory tree in chapter 4. After mounting your new partition you only do the following mkdir -p $LFS/static/usr/src Chapter 5: 1. There is no need to install chapter 5 as root. Just make $LFS/static (and subdirectories) writeable by an ordinary user account and build with that account. It will prevent you from screwing up your host system. 2. Keep and unpack all tarballs in (subdirectories of) $LFS/static/usr/src and install from there. 3. Install the packages according to the book, but wherever the book uses $LFS, use $LFS/static instead. To make it easier you could instead do `export LFS=$LFS/static'. But be careful with that as it's easy to get confused that way and the rest of this hint will assume you do *not* put "/static" into $LFS. 4. When building GCC, pass `--prefix=/static/usr' to ./configure instead of `--prefix=/usr' Do NOT create the cpp symlinks. It is not necessary. The cc symlink is created in $LFS/static/usr/bin. 5. Skip the installation of the Linux headers. We'll install them later. 6. mawk wants to install a manpage to $LFS/static/usr/share/man/man1 which it doesn't create. You have to create this directory manually before installing mawk. After installing mawk use the command ln -s mawk $LFS/static/usr/bin/awk to create the alias awk for mawk which is needed by GCC in chapter 6. 7. When you install sh-utils, skip the command "mv chroot ../sbin". If you install sh-utils as a non-root user you will get a warning message about lack of privileges and the su program will not be installed. Ignore this message. A static su is not needed for building LFS. In chapter 6 we do the sh-utils installation as root and the dynamic su will be properly installed (just to be overwritten by the one from net-tools later). 8. Unpack the util-linux package, enter the util-linux-* directory and compile a static version of the mount utility according to the following instructions. The cp command assumes that /static is not part of your $LFS variable. If it is, drop the /static from the cp command. ./configure && cp defines.h defines.h.old && sed /ENABLE_NLS/d defines.h.old >defines.h && make -C lib && make -C mount LDFLAGS=-static && cp mount/{mount,umount} $LFS/static/bin/ 9. Build a static version of findutils using the following commands (again I assume /static is not part of $LFS): patch -Np1 -i ../findutils-4.1.patch && ./configure --prefix=$LFS/static/usr --disable-nls && make LDFLAGS=-static CPPFLAGS=-Dre_max_failures=re_max_f2 && make libexecdir=$LFS/static/usr/bin install Chapter 5 1/2: You have now finished the instructions from the last section in chapter 5 titled "Installing " and have compiled the additional static mount and umount binaries and findutils. The next section in the book would be "Creating passwd and group files", which I refer to as chapter 5 1/2. Here is the clean break that this hint gives you. If you keep a copy of your $LFS/static tree you never need to go further back than chapter 5 1/2 when building an LFS system. You can just start reading here at this point in the hint. The following commands do not assume write access to $LFS/static, so you can burn it on a CD and mount it from there. This will help you save a lot space. Unlike the book which creates part of the LFS system from outside the LFS system, if you follow this hint you create everything from inside the LFS system. To achieve this we enter the chroot environment right now, BEFORE creating the Unix directory structure, passwd or group files,... This gives us a completely naked system. Everything from the outside world is contained inside the /static directory tree which can be wiped later. Everything we will keep on our LFS system is created from inside the new LFS system. A little side note: You can avoid chroot altogether and just boot a kernel with : init=/static/bin/bash root= For this to work you will need a directory /dev on that contains one or more of the following devices /dev/tty1, /dev/console, /dev/tty [IF SOMEONE KNOWS EXACTLY WHICH IS/ARE NEEDED, MAIL ME] 1. Enter the chroot environment using the following command (as root): cd $LFS && chroot $LFS /static/usr/bin/env -i HOME=/root TERM=$TERM \ PATH=/sbin:/bin:/usr/sbin:/usr/bin:/static/bin:/static/usr/bin \ SHELL=/static/bin/bash PS1='\u:\w\$ ' /static/bin/bash --login If you get the error message "--login: No such file or directory" you forgot the space between the PS1='\u:\w\$ ' and /static/bin/bash. It's easy to overlook because of the space before the closing quote. Note that the bash prompt will contain "I have no name!" This is normal because Glibc hasn't been installed yet. "And / was without form, and void; and darkness was upon the face of the prompt. And the Spirit of Root moved upon the face of chroot." 2. "And Root said, let there be a directory structure in the midst of chroot." Before we start creating directories, we need to check the base system's umask setting. To do this, we run umask. The result should be 022. If it isn't, then run the following command to ensure that the directories will be created with the correct permissions: umask 022 We would advise you to make sure that the umask is set to 022 throughout your LFS installation. Let's now create the directory tree on the LFS partition based on the FHS standard, which can be found at http://www.pathname.com/fhs/. Issuing the following commands will create a default directory layout: mkdir -p bin boot dev/pts etc/opt home lib mnt proc root sbin tmp var opt for dirname in /usr /usr/local do mkdir $dirname cd $dirname mkdir bin etc include lib sbin share src var ln -s share/man man ln -s share/doc doc ln -s share/info info cd $dirname/share mkdir dict doc info locale man nls misc terminfo zoneinfo cd $dirname/share/man mkdir man{1,2,3,4,5,6,7,8} done cd /var mkdir -p lock log mail run spool tmp opt cache lib/misc local cd /opt mkdir bin doc include info lib man cd /usr ln -s ../var/tmp tmp Normally, directories are created with permission mode 755, which isn't desired for all directories. The first change is a mode 0750 for the /root directory. This is to make sure that not just everybody can enter the /root directory (the same a user would do with /home/username directories). The second change is a mode 1777 for the tmp directories. This way, any user can write data to the /tmp or /var/tmp directory but cannot remove another user's files (the latter is caused by the so-called "sticky bit" - bit 1 of the 1777 bit mask). cd / && chmod 0750 root && chmod 1777 tmp var/tmp 3. "And Root said, Let the processes of the system be gathered together unto one place, and let the proc filesystem appear: and it was so." mount -n -t proc proc /proc If you ever leave the chroot environment for any reason (when rebooting for example) please remember to re-enter chroot and to remount /proc again before continuing with the book. 4. Now we create /etc/passwd and /etc/group echo "root:x:0:0:root:/root:/bin/bash" > /etc/passwd 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 5. Right now we have our tarballs in /static/usr/src but we don't want to build inside that directory (if it's mounted from CDROM we couldn't even if we wanted to). We could copy the tarballs to /usr/src/ but that would be a waste of diskspace, so we use symlinks. We do need to have real subdirectories in /usr/src, though, because symlinks would cause us to write to the /static directory. So what we do is to copy the directory structure of /static/usr/src but symlink the files contained therein: cd /usr/src && for d in $(find /static/usr/src -type d -not -path "/static/usr/src") ;\ do mkdir -p ${d#/static/usr/src/} ; done Be careful with the above command. Do NOT forget the "/" before "}" in "${d#/static/usr/src/}". It is significant!! Now we have the directories. Let's create the symlinks: cd /static/usr && find src -not -type d -exec ln -s /static/usr/{} /usr/{} \; 6. There are some additional symlinks we need to create: ln -s /static/bin/bash /bin/bash && ln -s /static/bin/sh /bin/sh && ln -s /static/usr/bin/cpp /lib/cpp && ln -s /static/bin/pwd /bin/pwd Explanation: cpp is needed for glibc compilation, pwd for linux's `make config' Chapter 6: 0. First a word of warning: Resist the urge to build several packages in parallel, even if it seems to work. Some packages would hardwire paths to programs in the /static tree into their executables or data files. This does not always show in the build output, the compile will be successful. You won't notice until a program fails with a "/static/...: no such file or directory" or similar error message. 1. You may create a $LFS/root/.bash_profile as the book instructs but it is not necessary. The chroot command given above already sets the prompt and the PATH correctly. If you do want to create a .bash_profile, do not forget to make the following change: Instead of PATH=/bin:/usr/bin:/sbin:/usr/sbin use PATH=/bin:/usr/bin:/sbin:/usr/sbin:/static/bin:/static/usr/bin i.e. add "/static/bin:/static/usr/bin" at the _end_ of PATH. 2. Before we install glibc, we need to install the Linux kernel headers. If you exited chroot for some reason, enter it again (we're doing everything from inside chroot, remember!) and don't forget to remount /proc if it was unmounted. Now install the Linux kernel headers with the following commands (from inside a freshly untarred /usr/src/linux): yes "" | make config && make include/linux/version.h && cd include && cp -a linux /usr/include/ && chown -R 0.0 /usr/include/linux && mkdir /usr/include/asm && cp -a asm/* /usr/include/asm && chown -R 0.0 /usr/include/asm 3. Now install the chapter 6 packages in the following order (see Appendix A for details about the changes compared to the standard book): glibc (makedev) gcc man-pages findutils mawk ncurses vim bison less groff textutils sed flex binutils fileutils sh-utils gettext net-tools perl m4 texinfo autoconf automake bash file libtool bin86 bzip2 ed kbd diffutils e2fsprogs grep gzip man lilo make modutils netkit-base patch procinfo procps psmisc shadow sysklogd sysvinit tar util-linux The building instructions for some packages have to be changed slightly: - When installing man, replace the line ./configure -default && with the line (Note that the PATH=... is NOT a separate command!) PATH="$PATH:/usr/bin:/bin" ./configure -default && Explanation: The paths to some programs get written into man's files. Unfortunately the stupid configure script picks the last location in PATH rather than the first where a program is found. By appending /usr/bin:/bin to PATH for the ./configure command we make sure that man doesn't use the /static versions of our programs. - After installing bash, do the following: cd /bin && ln -sf bash sh Explanation: Replaces the sh symlink that points to the static shell with the a symlink that points to the new bash. Note: You don't need to do `exec /bin/bash' after installing bash (it doesn't hurt, though), because we didn't overwrite the running shell's binary. - After installing GCC, do the following: cd /lib && ln -sf ../usr/bin/cpp && cd /usr/lib && ln -sf ../bin/cpp && cd /usr/bin && ln -sf gcc cc Explanation: These are the same links as created in chapter 5, but in chapter 5 we created them in /static. - After installing Fileutils, do the following: cd /usr/bin && ln -sf ../../bin/install Explanation: This is the same link as created in chapter 5, but in chapter 5 we created it in /static. - In the installation of bzip2, ignore the line rm /usr/lib/libbz2.a && because the file has been created in /static/usr/lib during chapter 5, and not in /usr/lib. Configuring essential software We are now completely back on track with the book (you may or may not want to remove the /static tree now). Continue with the standard instructions from the book at "Configuring essential software". Resolving the /static symlinks You may want to replace the symlinks in /usr/src that point into the /static tree with the real files after installing the system. The following script will achieve this: #!/bin/sh find /usr/src -type l -printf "%l %p %u %g\n" | { while [ true ]; do read || break case "$REPLY" in /static/usr/src/*) set -- $REPLY if [ -L $2 ]; then rm $2 || exit 1 cp -a $1 $2 || exit 1 chown $3.$4 $2 || exit 1 fi ;; esac done } FINAL NOTE: If you take the time to grep through all your files for "/static" (Be careful to exclude /proc from your scan as reading some files in /proc can cause disk corruption) you will notice that "/static/*" paths are still found in many libraries, such as libc.a. Don't panic. Your system will not break if you delete the /static tree. This is only debugging information. If you do strip --strip-debug /lib/* /usr/lib/* , these paths will disappear and there will remain no trace of the /static directory. Appendix A The package ordering changes (compared to LFS-3.0) in detail: Installing GCC as soon as possible is just a good idea. It is not related to this hint. You must install textutils before man, before perl and before bash, because man hardwires cat's location into its executable and because perl and bash have the path to cat hardwired as /bin/cat or /usr/bin/cat in some configure scripts so that they don't find the /static version. Note that textutils will output a warning if it doesn't find Perl. As the warning says, this is only relevant if you change the textutils sources. You must install sed before Perl because Perl hardwires its location into the perl executable. You must install binutils before Perl because Perl writes the path to ar into Config.pm. Install fileutils before Perl because the path to ln gets written to Config.pm . Note that fileutils will output another one of those warning messages that are only relevant if you change the sources (or want to use `make check'). Perl writes the location of hostname to Config.pm, so net-tools should be installed before Perl. Because net-tools has /usr/bin/env hardwired into its configure script, sh-utils must be installed before net-tools. This means that sh-utils is also installed before Perl and will output one of those annoying but harmless warnings. I am aware of the fact that you could install sh-utils before Perl and install net-tools later, because sh-utils has hostname, too. However, it is a mistake that the book does not have a sed command to suppress sh-utils hostname and instead relies on the overwriting of hostname by net-tools later. If the book had this sed, fewer people would encounter the "Why is my machine suddenly called `-f'" problem. People who write install scripts that are supposed to work for reinstalling a package later, MUST suppress sh-utils' hostname and consequently have to install net-tools before Perl. You must install fileutils before kbd because the latter has /usr/bin/install hardwired so that it doesn't find the /static version. sh-utils must be installed before net-tools, because the latter has /usr/bin/env hardwired. The LFS package order already has sh-utils before net-tools but impatient people might try to start building net-tools in a different console before sh-utils has finished. Don't do that. gettext needs to be installed before net-tools if you want i18n. Install binutils before libtool because libtool hardwires the paths to ld and nm into its executable. Install sed before e2fsprogs because the latter hardwires sed's location into mk_cmds. You must install gzip, bzip2, textutils and diffutils before man because man writes their paths into several of its files. Flex is installed before binutils to avoid a warning. As this is another warning that is only relevant if you changed the binutils sources, this is just a cosmetic issue.