4. 最后的准备工作
4.1. 关于环境变量 $LFS
环境变量 LFS 的使用贯穿全书。保持 LFS 总是已定义是很重要的,它应该被设置为 LFS 分区的挂载点。用下面的命令检查它的设置是否恰当:
echo $LFS
请确认输出的是 LFS 分区挂载点的路径,如果您遵循我们的例子,则应该是 /mnt/lfs 。如果输出结果不正确,用下述命令设置它:
export LFS=/mnt/lfs
设置这个环境变量的好处是您以后可以按照原样输入形如 mkdir $LFS/tools 的命令,当 shell 处理这个命令行的时候,会自动用"/mnt/lfs"(或者该环境变量所设定的值)替换"$LFS" 。
当您离开然后重新进入当前工作环境的时候(像 su 到 root 或者其他用户),不要忘记检查 $LFS 是否设置正确。
4.2. 创建 $LFS/tools 目录
第五章中编译的所有程序都将安装到 $LFS/tools 目录下,以便与第六章中编译的程序隔离开来。这里编译的程序只是临时使用的工具,不是最终 LFS 系统的组成部分。把这些程序放到一个单独的目录下,在使用过之后简单的删除掉就可以了。这样做也可以防止这些程序与宿主系统中相同的程序混淆(第五章中容易出现这样的事情)。
以 root 用户运行下面的命令来创建所需的目录:
mkdir -v $LFS/tools
下一步是在宿主系统上创建一个 /tools 符号链接,指向 LFS 分区上新创建的目录,这个命令同样要作为 root 用户运行:
ln -sv $LFS/tools /
注意
上述命令是正确的,ln 命令的语法有了一点变化。如果您认为发现了一个错误,在报告它之前,先用 info coreutils ln 和 ln(1) 命令查看手册页。
所创建的符号链接使得将要编译的工具链总是位于 /tools 目录下,这意味着编译器、汇编器和连接器在本章(这时我们还在使用宿主系统的一些工具)和下一章(这时我们"chrooted"到了 LFS 分区)都可以使用。
4.3. 添加 LFS 用户
以 root 用户登录的时候,犯一个错误就足以损坏甚至摧毁系统,因此,本章我们推荐使用一个无特权的用户来编译和安装软件包。您可以使用您自己的用户名,不过为了建立一个干净的工作环境,建议您新建一个名为 lfs 的组,并在其中添加一个名为 lfs 的用户,我们将在安装过程中使用这个用户。以 root 用户运行下列命令来添加新用户:
groupadd lfs
useradd -s /bin/bash -g lfs -m -k /dev/null lfs
命令行选项的含义:
-s /bin/bash
指定 bash 作为 lfs 用户的默认 shell
-g lfs
将 lfs 用户添加到 lfs 组
-m
为 lfs 用户创建 home 目录
-k /dev/null
这个参数通过修改输入位置为特殊的空设备来防止从框架目录(默认为 /etc/skel)拷贝文件
lfs
这是所创建的组和用户的实际名字
为了可以使用 lfs 用户登录(与从 root 用户切换到 lfs 用户不同,这种切换不需要 lfs 用户有一个密码),必须先为 lfs 用户设置一个密码:
passwd lfs
通过把 lfs 用户设置为 $LFS/tools 目录的所有者来授予 lfs 用户对该目录的完全访问权限:
chown -v lfs $LFS/tools
如果您依照建议创建了独立的工作目录,请将该目录的所有权赋予 lfs 用户:
chown -v lfs $LFS/sources
接下来,以 lfs 用户登录。您可以通过一个虚拟控制台,或者通过显示管理器,或者用下面的切换用户命令:
su - lfs
"-" 参数指示 su 开启一个登陆Shell(login shell)而不是非登陆Shell(non-login shell),这两种 shell 的不同之处请参考 bash(1) 和 info bash 。
4.4. 设置工作环境
通过给 bash shell 创建两个新的启动文件来设置一个良好的工作环境。用 lfs 用户登录,输入下面的命令来创建一个新的 .bash_profile 文件:
cat > ~/.bash_profile << "EOF"
exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash
EOF
作为 lfs 用户登录的时候,初始 shell 通常是一个登陆shell(login shell),它会首先读取宿主系统的 /etc/profile 文件(可能包含一些设置和环境变量),然后继续读取 .bash_profile 文件来完成登录初始化。.bash_profile 文件中的 exec env -i.../bin/bash 命令用完全空的环境来取代当前的环境(除了继承 HOME, TERM, PS1 变量外)。这样能保证我们的编译环境不会被宿主系统中不必要的或者有潜在危险的环境变量所影响,从而确保获得一个干净的工作环境。
另一个新的 shell 实例是非登陆shell(non-login shell),它不读取 /etc/profile 或 .bash_profile 文件,而是读取 .bashrc 文件。现在创建 .bashrc 文件:
cat > ~/.bashrc << "EOF"
set +h
umask 022
LFS=/mnt/lfs
LC_ALL=POSIX
PATH=/tools/bin:/bin:/usr/bin
export LFS LC_ALL PATH
EOF
set +h 命令关闭 bash 的 hash 功能,hash 通常是一个有用的特性:bash 使用一个 hash 表来记录可执行文件的完整路径,以避免为了找到同一个可执行文件而反复搜索 PATH 里的目录。然而,新工具装好之后就要立即使用,通过关闭 hash 功能,当要运行程序的时候,shell 将总是搜索 PATH 里的目录,这样新工具一编译好,shell 就可以在 $LFS/tools 目录里找到,而不是执行所记忆的其它地方的旧版本程序。
将用户文件创建掩码(umask)设为 022 ,使得新创建的文件和目录只有所有者可写,其他用户只能读取和运行(open(2) 系统调用的默认模式是新文件权限 644,新目录权限 755)。
LFS 环境变量应该设为所选择的挂载点。
LC_ALL 环境变量控制着某些程序的本地化,使其显示的信息遵循指定国家的惯例。如果宿主系统使用的 Glibc 版本低于 2.2.4,将 LC_ALL 环境变量设置为"POSIX"或"C"以外的值(在本章中)可能会在您退出虚根环境后再想返回的时候出现问题。请把 LC_ALL 设置为"POSIX"或"C"(这两者是等价的)以确保在虚根环境中的所有东西都像预期的那样正常工作。
通过把 /tools/bin 放在 PATH 的最前面,第五章中所有的程序安装好后,就可以立即被 shell 运行。将这一点和关闭 hash 功能结合起来,预防了宿主系统的旧程序在不该运行的时候却被运行了的风险。
最后,为了完全准备好编译临时工具的工作环境,导入刚刚创建的 profile 文件:
source ~/.bash_profile
4.5. 关于 SBU
许多人都想知道编译和安装一个软件包预计需要多长时间。因为 Linux From Scratch 可以在多种不同的系统上创建,准确估计所需的时间是不可能的。最快的系统上编译安装最大的软件包(Glibc)大约需要 20 分钟,但在很慢的系统上可能耗费长达三天时间。我们不提供准确时间,代之以标准编译时间单位(SBU)来度量。
SBU 度量具体说明如下,本书中第一个编译的软件包是第五章中静态编译的 Binutils 。编译这个软件包所花费的时间就作为标准编译时间单位(SBU)。所有其它软件的编译时间都用这个时间来衡量。
例如,对于一个编译时间为 4.5 SBU 的软件包,这意味着如果一个系统静态编译安装 Binutils 需要花费 10 分钟,那么编译这个软件包将大约需要 45 分钟。幸运的是,大多数软件包编译安装所需的时间都比 Binutils 所需的时间要短。
SBU并不十分精确,因为它依赖于许多因素,包括宿主系统 GCC 的版本。另外,在基于对称多处理器(SMP)的机器上,SBU 更加不准确。我们提供 SBU,仅仅是给出安装一个软件包所需时间的大概估计,在某些情况下实际花费的时间与预估计的时间之间可能有数十分钟的差异。
要查看在一些特定机器上的实际编译安装时间,我们推荐您查看 LinuxFromScratch SBU 的主页 http://www.linuxfromscratch.org/~bdubbs/ 。
4.6. 关于软件包测试套件
大多数软件包提供了测试程序集。编译完一个软件包之后立即运行一下它提供的测试程序是个好主意,因为测试程序将进行一次"健全检查"来确认所有的代码是否都正确编译了。通过了测试程序集的一系列检查,通常意味着软件包在按照开发者的预期工作,但是这并不保证这个软件包就完全没有 bug 了。
某些软件包的测试程序是极为重要的,例如核心工具链软件包 GCC 、Binutils 、Glibc 的测试程序,这是因为这些软件包在一个良好工作的系统里的处于核心角色。GCC 和 Glibc 的测试程序需要运行很长时间,尤其在速度慢的硬件上,但我们仍然强烈建议您运行这些测试程序。
注意
经验显示,运行第五章中的测试程序时会有点小问题。不可避免的是,宿主系统总是对这一章的测试程序施加某些影响,常常导致无法解释的测试失败。因为第五章中编译的工具是临时的,而且在最后会被丢弃,我们不推荐中等水平的读者运行第五章中的测试程序,这些测试程序的指令是为开发和测试人员准备的,它们不是必需的。
Binutils 和 GCC 的测试程序一个常见的问题就是在伪终端(PTY)外运行,这样可能会出现大量的测试失败。可能的原因有几个,但最可能的原因是宿主系统没有正确的设置 devpts 文件系统,这个问题在第五章中有详细的讨论。
某些软件包测试程序可能会给出错误的失败信息,请参考 LFS Wiki http://www.linuxfromscratch.org/lfs/build-logs/6.2/ 以确认您所遇到的测试失败是否是预期会出现的。这个站点的内容对于本书所有的测试都是正确的。