有关此软件包的详细信息,请参见 第 6.13.2 节,“Binutils 的内容。”
版权所有 © 1999–2005 Gerard Beekmans
版权所有 (c) 1999–2005, Gerard Beekmans
保留所有权利。
在满足以下条件的前提下,允许以源程序和二进制形式再发布和使用,无论是否经过修改
任何形式的再发布都必须保留上述版权声明、本条件列表和以下免责声明
未经事先明确的书面许可,不得使用 “Linux From Scratch” 的名称或其贡献者的名称来认可或推广源自本材料的产品
任何源自 Linux From Scratch 的材料都必须包含对 “Linux From Scratch” 项目的引用
本软件由版权所有者和贡献者按 “原样” 提供,不提供任何明示或暗示的保证,包括但不限于对适销性和特定用途适用性的暗示保证。在任何情况下,版权所有者或贡献者均不对任何直接、间接、附带、特殊、惩戒性或后果性损害(包括但不限于采购替代商品或服务;使用、数据或利润的损失;或业务中断)承担责任,无论其原因如何,无论基于合同、严格责任还是侵权(包括疏忽或其他)的责任理论,即使已被告知此类损害的可能性。
我在 Linux 上的冒险始于 1998 年,当时我下载并安装了我的第一个发行版。在使用了一段时间后,我发现了一些我非常希望改进的问题。例如,我不喜欢启动脚本的安排或程序默认配置的方式。我尝试了许多替代发行版来解决这些问题,但每个发行版都有其优点和缺点。最后,我意识到如果我想要从我的 Linux 系统中获得完全的满足感,我必须从头开始构建自己的系统。
这意味着什么?我决心不使用任何类型的预编译包,也不使用任何安装基本实用程序的 CD-ROM 或启动盘。我将使用我当前的 Linux 系统来开发我自己的自定义系统。这个 “完美” 的 Linux 系统将具有各种系统的优点,而没有其相关的缺点。一开始,这个想法相当令人生畏,但我仍然致力于这样一个理念:可以构建一个符合我的需求和愿望的系统,而不是仅仅符合一个不适合我需求的标准。
在解决了诸如循环依赖和编译时错误等问题后,我创建了一个自定义构建的 Linux 系统,该系统已完全运行并且适合个人需求。此过程还允许我创建紧凑且精简的 Linux 系统,这些系统比传统操作系统更快并且占用更少的空间。我将此系统称为 Linux From Scratch 系统,或简称为 LFS 系统。
当我与 Linux 社区的其他成员分享我的目标和经验时,很明显,人们对我的 Linux 冒险中所提出的想法持续感兴趣。这种定制构建的 LFS 系统不仅可以满足用户规范和要求,还可以为程序员和系统管理员提供理想的学习机会,以提高他们的 Linux 技能。出于这种广泛的兴趣,Linux From Scratch 项目诞生了。
这本 Linux From Scratch 书籍为读者提供了设计和构建自定义 Linux 系统的背景知识和指导。本书重点介绍了 Linux From Scratch 项目以及使用该系统的好处。用户可以决定其系统的所有方面,包括目录布局、脚本设置和安全性。最终的系统将完全从源代码编译,用户将能够指定程序安装的位置、原因和方式。本书使读者可以根据自己的需要完全自定义 Linux 系统,并允许用户更好地控制自己的系统。
我希望您能在自己的 LFS 系统上工作愉快,并享受拥有一个真正 属于您自己的 系统的众多好处。
--
Gerard Beekmans
gerard AT linuxfromscratch D0T org
人们想阅读本书的原因有很多。主要原因是希望从源代码安装 Linux 系统。许多人提出的一个问题是,“既然可以直接下载和安装现有的 Linux 系统,为什么还要费力地从头开始手动构建一个 Linux 系统呢?” 这是一个好问题,也是本书本节的推动力。
LFS 存在的一个重要原因是帮助人们了解 Linux 系统如何从内部工作。构建 LFS 系统有助于演示 Linux 的工作原理,以及事物如何协同工作和相互依赖。这种学习体验提供的最好的事情之一是能够根据自己的口味和需求自定义 Linux。
LFS 的一个关键好处是它允许用户更好地控制系统,而无需依赖他人的 Linux 实现。使用 LFS,您 处于驾驶员的位置,并决定系统的各个方面,例如目录布局和引导脚本设置。您还可以决定程序安装的位置、原因和方式。
LFS 的另一个好处是能够创建一个非常紧凑的 Linux 系统。在安装常规发行版时,人们通常被迫包含几个可能永远不会使用的程序。这些程序浪费磁盘空间,或者更糟的是,浪费 CPU 周期。构建一个小于 100 兆字节 (MB) 的 LFS 系统并不困难,这比大多数现有安装要小得多。这听起来仍然占用很多空间吗?我们中的一些人一直在努力创建一个非常小的嵌入式 LFS 系统。我们成功构建了一个专门运行 Apache Web 服务器的系统,大约使用了 8MB 的磁盘空间。进一步剥离可以将这个大小减少到 5 MB 或更少。用常规发行版试试看!这只是设计您自己的 Linux 实现的众多好处之一。
我们可以将 Linux 发行版比作在快餐店购买的汉堡包——你不知道你吃的东西可能含有什么。另一方面,LFS 不会给你一个汉堡包。相反,LFS 提供了制作所需汉堡包的确切食谱。这允许用户查看食谱,省略不需要的成分,并添加自己的成分以增强汉堡的味道。当您对食谱感到满意时,就可以开始准备它了。它可以按照精确的规格制作——烤、烘烤、油炸或烧烤。
我们可以使用的另一个类比是将 LFS 与已完工的房屋进行比较。LFS 提供了房屋的骨架计划,但由您来建造它。LFS 保持了在整个过程中调整计划的自由,根据用户的需求和偏好进行自定义。
自定义构建的 Linux 系统的另一个优点是安全性。通过从源代码编译整个系统,您可以审核所有内容并应用所有所需的安全补丁。不再需要等待其他人编译修复安全漏洞的二进制包。除非您检查补丁并自己实施,否则您无法保证新的二进制包已正确构建并充分修复了问题。
Linux From Scratch 的目标是构建一个完整且可用的基础级系统。不希望从头开始构建自己的 Linux 系统的读者可能无法从本书的信息中受益。如果您只想知道计算机启动时发生了什么,我们推荐 “从开机到 Bash 提示符” HOWTO,位于 http://axiom.anu.edu.au/~okeefe/p2b/ 或 The Linux Documentation Project (TLDP) 的网站 http://www.tldp.org/HOWTO/From-PowerUp-To-Bash-Prompt-HOWTO.html。该 HOWTO 构建的系统与本书类似,但它严格专注于创建一个能够启动到 BASH 提示符的系统。考虑一下您的目标。如果您希望在学习的过程中构建一个 Linux 系统,那么本书是您的最佳选择。
构建您自己的 LFS 系统的理由太多了,无法在此一一列出。本节只是冰山一角。随着您继续您的 LFS 体验,您会发现信息和知识真正带来的力量。
构建 LFS 系统并非易事。它需要具备一定的 Unix 系统管理知识,以便解决问题并正确执行列出的命令。特别是,作为最低要求,读者应该已经能够使用命令行(shell)复制或移动文件和目录,列出目录和文件内容,以及更改当前目录。还要求读者具备使用和安装 Linux 软件的合理知识。
由于 LFS 书籍假定 至少 具备这种基本技能,因此各种 LFS 支持论坛不太可能为您提供太多帮助;您会发现您关于此类基本知识的问题可能不会得到解答,或者您只会简单地被推荐到 LFS 必备预读清单。
在构建 LFS 系统之前,我们建议阅读以下 HOWTO:
Software-Building-HOWTO http://www.tldp.org/HOWTO/Software-Building-HOWTO.html
这是一份关于在 Linux 下构建和安装 “通用” Unix 软件发行版的综合指南。
The Linux Users' Guide http://www.linuxhq.com/guides/LUG/guide.html
本指南涵盖了各种 Linux 软件的使用。
The Essential Pre-Reading Hint http://www.linuxfromscratch.org/hints/downloads/files/essential_prereading.txt
这是一个专门为 Linux 新手编写的 LFS 提示。它包含指向关于各种主题的优秀信息来源的链接列表。任何试图安装 LFS 的人都应该理解本提示中的许多主题。
主机必须运行至少 2.6.2 内核,并使用 GCC-3.0 或更高版本编译。存在此要求的两个主要原因。首先,如果主机的内核未使用 GCC-3.0 或更高版本编译,则本机 POSIX 线程库 (NPTL) 测试套件将发生段错误。其次,使用 Udev 需要 2.6.2 或更高版本的内核。Udev 通过从sysfs文件系统读取来动态创建设备。但是,大多数内核驱动程序最近才实现对此文件系统的支持。我们必须确保所有关键系统设备都被正确创建。
为了确定主机内核是否满足上述要求,请运行以下命令
cat /proc/version
这将产生类似于以下的输出
Linux version 2.6.2 (user@host) (gcc version 3.4.0) #1 Tue Apr 20 21:22:18 GMT 2004
如果上述命令的结果未说明主机内核是 2.6.2(或更高版本),或者未使用 GCC-3.0(或更高版本)编译器编译,则需要安装一个。有两种方法可以解决这个问题。首先,查看您的 Linux 供应商是否提供 2.6.2(或更高版本)内核包。如果是这样,您可能希望安装它。如果您的供应商不提供 2.6.2(或更高版本)内核包,或者您更愿意不安装它,那么您可以自己编译一个 2.6 内核。编译内核和配置引导加载程序(假设主机使用 GRUB)的说明位于 第 8 章中。第二个选项也可以被视为衡量您当前 Linux 技能的标准。如果第二个要求过于苛刻,那么 LFS 书籍此时可能对您没有太大用处。
为了使内容更易于理解,本书中使用了一些排版约定。本节包含 Linux From Scratch 中使用的排版格式的一些示例。
./configure --prefix=/usr
除非周围的文本另有说明,否则此形式的文本旨在完全按照所见进行键入。它也用于解释部分中,以标识正在引用的命令。
install-info: unknown option '--dir-file=/mnt/lfs/usr/info/dir'
此形式的文本(固定宽度文本)显示屏幕输出,可能是由于执行命令的结果。此格式也用于显示文件名,例如/etc/ld.so.conf.
强调
本书中使用了这种形式的文本,用于多种目的。其主要目的是强调重要点或项目。
http://www.linuxfromscratch.org/
此格式用于 LFS 社区内部和外部页面的超链接。它包括 HOWTO、下载位置和网站。
cat > $LFS/etc/group << "EOF" root:x:0: bin:x:1: ...... EOF
创建配置文件时使用此格式。第一个命令告诉系统创建文件$LFS/etc/group从以下行中键入的内容,直到遇到文件结束 (EOF) 序列。因此,通常将整个部分按原样键入。
[REPLACED TEXT]
此格式用于封装不按原样键入或复制粘贴的文本。
passwd(5)
此格式用于引用特定的手册页(以下简称 “man” 页)。括号内的数字表示 man 中的特定部分。例如,passwd 有两个 man 页面。根据 LFS 安装说明,这两个 man 页面将位于/usr/share/man/man1/passwd.1和/usr/share/man/man5/passwd.5。两个 man 页面都包含不同的信息。当书中使用passwd(5)它专门指/usr/share/man/man5/passwd.5。man passwd 将打印它找到的第一个与 “passwd” 匹配的 man 页面,这将是/usr/share/man/man1/passwd.1。对于此示例,您需要运行 man 5 passwd 才能阅读被引用的特定页面。应该注意的是,大多数 man 页面在不同部分中没有重复的页面名称。因此,通常 man [程序名] 就足够了。
本书分为以下几个部分。
第一部分解释了关于如何继续 LFS 安装的一些重要注意事项。本节还提供了关于本书的元信息。
第二部分描述了如何为构建过程做准备——创建分区、下载软件包和编译临时工具。
第三部分指导读者构建 LFS 系统——逐个编译和安装所有软件包、设置引导脚本和安装内核。生成的 Linux 系统是构建其他软件的基础,可以根据需要扩展系统。在本书的结尾,有一个易于使用的参考,列出了所有已安装的程序、库和重要文件。
用于创建 LFS 系统的软件不断更新和增强。在 LFS 书籍发布后,可能会出现安全警告和错误修复。要检查此版本的 LFS 中的软件包版本或说明是否需要进行任何修改以适应安全漏洞或其他错误修复,请在继续构建之前访问 http://www.linuxfromscratch.org/lfs/errata/6.1.1/。您应该注意显示的任何更改,并在您进行构建 LFS 系统的过程中将其应用于本书的相关部分。
LFS 系统将通过使用先前安装的 Linux 发行版(例如 Debian、Mandrake、Red Hat 或 SuSE)来构建。这个现有的 Linux 系统(主机)将用作起点,以提供必要的程序,包括编译器、链接器和 shell,来构建新系统。在发行版安装期间选择 “开发” 选项,以便能够访问这些工具。
作为将整个单独的发行版安装到您的计算机上的替代方案,您可能希望使用 Linux From Scratch LiveCD。该 CD 作为主机系统运行良好,提供了成功遵循本书中说明所需的所有工具。此外,它还包含所有源代码包、补丁和本书的副本。因此,一旦您拥有 CD,就不需要网络连接或额外下载。有关 LFS LiveCD 的更多信息或下载副本,请访问 http://www.linuxfromscratch.org/livecd/。
本书的 第 2 章 描述了如何创建一个新的 Linux 本地分区和文件系统,这是将编译和安装新 LFS 系统的地方。第 3 章 解释了需要下载哪些软件包和补丁来构建 LFS 系统,以及如何将它们存储在新的文件系统上。第 4 章 讨论了适当的工作环境的设置。请仔细阅读 第 4 章,因为它解释了开发人员在开始通过 第 5 章 及之后的内容之前应该了解的几个重要问题。
第 5 章 解释了许多软件包的安装,这些软件包将形成基本开发套件(或工具链),用于在 第 6 章 中构建实际系统。需要其中一些软件包来解决循环依赖关系——例如,要编译一个编译器,您需要一个编译器。
第五章也向用户展示了如何构建工具链的第一个版本,包括Binutils和GCC(第一个版本基本上意味着这两个核心软件包将被重新安装第二次)。下一步是构建Glibc,即C语言库。Glibc将由第一个版本中构建的工具链程序编译。然后,将构建工具链的第二个版本。这一次,工具链将与新构建的Glibc动态链接。剩余的第五章软件包使用这个第二个版本的工具链构建。完成此操作后,除了运行中的内核外,LFS的安装过程将不再依赖于宿主发行版。
将新系统与宿主发行版隔离的这种努力可能看起来有些过度,但完整的技术解释在第 5.2 节,“工具链技术说明”中提供。
在第六章中,构建了完整的LFS系统。chroot (change root) 程序用于进入一个虚拟环境,并启动一个新的shell,其根目录将设置为LFS分区。这与重新启动并指示内核将LFS分区挂载为根分区非常相似。系统实际上并没有重新启动,而是使用了chroot,因为创建一个可启动系统需要额外的工作,而这目前还不是必需的。 主要优点是“chrooting”允许构建者在构建LFS的同时继续使用宿主系统。在等待软件包编译完成时,用户可以切换到不同的虚拟控制台 (VC) 或 X 桌面,并继续像往常一样使用计算机。
为了完成安装,LFS-Bootscripts在第七章中设置,内核和启动加载器在第八章中设置。第九章包含有关在此书之外进一步扩展 LFS 体验的信息。 完成本书中的步骤后,计算机就可以重新启动到新的 LFS 系统中了。
这就是整个过程的简要概述。有关每个步骤的详细信息将在后续章节和软件包描述中讨论。 那些看起来复杂的事项将被澄清,并且当读者开始 LFS 冒险时,一切都会变得清晰明了。
这是 Linux From Scratch 书籍的 6.1.1 版本,日期为 2005 年 11 月 30 日。如果本书超过六个月,可能已经有更新更好版本可用。要了解最新版本,请通过 http://www.linuxfromscratch.org/ 检查其中一个镜像站点。
以下是自本书上一个版本以来所做的更改列表。 首先是摘要,然后是详细日志。
已升级到
Perl 5.8.7
Zlib 1.2.3
已添加
binutils-2.15.94.0.2.2-gcc4-1.patch
bzip2-1.0.3-install_docs-1.patch
bzip2-1.0.3-bzgrep_security-1.patch
glibc-2.3.4-rtld_search_dirs-1.patch
glibc-2.3.4-tls_assert-1.patch
texinfo-4.8-tempfile_fix-1.patch
util-linux-2.12q-umount_fix-1.patch
vim-6.3-security_fix-2.patch
已移除
zlib-1.2.2-security_fix-1.patch;
2005 年 11 月 30 日 [matt]: LFS-6.1.1 发布。
2005 年 11 月 24 日 [matt]: LFS-6.1.1-pre2 发布。
2005 年 11 月 24 日 [matt]: 修复了 Glibc 中的一个问题,该问题阻止某些程序(包括 OpenOffice.org)运行。
2005 年 11 月 23 日 [gerard]: 在第 6 章/节中更正了对“man page”的引用,改为“HTML 文档”。
2005 年 11 月 18 日 [manuel]: 修复了 module-init-tools-testsuite 包的解压问题。
2005 年 11 月 18 日 [manuel]: PDF 修复。
2005 年 11 月 17 日 [matt]: LFS-6.1.1-pre1 发布。
2005 年 11 月 12 日 [matt]: 改进了用于确定 Glibc 和 LFS 之外的软件包都支持的区域设置的启发式方法(错误 1642)。 非常感谢 Alexander Patrakov 强调了众多问题并审查了各种建议的修复方法。
2005 年 11 月 12 日 [matt]: 省略了作为单独步骤运行 Bzip2 的测试套件,因为 make 会自动运行它(错误 1652)。
2005 年 11 月 7 日 [matt]: 阻止 Udev 终止宿主系统上的 udevd 进程(修复了错误 1651)。 感谢 Alexander Patrakov 提供的报告和修复程序。
2005 年 11 月 5 日 [matt]: 在第 5 章的工具链健全性检查中添加一条注释,解释说如果 TCL 构建失败,则表明工具链已损坏(错误 1581)。
2005 年 11 月 4 日 [matt]: 更正了运行 Module-Init-Tools 测试套件的说明(修复了错误 1597)。 感谢 Greg Schafer、Tushar Teredesai 和 Randy McMurchy 提供的补丁。
2005 年 10 月 29 日 [manuel]: PDF 修复。
2005 年 10 月 23 日 [manuel]: 添加了 Bash 文档安装。 添加了关于 libiconv 和 Cracklib 的注释。 修复了 Sed 文档的安装。 用 sed 命令替换了 IPRoute2 的补丁。
2005 年 10 月 19 日 [manuel]: 将致谢更新为当前 trunk 版本。 在 preface 和 chapter01 页面中移植了一些修订更改。 将 chapter02 移至第二部分。 添加了 -v 开关。 从 trunk 移植了一些拼写错误和修订修复。
2005 年 10 月 19 日 [manuel]: 将样式表、Makefile 和相关文件更新为当前 trunk 版本。
2005 年 10 月 15 日 [matt]: 使用了更新版本的 Udev 规则文件(修复了错误 1639)。
2005 年 10 月 15 日 [matt]: 添加了 Udev 规则文件所需的 cdrom 组
2005 年 10 月 14 日 [ken]: 添加了一个补丁,允许从运行 gcc-4 的主机构建 binutils,更新了 glibc 指令以用于 rtld 补丁,更新了 perl 和 zlib 的空间/时间。
2005 年 10 月 14 日 [matt]: 添加了一个补丁来修复 util-linux 中的安全漏洞。
2005 年 10 月 14 日 [matt]: 添加了更新的 vim 安全补丁。
2005 年 10 月 14 日 [jhuntwork]: 添加了 bzip2 安全和安装文档补丁。
2005 年 10 月 14 日 [jhuntwork]: 为 texinfo 添加了 tempfile 补丁。
2005 年 10 月 14 日 [ken]: 更新了更新日志中的软件包和补丁,仅反映自 6.1 以来的更改。 更新 zlib。
2005 年 10 月 13 日 [ken]: 修复了已安装文件列表中的已知错误并提高了 perl 版本。
如果在构建 LFS 系统期间遇到任何错误,有任何疑问,或者认为书中存在拼写错误,请首先查阅位于 http://www.linuxfromscratch.org/faq/ 的常见问题解答 (FAQ)。
的linuxfromscratch.org服务器托管了许多用于 LFS 项目开发的邮件列表。 这些列表包括主要的开发和支持列表等。 如果常见问题解答不能解决您遇到的问题,下一步是在 http://www.linuxfromscratch.org/search.html 上搜索邮件列表。
有关不同列表的信息、如何订阅、存档位置和其他信息,请访问 http://www.linuxfromscratch.org/mail.html。
托管在linuxfromscratch.org的邮件列表也可以通过网络新闻传输协议 (NNTP) 服务器访问。 发布到邮件列表的所有消息都会复制到相应的新闻组,反之亦然。
新闻服务器位于news.linuxfromscratch.org.
LFS 社区的几位成员在我们的社区 Internet Relay Chat (IRC) 网络上提供帮助。 在使用此支持之前,请确保您的问题尚未在 LFS 常见问题解答或邮件列表存档中找到答案。 您可以在
上找到 IRC 网络irc.linuxfromscratch.org。 支持频道名为 #LFS-support。
有关软件包的其他信息,有用的提示可在位于 http://www.linuxfromscratch.org/~matthew/LFS-references.html 的 LFS 软件包参考页面中找到。
LFS 项目在全球范围内拥有多个镜像站点,以便更方便地访问网站和下载所需的软件包。 请访问 LFS 网站 http://www.linuxfromscratch.org/mirrors.html 以获取当前镜像站点的列表。
如果在阅读本书时遇到问题或疑问,请查看 http://www.linuxfromscratch.org/faq/#generalfaq 上的常见问题解答页面。 问题通常已经在那里得到解答。 如果您的问题未在此页面上得到解答,请尝试找到问题的根源。 以下提示将为您提供一些故障排除指导: http://www.linuxfromscratch.org/hints/downloads/files/errors.txt。
如果您在常见问题解答中找不到您的问题,请在 http://www.linuxfromscratch.org/search.html 上搜索邮件列表。
我们还有一个出色的 LFS 社区,愿意通过邮件列表和 IRC 提供帮助(请参阅本书的 第 1.3 节,“资源”)。 但是,我们每天都会收到几个支持问题,其中许多问题可以通过首先访问常见问题解答和搜索邮件列表来轻松解答。 因此,为了让我们能够提供最好的帮助,您需要先自己做一些研究。 这使我们能够专注于更多不寻常的支持需求。 如果您的搜索没有产生解决方案,请在您的帮助请求中包含所有相关信息(如下所述)。
除了对所经历问题的简要说明之外,在任何帮助请求中都需要包含的基本事项包括
所使用的书籍版本(在本例中为 6.1.1)
用于创建 LFS 的宿主发行版和版本
遇到问题的软件包或部分
收到的确切错误消息或症状
请注意您是否完全按照本书进行操作
偏离本书的内容并不意味着我们将不会帮助你。毕竟,LFS 是关于个人偏好的。坦诚地说明对既定流程的任何更改,有助于我们评估并确定您的问题的可能原因。
如果在运行 configure 脚本时出现问题,请查看config.log文件。此文件可能包含在 configure 期间遇到的但未在屏幕上打印的错误。如果您需要寻求帮助,请包含相关的行。
屏幕输出和各种文件的内容对于确定编译问题的原因都很有用。来自 configure 脚本和 make 运行的屏幕输出可能很有帮助。没有必要包含整个输出,但要包含足够的相关信息。以下是从 make 的屏幕输出中包含的信息类型的示例
gcc -DALIASPATH=\"/mnt/lfs/usr/share/locale:.\" -DLOCALEDIR=\"/mnt/lfs/usr/share/locale\" -DLIBDIR=\"/mnt/lfs/usr/lib\" -DINCLUDEDIR=\"/mnt/lfs/usr/include\" -DHAVE_CONFIG_H -I. -I. -g -O2 -c getopt1.c gcc -g -O2 -static -o make ar.o arscan.o commands.o dir.o expand.o file.o function.o getopt.o implicit.o job.o main.o misc.o read.o remake.o rule.o signame.o variable.o vpath.o default.o remote-stub.o version.o opt1.o -lutil job.o: In function `load_too_high': /lfs/tmp/make-3.79.1/job.c:1565: undefined reference to `getloadavg' collect2: ld returned 1 exit status make[2]: *** [make] Error 1 make[2]: Leaving directory `/lfs/tmp/make-3.79.1' make[1]: *** [all-recursive] Error 1 make[1]: Leaving directory `/lfs/tmp/make-3.79.1' make: *** [all-recursive-am] Error 2
在这种情况下,很多人只会包含底部部分
make [2]: *** [make] Error 1
这不足以正确诊断问题,因为它只指出发生了错误,而不是什么出错了。应该保存整个部分,如上面的示例所示,因为它包含执行的命令和相关的错误消息。
一篇关于在互联网上寻求帮助的优秀文章可以在网上找到:http://catb.org/~esr/faqs/smart-questions.html。阅读并遵循本文档中的提示,以增加获得所需帮助的可能性。
像大多数其他操作系统一样,LFS 通常安装在专用分区上。构建 LFS 系统的推荐方法是使用可用的空分区,或者如果您有足够的未分区空间,则创建一个。但是,LFS 系统(实际上甚至可以有多个 LFS 系统)也可以安装在已经被另一个操作系统占用的分区上,并且不同的系统将和平共存。文档 http://www.linuxfromscratch.org/hints/downloads/files/lfs_next_to_existing_systems.txt 解释了如何实现这一点,而本书讨论了使用全新分区进行安装的方法。
一个最小系统需要一个大约 1.3 GB (千兆字节) 的分区。这足以存储所有源 tarball 并编译软件包。但是,如果 LFS 系统旨在成为主要的 Linux 系统,则可能会安装其他软件,这将需要额外的空间 (2-3 GB)。LFS 系统本身不会占用这么多空间。这部分需求的主要目的是提供足够的可用临时存储空间。编译软件包可能需要大量的磁盘空间,这些空间将在软件包安装后被回收。
因为并非总是有足够的随机存取内存 (RAM) 可用于编译过程,所以最好使用一个小磁盘分区作为交换空间。内核使用它来存储不常用的数据,并为活动进程留下更多内存。LFS 系统的交换分区可以与宿主系统使用的交换分区相同,在这种情况下,不需要创建另一个。
启动磁盘分区程序,例如 cfdisk 或 fdisk,并使用命令行选项命名将在其上创建新分区的硬盘 - 例如/dev/hda对于主集成驱动器电子设备 (IDE) 磁盘。创建 Linux 本地分区和交换分区(如果需要)。请参考cfdisk(8)或者fdisk(8)如果您还不知道如何使用这些程序。
记住新分区的指定 (例如,hda5)。本书将此称为 LFS 分区。还要记住交换分区的指定。稍后需要在/etc/fstab文件中使用这些名称。
现在已经设置了一个空白分区,可以创建文件系统了。 Linux 世界中最广泛使用的系统是第二个扩展文件系统 (ext2),但随着更新的高容量硬盘的出现,日志文件系统越来越受欢迎。我们将创建一个 ext2 文件系统。可以在 http://www.linuxfromscratch.org/blfs/view/svn/postlfs/filesystems.html 找到其他文件系统的构建说明。
要在 LFS 分区上创建 ext2 文件系统,请运行以下命令
mke2fs -v /dev/[xxx]
将 [xxx] 替换为 LFS 分区的名称(hda5在我们之前的例子中)。
某些宿主发行版在其文件系统创建工具 (e2fsprogs) 中使用自定义功能。这可能会导致在第 9 章中启动到新的 LFS 时出现问题,因为 LFS 安装的 e2fsprogs 不支持这些功能;您会收到类似于“unsupported filesystem features, upgrade your e2fsprogs”的错误。要检查您的宿主系统是否使用自定义增强功能,请运行以下命令
debugfs -R feature /dev/[xxx]
如果输出包含除以下之外的功能:dir_index; filetype; large_file; resize_inode or sparse_super 那么您的宿主系统可能具有自定义增强功能。在这种情况下,为了避免以后的问题,您应该编译标准的 e2fsprogs 软件包,并使用生成的二进制文件来重新创建 LFS 分区上的文件系统
cd /tmp tar -xjvf /path/to/sources/e2fsprogs-1.37.tar.bz2 cd e2fsprogs-1.37 mkdir -v build cd build ../configure make #note that we intentionally don't 'make install' here! ./misc/mke2fs -v /dev/[xxx] cd /tmp rm -rfv e2fsprogs-1.37
如果创建了交换分区,则需要通过发出以下命令对其进行初始化以供使用。如果您使用的是现有交换分区,则无需格式化它。
mkswap -v /dev/[yyy]
将 [yyy] 替换为交换分区的名称。
现在已经创建了文件系统,需要使分区可访问。为了做到这一点,需要在所选的挂载点挂载分区。就本书而言,假设文件系统挂载在/mnt/lfs下,但目录选择由您决定。
选择一个挂载点并将其分配给LFS环境变量,方法是运行
export LFS=/mnt/lfs
接下来,创建挂载点并挂载 LFS 文件系统,方法是运行
mkdir -pv $LFS mount -v /dev/[xxx] $LFS
将 [xxx] 替换为 LFS 分区的指定。
如果使用多个分区用于 LFS(例如,一个用于///usr),请使用以下命令挂载它们
mkdir -pv $LFS mount -v /dev/[xxx] $LFS mkdir -v $LFS/usr mount -v /dev/[yyy] $LFS/usr
将 [xxx] 和 [yyy] 替换为适当的分区名称。
确保没有使用过于严格的权限(例如 nosuid、nodev 或 noatime 选项)挂载此新分区。运行没有任何参数的 mount 命令,以查看为已挂载的 LFS 分区设置了哪些选项。如果设置了 nosuid、nodev 和/或 noatime,则需要重新挂载该分区。
现在已经建立了一个可以工作的地方,是时候下载软件包了。
本章包括构建基本 Linux 系统需要下载的软件包列表。列出的版本号对应于已知可以工作的软件版本,本书是基于它们的使用编写的。我们强烈建议不要使用较新版本,因为一个版本的构建命令可能不适用于较新版本。最新的软件包版本也可能存在需要解决的问题。这些解决方法将在本书的开发版本中开发和稳定。
下载位置可能并非始终可访问。如果自本书出版以来下载位置发生了变化,Google (http://www.google.com/) 为大多数软件包提供了一个有用的搜索引擎。如果此搜索不成功,请尝试在 http://www.linuxfromscratch.org/lfs/packages.html 讨论的替代下载方式之一。
下载的软件包和补丁需要存储在某个方便在整个构建过程中可用的位置。还需要一个工作目录来解压源代码并构建它们。$LFS/sources可以同时用作存储 tarball 和补丁的地方以及用作工作目录。通过使用此目录,所需的元素将位于 LFS 分区上,并且在构建过程的所有阶段都可用。
要创建此目录,请在开始下载会话之前,以用户 root 身份执行以下命令
mkdir -v $LFS/sources
使此目录可写且粘滞。“粘滞”意味着即使多个用户对目录具有写权限,也只有文件的所有者才能删除粘滞目录中的文件。以下命令将启用写入和粘滞模式
chmod -v a+wt $LFS/sources
下载或以其他方式获取以下软件包
ftp://ftp.gw.com/mirrors/pub/unix/file/
文件 (4.13) 可能已无法在所列位置找到。主下载站点的管理员有时会在发布新版本时删除旧版本。您也可以在以下位置找到可能包含正确版本的替代下载站点: http://www.linuxfromscratch.org/lfs/download.html#ftp。
https://linuxkernel.org.cn/pub/linux/utils/kernel/module-init-tools/
https://linuxkernel.org.cn/pub/linux/utils/kernel/module-init-tools/
ftp://ftp.pld.org.pl/software/shadow/
Shadow (4.0.9) 可能已无法在所列位置找到。主下载站点的管理员有时会在发布新版本时删除旧版本。您也可以在以下位置找到可能包含正确版本的替代下载站点: http://www.linuxfromscratch.org/lfs/download.html#ftp。
这些软件包的总大小:146 MB
除了软件包之外,还需要一些补丁。这些补丁修复了软件包中应该由维护者修复的任何错误。这些补丁还对软件包进行小的修改,使其更易于使用。构建 LFS 系统需要以下补丁
http://www.linuxfromscratch.org/patches/lfs/6.1.1/bash-3.0-avoid_WCONTINUED-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/bash-3.0-fixes-3.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/binutils-2.15.94.0.2.2-gcc4-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/bzip2-1.0.3-install_docs-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/bzip2-1.0.3-bzgrep_security-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/coreutils-5.2.1-suppress_uptime_kill_su-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/coreutils-5.2.1-uname-2.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/expect-5.43.0-spawn-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/flex-2.5.31-debian_fixes-3.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/gcc-3.4.3-linkonce-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/gcc-3.4.3-no_fixincludes-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/gcc-3.4.3-specs-2.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/glibc-2.3.4-rtld_search_dirs-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/glibc-2.3.4-fix_test-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/glibc-2.3.4-tls_assert-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/gzip-1.3.5-security_fixes-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/inetutils-1.4.2-kernel_headers-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/inetutils-1.4.2-no_server_man_pages-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/mktemp-1.5-add_tempfile-2.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/perl-5.8.7-libc-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/readline-5.0-fixes-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/sysklogd-1.4.1-fixes-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/tar-1.15.1-sparse_fix-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/texinfo-4.8-tempfile_fix-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/util-linux-2.12q-cramfs-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/util-linux-2.12q-umount_fix-1.patch
http://www.linuxfromscratch.org/patches/lfs/6.1.1/vim-6.3-security_fix-2.patch
除了上述必需的补丁之外,LFS 社区还创建了许多可选补丁。这些可选补丁解决了小问题或启用了默认情况下未启用的功能。您可以随意浏览位于 http://www.linuxfromscratch.org/patches/ 的补丁数据库,并获取任何其他补丁以满足系统需求。
在本书中,环境变量LFS将被使用多次。始终定义此变量至关重要。它应该设置为为 LFS 分区选择的挂载点。检查LFS变量是否已正确设置
echo $LFS
确保输出显示 LFS 分区挂载点的路径,如果遵循提供的示例,则为/mnt/lfs。如果输出不正确,可以使用以下命令设置变量
export LFS=/mnt/lfs
设置此变量的好处是,您可以按字面意思键入诸如 mkdir $LFS/tools 之类的命令。当 shell 处理命令行时,它会自动将“$LFS”替换为“/mnt/lfs”(或变量设置的任何值)。
不要忘记检查$LFS在您离开并重新进入当前工作环境时(例如,对 root 或其他用户执行“su”时)是否已设置。
在 第 5 章 中编译的所有程序都将安装在$LFS/tools下,以使其与在 第 6 章 中编译的程序分开。此处编译的程序是临时工具,不会成为最终 LFS 系统的一部分。通过将这些程序保存在单独的目录中,可以在使用后轻松丢弃它们。这还可以防止这些程序最终出现在主机生产目录中(在 第 5 章 中很容易意外地发生)。
以 root 身份运行以下命令来创建所需的目录
mkdir -v $LFS/tools
下一步是创建一个/tools主机系统上的符号链接。这将指向 LFS 分区上新创建的目录。也以 root 身份运行此命令
ln -sv $LFS/tools /
上述命令是正确的。ln 命令有一些语法变体,因此请务必在报告您认为的错误之前检查 info coreutils ln 和ln(1)。
创建的符号链接使工具链能够被编译,以便它始终引用/tools,这意味着编译器、汇编器和链接器将在本章(当我们仍在使用主机中的某些工具时)和下一章(当我们“chrooted”到 LFS 分区时)中工作。
当以用户 root 身份登录时,一个小错误可能会损坏或破坏系统。因此,我们建议以非特权用户身份构建本章中的软件包。您可以使用自己的用户名,但为了更容易设置干净的工作环境,请创建一个名为 lfs 的新用户作为新组(也称为 lfs)的成员,并在安装过程中使用此用户。以 root 身份,发出以下命令以添加新用户
groupadd lfs useradd -s /bin/bash -g lfs -m -k /dev/null lfs
命令行选项的含义
这使 bash 成为用户 lfs 的默认 shell。
此选项将用户 lfs 添加到组 lfs。
这将为 lfs 创建一个主目录。
此参数通过将输入位置更改为特殊空设备来防止从骨架目录(默认为/etc/skel)可能复制文件。
这是创建的组和用户的实际名称。
要以 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,而不是非登录 shell。这两种类型的 shell 之间的区别可以在bash(1)和 info bash 中找到详细信息。
通过为 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,它会读取主机上的/etc/profile(可能包含一些设置和环境变量),然后读取.bash_profile。exec env -i.../bin/bash 命令在.bash_profile文件中将正在运行的 shell 替换为一个全新的 shell,其环境完全为空,除了HOME, TERM和PS1变量。这确保了主机系统上任何不需要且可能有害的环境变量都不会泄漏到构建环境中。此处使用的技术实现了确保干净环境的目标。
shell 的新实例是一个 非登录 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 的哈希功能。哈希通常是一个有用的功能——bash 使用哈希表来记住可执行文件的完整路径,以避免一次又一次地搜索PATH来查找同一个可执行文件。但是,应该尽快使用新的工具。通过关闭哈希功能,shell 将始终搜索PATH,以便在程序运行时找到。这样,shell 将在$LFS/tools中找到新编译的工具,一旦它们可用,而不会记住同一程序先前版本的不同位置。
将用户文件创建掩码 (umask) 设置为 022 可确保新创建的文件和目录只能由其所有者写入,但可由任何人读取和执行(假设 open(2) 系统调用使用默认模式,新文件最终将具有权限模式 644,目录具有模式 755)。
的LFS变量应设置为所选的挂载点。
的LC_ALL变量控制某些程序的本地化,使其消息遵循指定国家/地区的约定。如果主机系统使用的 Glibc 版本低于 2.2.4,则将LC_ALL设置为 “POSIX” 或 “C” 以外的值(在本章中)可能会导致您退出 chroot 环境并希望稍后返回时出现问题。 将LC_ALL设置为 “POSIX” 或 “C”(两者等效)可确保一切在 chroot 环境中按预期工作。
通过将/tools/bin放在标准PATH之前,在 第 5 章中安装的所有程序都会在安装后立即被 shell 拾取。 结合关闭哈希功能,这限制了当第 5 章环境中提供相同程序时,使用来自主机的旧程序的风险。
最后,为了使环境完全准备好构建临时工具,请执行刚创建的用户配置文件。
source ~/.bash_profile
许多人想预先知道编译和安装每个软件包大约需要多长时间。 因为 Linux From Scratch 可以在许多不同的系统上构建,所以不可能提供准确的时间估计。 最大的软件包 (Glibc) 在最快的系统上大约需要 20 分钟,但在较慢的系统上可能需要长达三天的时间! 将使用标准构建单元 (SBU) 度量而不是提供实际时间。
SBU 度量的运作方式如下。 从本书中编译的第一个软件包是 第 5 章中的 Binutils。 编译此软件包所花费的时间将被称为标准构建单元或 SBU。 所有其他编译时间将相对于此时间表示。
例如,假设一个软件包的编译时间为 4.5 SBU。 这意味着如果一个系统花费 10 分钟来编译和安装 Binutils 的第一次传递,那么构建此示例软件包将花费 大约 45 分钟。 幸运的是,大多数构建时间都比 Binutils 的时间短。
一般来说,SBU 并不是完全准确的,因为它们取决于许多因素,包括主机系统的 GCC 版本。 请注意,在基于对称多处理器 (SMP) 的机器上,SBU 的准确性甚至更低。 提供它们是为了估计安装软件包可能需要多长时间,但在某些情况下,这些数字可能会相差几十分钟。
要查看一些特定机器的实际计时,我们建议访问 LinuxFromScratch SBU 主页:http://www.linuxfromscratch.org/~bdubbs/。
大多数软件包都提供测试套件。 运行新构建软件包的测试套件是一个好主意,因为它可以提供“健全性检查”,表明一切都已正确编译。 通过其一组检查的测试套件通常证明该软件包的运行方式与开发人员的预期一样。 但是,它并不能保证该软件包完全没有错误。
有些测试套件比其他测试套件更重要。 例如,由于核心工具链软件包(GCC、Binutils 和 Glibc)在正常运行的系统中起着核心作用,因此它们的测试套件至关重要。 GCC 和 Glibc 的测试套件可能需要很长时间才能完成,尤其是在较慢的硬件上,但强烈建议使用。
运行 Binutils 和 GCC 的测试套件的一个常见问题是缺少伪终端 (PTY)。 这可能导致大量测试失败。 这可能出于多种原因发生,但最可能的原因是主机系统没有devpts文件系统设置正确。 第 5 章更详细地讨论了此问题。
有时,软件包测试套件会失败,但由于开发人员知道并且认为不重要的原因。 请查看位于 http://www.linuxfromscratch.org/lfs/build-logs/6.1.1/ 的日志,以验证这些失败是否是预期的。 该站点适用于本书中的所有测试。
本章介绍如何编译和安装最小的 Linux 系统。 该系统将包含足够的工具来开始在 第 6 章中构建最终 LFS 系统,并允许使用比最小环境更方便的工作环境。
构建此最小系统有两个步骤。 第一步是构建一个新的、独立于主机的工具链(编译器、汇编器、链接器、库和一些有用的实用程序)。 第二步使用此工具链来构建其他基本工具。
在本章中编译的文件将安装在$LFS/tools目录下,以将它们与下一章和主机生产目录中安装的文件分开。 由于此处编译的软件包是临时的,因此我们不希望它们污染即将到来的 LFS 系统。
在发出软件包的构建指令之前,应以用户 lfs 身份解压软件包,并 cd 到创建的目录中。 构建说明假定正在使用 bash shell。
在编译之前,会修补几个软件包,但仅当需要修补程序来规避问题时才这样做。 在本章和下一章中通常都需要补丁,但有时只需要在一章中进行补丁。 因此,如果下载的补丁的说明似乎丢失,请不要担心。 应用补丁时也可能遇到有关 offset 或 fuzz 的警告消息。 不要担心这些警告,因为补丁仍然已成功应用。
在编译大多数软件包期间,屏幕上会滚动显示几个警告。 这些是正常的,可以安全地忽略。 这些警告与它们的外观一样,是关于不赞成使用但并非无效的 C 或 C++ 语法的警告。 C 标准经常更改,并且某些软件包仍使用较旧的标准。 这不是问题,但会提示警告。
安装每个软件包后,删除其源目录和构建目录,除非另有明确说明。 删除源可防止以后重新安装同一软件包时出现错误配置。 只有三个软件包需要保留源目录和构建目录,以便以后的命令使用其内容。 请特别注意这些提醒。
最后一次检查LFS环境变量是否设置正确
echo $LFS
确保输出显示 LFS 分区挂载点的路径,如果遵循提供的示例,则为/mnt/lfs,使用我们的示例。
本节介绍整体构建方法背后的一些原理和技术细节。 立即理解本节中的所有内容并非必不可少。 在执行实际构建之后,这些信息中的大多数会更清晰。 可以在过程中的任何时间参考本节。
第 5 章的总体目标是提供一个临时的环境,可以 chroot 到其中,并从中可以生成干净、无故障的目标 LFS 系统构建,如 第 6 章所示。 在此过程中,我们会尽可能地将新系统与主机系统分离,并在此过程中构建一个独立的、自托管的工具链。 应该注意的是,构建过程旨在最大限度地降低新读者的风险,并同时提供最大的教育价值。
在继续之前,请注意工作平台的名称,通常被称为目标三元组(target triplet)。很多时候,目标三元组很可能是 i686-pc-linux-gnu。一个确定目标三元组名称的简单方法是运行许多软件包源代码自带的 config.guess 脚本。解压 Binutils 源代码并运行该脚本:./config.guess,并注意输出结果。
同时请注意平台的动态链接器的名称,通常被称为动态加载器(不要与 Binutils 自带的标准链接器 ld 混淆)。Glibc 提供的动态链接器负责查找和加载程序所需的共享库,准备程序运行,然后运行该程序。动态链接器的名称通常是ld-linux.so.2。 在不太常见的平台上,名称可能是ld.so.1,而较新的 64 位平台可能完全是其他名称。可以通过查看主机系统的/lib目录来确定平台动态链接器的名称。确定名称的万无一失的方法是通过运行:readelf -l <name of binary> | grep interpreter 来检查主机系统中的随机二进制文件并注意输出结果。涵盖所有平台的权威参考资料在 Glibc 源代码树根目录下的shlib-versions文件中。
以下是 第五章 构建方法的一些关键技术要点:
该过程在原则上类似于交叉编译,即安装在相同前缀中的工具协同工作,因此利用了一点 GNU 的“魔法”。
仔细操作标准链接器的库搜索路径,确保程序仅与选定的库链接。
仔细操作 gcc 的specs文件,告诉编译器将使用哪个目标动态链接器。
首先安装 Binutils,因为 GCC 和 Glibc 的 configure 运行都会对汇编器和链接器执行各种功能测试,以确定要启用或禁用哪些软件功能。这一点比人们最初意识到的更为重要。错误配置的 GCC 或 Glibc 可能会导致工具链出现细微的损坏,这种损坏的影响可能要到整个发行版的构建接近尾声时才会显现出来。测试套件的失败通常会在执行过多额外工作之前突出显示此错误。
Binutils 将其汇编器和链接器安装在两个位置:/tools/bin和/tools/$TARGET_TRIPLET/bin。一个位置中的工具硬链接到另一个位置。链接器的一个重要方面是其库搜索顺序。可以通过将 --verbose 标志传递给 ld 来获得详细信息。例如,ld --verbose | grep SEARCH 将说明当前的搜索路径及其顺序。它通过编译一个虚拟程序并将 --verbose 开关传递给链接器,显示哪些文件由 ld 链接。例如,gcc dummy.c -Wl,--verbose 2>&1 | grep succeeded 将显示在链接期间成功打开的所有文件。
下一个安装的软件包是 GCC。可以在其 configure 运行期间看到的一个示例是
checking what assembler to use... /tools/i686-pc-linux-gnu/bin/as checking what linker to use... /tools/i686-pc-linux-gnu/bin/ld
这很重要,原因如上所述。它还表明 GCC 的 configure 脚本不会搜索 PATH 目录来查找要使用的工具。但是,在 gcc 本身的实际操作过程中,不一定使用相同的搜索路径。要找出 gcc 将使用哪个标准链接器,请运行:gcc -print-prog-name=ld。
通过在编译虚拟程序时将 -v 命令行选项传递给 gcc,可以获得详细信息。例如,gcc -v dummy.c 将显示有关预处理器、编译和汇编阶段的详细信息,包括 gcc 包含的搜索路径及其顺序。
下一个安装的软件包是 Glibc。构建 Glibc 最重要的考虑因素是编译器、二进制工具和内核头文件。编译器通常不是问题,因为 Glibc 总是使用在PATH目录中找到的 gcc。二进制工具和内核头文件可能有点复杂。因此,不要冒险,并使用可用的配置开关来强制进行正确的选择。在运行 configure 之后,检查config.make文件中glibc-build目录中的所有重要详细信息。请注意使用 CC="gcc -B/tools/bin/" 来控制使用哪些二进制工具,以及使用 -nostdinc 和 -isystem 标志来控制编译器的包含搜索路径。这些项突出了 Glibc 软件包的一个重要方面——它在构建机制方面非常自给自足,并且通常不依赖于工具链的默认设置。
在安装 Glibc 之后,进行一些调整以确保搜索和链接仅在/tools前缀内进行。安装一个调整后的 ld,它具有硬连线的搜索路径,该路径仅限于/tools/lib。然后修改 gcc 的 specs 文件,以指向/tools/lib中的新动态链接器。最后一步对于整个过程至关重要。如上所述,到动态链接器的硬连线路径嵌入到每个可执行和链接格式 (ELF) 共享可执行文件中。可以通过运行:readelf -l <name of binary> | grep interpreter 来检查这一点。修改 gcc 的 specs 文件可确保从此处到本章末尾编译的每个程序都将使用/tools/lib.
中的新动态链接器。需要使用新的动态链接器也是为 GCC 的第二遍应用 Specs 补丁的原因。如果不这样做,将导致 GCC 程序本身具有主机系统的/lib目录中的动态链接器的名称嵌入到其中,这将破坏摆脱主机的目标。
在 Binutils 的第二遍期间,我们能够利用 --with-lib-path 配置开关来控制 ld 的库搜索路径。从此时起,核心工具链是自包含和自托管的。 第五章 的其余软件包都针对/tools.
中的新 Glibc 构建。在 第六章 中进入 chroot 环境后,由于上述 Glibc 的自给自足的性质,要安装的第一个主要软件包是 Glibc。一旦将此 Glibc 安装到/usr中,就快速更改工具链的默认设置,然后继续构建目标 LFS 系统的其余部分。
Binutils 软件包包含一个链接器、一个汇编器和其他用于处理目标文件的工具。
重要的是,Binutils 是第一个编译的软件包,因为 Glibc 和 GCC 都会对可用的链接器和汇编器执行各种测试,以确定要启用哪些自己的功能。
已知此软件包在其默认优化标志(包括 -march 和 -mcpu 选项)被更改时会出现问题。如果定义了任何覆盖默认优化的环境变量,例如CFLAGS和CXXFLAGS,请在构建 Binutils 时取消设置它们。
如果您是从运行 Gcc-4 或更高版本的主机构建的,则必须修补此版本的 Binutils 的第一个构建,以便它可以由主机系统编译。
patch -Np1 -i ../binutils-2.15.94.0.2.2-gcc4-1.patch
Binutils 文档建议在源代码目录之外的专用构建目录中构建 Binutils。
mkdir -v ../binutils-build cd ../binutils-build
为了使本书其余部分中列出的 SBU 值发挥作用,请测量从配置到第一次安装(包括第一次安装)构建此软件包所花费的时间。为了轻松实现这一点,请将这三个命令包装在一个 time 命令中,如下所示:time { ./configure ... && make && make install; }。
现在准备编译 Binutils
../binutils-2.15.94.0.2.2/configure --prefix=/tools --disable-nls
configure 选项的含义
这告诉 configure 脚本准备将 Binutils 程序安装在/tools目录中。
由于临时工具不需要 i18n,因此禁用国际化。
继续编译软件包
make
编译现已完成。通常,我们现在将运行测试套件,但在此早期阶段,测试套件框架(Tcl、Expect 和 DejaGNU)尚未到位。此时运行测试的好处是最小的,因为此第一遍的程序将很快被第二遍的程序替换。
安装软件包
make install
接下来,为稍后的“调整”阶段准备链接器
make -C ld clean make -C ld LIB_PATH=/tools/lib
make 参数的含义
这告诉 make 程序删除ld子目录中的所有已编译文件。
此选项重建ld子目录中的所有内容。指定LIB_PATHMakefile 命令行变量允许我们覆盖默认值,并将其指向临时工具的位置。此变量的值指定链接器的默认库搜索路径。此准备工作将在本章后面用到。
不要移除 Binutils 的构建和源码目录。本章后面的步骤还需要它们保持当前状态。
有关此软件包的详细信息,请参见 第 6.13.2 节,“Binutils 的内容。”
GCC 软件包包含 GNU 编译器集合,其中包括 C 和 C++ 编译器。
已知此软件包在其默认优化标志(包括 -march 和 -mcpu 选项)被更改时会出现问题。如果定义了任何覆盖默认优化的环境变量,例如CFLAGS和CXXFLAGS,在构建 GCC 时取消设置它们。
GCC 文档建议在源代码目录之外的专用构建目录中构建 GCC
mkdir -v ../gcc-build cd ../gcc-build
准备 GCC 进行编译
../gcc-3.4.3/configure --prefix=/tools \ --libexecdir=/tools/lib --with-local-prefix=/tools \ --disable-nls --enable-shared --enable-languages=c
configure 选项的含义
此开关的目的是移除/usr/local/include从 gcc 的包含搜索路径中移除。这不是绝对必要的,但是,它有助于最小化宿主系统的影响。
此开关允许构建libgcc_s.so.1和libgcc_eh.a。拥有libgcc_eh.a可用可确保 Glibc(我们编译的下一个软件包)的配置脚本生成正确的结果。
此选项确保仅构建 C 编译器。
继续编译软件包
make bootstrap
make 参数的含义
此目标不仅仅编译 GCC,还会多次编译它。它使用第一轮编译的程序再次编译自身,然后再编译第三次。然后它会比较第二次和第三次编译,以确保它可以完美地重现自身。这也意味着它被正确编译。
编译现已完成。 此时,通常会运行测试套件,但是,如前所述,测试套件框架尚未到位。 此时运行测试的好处是最小的,因为第一次传递的程序将很快被替换。
安装软件包
make install
作为最后的润色,创建一个符号链接。许多程序和脚本运行 cc 而不是 gcc,这用于使程序保持通用性,因此可在未安装 GNU C 编译器的各种 UNIX 系统上使用。 运行 cc 使系统管理员可以自由决定要安装哪个 C 编译器。
ln -vs gcc /tools/bin/cc
有关此软件包的详细信息,请参见 第 6.14.2 节,“GCC 的内容。”
Linux-Libc-Headers 软件包包含“净化”的内核头文件。
多年来,通常的做法是在/usr/include中使用“原始”内核头文件(直接来自内核 tarball),但是在过去的几年中,内核开发人员采取了强硬的立场,认为不应该这样做。 这催生了 Linux-Libc-Headers 项目,该项目旨在维护 Linux 头文件的应用程序编程接口 (API) 稳定版本。
安装头文件
cp -Rv include/asm-i386 /tools/include/asm cp -Rv include/linux /tools/include
如果您的架构不是 i386(兼容),请相应地调整第一个命令。
有关此软件包的详细信息,请参见 第 6.9.2 节,“Linux-Libc-Headers 的内容。”
Glibc 软件包包含主要的 C 库。 此库提供用于分配内存、搜索目录、打开和关闭文件、读取和写入文件、字符串处理、模式匹配、算术等的例程。
已知此软件包在其默认优化标志(包括 -march 和 -mcpu 选项)被更改时会出现问题。如果定义了任何覆盖默认优化的环境变量,例如CFLAGS和CXXFLAGS,在构建 Glibc 时取消设置它们。
应该注意的是,以除本书中建议的方法以外的任何方式编译 Glibc 都会使系统的稳定性面临风险。
当运行的内核是 2.6.11 或更高版本时,Glibc 有两个测试会失败。 该问题已被确定为测试本身的问题,而不是 C 库或内核的问题。 如果您计划运行测试套件,请应用此补丁
patch -Np1 -i ../glibc-2.3.4-fix_test-1.patch
Glibc 文档建议在源代码目录之外的专用构建目录中构建 Glibc
mkdir -v ../glibc-build cd ../glibc-build
接下来,准备 Glibc 进行编译
../glibc-2.3.4/configure --prefix=/tools \ --disable-profile --enable-add-ons \ --enable-kernel=2.6.0 --with-binutils=/tools/bin \ --without-gd --with-headers=/tools/include \ --without-selinux
configure 选项的含义
这会构建不带分析信息的库。 如果需要对临时工具进行分析,请省略此选项。
这会告诉 Glibc 使用 NPTL 插件作为其线程库。
这告诉 Glibc 编译该库,以支持 2.6.x Linux 内核。
虽然不是必需的,但此开关可确保在 Glibc 构建期间不会出现与使用哪个 Binutils 程序有关的错误。
这会阻止 memusagestat 程序的构建,该程序坚持链接到宿主系统的库(libgd、libpng、libz 等)。
这告诉 Glibc 针对最近安装到 tools 目录中的头文件编译自身,以便它确切地知道内核具有哪些功能,并可以相应地进行优化。
从包含 SELinux 功能的主机(例如 Fedora Core 3)进行构建时,Glibc 将构建为支持 SELinux。由于 LFS 工具环境不包含对 SELinux 的支持,因此使用此类支持编译的 Glibc 将无法正常运行。
在此阶段,可能会出现以下警告
configure: WARNING: *** These auxiliary programs are missing or *** incompatible versions: msgfmt *** some features will be disabled. *** Check the INSTALL file for required versions.
缺少或不兼容的 msgfmt 程序通常是无害的,但有时会在运行测试套件时引起问题。 此 msgfmt 程序是 Gettext 软件包的一部分,宿主发行版应提供该软件包。 如果 msgfmt 存在但被认为是不兼容的,请升级宿主系统的 Gettext 软件包,或继续不使用它,并查看测试套件是否可以正常运行。
编译软件包
make
编译现已完成。 如前所述,运行本章中安装的临时工具的测试套件不是强制性的。 要运行 Glibc 测试套件(如果需要),以下命令将执行此操作
make check
有关特别重要的测试失败的讨论,请参见 第 6.11 节,“Glibc-2.3.4。”
在本章中,某些测试可能会受到宿主系统上现有工具或环境问题的不利影响。 本章中 Glibc 测试套件的失败通常不必担心。 在第 6 章中安装的 Glibc 是最终将被使用的 Glibc,因此它是需要通过大多数测试的 Glibc(即使在第 6 章中,仍然可能会发生一些失败,例如,对于数学测试)。
遇到故障时,请记下它,然后通过重新发出 make check 命令继续。 测试套件应从中断的地方开始并继续。 可以通过发出 make -k check 命令来避免此停止-启动序列。 如果使用此选项,请务必记录输出,以便以后可以检查日志文件中的失败。
Glibc 的安装阶段将在最后发出一个关于缺少/tools/etc/ld.so.conf的无害警告。 使用以下方法阻止此警告
mkdir -v /tools/etc touch /tools/etc/ld.so.conf
安装软件包
make install
不同的国家和文化对于如何交流有着不同的习惯。 这些习惯的范围从表示日期和时间的格式到更复杂的问题,例如所说的语言。 GNU 程序的“国际化”通过区域设置进行工作。
如果未在本章中运行测试套件(按照建议),则无需立即安装区域设置。 适当的区域设置将在下一章中安装。
无论如何都要安装 Glibc 区域设置,请使用以下命令
make localedata/install-locales
为了节省时间,运行上一个命令(该命令生成并安装 Glibc 知道的每个区域设置)的替代方法是仅安装那些想要和需要的区域设置。 这可以使用 localedef 命令来实现。 有关此命令的信息位于 Glibc 源代码的INSTALL文件中。 但是,为了使将来软件包的测试能够通过,特别是 GCC 中的 libstdc++ 测试,需要许多区域设置。 以下说明(代替上面使用的 install-locales 目标)将安装成功运行测试所需的最小区域设置集
mkdir -pv /tools/lib/locale localedef -i de_DE -f ISO-8859-1 de_DE localedef -i de_DE@euro -f ISO-8859-15 de_DE@euro localedef -i en_HK -f ISO-8859-1 en_HK localedef -i en_PH -f ISO-8859-1 en_PH localedef -i en_US -f ISO-8859-1 en_US localedef -i es_MX -f ISO-8859-1 es_MX localedef -i fa_IR -f UTF-8 fa_IR localedef -i fr_FR -f ISO-8859-1 fr_FR localedef -i fr_FR@euro -f ISO-8859-15 fr_FR@euro localedef -i it_IT -f ISO-8859-1 it_IT localedef -i ja_JP -f EUC-JP ja_JP
有关此软件包的详细信息,请参见 第 6.11.4 节,“Glibc 的内容。”
现在已安装了临时 C 库,本章其余部分中编译的所有工具都应链接到这些库。 为了完成此操作,需要调整链接器和编译器的 specs 文件。
链接器在 Binutils 的第一遍结束时进行了调整,通过在binutils-build目录中运行以下命令来安装
make -C ld install
从现在开始,所有内容将仅链接到/tools/lib.
中的库。 如果错过了先前关于保留来自第一遍的 Binutils 源代码和构建目录的警告,请忽略上面的命令。 这会导致后续测试程序有很小的机会链接到宿主上的库。 这不是理想的,但不是一个大问题。 当稍后安装 Binutils 的第二遍时,情况会得到纠正。
现在已安装了调整后的链接器,应删除 Binutils 构建和源代码目录。
下一个任务是修改 GCC specs 文件,使其指向新的动态链接器。 一个简单的 sed 脚本将完成此操作
SPECFILE=`gcc --print-file specs` && sed 's@ /lib/ld-linux.so.2@ /tools/lib/ld-linux.so.2@g' \ $SPECFILE > tempspecfile && mv -f tempspecfile $SPECFILE && unset SPECFILE
建议复制并粘贴上述命令,以确保准确性。 或者,可以手动编辑 specs 文件。 这是通过将每次出现的“/lib/ld-linux.so.2”替换为“/tools/lib/ld-linux.so.2”来完成的
请务必目视检查 specs 文件,以验证是否已进行预期的更改。
如果在动态链接器的名称不是ld-linux.so.2的平台上工作,请在上面的命令中将“ld-linux.so.2”替换为平台的动态链接器的名称。 如有必要,请参阅第 5.2 节,“工具链技术说明”。
宿主系统中的某些包含文件有可能已进入 GCC 的私有包含目录。 这可能是由于 GCC 的“fixincludes”过程导致的,该过程作为 GCC 构建的一部分运行。 本章稍后将对此进行更详细的说明。 运行以下命令以消除这种可能性
rm -vf /tools/lib/gcc/*/*/include/{pthread.h,bits/sigthread.h}
此时,必须停止并确保新工具链的基本功能(编译和链接)按预期工作。 要执行健全性检查,请运行以下命令
echo 'main(){}' > dummy.c cc dummy.c readelf -l a.out | grep ': /tools'
如果一切正常,应该没有错误,并且最后一个命令的输出应该具有以下形式:
[Requesting program interpreter: /tools/lib/ld-linux.so.2]
请注意:/tools/lib显示为动态链接器的前缀。
如果输出未如上所示或根本没有输出,则表示出现问题。调查并重新执行这些步骤,找出问题所在并加以纠正。必须先解决此问题,然后才能继续。首先,再次执行健全性检查,使用 gcc 而不是 cc。如果这可行,则/tools/bin/cc符号链接丢失。请回顾 第 5.4 节,“GCC-3.4.3 - 第一遍” 并安装符号链接。接下来,确保PATH是正确的。可以通过运行 echo $PATH 并验证/tools/bin位于列表的开头。如果PATH是错误的,则可能意味着您未以用户 lfs 身份登录,或者在 第 4.4 节,“设置环境” 中出现了问题。另一种可能是上面的 specs 文件修改出现问题。在这种情况下,重新进行 specs 文件修改,注意复制并粘贴命令。
一切就绪后,清理测试文件
rm -v dummy.c a.out
在下一节中构建 TCL 将作为工具链已正确构建的附加检查。如果 TCL 构建失败,则表明 Binutils、GCC 或 Glibc 安装出现问题,而不是 TCL 本身。
Tcl 软件包包含工具命令语言。
安装此软件包和接下来的两个软件包(Expect 和 DejaGNU)是为了支持运行 GCC 和 Binutils 的测试套件。为了测试目的而安装三个软件包可能看起来有些过分,但是知道最重要的工具正在正常工作是非常令人放心的,甚至至关重要。即使在本章中未运行测试套件(它们不是强制性的),也需要在 第 6 章 中运行测试套件。
准备 Tcl 以进行编译
cd unix ./configure --prefix=/tools
构建软件包
make
要测试结果,请发出:TZ=UTC make test。已知 Tcl 测试套件在某些尚未完全了解的主机条件下会遇到故障。因此,此处的测试套件故障并不令人意外,并且不被认为是关键的。TZ=UTC 参数将时区设置为协调世界时 (UTC),也称为格林威治标准时间 (GMT),但仅在测试套件运行期间有效。这样可以确保正确执行时钟测试。有关TZ环境变量的详细信息在 第 7 章 中提供。
安装软件包
make install
不要删除tcl8.4.9源目录,因为下一个软件包将需要其内部标头。
设置一个变量,其中包含当前目录的完整路径。下一个软件包 Expect 将使用此变量来查找 Tcl 的标头。
cd .. export TCLPATH=`pwd`
现在创建一个必要的符号链接
ln -sv tclsh8.4 /tools/bin/tclsh
Expect 软件包包含一个程序,用于与其他交互式程序进行脚本对话。
首先,修复一个可能导致 GCC 测试套件运行期间出现错误失败的错误
patch -Np1 -i ../expect-5.43.0-spawn-1.patch
现在准备 Expect 以进行编译
./configure --prefix=/tools --with-tcl=/tools/lib \ --with-tclinclude=$TCLPATH --with-x=no
configure 选项的含义
这样可以确保 configure 脚本在临时工具位置中找到 Tcl 安装,而不是可能在主机系统上找到现有安装。
这明确告诉 Expect 在哪里可以找到 Tcl 的源目录和内部标头。使用此选项可以避免由于 configure 无法自动发现 Tcl 源目录的位置而导致失败的情况。
这告诉 configure 脚本不要搜索 Tk(Tcl GUI 组件)或 X Window System 库,它们可能都位于主机系统上,但不会存在于临时环境中。
构建软件包
make
要测试结果,请发出:make test。请注意,已知 Expect 测试套件在某些我们无法控制的主机条件下会遇到故障。因此,此处的测试套件故障并不令人意外,并且不被认为是关键的。
安装软件包
make SCRIPTS="" install
make 参数的含义
这可以防止安装不需要的补充 expect 脚本。
现在删除TCLPATH变量
unset TCLPATH
现在可以删除 Tcl 和 Expect 的源目录。
DejaGNU 软件包包含一个用于测试其他程序的框架。
准备 DejaGNU 以进行编译
./configure --prefix=/tools
构建并安装软件包
make install
已知此软件包在其默认优化标志(包括 -march 和 -mcpu 选项)被更改时会出现问题。如果定义了任何覆盖默认优化的环境变量,例如CFLAGS和CXXFLAGS,在构建 GCC 时取消设置它们。
现在已安装测试 GCC 和 Binutils 所需的工具 - Tcl、Expect 和 DejaGNU。 现在可以重建 GCC 和 Binutils,将它们与新的 Glibc 链接并正确测试它们(如果在本章中运行测试套件)。 请注意,这些测试套件高度依赖于主机提供的功能正常的 PTY。 PTY 通常通过devpts文件系统实现。 通过执行快速测试,检查主机系统在此方面是否已正确设置
expect -c "spawn ls"
响应可能是
The system has no more ptys. Ask your system administrator to create more.
如果收到以上消息,则主机未正确设置其 PTY。 在这种情况下,在解决此问题之前,运行 GCC 和 Binutils 的测试套件毫无意义。 请查阅 LFS 常见问题解答,网址为 http://www.linuxfromscratch.org//lfs/faq.html#no-ptys,以获取有关如何使 PTY 正常工作的更多信息。
首先更正一个已知问题,并进行必要的调整
patch -Np1 -i ../gcc-3.4.3-no_fixincludes-1.patch patch -Np1 -i ../gcc-3.4.3-specs-2.patch
第一个补丁禁用了 GCC fixincludes 脚本。 前面已经简要提到了这一点,但是这里需要对 fixincludes 过程进行更深入的解释。 在正常情况下,GCC fixincludes 脚本会扫描系统以查找需要修复的头文件。 它可能会发现主机系统上的某些 Glibc 头文件需要修复,并会修复它们,然后将它们放在 GCC 私有 include 目录中。 在 第 6 章 中,安装了较新的 Glibc 之后,将在系统 include 目录之前搜索此私有 include 目录。 这可能会导致 GCC 找到主机系统上已修复的标头,这些标头很可能与用于 LFS 系统的 Glibc 版本不匹配。
第二个补丁更改了 GCC 动态链接器的默认位置(通常是ld-linux.so.2)。 它还删除了/usr/include从 GCC 的 include 搜索路径中删除。 现在进行修补,而不是在安装后调整 specs 文件,可以确保在 GCC 的实际构建过程中使用新的动态链接器。 也就是说,在构建过程中创建的所有最终(和临时)二进制文件都将链接到新的 Glibc。
以上补丁对于确保整体构建成功至关重要。 请勿忘记应用它们。
再次创建一个单独的构建目录
mkdir -v ../gcc-build cd ../gcc-build
在开始构建 GCC 之前,请记住取消设置任何覆盖默认优化标志的环境变量。
现在准备 GCC 以进行编译
../gcc-3.4.3/configure --prefix=/tools \ --libexecdir=/tools/lib --with-local-prefix=/tools \ --enable-clocale=gnu --enable-shared \ --enable-threads=posix --enable-__cxa_atexit \ --enable-languages=c,c++ --disable-libstdcxx-pch
新的 configure 选项的含义
此选项确保在任何情况下都为 C++ 库选择正确的区域设置模型。 如果配置脚本找到已安装的 de_DE 区域设置,它将选择正确的 gnu 区域设置模型。 但是,如果未安装 de_DE 区域设置,则存在构建应用程序二进制接口 (ABI) 不兼容的 C++ 库的风险,因为可能会选择不正确的通用区域设置模型。
此选项为多线程代码启用 C++ 异常处理。
此选项允许使用 __cxa_atexit 而不是 atexit 来注册本地静态变量和全局对象的 C++ 析构函数。 对于完全符合标准的析构函数处理,此选项至关重要。 它还会影响 C++ ABI,因此生成的 C++ 共享库和 C++ 程序可以与其他 Linux 发行版互操作。
此选项确保构建 C 和 C++ 编译器。
不要为以下项目构建预编译头文件 (PCH):libstdc++。 它占用大量空间,而且我们不需要它。
编译软件包
make
现在不需要使用 bootstrap 目标,因为用于编译此 GCC 的编译器是从与之前使用的 GCC 源代码完全相同的版本构建的。
编译现已完成。 如前所述,运行本章中编译的临时工具的测试套件不是强制性的。 若无论如何都要运行 GCC 测试套件,请使用以下命令:
make -k check
-k 标志用于使测试套件运行到完成,而不是在第一次失败时停止。 GCC 测试套件非常全面,几乎可以保证会产生一些失败。 要接收测试套件结果的摘要,请运行
../gcc-3.4.3/contrib/test_summary
仅对于摘要,请通过 grep -A7 Summ 管道输出。
可以将结果与位于 http://www.linuxfromscratch.org/lfs/build-logs/6.1.1/ 的结果进行比较。
一些意想不到的失败并不总是可以避免的。 GCC 开发人员通常意识到这些问题,但尚未解决。 除非测试结果与上述 URL 的结果差异很大,否则可以安全地继续。
安装软件包
make install
此时强烈建议重复我们在本章前面执行的健全性检查。 请参阅 第 5.7 节“调整工具链”,并重复测试编译。 如果结果错误,最可能的原因是没有正确应用 GCC Specs 补丁。
有关此软件包的详细信息,请参见 第 6.14.2 节,“GCC 的内容。”
Binutils 软件包包含一个链接器、一个汇编器和其他用于处理目标文件的工具。
已知此软件包在其默认优化标志(包括 -march 和 -mcpu 选项)被更改时会出现问题。如果定义了任何覆盖默认优化的环境变量,例如CFLAGS和CXXFLAGS,请在构建 Binutils 时取消设置它们。
再次创建一个单独的构建目录
mkdir -v ../binutils-build cd ../binutils-build
准备编译 Binutils
../binutils-2.15.94.0.2.2/configure --prefix=/tools \ --disable-nls --enable-shared --with-lib-path=/tools/lib
新的 configure 选项的含义
此命令告诉配置脚本在编译 Binutils 期间指定库搜索路径,从而导致/tools/lib被传递给链接器。 这可以防止链接器搜索主机上的库目录。
编译软件包
make
编译现已完成。 如前所述,运行此章节中临时工具的测试套件不是强制性的。 若无论如何都要运行 Binutils 测试套件,请执行以下命令
make check
安装软件包
make install
现在为下一章中的“重新调整”阶段准备链接器
make -C ld clean make -C ld LIB_PATH=/usr/lib:/lib
不要 删除 Binutils 源代码和构建目录。 下一章中仍需要这些目录的当前状态。
有关此软件包的详细信息,请参见 第 6.13.2 节,“Binutils 的内容。”
Gawk 包包含用于处理文本文件的程序。
准备编译 Gawk
./configure --prefix=/tools
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
有关此软件包的详细信息,请参阅 第 6.20.2 节“Gawk 的内容”。
Coreutils 包包含用于显示和设置基本系统特征的实用程序。
准备编译 Coreutils
DEFAULT_POSIX2_VERSION=199209 ./configure --prefix=/tools
在针对 2.3.2 之后版本的 Glibc 编译时,此软件包存在问题。 一些 Coreutils 实用程序(例如 head、tail 和 sort)将拒绝其传统语法,这种语法已使用了大约 30 年。 这种旧语法非常普遍,因此应该保持兼容性,直到可以更新使用它的许多位置。 通过设置DEFAULT_POSIX2_VERSION环境变量为 “199209” 即可实现向后兼容。 如果不希望 Coreutils 与传统语法向后兼容,则省略设置DEFAULT_POSIX2_VERSION环境变量。 重要的是要记住,这样做会产生后果,包括需要修补仍然使用旧语法的许多软件包。 因此,建议严格按照给出的说明进行操作。
编译软件包
make
要测试结果,请执行:make RUN_EXPENSIVE_TESTS=yes check。 RUN_EXPENSIVE_TESTS=yes 参数告诉测试套件运行几个额外的测试,这些测试在某些平台上被认为相对昂贵(在 CPU 功率和内存使用方面),但在 Linux 上通常没有问题。
安装软件包
make install
有关此软件包的详细信息,请参阅 第 6.15.2 节“Coreutils 的内容”。
Bzip2 包包含用于压缩和解压缩文件的程序。 使用 bzip2 压缩文本文件比使用传统的 gzip 压缩百分比更高。
Bzip2 包不包含 configure 脚本。 使用以下命令编译和测试它
make
安装软件包
make PREFIX=/tools install
有关此软件包的详细信息,请参阅 第 6.40.2 节“Bzip2 的内容”。
Gzip 包包含用于压缩和解压缩文件的程序。
准备编译 Gzip
./configure --prefix=/tools
编译软件包
make
此软件包没有测试套件。
安装软件包
make install
有关此软件包的详细信息,请参阅 第 6.46.2 节“Gzip 的内容”。
Diffutils 包包含显示文件或目录之间差异的程序。
准备编译 Diffutils
./configure --prefix=/tools
编译软件包
make
此软件包没有测试套件。
安装软件包
make install
有关此软件包的详细信息,请参阅 第 6.41.2 节“Diffutils 的内容”。
Findutils 包包含用于查找文件的程序。 提供这些程序是为了递归搜索目录树并创建、维护和搜索数据库(通常比递归查找更快,但如果数据库没有最近更新则不可靠)。
准备编译 Findutils
./configure --prefix=/tools
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
有关此软件包的详细信息,请参阅 第 6.19.2 节“Findutils 的内容”。
Make 包包含用于编译软件包的程序。
准备编译 Make
./configure --prefix=/tools
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
有关此软件包的详细信息,请参阅 第 6.49.2 节“Make 的内容”。
Grep 包包含用于搜索文件的程序。
准备编译 Grep
./configure --prefix=/tools \ --disable-perl-regexp
configure 选项的含义
这确保 grep 程序不会链接到主机上可能存在的 Perl 兼容正则表达式 (PCRE) 库,但一旦我们进入 chroot 环境,该库将不可用。
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
有关此软件包的详细信息,请参阅 第 6.44.2 节“Grep 的内容”。
Sed 包包含一个流编辑器。
准备编译 Sed
./configure --prefix=/tools
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
有关此软件包的详细信息,请参阅 第 6.28.2 节“Sed 的内容”。
Gettext 包包含用于国际化和本地化的实用程序。 这些实用程序允许使用 NLS(本机语言支持)编译程序,从而使它们能够以用户的母语输出消息。
准备编译 Gettext
./configure --prefix=/tools --disable-libasprintf \ --without-csharp
configure 选项的含义
此标志告诉 Gettext 不要构建asprintf库。 因为本章和下一章中的任何内容都不需要此库,并且 Gettext 稍后会重新构建,所以排除它以节省时间和空间。
这确保 Gettext 不会构建对 C# 编译器的支持,该编译器可能存在于主机上,但一旦我们进入 chroot 环境,该编译器将不可用。
编译软件包
make
要测试结果,请执行:make check。 这需要相当长的时间,大约 7 个 SBU。 众所周知,Gettext 测试套件在某些主机条件下会遇到故障,例如,当它在主机上找到 Java 编译器时。 LFS 补丁项目提供了一个实验性补丁,用于禁用 Java,网址为 http://www.linuxfromscratch.org/patches/。
安装软件包
make install
该软件包的详细信息位于第 6.30.2 节,“Gettext 的内容”。
Ncurses 软件包包含用于终端无关处理字符屏幕的库。
准备编译 Ncurses
./configure --prefix=/tools --with-shared \ --without-debug --without-ada --enable-overwrite
configure 选项的含义
这确保 Ncurses 不会构建对 Ada 编译器的支持,该编译器可能存在于宿主机上,但在进入 chroot 环境后将不可用。
这告诉 Ncurses 将其头文件安装到/tools/include,而不是/tools/include/ncurses,以确保其他软件包可以成功找到 Ncurses 头文件。
编译软件包
make
此软件包没有测试套件。
安装软件包
make install
该软件包的详细信息位于第 6.21.2 节,“Ncurses 的内容”。
Patch 软件包包含一个程序,用于通过应用通常由 diff 程序创建的“patch”文件来修改或创建文件。
准备编译 Patch
CPPFLAGS=-D_GNU_SOURCE ./configure --prefix=/tools
预处理器标志 -D_GNU_SOURCE 仅在 PowerPC 平台上需要。在其他架构上可以省略。
编译软件包
make
此软件包没有测试套件。
安装软件包
make install
该软件包的详细信息位于第 6.51.2 节,“Patch 的内容”。
Tar 软件包包含一个归档程序。
准备编译 Tar
./configure --prefix=/tools
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
该软件包的详细信息位于第 6.57.2 节,“Tar 的内容”。
Texinfo 软件包包含用于读取、编写和转换 info 页面的程序。
准备编译 Texinfo
./configure --prefix=/tools
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
该软件包的详细信息位于第 6.34.2 节,“Texinfo 的内容”。
Bash 软件包包含 Bourne-Again SHell。
当针对较新版本的 Glibc 编译时,Bash 存在问题,导致它不适当地挂起。 此补丁修复了该问题
patch -Np1 -i ../bash-3.0-avoid_WCONTINUED-1.patch
准备编译 Bash
./configure --prefix=/tools --without-bash-malloc
configure 选项的含义
此选项关闭使用 Bash 的内存分配 (malloc) 函数,该函数已知会导致分段错误。 通过关闭此选项,Bash 将使用 Glibc 中的 malloc 函数,该函数更稳定。
编译软件包
make
要测试结果,请执行: make tests。
安装软件包
make install
为使用 sh 作为 shell 的程序创建一个链接
ln -vs bash /tools/bin/sh
该软件包的详细信息位于第 6.37.2 节,“Bash 的内容”。
M4 软件包包含一个宏处理器。
准备编译 M4
./configure --prefix=/tools
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
该软件包的详细信息位于第 6.24.2 节,“M4 的内容”。
Bison 软件包包含一个解析器生成器。
准备编译 Bison
./configure --prefix=/tools
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
该软件包的详细信息位于第 6.25.2 节,“Bison 的内容”。
Flex 软件包包含一个实用程序,用于生成识别文本中模式的程序。
Flex 包含几个已知错误。 这些可以使用以下补丁修复
patch -Np1 -i ../flex-2.5.31-debian_fixes-3.patch
GNU autotools 将检测到 Flex 源代码已被之前的补丁修改,并尝试相应地更新手册页。 这在许多系统上不起作用,并且默认页面很好,因此请确保它不会被重新生成
touch doc/flex.1
现在准备编译 Flex
./configure --prefix=/tools
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
该软件包的详细信息位于第 6.29.2 节,“Flex 的内容”。
Util-linux 软件包包含各种实用程序。 其中包括用于处理文件系统、控制台、分区和消息的实用程序。
默认情况下,Util-linux 不使用来自以下目录的最新安装的头文件和库/tools。这可以通过更改 configure 脚本来修复
sed -i 's@/usr/include@/tools/include@g' configure
准备编译 Util-linux
./configure
编译一些支持例程
make -C lib
只需要构建此软件包中包含的几个实用程序
make -C mount mount umount make -C text-utils more
此软件包没有测试套件。
将这些程序复制到临时工具目录
cp mount/{,u}mount text-utils/more /tools/bin
该软件包的详细信息位于第 6.59.3 节,“Util-linux 的内容”。
Perl 软件包包含 Practical Extraction and Report Language。
首先,通过应用以下补丁来调整一些硬编码到 C 库的路径
patch -Np1 -i ../perl-5.8.7-libc-1.patch
准备编译 Perl(确保获得命令的“IO Fcntl POSIX”部分 - 它们都是字母)
./configure.gnu --prefix=/tools -Dstatic_ext='IO Fcntl POSIX'
configure 选项的含义
这告诉 Perl 构建安装和测试下一章中的 Coreutils 软件包所需的最小静态扩展集。
只需要构建此软件包中包含的几个实用程序
make perl utilities
虽然 Perl 附带了一个测试套件,但不建议此时运行它。 只构建了 Perl 的一部分,并且现在运行 make test 也会导致构建 Perl 的其余部分,这在此时是不必要的。 如果需要,可以在下一章中运行测试套件。
安装这些工具及其库
cp -v perl pod/pod2man /tools/bin mkdir -pv /tools/lib/perl5/5.8.7 cp -Rv lib/* /tools/lib/perl5/5.8.7
该软件包的详细信息位于第 6.33.2 节,“Perl 的内容”。
本节中的步骤是可选的,但如果 LFS 分区相当小,则学习可以删除的不必要项目是有益的。 到目前为止构建的可执行文件和库包含大约 130 MB 的不需要的调试符号。 使用以下命令删除这些符号
strip --strip-debug /tools/lib/* strip --strip-unneeded /tools/{,s}bin/*
上述命令中的最后一个命令将跳过大约 20 个文件,报告它无法识别它们的文件格式。 其中大多数是脚本而不是二进制文件。
请注意不要在库上使用--strip-unneeded。 静态库将被破坏,并且工具链软件包需要重新构建。
为了节省另外 30 MB,请删除文档
rm -rf /tools/{info,man}
现在 LFS 文件系统上将至少有 850 MB 的可用空间,可用于在下一阶段构建和安装 Glibc。 如果您可以构建和安装 Glibc,您也可以构建和安装其余部分。
在本章中,我们进入构建站点并开始认真地构建 LFS 系统。 也就是说,我们 chroot 到临时迷你 Linux 系统中,进行一些最后的准备工作,然后开始安装软件包。
此软件的安装非常简单。 尽管在许多情况下,安装说明可以缩短和更通用,但我们选择为每个软件包提供完整的说明,以最大程度地减少出错的可能性。 了解 Linux 系统工作原理的关键是了解每个软件包的用途以及用户(或系统)为什么需要它。 对于每个已安装的软件包,都会给出其内容的摘要,然后是软件包安装的每个程序和库的简明描述。
如果使用本章中提供的编译器优化,请查看 http://www.linuxfromscratch.org/hints/downloads/files/optimization.txt 中的优化提示。 编译器优化可以使程序运行得更快一些,但它们也可能导致编译困难和运行程序时出现问题。 如果软件包在使用优化时拒绝编译,请尝试在不使用优化的情况下编译它,看看是否可以解决问题。 即使软件包在使用优化时确实可以编译,也存在因代码和构建工具之间的复杂交互而导致编译不正确的风险。 使用编译器优化所获得的潜在收益通常会被风险所抵消。 建议 LFS 的首次构建者在不进行自定义优化的情况下进行构建。 后续系统仍将运行非常快且同时稳定。
本章中安装软件包的顺序需要严格遵循,以确保没有程序意外获取引用/tools硬编码到其中的路径。 出于同样的原因,不要并行编译软件包。 并行编译可以节省时间(尤其是在双 CPU 机器上),但它可能会导致程序包含硬编码到/tools的路径,这将导致程序在删除该目录时停止工作。
在安装说明之前,每个安装页面都会提供关于软件包的信息,包括对其所包含内容的简要描述、大致的构建时间、构建过程所需的磁盘空间大小以及成功构建该软件包所需的任何其他软件包。安装说明之后,会列出软件包安装的程序和库(以及对这些程序和库的简要描述)。
为了跟踪哪个软件包安装了特定文件,可以使用软件包管理器。有关不同风格的软件包管理器的概述,请参阅 http://www.linuxfromscratch.org/blfs/view/svn/introduction/important.html。对于专门为 LFS 设计的软件包管理方法,我们推荐 http://www.linuxfromscratch.org/hints/downloads/files/more_control_and_pkg_man.txt。
本书的其余部分将在以 root 用户身份登录的情况下执行,而不再是以 lfs 用户身份登录。 此外,请仔细检查是否设置了$LFS已设置。
内核导出的各种文件系统用于与内核本身进行通信。 这些文件系统是虚拟的,因为它们不占用磁盘空间。 文件系统的内容驻留在内存中。
首先创建将要挂载文件系统的目录
mkdir -pv $LFS/{proc,sys}
现在挂载文件系统
mount -vt proc proc $LFS/proc mount -vt sysfs sysfs $LFS/sys
请记住,如果由于任何原因停止处理 LFS 系统并稍后重新启动,请务必在进入 chroot 环境之前再次检查这些文件系统是否已挂载。
很快将从 chroot 环境中挂载其他文件系统。 为了使主机保持最新,现在为每个文件系统执行“伪挂载”
mount -vft tmpfs tmpfs $LFS/dev mount -vft tmpfs tmpfs $LFS/dev/shm mount -vft devpts -o gid=4,mode=620 devpts $LFS/dev/pts
现在是进入 chroot 环境以开始构建和安装最终 LFS 系统的时候了。 以用户 root 身份,运行以下命令以进入目前仅填充临时工具的领域
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
传递给 env 命令的 -i 选项将清除 chroot 环境的所有变量。 之后,只有HOME, TERM, PS1和PATH变量会被重新设置。 TERM=$TERM 结构会将 chroot 中的TERM变量设置为与 chroot 外部相同的值。 vim 和 less 等程序需要此变量才能正常运行。 如果需要其他变量,例如CFLAGS或者CXXFLAGS,这是一个再次设置它们的好地方。
从现在开始,不再需要使用LFS变量了,因为所有工作都将仅限于 LFS 文件系统。 这是因为 Bash shell 被告知$LFS现在是根 (/) 目录。
请注意/tools/bin位于PATH中的最后。 这意味着一旦安装了临时工具的最终版本,它将不再被使用。 当 shell 不“记住”已执行二进制文件的位置时,就会发生这种情况——因此,通过将 +h 选项传递给 bash 来关闭哈希。
重要的是,本章和以下各章中的所有命令都必须在 chroot 环境中运行。 如果由于任何原因离开此环境(例如,重新启动),请记住首先挂载proc和devpts文件系统(在上一节中讨论),然后再次进入 chroot,然后再继续安装。
请注意,bash 提示符会显示I have no name!这是正常的,因为/etc/passwd文件尚未创建。
目前,/tools目录由用户 lfs 拥有,该用户仅存在于主机系统上。 尽管/tools目录可以在 LFS 系统完成后删除,但可以保留它以构建其他 LFS 系统。 如果/tools目录保持原样,则这些文件由没有相应帐户的用户 ID 拥有。 这是危险的,因为以后创建的用户帐户可能会获得相同的用户 ID,并且会拥有/tools目录及其中的所有文件,从而使这些文件容易受到恶意操作。
为了避免此问题,请稍后在创建/etc/passwd文件时,将 lfs 用户添加到新的 LFS 系统,并注意为其分配与主机系统上相同的用户和组 ID。 或者,通过运行以下命令将/tools目录的内容分配给用户 root
chown -R 0:0 /tools
该命令使用 0:0 而不是 root:root,因为在创建密码文件之前,chown 无法解析名称“root”。 本书假定您运行了此 chown 命令。
现在是时候在 LFS 文件系统中创建一些结构了。 通过发出以下命令来创建标准目录树
install -dv /{bin,boot,dev,etc/opt,home,lib,mnt} install -dv /{sbin,srv,usr/local,var,opt} install -dv /root -m 0750 install -dv /tmp /var/tmp -m 1777 install -dv /media/{floppy,cdrom} install -dv /usr/{bin,include,lib,sbin,share,src} ln -sv share/{man,doc,info} /usr install -dv /usr/share/{doc,info,locale,man} install -dv /usr/share/{misc,terminfo,zoneinfo} install -dv /usr/share/man/man{1,2,3,4,5,6,7,8} install -dv /usr/local/{bin,etc,include,lib,sbin,share,src} ln -sv share/{man,doc,info} /usr/local install -dv /usr/local/share/{doc,info,locale,man} install -dv /usr/local/share/{misc,terminfo,zoneinfo} install -dv /usr/local/share/man/man{1,2,3,4,5,6,7,8} install -dv /var/{lock,log,mail,run,spool} install -dv /var/{opt,cache,lib/{misc,locate},local} install -dv /opt/{bin,doc,include,info} install -dv /opt/{lib,man/man{1,2,3,4,5,6,7,8}}
默认情况下,创建目录的权限模式为 755,但这并非对所有目录都适用。 在上面的命令中,进行了两项更改——一项更改为用户 root 的主目录,另一项更改为临时文件的目录。
第一种模式更改确保不仅仅是任何人都可以进入/root目录——与普通用户对其主目录的处理方式相同。 第二种模式更改确保任何用户都可以写入/tmp和/var/tmp目录,但不能从中删除另一个用户的文件。 后者被所谓的“粘滞位”禁止,即 1777 位掩码中的最高位 (1)。
目录树基于文件系统层次结构标准 (FHS)(可在 http://www.pathname.com/fhs/ 中找到)。 除了上面创建的树之外,此标准还规定了/usr/local/games和/usr/share/games的存在。 FHS 对/usr/local/share子目录的结构并不精确,因此我们只创建所需的目录。 但是,如果您更喜欢严格遵守 FHS,请随意创建这些目录。
某些程序使用硬编码的程序路径,这些程序尚未存在。 为了满足这些程序的需求,请创建一些符号链接,这些符号链接将在本章的过程中,在安装软件后被实际文件替换。
ln -sv /tools/bin/{bash,cat,pwd,stty} /bin ln -sv /tools/bin/perl /usr/bin ln -sv /tools/lib/libgcc_s.so{,.1} /usr/lib ln -sv bash /bin/sh
为了使用户 root 能够登录并且名称“root”能够被识别,必须在/etc/passwd和/etc/group文件中包含相关条目。
通过运行以下命令来创建/etc/passwd文件
cat > /etc/passwd << "EOF" root:x:0:0:root:/root:/bin/bash EOF
root 的实际密码(此处使用的“x”只是一个占位符)将在稍后设置。
通过运行以下命令来创建/etc/group文件
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: video:x:12: utmp:x:13: usb:x:14: cdrom:x:15: EOF
创建的组不属于任何标准——这些组的确定部分基于本章中 Udev 配置的要求,部分基于许多现有 Linux 发行版采用的常见约定。 Linux 标准库 (LSB,可在 http://www.linuxbase.org 中找到) 仅建议除了 GID 为 0 的组“root”之外,还应存在 GID 为 1 的组“bin”。 所有其他组名和 GID 都可以由系统管理员自由选择,因为编写良好的程序不依赖于 GID 编号,而是使用组的名称。
要删除“I have no name!”提示,请启动一个新 shell。 由于完整的 Glibc 已在 第 5 章 中安装,并且/etc/passwd和/etc/group文件已创建,因此用户名和组名的解析现在可以工作了。
exec /tools/bin/bash --login +h
请注意 +h 指令的使用。 这告诉 bash 不要使用其内部路径哈希。 如果没有此指令,bash 会记住它已执行的二进制文件的路径。 为了确保在安装后立即使用新编译的二进制文件,+h 指令将在本章的剩余时间内使用。
login、agetty 和 init 程序(以及其他程序)使用许多日志文件来记录诸如谁登录到系统以及何时登录的信息。 但是,如果这些日志文件尚不存在,则这些程序不会写入这些日志文件。 初始化日志文件并赋予它们正确的权限
touch /var/run/utmp /var/log/{btmp,lastlog,wtmp} chgrp -v utmp /var/run/utmp /var/log/lastlog chmod -v 664 /var/run/utmp /var/log/lastlog
的/var/run/utmp文件记录当前已登录的用户。/var/log/wtmp文件记录所有登录和注销。/var/log/lastlog文件记录每个用户上次登录的时间。/var/log/btmp文件记录错误的登录尝试。
当内核启动系统时,它需要存在一些设备节点,特别是console和null设备。 设备节点将在硬盘上创建,以便在 udev 启动之前可用,并且在单用户模式下启动 Linux 时也可用(因此对console的权限有严格限制)。 通过运行以下命令来创建设备
mknod -m 600 /dev/console c 5 1 mknod -m 666 /dev/null c 1 3
填充/dev目录的最佳方法是挂载一个虚拟文件系统(例如tmpfs)在/dev目录上,并允许在虚拟文件系统上动态创建设备,因为它们被检测到或访问。 这通常在启动过程中完成。 由于此新系统尚未启动,因此有必要执行 LFS-Bootscripts 软件包本来会执行的操作,即挂载/dev:
mount -nvt tmpfs none /dev
Udev 软件包实际上是在/dev目录中创建设备的原因。 由于它将在过程的稍后阶段安装,因此手动创建完成此系统构建所需的最小设备节点集
mknod -m 622 /dev/console c 5 1 mknod -m 666 /dev/null c 1 3 mknod -m 666 /dev/zero c 1 5 mknod -m 666 /dev/ptmx c 5 2 mknod -m 666 /dev/tty c 5 0 mknod -m 444 /dev/random c 1 8 mknod -m 444 /dev/urandom c 1 9 chown -v root:tty /dev/{console,ptmx,tty}
LFS 需要一些符号链接和目录,这些符号链接和目录是在系统启动期间由 LFS-Bootscripts 软件包创建的。 由于这是一个 chroot 环境而不是启动的环境,因此需要在其中创建这些符号链接和目录
ln -sv /proc/self/fd /dev/fd ln -sv /proc/self/fd/0 /dev/stdin ln -sv /proc/self/fd/1 /dev/stdout ln -sv /proc/self/fd/2 /dev/stderr ln -sv /proc/kcore /dev/core mkdir -v /dev/pts mkdir -v /dev/shm
最后,在新创建的目录上挂载正确的虚拟(内核)文件系统
mount -vt devpts -o gid=4,mode=620 none /dev/pts mount -vt tmpfs none /dev/shm
上面执行的 mount 命令可能会导致以下警告消息
can't open /etc/fstab: No such file or directory.
This file—/etc/fstab—has not been created yet but is also not required for the file systems to be properly mounted. As such, the warning can be safely ignored.
Linux-Libc-Headers 软件包包含“净化”的内核头文件。
多年来,通常的做法是在/usr/include,但在过去几年中,内核开发人员一直坚决反对这样做。 这催生了 Linux-Libc-Headers 项目,该项目旨在维护 Linux 标头的 API 稳定版本。
安装头文件
cp -Rv include/asm-i386 /usr/include/asm cp -Rv include/linux /usr/include
确保所有标头都归 root 所有
chown -Rv root:root /usr/include/{asm,linux}
确保用户可以读取标头
find /usr/include/{asm,linux} -type d -exec chmod -v 755 {} \; find /usr/include/{asm,linux} -type f -exec chmod -v 644 {} \;
Man-pages 软件包包含超过 1200 个 man 手册页。
运行以下命令安装 Man-pages
make install
Glibc 软件包包含主要的 C 库。 此库提供用于分配内存、搜索目录、打开和关闭文件、读取和写入文件、字符串处理、模式匹配、算术等的例程。
LFS 之外的一些软件包建议安装 GNU libiconv,以便在不同的编码之间转换数据。该项目的主页 (https://gnu.ac.cn/software/libiconv/) 上说:“该库提供了一个 iconv() 实现,用于那些没有该实现的系统,或者其实现无法从/向 Unicode 转换的系统。” Glibc 提供了一个iconv()实现,并且可以从/向 Unicode 转换,因此 LFS 系统不需要 libiconv。
已知此软件包在其默认优化标志(包括 -march 和 -mcpu 选项)被更改时会出现问题。如果定义了任何覆盖默认优化的环境变量,例如CFLAGS和CXXFLAGS,在构建 Glibc 时取消设置它们。
Glibc 构建系统是自包含的,即使编译器规范文件和链接器仍然指向/tools,它也可以完美地安装。在安装 Glibc 之前,不能调整规范和链接器,因为 Glibc autoconf 测试会给出错误的结果,并破坏实现干净构建的目标。
linuxthreads tarball 包含 Glibc 安装的线程库的 man 手册页。从 Glibc 源代码目录中解包 tarball
tar -xjvf ../glibc-linuxthreads-2.3.4.tar.bz2
在某些罕见的情况下,当不存在标准搜索目录时,Glibc 可能会出现段错误。以下补丁可以防止这种情况发生
patch -Np1 -i ../glibc-2.3.4-rtld_search_dirs-1.patch
当运行的内核是 2.6.11.x 时,Glibc 有两个测试会失败。问题已确定是测试本身的问题,而不是 libc 或内核的问题。此补丁修复了该问题
patch -Np1 -i ../glibc-2.3.4-fix_test-1.patch
应用以下补丁以修复 Glibc 中的一个错误,该错误可能阻止某些程序(包括 OpenOffice.org)运行
patch -Np1 -i ../glibc-2.3.4-tls_assert-1.patch
Glibc 文档建议在源代码目录之外的专用构建目录中构建 Glibc
mkdir -v ../glibc-build cd ../glibc-build
准备编译 Glibc
../glibc-2.3.4/configure --prefix=/usr \ --disable-profile --enable-add-ons \ --enable-kernel=2.6.0 --libexecdir=/usr/lib/glibc
新的 configure 选项的含义
这将 pt_chown 程序的默认位置从/usr/libexec更改为/usr/lib/glibc.
编译软件包
make
在本节中,Glibc 的测试套件被认为是至关重要的。在任何情况下都不要跳过它。
测试结果
make -k check >glibc-check-log 2>&1 grep Error glibc-check-log
Glibc 测试套件高度依赖于主机系统的某些功能,尤其是内核。一般来说,Glibc 测试套件总是期望通过。但是,在某些情况下,一些失败是不可避免的。这是最常见的问题列表
当在 CPU 不是相对较新的真正的 Intel 或正宗的 AMD 的系统上运行时,math 测试有时会失败。某些优化设置也已知是一个因素。
由于主机系统问题,gettext 测试有时会失败。确切原因尚不清楚。
如果您使用 noatime 选项挂载 LFS 分区,则 atime 测试将失败。正如 第 2.4 节“挂载新分区” 中提到的,在构建 LFS 时不要使用 noatime 选项。
在较旧和较慢的硬件上运行时,由于超过了测试超时,某些测试可能会失败。
虽然这是一个无害的消息,但 Glibc 的安装阶段会抱怨缺少/etc/ld.so.conf的无害警告。 使用以下方法阻止此警告
touch /etc/ld.so.conf
安装软件包
make install
上述命令没有安装可以使系统以不同语言响应的语言环境。使用以下命令安装它
make localedata/install-locales
为了节省时间,另一种运行前一个命令(它生成并安装 glibc-2.3.4/localedata/SUPPORTED 文件中列出的每个语言环境)的替代方法是仅安装那些需要和想要的语言环境。这可以通过使用 localedef 命令来实现。有关此命令的信息位于INSTALL文件中。 但是,为了使将来软件包的测试能够通过,特别是 GCC 中的 libstdc++ 测试,需要许多区域设置。 以下说明(代替上面使用的 install-locales 目标)将安装成功运行测试所需的最小区域设置集
mkdir -pv /usr/lib/locale localedef -i de_DE -f ISO-8859-1 de_DE localedef -i de_DE@euro -f ISO-8859-15 de_DE@euro localedef -i en_HK -f ISO-8859-1 en_HK localedef -i en_PH -f ISO-8859-1 en_PH localedef -i en_US -f ISO-8859-1 en_US localedef -i es_MX -f ISO-8859-1 es_MX localedef -i fa_IR -f UTF-8 fa_IR localedef -i fr_FR -f ISO-8859-1 fr_FR localedef -i fr_FR@euro -f ISO-8859-15 fr_FR@euro localedef -i it_IT -f ISO-8859-1 it_IT localedef -i ja_JP -f EUC-JP ja_JP
上述 make localedata/install-locales 命令安装的某些语言环境未被 LFS 和 BLFS 书籍中的某些应用程序正确支持。由于应用程序程序员做出假设导致在这种语言环境中出现各种问题,因此不应在利用多字节字符集(包括 UTF-8)或从右到左书写顺序的语言环境中使用 LFS。需要许多非官方和不稳定的补丁来解决这些问题,并且 LFS 开发人员已决定目前不支持如此复杂的语言环境。这同样适用于 ja_JP 和 fa_IR 语言环境——它们仅用于通过 GCC 和 Gettext 测试,并且 watch 程序(Procps 软件包的一部分)在其中无法正常工作。各种试图规避这些限制的尝试都记录在国际化相关的提示中。
构建 linuxthreads man 手册页,这是关于线程 API 的一个很好的参考(也适用于 NPTL)
make -C ../glibc-2.3.4/linuxthreads/man
安装这些手册页
make -C ../glibc-2.3.4/linuxthreads/man install
的/etc/nsswitch.conf需要创建文件,因为虽然 Glibc 在缺少或损坏此文件时提供默认值,但 Glibc 默认值在网络环境中效果不佳。还需要配置时区。
创建一个新文件/etc/nsswitch.conf通过运行以下命令
cat > /etc/nsswitch.conf << "EOF" # Begin /etc/nsswitch.conf passwd: files group: files shadow: files hosts: files dns networks: files protocols: files services: files ethers: files rpc: files # End /etc/nsswitch.conf EOF
要确定本地时区,请运行以下脚本
tzselect
在回答了有关位置的一些问题后,脚本将输出时区的名称(例如,EST5EDT 或 Canada/Eastern)。然后创建/etc/localtime通过运行
cp -v --remove-destination /usr/share/zoneinfo/[xxx] \ /etc/localtime
将 [xxx] 替换为 tzselect 提供的时区名称(例如,Canada/Eastern)。
cp 选项的含义
这是强制删除已存在的符号链接所必需的。复制文件而不是使用符号链接的原因是为了涵盖以下情况/usr位于单独的分区上。这在引导到单用户模式时可能很重要。
默认情况下,动态加载器(/lib/ld-linux.so.2)搜索/lib和/usr/lib以查找程序运行时所需的动态库。但是,如果目录中存在库,而不是/lib和/usr/lib,则需要将这些目录添加到/etc/ld.so.conf文件中,以便动态加载器可以找到它们。通常已知包含其他库的两个目录是/usr/local/lib和/opt/lib,因此将这些目录添加到动态加载器的搜索路径中。
创建一个新文件/etc/ld.so.conf通过运行以下命令
cat > /etc/ld.so.conf << "EOF" # Begin /etc/ld.so.conf /usr/local/lib /opt/lib # End /etc/ld.so.conf EOF
现在已经安装了最终的 C 库,是时候再次调整工具链了。 将调整工具链,以便将任何新编译的程序与这些新库链接。 这与第 5 章开始时的“调整”阶段使用的过程相同,但是调整是相反的。 在第 5 章中,链条是从主机的/{,usr/}lib目录引导到新的/tools/lib目录。 现在,该链条将从同一/tools/lib目录引导到 LFS/{,usr/}lib目录。
首先调整链接器。 Binutils 第二次传递的源代码和构建目录被保留用于此目的。 通过在以下位置运行以下命令来安装已调整的链接器binutils-build目录中运行以下命令来安装
make -C ld INSTALL=/tools/bin/install install
如果错过了先前在第 5 章中保留 Binutils 源代码和第二次传递的构建目录的警告,或者如果它们被意外删除或无法访问,请忽略上面的命令。 结果是,下一个软件包 Binutils 将链接到 C 库/tools中,而不是/{,usr/}lib中。 这不是理想的情况,但是,测试表明生成的 Binutils 程序二进制文件应该是相同的。
从现在开始,每个编译的程序都将仅与以下位置的库链接/usr/lib和/lib。 需要额外的 INSTALL=/tools/bin/install 选项,因为Makefile文件在第二次传递期间创建,仍然包含对 /usr/bin/install 的引用,该引用尚未安装。 某些主机发行版包含一个ginstall符号链接,该链接在Makefile文件中优先,并且可能导致问题。 上面的命令解决了这个问题。
现在删除 Binutils 源代码和构建目录。
接下来,修改 GCC specs 文件,使其指向新的动态链接器。 一个 perl 命令完成了此操作
perl -pi -e 's@ /tools/lib/ld-linux.so.2@ /lib/ld-linux.so.2@g;' \ -e 's@\*startfile_prefix_spec:\n@$_/usr/lib/ @g;' \ `gcc --print-file specs`
最好目视检查 specs 文件,以验证是否实际进行了预期的更改。
如果在动态链接器的名称不是ld-linux.so.2,在上面的命令中,用平台动态链接器的名称替换“ld-linux.so.2”。 如果有必要,请回顾5.2 节“工具链技术说明”。
此时必须停止并确保已调整的工具链的基本功能(编译和链接)按预期工作。 为此,请执行完整性检查
echo 'main(){}' > dummy.c cc dummy.c readelf -l a.out | grep ': /lib'
如果一切正常,则不应有任何错误,并且最后一个命令的输出将是(允许动态链接器名称中的特定于平台的差异)
[Requesting program interpreter: /lib/ld-linux.so.2]
请注意:/lib现在是我们动态链接器的前缀。
如果输出未如上所示或根本未收到,则说明情况严重。 调查并重溯步骤以找出问题所在并加以纠正。 最可能的原因是 specs 文件修改出了问题。 在继续该过程之前,需要解决所有问题。
一切正常后,清除测试文件
rm -v dummy.c a.out
Binutils 软件包包含一个链接器、一个汇编器和其他用于处理目标文件的工具。
已知此软件包在其默认优化标志(包括 -march 和 -mcpu 选项)被更改时会出现问题。如果定义了任何覆盖默认优化的环境变量,例如CFLAGS和CXXFLAGS,请在构建 Binutils 时取消设置它们。
验证 PTY 是否在 chroot 环境中正常工作。 通过执行一个简单的测试来检查所有设置是否正确
expect -c "spawn ls"
如果出现以下消息,则 chroot 环境未设置为正确的 PTY 操作
The system has no more ptys. Ask your system administrator to create more.
在运行 Binutils 和 GCC 的测试套件之前,需要解决此问题。
Binutils 文档建议在源代码目录之外的专用构建目录中构建 Binutils。
mkdir -v ../binutils-build cd ../binutils-build
准备编译 Binutils
../binutils-2.15.94.0.2.2/configure --prefix=/usr \ --enable-shared
编译软件包
make tooldir=/usr
通常,tooldir(最终放置可执行文件的目录)设置为$(exec_prefix)/$(target_alias)。 例如,i686 机器会将此扩展为/usr/i686-pc-linux-gnu。 因为这是一个自定义系统,所以不需要/usr中的特定于目标的目录。$(exec_prefix)/$(target_alias)如果该系统用于交叉编译(例如,在 Intel 机器上编译一个可以在 PowerPC 机器上执行的代码的软件包),则可以使用。
本节中 Binutils 的测试套件被认为是至关重要的。 在任何情况下都不要跳过它。
测试结果
make check
安装软件包
make tooldir=/usr install
安装一些软件包需要的libiberty头文件
cp -v ../binutils-2.15.94.0.2.2/include/libiberty.h /usr/include
GCC 软件包包含 GNU 编译器集合,其中包括 C 和 C++ 编译器。
已知此软件包在其默认优化标志(包括 -march 和 -mcpu 选项)被更改时会出现问题。如果定义了任何覆盖默认优化的环境变量,例如CFLAGS和CXXFLAGS,在构建 GCC 时取消设置它们。
仅应用前一章中也使用的 No-Fixincludes 补丁(而不是 Specs 补丁)
patch -Np1 -i ../gcc-3.4.3-no_fixincludes-1.patch
当与较新版本的 Binutils 结合使用时,GCC 无法编译基本 Linux From Scratch 安装之外的一些软件包(例如,Mozilla 和 kdegraphics)。应用以下补丁来解决此问题
patch -Np1 -i ../gcc-3.4.3-linkonce-1.patch
应用一个 sed 替换,它将抑制安装libiberty.a的版本。libiberty.a而是使用Binutils提供的版本。
sed -i 's/install_to_$(INSTALL_DEST) //' libiberty/Makefile.in
GCC 文档建议在源代码目录之外的专用构建目录中构建 GCC
mkdir -v ../gcc-build cd ../gcc-build
准备 GCC 进行编译
../gcc-3.4.3/configure --prefix=/usr \ --libexecdir=/usr/lib --enable-shared \ --enable-threads=posix --enable-__cxa_atexit \ --enable-clocale=gnu --enable-languages=c,c++
编译软件包
make
在本节中,GCC 的测试套件被认为是至关重要的。 无论如何都不要跳过它。
测试结果,但不要因为错误而停止
make -k check
其中一些错误是已知问题,并在上一章中已注明。 第 5.11 节,“GCC-3.4.3 - Pass 2”中的测试套件说明仍然适用。 请务必根据需要参考它们。
安装软件包
make install
一些软件包希望 C 预处理器安装在/lib目录中。 为了支持这些软件包,请创建此符号链接
ln -sv ../usr/bin/cpp /lib
许多软件包使用名称 cc 来调用 C 编译器。 为了满足这些软件包,请创建一个符号链接
ln -sv gcc /usr/bin/cc
此时,强烈建议重复本章前面执行的健全性检查。 回顾第 6.12 节,“重新调整工具链”并重复检查。 如果结果出错,那么最可能的原因是从第 5 章 错误地应用了 GCC Specs 补丁。
Coreutils 包包含用于显示和设置基本系统特征的实用程序。
此软件包中的 uname 程序的一个已知问题是 -p 开关始终返回unknown. 以下补丁修复了 Intel 架构的此行为
patch -Np1 -i ../coreutils-5.2.1-uname-2.patch
阻止 Coreutils 安装稍后将由其他软件包安装的二进制文件
patch -Np1 -i ../coreutils-5.2.1-suppress_uptime_kill_su-1.patch
现在准备编译 Coreutils
DEFAULT_POSIX2_VERSION=199209 ./configure --prefix=/usr
编译软件包
make
Coreutils 的测试套件对系统用户和组的存在做了一些假设,这些假设在当前存在的最小环境中无效。 因此,在运行测试之前需要设置其他项目。 如果不运行测试套件,请跳到“安装软件包”。
创建两个虚拟组和一个虚拟用户
echo "dummy1:x:1000:" >> /etc/group echo "dummy2:x:1001:dummy" >> /etc/group echo "dummy:x:1000:1000:::/bin/bash" >> /etc/passwd
现在测试套件已准备好运行。 首先,运行旨在以用户 root 身份运行的测试
make NON_ROOT_USERNAME=dummy check-root
然后以 dummy 用户身份运行其余测试
src/su dummy -c "make RUN_EXPENSIVE_TESTS=yes check"
测试完成后,删除虚拟用户和组
sed -i '/dummy/d' /etc/passwd /etc/group
安装软件包
make install
将程序移动到 FHS 指定的位置
mv -v /usr/bin/{cat,chgrp,chmod,chown,cp,date,dd,df,echo} /bin mv -v /usr/bin/{false,hostname,ln,ls,mkdir,mknod,mv,pwd,rm} /bin mv -v /usr/bin/{rmdir,stty,sync,true,uname} /bin mv -v /usr/bin/chroot /usr/sbin
LFS-Bootscripts 包中的一些脚本依赖于 head 和 sleep。 由于/usr在引导的早期阶段可能不可用,因此这些二进制文件需要位于根分区上
mv -v /usr/bin/{head,sleep} /bin
Zlib 软件包包含一些程序使用的压缩和解压缩例程。
如果CFLAGS在环境中指定,则已知 Zlib 会不正确地构建其共享库。 如果使用指定的CFLAGS变量,请务必将 -fPIC 指令添加到CFLAGS在下面的 configure 命令期间使用该变量,然后在之后将其删除。
准备 Zlib 进行编译
./configure --prefix=/usr --shared --libdir=/lib
编译软件包
make
要测试结果,请执行:make check。
安装共享库
make install
之前的命令安装了一个.so文件在/lib中。我们将删除它并将其重新链接到/usr/lib:
rm -v /lib/libz.so ln -sfv ../../lib/libz.so.1.2.3 /usr/lib/libz.so
构建静态库
make clean ./configure --prefix=/usr make
要再次测试结果,请发出: make check。
安装静态库
make install
修复静态库的权限
chmod -v 644 /usr/lib/libz.a
Mktemp 软件包包含用于在 shell 脚本中创建安全临时文件的程序。
许多脚本仍然使用已弃用的 tempfile 程序,该程序具有与 mktemp 类似的功能。 补丁 Mktemp 以包含 tempfile 包装器
patch -Np1 -i ../mktemp-1.5-add_tempfile-2.patch
准备 Mktemp 进行编译
./configure --prefix=/usr --with-libc
configure 选项的含义
这会导致 mktemp 程序使用系统 C 库中的 mkstemp 和 mkdtemp 函数。
编译软件包
make
安装软件包
make install make install-tempfile
Iana-Etc软件包提供网络服务和协议的数据。
以下命令将 IANA 提供的原始数据转换为以下文件的正确格式:/etc/protocols和/etc/services数据文件
make
安装软件包
make install
Findutils 包包含用于查找文件的程序。 提供这些程序是为了递归搜索目录树并创建、维护和搜索数据库(通常比递归查找更快,但如果数据库没有最近更新则不可靠)。
准备编译 Findutils
./configure --prefix=/usr --libexecdir=/usr/lib/locate \ --localstatedir=/var/lib/locate
configure 选项的含义
此选项将 locate 数据库的位置更改为/var/lib/locate,这是符合 FHS 标准的。
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
Gawk 包包含用于处理文本文件的程序。
准备编译 Gawk
./configure --prefix=/usr --libexecdir=/usr/lib
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
Ncurses 软件包包含用于终端无关处理字符屏幕的库。
准备编译 Ncurses
./configure --prefix=/usr --with-shared --without-debug
编译软件包
make
此软件包没有测试套件。
安装软件包
make install
赋予 Ncurses 库执行权限
chmod -v 755 /usr/lib/*.5.4
修复一个不应执行的库
chmod -v 644 /usr/lib/libncurses++.a
将库移动到/lib目录,它们应该驻留在其中
mv -v /usr/lib/libncurses.so.5* /lib
由于库已移动,因此一些符号链接指向不存在的文件。重新创建这些符号链接
ln -sfv ../../lib/libncurses.so.5 /usr/lib/libncurses.so ln -sfv libncurses.so /usr/lib/libcurses.so
Readline 软件包是一组库,提供命令行编辑和历史记录功能。
以下补丁包括针对 Readline 有时仅在一行上显示 33 个字符然后换到下一行的问题的修复程序。它还包括 Readline 作者推荐的其他修复程序。
patch -Np1 -i ../readline-5.0-fixes-1.patch
准备 Readline 进行编译
./configure --prefix=/usr --libdir=/lib
编译软件包
make SHLIB_XLDFLAGS=-lncurses
make 选项的含义
此选项强制 Readline 链接到libncurses库。
安装软件包
make install
赋予 Readline 的动态库更适当的权限
chmod -v 755 /lib/lib{readline,history}.so*
现在将静态库移动到更适当的位置
mv -v /lib/lib{readline,history}.a /usr/lib
接下来,删除.so中的文件/lib并将它们重新链接到/usr/lib.
rm -v /lib/lib{readline,history}.so ln -sfv ../../lib/libreadline.so.5 /usr/lib/libreadline.so ln -sfv ../../lib/libhistory.so.5 /usr/lib/libhistory.so
Vim 软件包包含一个强大的文本编辑器。
如果您更喜欢另一个编辑器,例如 Emacs、Joe 或 Nano,请参阅 http://www.linuxfromscratch.org/blfs/view/svn/postlfs/editors.html 以获取建议的安装说明。
首先,解压缩vim-6.3.tar.bz2和(可选)vim-6.3-lang.tar.gz存档到同一目录中。 然后,将vimrc配置文件的默认位置更改为/etc:
echo '#define SYS_VIMRC_FILE "/etc/vimrc"' >> src/feature.h
Vim 有两个已知的安全漏洞,这些漏洞已在上游解决。 以下补丁修复了这些问题
patch -Np1 -i ../vim-6.3-security_fix-2.patch
现在准备 Vim 进行编译
./configure --prefix=/usr --enable-multibyte
configure 选项的含义
此可选但强烈推荐的开关启用对编辑多字节字符编码文件的支持。 如果使用具有多字节字符集的语言环境,则需要此选项。 此开关也有助于能够编辑最初在 Linux 发行版(如 Fedora Core)中创建的文本文件,这些文件使用 UTF-8 作为默认字符集。
编译软件包
make
要测试结果,请执行: make test。 但是,此测试套件会将大量二进制数据输出到屏幕,这可能会导致当前终端的设置出现问题。 这可以通过将输出重定向到日志文件来解决。
安装软件包
make install
许多用户习惯于使用 vi 而不是 vim。 为了允许在用户习惯性地输入 vi 时执行 vim,请创建一个符号链接
ln -sv vim /usr/bin/vi
如果要在 LFS 系统上安装 X Window 系统,则可能需要在安装 X 后重新编译 Vim。 Vim 附带一个 GUI 版本的编辑器,该编辑器需要安装 X 和一些额外的库。 有关此过程的更多信息,请参阅 Vim 文档和 BLFS 书籍中的 Vim 安装页面,网址为 http://www.linuxfromscratch.org/blfs/view/svn/postlfs/editors.html#postlfs-editors-vim。
默认情况下,vim 运行在 vi 不兼容模式。对于过去使用过其他编辑器的用户来说,这可能是全新的。“nocompatible”设置包含在下方,用于突出显示正在使用新行为。它也提醒那些想要更改为“compatible”模式的人,这应该是配置文件中的第一个设置。这是必要的,因为它会更改其他设置,并且重写必须在此设置之后进行。 通过运行以下命令创建一个默认的 vim 配置文件
cat > /etc/vimrc << "EOF" " Begin /etc/vimrc set nocompatible set backspace=2 syntax on if (&term == "iterm") || (&term == "putty") set background=dark endif " End /etc/vimrc EOF
set nocompatible 使 vim 的行为方式比 vi 兼容模式更有用(默认)。删除“no”以保留旧的 vi 行为。 set backspace=2 允许在换行符、自动缩进和插入开头处使用退格键。 syntax on 启用 vim 的语法高亮显示。最后,包含 set background=dark 的 if 语句纠正了 vim 对某些终端模拟器背景颜色的猜测。这为在这些程序的黑色背景上使用高亮显示提供了更好的配色方案。
可以通过运行以下命令获取其他可用选项的文档
vim -c ':options'
M4 软件包包含一个宏处理器。
准备编译 M4
./configure --prefix=/usr
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
Bison 软件包包含一个解析器生成器。
准备编译 Bison
./configure --prefix=/usr
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
Less 软件包包含一个文本文件查看器。
准备 Less 以进行编译
./configure --prefix=/usr --bindir=/bin --sysconfdir=/etc
configure 选项的含义
此选项告诉软件包创建的程序在/etc中查找配置文件。
编译软件包
make
安装软件包
make install
Groff 软件包包含用于处理和格式化文本的程序。
Groff 期望环境变量PAGE包含默认纸张尺寸。 对于美国的用户,PAGE=letter 是合适的。 在其他地方,PAGE=A4 可能更合适。
准备 Groff 以进行编译
PAGE=[paper_size] ./configure --prefix=/usr
编译软件包
make
安装软件包
make install
某些文档程序(例如 xman)如果没有以下符号链接,将无法正常工作
ln -sv soelim /usr/bin/zsoelim ln -sv eqn /usr/bin/geqn ln -sv tbl /usr/bin/gtbl
Sed 包包含一个流编辑器。
默认情况下,Sed 将其 HTML 文档安装在/usr/share/doc. 将其更改为/usr/share/doc/sed-4.1.4,方法是应用以下 sed。
sed -i 's@/doc@&/sed-4.1.4@' doc/Makefile.in
准备编译 Sed
./configure --prefix=/usr --bindir=/bin
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
Flex 软件包包含一个实用程序,用于生成识别文本中模式的程序。
Flex 包含几个已知错误。使用以下补丁修复这些错误。
patch -Np1 -i ../flex-2.5.31-debian_fixes-3.patch
GNU autotools 检测到 Flex 源代码已被先前的补丁修改,并尝试相应地更新 man 页面。这在许多系统上无法正常工作,并且默认页面很好,因此请确保它不会被重新生成。
touch doc/flex.1
准备编译 Flex。
./configure --prefix=/usr
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
有一些软件包希望在lex库中找到它。/usr/lib. 创建一个符号链接来解决这个问题。
ln -sv libfl.a /usr/lib/libl.a
一些程序尚不知道 flex,并尝试运行其前身 lex。为了支持这些程序,创建一个名为lex的包装脚本,该脚本调用flex在 lex 仿真模式下。
cat > /usr/bin/lex << "EOF" #!/bin/sh # Begin /usr/bin/lex exec /usr/bin/flex -l "$@" # End /usr/bin/lex EOF chmod -v 755 /usr/bin/lex
Gettext 包包含用于国际化和本地化的实用程序。 这些实用程序允许使用 NLS(本机语言支持)编译程序,从而使它们能够以用户的母语输出消息。
准备编译 Gettext
./configure --prefix=/usr
编译软件包
make
要测试结果,请执行:make check。这需要很长时间,大约 7 个 SBUs。
安装软件包
make install
Inetutils 包包含用于基本网络的程序。
Inetutils 在 Linux 2.6 内核系列中存在问题。通过应用以下补丁来解决这些问题
patch -Np1 -i ../inetutils-1.4.2-kernel_headers-1.patch
Inetutils 附带的所有程序都不会被安装。但是,Inetutils 构建系统将坚持安装所有 man 手册。以下补丁将纠正这种情况
patch -Np1 -i ../inetutils-1.4.2-no_server_man_pages-1.patch
准备编译 Inetutils
./configure --prefix=/usr --libexecdir=/usr/sbin \ --sysconfdir=/etc --localstatedir=/var \ --disable-logger --disable-syslogd \ --disable-whois --disable-servers
configure 选项的含义
此选项阻止 Inetutils 安装 logger 程序,该程序由脚本用于将消息传递到系统日志守护程序。不要安装它,因为 Util-linux 稍后会安装一个更好的版本。
此选项阻止 Inetutils 安装系统日志守护程序,该守护程序与 Sysklogd 包一起安装。
此选项禁用 Inetutils whois 客户端的构建,该客户端已过时。BLFS 书中有关于更好的 whois 客户端的说明。
这将禁用作为 Inetutils 包一部分包含的各种网络服务器的安装。这些服务器被认为不适合基本的 LFS 系统。有些服务器本质上是不安全的,并且仅在受信任的网络上才被认为是安全的。有关更多信息,请访问 http://www.linuxfromscratch.org/blfs/view/svn/basicnet/inetutils.html。请注意,许多这些服务器都有更好的替代品。
编译软件包
make
安装软件包
make install
将 ping 程序移动到其符合 FHS 的位置
mv -v /usr/bin/ping /bin
IPRoute2 包包含用于基于基本和高级 IPV4 的网络的程序。
此软件包中包含的 arpd 二进制文件依赖于 Berkeley DB。因为 arpd 不是基本 Linux 系统上的一个非常常见的需求,请通过应用下面的 sed 命令来删除对 Berkeley DB 的依赖。如果需要 arpd 二进制文件,可以在 BLFS Book 中找到编译 Berkeley DB 的说明,网址为 http://www.linuxfromscratch.org/blfs/view/svn/server/databases.html#db。
sed -i '/^TARGETS/s@arpd@@g' misc/Makefile
准备编译 IPRoute2
./configure
编译软件包
make SBINDIR=/sbin
make 选项的含义
这确保了 IPRoute2 二进制文件将被安装到/sbin。 这是根据 FHS 的正确位置,因为 LFS-Bootscripts 包使用了一些 IPRoute2 二进制文件。
安装软件包
make SBINDIR=/sbin install
Perl 软件包包含 Practical Extraction and Report Language。
为了完全控制 Perl 的设置方式,请运行交互式 Configure 脚本并手动选择构建此软件包的方式。 如果它自动检测到的默认值是合适的,请使用以下命令准备编译 Perl
./configure.gnu --prefix=/usr -Dpager="/bin/less -isR"
configure 选项的含义
这纠正了 perldoc 调用 less 程序的方式中的错误。
编译软件包
make
要运行测试套件,首先创建一个基本的/etc/hosts文件,几个测试需要该文件来解析网络名称 localhost
echo "127.0.0.1 localhost $(hostname)" > /etc/hosts
现在运行测试,如果需要
make test
安装软件包
make install
Texinfo 软件包包含用于读取、编写和转换 info 页面的程序。
Texinfo 允许本地用户通过对临时文件的符号链接攻击覆盖任意文件。应用以下补丁来修复此问题
patch -Np1 -i ../texinfo-4.8-tempfile_fix-1.patch
准备编译 Texinfo
./configure --prefix=/usr
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
(可选)安装属于 TeX 安装的组件
make TEXMF=/usr/share/texmf install-tex
make 参数的含义
的TEXMFmakefile 变量保存 TeX 树根目录的位置,例如,如果稍后将安装 TeX 包。
Info 文档系统使用纯文本文件来保存其菜单条目列表。 该文件位于/usr/share/info/dir。 遗憾的是,由于各种软件包的 Makefile 中偶尔出现的问题,它有时会与系统上安装的 info 页面失去同步。 如果/usr/share/info/dir文件需要重新创建,以下可选命令将完成该任务
cd /usr/share/info rm dir for f in * do install-info $f dir 2>/dev/null done
Autoconf 包包含用于生成可以自动配置源代码的 shell 脚本的程序。
准备 Autoconf 进行编译
./configure --prefix=/usr
编译软件包
make
要测试结果,请发出: make check。这需要很长时间,大约 2 个 SBU。
安装软件包
make install
Automake 包包含用于生成与 Autoconf 一起使用的 Makefile 的程序。
准备 Automake 进行编译
./configure --prefix=/usr
编译软件包
make
要测试结果,请发出: make check。这需要很长时间,大约 5 个 SBU。
安装软件包
make install
Bash 软件包包含 Bourne-Again SHell。
如果您下载了 Bash 文档 tarball 并且希望安装 HTML 文档,请执行以下命令
tar -xvf ../bash-doc-3.0.tar.gz && sed -i "s|htmldir = @htmldir@|htmldir = /usr/share/doc/bash-3.0|" \ Makefile.in
以下补丁修复了各种问题,包括 Bash 有时只在一行上显示 33 个字符,然后换到下一行的问题
patch -Np1 -i ../bash-3.0-fixes-3.patch
当针对较新版本的 Glibc 编译时,Bash 也会出现问题。 以下补丁解决了这个问题
patch -Np1 -i ../bash-3.0-avoid_WCONTINUED-1.patch
准备编译 Bash
./configure --prefix=/usr --bindir=/bin \ --without-bash-malloc --with-installed-readline
configure 选项的含义
此选项告诉 Bash 使用readline系统上已安装的库,而不是使用自己的 readline 版本。
编译软件包
make
要测试结果,请执行: make tests。
安装软件包
make install
运行新编译的 bash 程序(替换当前正在执行的程序)
exec /bin/bash --login +h
使用的参数使 bash 进程成为交互式登录 shell,并继续禁用哈希,以便在新程序可用时找到它们。
File 包包含一个用于确定给定文件或文件类型的实用程序。
准备 File 以进行编译
./configure --prefix=/usr
编译软件包
make
安装软件包
make install
Libtool 包包含 GNU 通用库支持脚本。它将使用共享库的复杂性包装在一个一致的、可移植的接口中。
准备 Libtool 以进行编译
./configure --prefix=/usr
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
Bzip2 包包含用于压缩和解压缩文件的程序。 使用 bzip2 压缩文本文件比使用传统的 gzip 压缩百分比更高。
应用一个补丁来安装这个软件包的文档
patch -Np1 -i ../bzip2-1.0.3-install_docs-1.patch
bzgrep 命令不会转义传递给它的文件名中的 '|' 和 '&'。 这允许使用运行 bzgrep 的用户的权限执行任意命令。 应用以下补丁来解决这个问题
patch -Np1 -i ../bzip2-1.0.3-bzgrep_security-1.patch
准备 Bzip2 以进行编译,使用
make -f Makefile-libbz2_so make clean
-f 标志将导致 Bzip2 使用不同的Makefile文件来构建,在本例中为Makefile-libbz2_so文件,它创建一个动态libbz2.so库并将 Bzip2 实用程序链接到它。
编译并测试软件包
make
如果重新安装 Bzip2,请先执行 rm -vf /usr/bin/bz*,否则以下 make install 将会失败。
安装程序
make install
将共享的 bzip2 二进制文件安装到/bin目录中,创建一些必要的符号链接,并进行清理
cp -v bzip2-shared /bin/bzip2 cp -av libbz2.so* /lib ln -sv ../../lib/libbz2.so.1.0 /usr/lib/libbz2.so rm -v /usr/bin/{bunzip2,bzcat,bzip2} ln -sv bzip2 /bin/bunzip2 ln -sv bzip2 /bin/bzcat
Diffutils 包包含显示文件或目录之间差异的程序。
准备编译 Diffutils
./configure --prefix=/usr
编译软件包
make
此软件包没有测试套件。
安装软件包
make install
Kbd 包包含键盘表文件和键盘实用程序。
准备 Kbd 以进行编译
./configure
编译软件包
make
安装软件包
make install
E2fsprogs 软件包包含用于处理ext2文件系统的实用程序。 它还支持ext3日志文件系统。
修复 E2fsprogs 测试套件中的编译错误
sed -i -e 's/-DTEST/$(ALL_CFLAGS) &/' lib/e2p/Makefile.in
建议在源树的子目录中构建 E2fsprogs
mkdir -v build cd build
准备 E2fsprogs 进行编译
../configure --prefix=/usr --with-root-prefix="" \ --enable-elf-shlibs --disable-evms
configure 选项的含义
某些程序(例如 e2fsck 程序)被认为是必要的程序。 例如,当/usr未挂载时,这些程序仍然需要可用。 它们属于像这样的目录/lib和/sbin。 如果未将此选项传递给 E2fsprogs 的 configure,则这些程序将安装到/usr目录中。
这会创建此软件包中的某些程序使用的共享库。
这会禁用 Enterprise Volume Management System (EVMS) 插件的构建。 此插件不是最新的 EVMS 内部接口,并且 EVMS 不作为基本 LFS 系统的一部分安装,因此不需要该插件。 有关 EVMS 的更多信息,请访问 EVMS 网站 http://evms.sourceforge.net/。
编译软件包
make
要测试结果,请执行:make check。
安装二进制文件和文档
make install
安装共享库
make install-libs
Grep 包包含用于搜索文件的程序。
准备编译 Grep
./configure --prefix=/usr --bindir=/bin
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
GRUB 软件包包含 GRand Unified Bootloader。
已知此软件包在其默认优化标志(包括 -march 和 -mcpu 选项)被更改时会出现问题。如果定义了任何覆盖默认优化的环境变量,例如CFLAGS和CXXFLAGS,在构建 GRUB 时取消设置它们。
准备 GRUB 进行编译
./configure --prefix=/usr
编译软件包
make
要测试结果,请执行:make check。
请注意,测试结果将始终显示错误“ufs2_stage1_5 太大。”这是由于编译器问题,但可以忽略,除非您计划从 UFS 分区启动。 这些分区通常仅由 Sun 工作站使用。
安装软件包
make install mkdir -v /boot/grub cp -v /usr/lib/grub/i386-pc/stage{1,2} /boot/grub
替换i386-pc替换为适合所用硬件的任何目录。
的i386-pc目录包含许多*stage1_5文件,不同的文件适用于不同的文件系统。 查看可用文件并将相应的文件复制到/boot/grub目录。 大多数用户将复制e2fs_stage1_5和/或reiserfs_stage1_5文件中包含相关条目。
Gzip 包包含用于压缩和解压缩文件的程序。
Gzip 有 2 个已知的安全漏洞。以下补丁解决了这两个问题
patch -Np1 -i ../gzip-1.3.5-security_fixes-1.patch
准备编译 Gzip
./configure --prefix=/usr
gzexe 脚本将 gzip 二进制文件的位置硬编码到其中。由于二进制文件的位置稍后会更改,因此以下命令可确保将新位置放置到脚本中
sed -i 's@"BINDIR"@/bin@g' gzexe.in
编译软件包
make
安装软件包
make install
将 gzip 程序移动到/bin目录,并创建一些常用的到它的符号链接
mv -v /usr/bin/gzip /bin rm -v /usr/bin/{gunzip,zcat} ln -sv gzip /bin/gunzip ln -sv gzip /bin/zcat ln -sv gzip /bin/compress ln -sv gunzip /bin/uncompress
Hotplug 包包含一些脚本,这些脚本对内核生成的 hotplug 事件作出反应。 这些事件对应于内核状态中在sysfs文件系统中可见的每次更改,例如,硬件的添加和删除。 此软件包还检测启动期间的现有硬件,并将相关模块插入到正在运行的内核中。
安装 Hotplug 包
make install
复制 “install” 目标省略的文件。
cp -v etc/hotplug/pnp.distmap /etc/hotplug
删除 Hotplug 安装的 init 脚本,因为我们将使用 LFS-Bootscripts 包中包含的脚本
rm -rfv /etc/init.d
LFS-Bootscripts 包尚不支持网络设备热插拔。 因此,请删除网络热插拔代理
rm -fv /etc/hotplug/net.agent
创建一个目录,用于存储可由 hotplug 加载的固件
mkdir -v /lib/firmware
Man 包包含用于查找和查看 man 页面的程序。
需要对 Man 的源代码进行两项调整。
第一个是 sed 替换,以将 -R 开关添加到PAGER变量,以便 Less 正确处理转义序列
sed -i 's@-is@&R@g' configure
第二个也是 sed 替换,以注释掉man.conf文件中的 “MANPATH /usr/man” 行,以防止在使用 whatis 等程序时出现冗余结果
sed -i 's@MANPATH./usr/man@#&@g' src/man.conf.in
准备 Man 进行编译
./configure -confdir=/etc
configure 选项的含义
这告诉 man 程序在man.conf配置文件的/etc目录中。
编译软件包
make
安装软件包
make install
如果您将在不支持文本属性(如颜色和粗体)的终端上工作,则可以通过编辑man.conf文件并将 -c 选项添加到NROFF变量中来禁用选择图形再现 (SGR) 转义序列。 如果您为一个计算机使用多种终端类型,则最好为不支持 SGR 的终端选择性地添加GROFF_NO_SGR环境变量。
如果区域设置的字符集使用 8 位字符,请搜索/etc/man.conf中以 “NROFF” 开头的行,并验证它是否与以下内容匹配
NROFF /usr/bin/nroff -Tlatin1 -mandoc
注意,即使“latin1”不是本地设置的字符集,也应该使用它。原因是,根据规范,如果没有一些奇怪的转义代码,groff无法排版国际标准化组织 (ISO) 8859-1 以外的字符。格式化 man 页面时,groff 认为它们是 ISO 8859-1 编码,此 -Tlatin1 开关告诉 groff 对输出使用相同的编码。由于 groff 不对输入字符进行重新编码,因此格式化结果实际上与输入编码相同,因此可以用作寻呼机的输入。
这并不能解决非 ISO 8859-1 本地设置中本地化 man 页面的 man2dvi 程序无法工作的问题。此外,它不适用于多字节字符集。第一个问题目前没有解决方案。第二个问题不需担心,因为 LFS 安装不支持多字节字符集。
有关 man 和 info 页面压缩的其他信息,请参阅 BLFS 书籍,网址为 http://www.linuxfromscratch.org/blfs/view/cvs/postlfs/compressdoc.html。
Make 包包含用于编译软件包的程序。
准备编译 Make
./configure --prefix=/usr
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
Module-Init-Tools 软件包包含用于处理 Linux 内核(大于或等于 2.5.47 版本)中的内核模块的程序。
Module-Init-Tools 尝试重写它的modprobe.conf在构建过程中生成 man 页面。这是不必要的,并且还依赖于 docbook2man — 它未安装在 LFS 中。运行以下命令以避免这种情况
touch modprobe.conf.5
如果您希望运行 Module-Init-Tools 的测试套件,您需要下载单独的测试套件 tarball。发出以下命令来执行测试(请注意,需要 make distclean 命令来清理源树,因为源作为测试过程的一部分被重新编译)
tar -xvf ../module-init-tools-testsuite-3.1.tar.bz2 --strip-path=1 && ./configure && make check && make distclean
准备编译 Module-Init-Tools
./configure --prefix="" --enable-zlib
configure 选项的含义
这允许 Module-Init-Tools 软件包处理压缩的内核模块。
编译软件包
make
安装软件包
make install
Patch 软件包包含一个程序,用于通过应用通常由 diff 程序创建的“patch”文件来修改或创建文件。
准备编译 Patch。预处理器标志 -D_GNU_SOURCE 仅在 PowerPC 平台上需要。它可以从其他架构中省略
CPPFLAGS=-D_GNU_SOURCE ./configure --prefix=/usr
编译软件包
make
此软件包没有测试套件。
安装软件包
make install
Procps 软件包包含用于监视进程的程序。
编译软件包
make
安装软件包
make install
Psmisc 软件包包含用于显示有关运行进程的信息的程序。
准备编译 Psmisc
./configure --prefix=/usr --exec-prefix=""
configure 选项的含义
这确保 Psmisc 二进制文件将安装到/bin而不是/usr/bin。 这是根据 FHS 的正确位置,因为 LFS-Bootscripts 软件包使用了一些 Psmisc 二进制文件。
编译软件包
make
安装软件包
make install
没有理由让 pstree 和 pstree.x11 程序保留在/bin。因此,将它们移动到/usr/bin:
mv -v /bin/pstree* /usr/bin
默认情况下,Psmisc 的 pidof 程序不会安装。这通常不是问题,因为它稍后会在 Sysvinit 包中安装,该包提供了一个更好的 pidof 程序。如果特定系统不使用 Sysvinit,请通过创建以下符号链接来完成 Psmisc 的安装。
ln -sv killall /bin/pidof
Shadow 包包含用于以安全方式处理密码的程序。
如果您想强制使用强密码,请参考 http://www.linuxfromscratch.org/blfs/view/svn/postlfs/cracklib.html 在构建 Shadow 之前安装 Cracklib。 然后将 --with-libcrack 添加到下面的 configure 命令中。
准备编译 Shadow
./configure --libdir=/lib --enable-shared
禁用 groups 程序及其手册页的安装,因为 Coreutils 提供了一个更好的版本
sed -i 's/groups$(EXEEXT) //' src/Makefile sed -i '/groups/d' man/Makefile
编译软件包
make
安装软件包
make install
Shadow 使用两个文件来配置系统的身份验证设置。 安装这两个配置文件
cp -v etc/{limits,login.access} /etc
不要使用默认的 crypt 方法,而是使用更安全的 MD5 密码加密方法,该方法还允许密码超过 8 个字符。 还需要更改过时的/var/spool/mailShadow 默认使用的用户邮箱位置到/var/mail当前使用的位置。 这两个都可以通过在将相关配置文件复制到目标位置时更改它来实现
如果您使用 Cracklib 支持构建了 Shadow,请将以下内容插入到下面给出的 sed 中
-e 's@DICTPATH.*@DICTPATH\t/lib/cracklib/pw_dict@'
sed -e's@#MD5_CRYPT_ENAB.no@MD5_CRYPT_ENAB yes@' \ -e 's@/var/spool/mail@/var/mail@' \ etc/login.defs.linux > /etc/login.defs
将放错位置的程序移动到其正确的位置
mv -v /usr/bin/passwd /bin
将 Shadow 的库移动到更合适的位置
mv -v /lib/libshadow.*a /usr/lib rm -v /lib/libshadow.so ln -sfv ../../lib/libshadow.so.0 /usr/lib/libshadow.so
useradd 程序的 -D 选项需要/etc/default目录才能正常工作
mkdir -v /etc/default
该软件包包含添加、修改和删除用户和组的实用程序; 设置和更改他们的密码; 并执行其他管理任务。 有关 密码隐藏 含义的完整说明,请参见doc/HOWTO解压缩的源代码树中的文件。 如果使用 Shadow 支持,请记住,需要验证密码的程序(显示管理器、FTP 程序、pop3 守护程序等)必须符合 Shadow 标准。 也就是说,他们需要能够使用隐藏密码。
要启用隐藏密码,请运行以下命令
pwconv
要启用隐藏组密码,请运行
grpconv
在正常情况下,密码尚未创建。 但是,如果稍后返回本节以启用隐藏,请使用 passwd 命令重置任何当前用户密码,或使用 gpasswd 命令重置任何组密码。
选择用户 root 的密码并通过运行以下命令进行设置
passwd root
Sysklogd 包包含用于记录系统消息的程序,例如内核在发生异常情况时给出的消息。
以下补丁修复了各种问题,包括使用 Linux 2.6 系列内核构建 Sysklogd 的问题
patch -Np1 -i ../sysklogd-1.4.1-fixes-1.patch
编译软件包
make
安装软件包
make install
创建一个新的/etc/syslog.conf通过运行以下命令创建文件
cat > /etc/syslog.conf << "EOF" # Begin /etc/syslog.conf auth,authpriv.* -/var/log/auth.log *.*;auth,authpriv.none -/var/log/sys.log daemon.* -/var/log/daemon.log kern.* -/var/log/kern.log mail.* -/var/log/mail.log user.* -/var/log/user.log *.emerg * # log the bootscript output: local2.* -/var/log/boot.log # End /etc/syslog.conf EOF
Sysvinit 包包含用于控制系统的启动、运行和关闭的程序。
当运行级别改变时(例如,当停止系统时),init 会向由 init 自身启动且不应在新运行级别中运行的那些进程发送终止信号。 在执行此操作时,init 输出诸如“发送进程 TERM 信号”之类的消息,这似乎暗示它正在向所有当前正在运行的进程发送这些信号。 为了避免这种误解,请修改源代码,以便这些消息读起来像“向由 init 启动的进程发送 TERM 信号”
sed -i 's@Sending processes@& started by init@g' \ src/init.c
编译软件包
make -C src
安装软件包
make -C src install
创建一个新文件/etc/inittab通过运行以下命令
cat > /etc/inittab << "EOF" # Begin /etc/inittab id:3:initdefault: si::sysinit:/etc/rc.d/init.d/rc sysinit l0:0:wait:/etc/rc.d/init.d/rc 0 l1:S1:wait:/etc/rc.d/init.d/rc 1 l2:2:wait:/etc/rc.d/init.d/rc 2 l3:3:wait:/etc/rc.d/init.d/rc 3 l4:4:wait:/etc/rc.d/init.d/rc 4 l5:5:wait:/etc/rc.d/init.d/rc 5 l6:6:wait:/etc/rc.d/init.d/rc 6 ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now su:S016:once:/sbin/sulogin 1:2345:respawn:/sbin/agetty -I '\033(K' tty1 9600 2:2345:respawn:/sbin/agetty -I '\033(K' tty2 9600 3:2345:respawn:/sbin/agetty -I '\033(K' tty3 9600 4:2345:respawn:/sbin/agetty -I '\033(K' tty4 9600 5:2345:respawn:/sbin/agetty -I '\033(K' tty5 9600 6:2345:respawn:/sbin/agetty -I '\033(K' tty6 9600 # End /etc/inittab EOF
-I '\033(K' 选项告诉 agetty 在执行任何其他操作之前,向终端发送此转义序列。此转义序列将控制台字符集切换为用户自定义的字符集,该字符集可以通过运行 setfont 程序进行修改。来自 LFS-Bootscripts 包的 console initscript 在系统启动期间调用 setfont 程序。对于使用非 ISO 8859-1 屏幕字体的人来说,发送此转义序列是必要的,但它不会影响以英语为母语的人。
Tar 软件包包含一个归档程序。
当 -S 选项与大于 4 GB 的文件一起使用时,Tar 存在一个错误。以下补丁正确地修复了这个问题
patch -Np1 -i ../tar-1.15.1-sparse_fix-1.patch
准备编译 Tar
./configure --prefix=/usr --bindir=/bin --libexecdir=/usr/sbin
编译软件包
make
要测试结果,请执行:make check。
安装软件包
make install
Udev 包包含用于动态创建设备节点的程序。
编译软件包
make udevdir=/dev
这告诉 udev 在哪个目录中创建设备节点。
要测试结果,执行:make test。
安装软件包
make DESTDIR=/ udevdir=/dev install
make 选项的含义
这可以防止 Udev 构建过程杀死可能在主机系统上运行的任何 udevd 进程。
默认情况下,Udev 的配置远非理想,因此请在此处安装配置文件
cp -v ../udev-config-4.rules /etc/udev/rules.d/25-lfs.rules
运行 udevstart 程序以创建我们完整的设备节点补充。
/sbin/udevstart
Util-linux 软件包包含各种实用程序。 其中包括用于处理文件系统、控制台、分区和消息的实用程序。
FHS 建议使用/var/lib/hwclock目录而不是通常的/etc目录作为adjtime文件的位置。为了使 hwclock 程序符合 FHS,请运行以下命令
sed -i 's@etc/adjtime@var/lib/hwclock/adjtime@g' \ hwclock/hwclock.c mkdir -p /var/lib/hwclock
Util-linux 无法针对较新版本的 Linux-Libc-Headers 进行编译。以下补丁正确地修复了这个问题
patch -Np1 -i ../util-linux-2.12q-cramfs-1.patch
Util-linux 存在一个安全漏洞,可能允许用户在没有nosuid选项的情况下重新挂载卷。 以下补丁修复了这个问题
patch -Np1 -i ../util-linux-2.12q-umount_fix-1.patch
准备编译 Util-linux
./configure
编译软件包
make HAVE_KILL=yes HAVE_SLN=yes
make 参数的含义
这可以防止 kill 程序(已由 Procps 安装)被再次构建和安装。
这可以防止 sln 程序(Glibc 已经安装的 ln 的静态链接版本)被再次构建和安装。
此软件包没有测试套件。
安装包并将 logger 二进制文件移动到/bin因为 LFS-Bootscripts 包需要它
make HAVE_KILL=yes HAVE_SLN=yes install mv /usr/bin/logger /bin
默认情况下,大多数程序和库在编译时都包含调试符号(使用 gcc 的 -g 选项)。 这意味着当调试包含调试信息的程序或库时,调试器不仅可以提供内存地址,还可以提供例程和变量的名称。
但是,包含这些调试符号会显着扩大程序或库的体积。 以下是一个例子,说明了这些符号占用的空间量
带有调试符号的 bash 二进制文件:1200 KB
不带调试符号的 bash 二进制文件:480 KB
带有调试符号的 Glibc 和 GCC 文件(/lib和/usr/lib):87 MB
不带调试符号的 Glibc 和 GCC 文件:16 MB
大小可能因使用的编译器和 C 库而异,但比较带有和不带有调试符号的程序时,差异通常是 2 到 5 倍。
因为大多数用户永远不会在其系统软件上使用调试器,因此可以通过删除这些符号来回收大量磁盘空间。 下一节将介绍如何从程序和库中剥离所有调试符号。 有关系统优化的更多信息,请访问 http://www.linuxfromscratch.org/hints/downloads/files/optimization.txt。
如果目标用户不是程序员,并且不打算对系统软件进行任何调试,则可以通过从二进制文件和库中删除调试符号来减少大约 200 MB 的系统大小。 除了无法再完全调试该软件之外,这不会造成任何不便。
大多数使用下面提到的命令的人都不会遇到任何困难。 但是,很容易发生拼写错误并使新系统无法使用,因此在运行 strip 命令之前,最好备份当前情况。
在执行剥离之前,请特别注意确保要剥离的二进制文件没有正在运行。 如果不确定用户是否使用第 6.3 节“进入 Chroot 环境”中给出的命令进入了 chroot,请先从 chroot 中退出
logout
然后使用以下命令重新进入
chroot $LFS /tools/bin/env -i \ HOME=/root TERM=$TERM PS1='\u:\w\$ ' \ PATH=/bin:/usr/bin:/sbin:/usr/sbin \ /tools/bin/bash --login
现在可以安全地剥离二进制文件和库
/tools/bin/find /{,usr/}{bin,lib,sbin} -type f \ -exec /tools/bin/strip --strip-debug '{}' ';'
将会报告大量文件的文件格式无法识别。 可以安全地忽略这些警告。 这些警告表明这些文件是脚本而不是二进制文件。
如果磁盘空间非常紧张,则可以在/{,usr/}{bin,sbin}中使用 --strip-all 选项来获取更多兆字节。 不要在库上使用此选项——它们会被破坏。
从现在开始,在退出后重新进入 chroot 环境时,请使用以下修改后的 chroot 命令
chroot "$LFS" /usr/bin/env -i \ HOME=/root TERM="$TERM" PS1='\u:\w\$ ' \ PATH=/bin:/usr/bin:/sbin:/usr/sbin \ /bin/bash --login
原因是/tools中的程序不再需要。 由于不再需要它们,因此您可以根据需要删除/tools目录,或者将其打包并保存起来以构建另一个最终系统。
删除/tools还将删除用于运行工具链测试的 Tcl、Expect 和 DejaGNU 的临时副本。 如果您以后需要这些程序,则需要重新编译和重新安装它们。 BLFS 书籍包含有关此操作的说明(请参阅 http://www.linuxfromscratch.org/blfs/)。
本章详细介绍如何安装和配置 LFS-Bootscripts 软件包。 这些脚本中的大多数都可以在不修改的情况下工作,但一些脚本需要额外的配置文件,因为它们处理的是依赖于硬件的信息。
本书中使用 System-V 样式的 init 脚本,因为它们被广泛使用。 有关其他选项,请访问 http://www.linuxfromscratch.org/hints/downloads/files/bsd-init.txt 获取详细的 BSD 样式 init 设置提示。 在 LFS 邮件列表中搜索“depinit”也会提供更多选择。
如果使用替代样式的 init 脚本,请跳过本章并转到第 8 章。
LFS-Bootscripts 软件包包含一组在启动/关闭时启动/停止 LFS 系统的脚本。
安装软件包
make install
Linux 使用一种名为 SysVinit 的特殊启动机制,它基于运行级别的概念。 不同系统的运行级别可能差异很大,因此不能因为在某个特定的 Linux 发行版中正常工作,就认为它们在 LFS 中也应该以相同的方式工作。 LFS 有自己做事的方式,但它尊重普遍接受的标准。
SysVinit(从现在起简称为“init”)使用运行级别方案。 有七个运行级别(编号为 0 到 6)(实际上,还有更多运行级别,但它们用于特殊情况,通常不使用。 请参见init(8)了解更多详细信息),每个运行级别对应于计算机启动时应执行的操作。 默认运行级别为 3。以下是不同运行级别的描述,正如它们所实现的
0: 停止计算机
1: 单用户模式
2: 没有联网的多用户模式
3: 具有联网的多用户模式
4: 保留用于自定义,否则与 3 相同
5: 与 4 相同,通常用于 GUI 登录(如 X 的 xdm 或 KDE 的 kdm)
6: 重启计算机
用于更改运行级别的命令是 init [运行级别],其中 [运行级别] 是目标运行级别。 例如,要重启计算机,用户可以发出 init 6 命令,该命令是 reboot 命令的别名。 同样,init 0 是 halt 命令的别名。
下有许多目录/etc/rc.d看起来像rc?.d(其中 ? 是运行级别的编号)和rcsysinit.d,都包含许多符号链接。 有些以 K 开头,另一些以 S 开头,并且它们都以两个数字紧随其后。 K 表示停止(kill)服务,S 表示启动服务。 这些数字决定了脚本的运行顺序,从 00 到 99—数字越小,执行得越早。 当 init 切换到另一个运行级别时,根据选择的运行级别,将启动或停止相应的服务。
真正的脚本位于/etc/rc.d/init.d。 它们执行实际工作,所有符号链接都指向它们。 停止链接和启动链接指向/etc/rc.d/init.d中的同一个脚本。 这是因为可以使用不同的参数(例如 start、stop、restart、reload 和 status)调用这些脚本。 遇到 K 链接时,将使用 stop 参数运行相应的脚本。 遇到 S 链接时,将使用 start 参数运行相应的脚本。
此解释有一个例外。 在rc0.d和rc6.d目录中以 S 开头的链接不会导致任何启动。 将使用参数 stop 调用它们来停止某些内容。 这背后的逻辑是,当用户要重启或停止系统时,不需要启动任何内容。 系统只需要停止。
以下是对参数使脚本执行的操作的描述
服务已启动。
服务已停止。
服务已停止,然后再次启动。
服务的配置已更新。 这在修改了服务的配置文件后使用,而无需重新启动服务。
告知服务是否正在运行以及使用哪个 PID。
随意修改启动过程的工作方式(毕竟,这是您自己的 LFS 系统)。 此处给出的文件是它如何完成的一个示例。
在第 6 章中,我们安装了 Udev 软件包。 在我们深入研究其工作原理的细节之前,有必要简要回顾一下以前的设备处理方法。
通常,Linux 系统传统上使用静态设备创建方法,该方法在/dev下创建大量设备节点(有时实际上是数千个节点),而不管相应的硬件设备是否实际存在。 这通常通过 MAKEDEV 脚本完成,该脚本包含对 mknod 程序的多次调用,其中包含世界上可能存在的每个设备的相关的设备主编号和次编号。 使用 Udev 方法,只有内核检测到的设备才会创建设备节点。 因为每次系统启动时都会创建这些设备节点,所以它们将存储在tmpfs文件系统上(完全驻留在系统内存中的虚拟文件系统)。 设备节点不需要太多空间,因此使用的内存可以忽略不计。
2000 年 2 月,一个名为devfs的新文件系统合并到 2.3.46 内核中,并在 2.4 系列的稳定内核中可用。 尽管它存在于内核源代码本身中,但这种动态创建设备的方法从未得到核心内核开发人员的广泛支持。
采用的方法的主要问题devfs是它处理设备检测、创建和命名的方式。 最后一个问题,即设备节点命名,也许是最关键的。 人们普遍认为,如果允许配置设备名称,则设备命名策略应由系统管理员决定,而不是由任何特定开发人员强加给他们。 的devfs文件系统还存在其设计中固有的竞争条件,如果没有对内核进行重大修改,则无法修复。 由于最近缺乏维护,它也被标记为已弃用。
随着不稳定的 2.5 内核树的开发,后来发布为 2.6 系列的稳定内核,一个新的虚拟文件系统名为sysfs出现了。 的工作sysfs是将系统硬件配置的视图导出到用户空间进程。 有了这种用户空间可见的表示形式,看到用户空间替代devfs的可能性变得更加现实。
的sysfs文件系统在上面已简要提及。 人们可能想知道sysfs如何知道系统上存在的设备以及应该为它们使用什么设备编号。 直接编译到内核中的驱动程序会在内核检测到它们时,将它们的对象注册到sysfs。 对于编译为模块的驱动程序,此注册将在加载模块时发生。 一旦sysfs文件系统被挂载(在/sys上),内置驱动程序注册到sysfs的数据可用于用户空间进程和 udev 进行设备节点创建。
在 Linux 启动时,S10udev init 脚本负责创建这些设备节点。该脚本首先注册 /sbin/udevsend 作为热插拔事件处理程序。热插拔事件(如下所述)通常不会在此阶段生成,但会注册 udev 以防万一它们确实发生。然后,udevstart 程序会遍历/sys文件系统,并在/dev下创建与描述匹配的设备。例如,/sys/class/tty/vcs/dev包含字符串 “7:0”。udevstart 使用此字符串来创建/dev/vcs,主设备号为 7,次设备号为 0。在/dev目录下创建的节点的名称和权限是根据/etc/udev/rules.d/目录中的文件中指定的规则配置的。这些文件的编号方式与 LFS-Bootscripts 包类似。如果 udev 无法找到它正在创建的设备的规则,它会将权限默认设置为 660,所有者设置为 root:root。
完成上述阶段后,所有已存在且具有编译到内核中的驱动程序的设备都将可供使用。 这就引出了具有模块化驱动程序的设备。
之前,我们提到了“热插拔事件处理程序”的概念。当内核检测到新的设备连接时,内核会生成一个热插拔事件,并查看文件/proc/sys/kernel/hotplug以确定处理设备连接的用户空间程序。 udev 启动脚本将 udevsend 注册为此处理程序。生成这些热插拔事件时,内核会告诉 udev 检查/sys文件系统以获取有关此新设备的信息,并创建该设备的/dev条目。
这就引出了 udev 存在的一个问题,以及devfs之前存在的类似问题。它通常被称为“鸡和蛋”问题。大多数 Linux 发行版通过/etc/modules.conf中的条目来处理模块加载。访问设备节点会导致加载相应的内核模块。对于 udev,此方法不起作用,因为设备节点在模块加载之前不存在。为了解决这个问题,LFS-Bootscripts 包中添加了 S05modules 启动脚本,以及/etc/sysconfig/modules文件。通过将模块名称添加到模块文件中,这些模块将在计算机启动时加载。这允许 udev 检测设备并创建相应的设备节点。
请注意,在较慢的机器上或对于创建大量设备节点的驱动程序,创建设备的过程可能需要几秒钟才能完成。这意味着某些设备节点可能无法立即访问。
当您插入设备时,例如通用串行总线 (USB) MP3 播放器,内核会识别出该设备现在已连接,并生成一个热插拔事件。如果驱动程序已加载(无论是编译到内核中还是通过 S05modules 启动脚本加载),则将调用 udev 来根据sysfs中可用的数据创建相关的设备节点。/sys.
如果刚插入的设备的驱动程序可用作模块但当前未加载,则 Hotplug 包将加载相应的模块,并通过为其创建设备节点来使该设备可用。
自动创建设备节点时,存在一些已知问题
1) 内核驱动程序可能不会将其数据导出到sysfs.
这在来自内核树外部的第三方驱动程序中最常见。Udev 将无法自动创建此类驱动程序的设备节点。使用/etc/sysconfig/createfiles配置文件手动创建设备。查阅devices.txt内核文档中的文件或该驱动程序的文档以查找正确的主/次设备号。
2) 需要非硬件设备。这在高级 Linux 音频架构 (ALSA) 项目的开放声音系统 (OSS) 兼容性模块中最常见。可以通过以下两种方式之一处理这些类型的设备
将模块名称添加到/etc/sysconfig/modules
在/etc/modprobe.conf中使用 “install” 行。 这告诉 modprobe 命令 “加载此模块时,同时加载此其他模块。” 例如
install snd-pcm modprobe -i snd-pcm ; modprobe \ snd-pcm-oss ; true
这将导致系统在任何请求加载驱动程序 snd-pcm 时,同时加载 snd-pcm 和 snd-pcm-oss 模块。
以下站点提供了其他有用的文档
setclock 脚本从硬件时钟读取时间,硬件时钟也称为 BIOS 或互补金属氧化物半导体 (CMOS) 时钟。如果硬件时钟设置为 UTC,则此脚本将使用/etc/localtime文件将硬件时钟的时间转换为本地时间(该文件告诉 hwclock 程序用户所在的时区)。无法检测硬件时钟是否设置为 UTC,因此需要手动配置。
如果您不记得硬件时钟是否设置为 UTC,请运行 hwclock --localtime --show 命令来找出答案。这将显示根据硬件时钟的当前时间。如果此时间与您的手表显示的时间匹配,则表示硬件时钟设置为本地时间。如果 hwclock 的输出不是本地时间,则很可能将其设置为 UTC 时间。通过为时区加或减去适当的小时数来验证这一点。例如,如果您当前位于 MST 时区,也称为 GMT -0700,则将七个小时添加到本地时间。
将UTC变量的值更改为 0(零),如果硬件时钟 未 设置为 UTC 时间。
创建一个新文件/etc/sysconfig/clock通过运行以下命令
cat > /etc/sysconfig/clock << "EOF" # Begin /etc/sysconfig/clock UTC=1 # End /etc/sysconfig/clock EOF
在 http://www.linuxfromscratch.org/hints/downloads/files/time.txt 中可以找到一个很好的提示,解释如何在 LFS 上处理时间。它解释了时区、UTC 和TZ环境变量等问题。
本节讨论如何配置设置键盘映射和控制台字体的 console 启动脚本。如果不会使用非 ASCII 字符(例如,英镑符号和欧元字符),并且键盘是美国键盘,请跳过本节。如果没有配置文件,console 启动脚本将不执行任何操作。
console 脚本读取/etc/sysconfig/console文件以获取配置信息。决定将使用哪个键盘映射和屏幕字体。各种特定于语言的 HOWTO 也可以对此有所帮助(请参阅 http://www.tldp.org/HOWTO/HOWTO-INDEX/other-lang.html。一个预制的/etc/sysconfig/console文件,其中包含 LFS-Bootscripts 包安装的几个国家的已知设置,因此如果支持该国家/地区,则可以取消注释相关的部分。如果仍然不确定,请查看/usr/share/kbd目录以获取有效的键盘映射和屏幕字体。阅读loadkeys(1)和setfont(8)以确定这些程序的正确参数。确定后,使用以下命令创建配置文件
cat >/etc/sysconfig/console <<"EOF" KEYMAP="[arguments for loadkeys]" FONT="[arguments for setfont]" EOF
例如,对于想要使用欧元字符(可以通过按 AltGr+E 访问)的西班牙用户,以下设置是正确的
cat >/etc/sysconfig/console <<"EOF" KEYMAP="es euro2" FONT="lat9-16 -u iso01" EOF
的只有对于 ISO 8859-15 字符集,上面的 FONT行才是正确的。如果使用 ISO 8859-1,因此使用英镑符号而不是欧元,则正确的只有对于 ISO 8859-15 字符集,上面的 FONT行将是
FONT="lat1-16"
如果未设置KEYMAP或者只有对于 ISO 8859-15 字符集,上面的 FONT变量,则 console init 脚本将不会运行相应的程序。
在某些键盘映射中,退格键和删除键发送的字符与内核中内置的默认键盘映射中的字符不同。这会混淆某些应用程序。例如,当按下退格键时,Emacs 会显示其帮助(而不是删除光标之前的字符)。要检查正在使用的键盘映射是否受到影响(这仅适用于 i386 键盘映射)
zgrep '\W14\W' [/path/to/your/keymap]
如果键码 14 是退格键而不是删除键,请创建以下键盘映射代码段来解决此问题
mkdir -pv /etc/kbd && cat > /etc/kbd/bs-sends-del <<"EOF" keycode 14 = Delete Delete Delete Delete alt keycode 14 = Meta_Delete altgr alt keycode 14 = Meta_Delete keycode 111 = Remove altgr control keycode 111 = Boot control alt keycode 111 = Boot altgr control alt keycode 111 = Boot EOF
告诉 console 脚本在主键盘映射之后加载此代码段
cat >>/etc/sysconfig/console <<"EOF" KEYMAP_CORRECTIONS="/etc/kbd/bs-sends-del" EOF
要将键盘映射直接编译到内核中,而不是每次都从 console 启动脚本中设置它,请按照 第 8.3 节,“Linux-2.6.11.12” 中给出的说明进行操作。这样做可以确保键盘始终按预期工作,即使在启动到维护模式时(通过将 init=/bin/sh 传递给内核),因为在这种情况下不会运行 console 启动脚本。此外,内核不会自动设置屏幕字体。这不应该造成太多问题,因为 ASCII 字符将被正确处理,并且用户不太可能在维护模式下依赖非 ASCII 字符。
由于内核将设置键盘映射,因此可以省略KEYMAP配置文件中的/etc/sysconfig/console变量。如果需要,也可以将其保留在原位,而不会产生任何后果。如果运行多个不同的内核,很难确保键盘映射已编译到每个内核中,则保留它可能是有益的。
的sysklogd脚本使用 -m 0 选项调用 syslogd 程序。此选项关闭 syslogd 默认每 20 分钟写入日志文件的周期性时间戳标记。如果想打开此周期性时间戳标记,请编辑sysklogd脚本并进行相应的更改。有关详细信息,请参阅 man syslogd。
的inputrc文件处理特定情况下的键盘映射。此文件是 Bash 和大多数其他 shell 使用的 Readline(与输入相关的库)使用的启动文件。
大多数人不需要特定于用户的键盘映射,因此以下命令会创建一个全局/etc/inputrc供所有登录用户使用。如果您之后决定需要按用户覆盖默认设置,可以创建一个.inputrc文件,放在用户的主目录下,其中包含修改后的映射。
要了解更多关于如何编辑inputrc文件的信息,请参考 info bash 中的 Readline Init File 章节。info readline 也是一个很好的信息来源。
以下是一个通用的全局inputrc,以及解释各种选项作用的注释。请注意,注释不能与命令在同一行。使用以下命令创建该文件:
cat > /etc/inputrc << "EOF" # Begin /etc/inputrc # Modified by Chris Lynn <roryo@roryo.dynup.net> # Allow the command prompt to wrap to the next line set horizontal-scroll-mode Off # Enable 8bit input set meta-flag On set input-meta On # Turns off 8th bit stripping set convert-meta Off # Keep the 8th bit for display set output-meta On # none, visible or audible set bell-style none # All of the following map the escape sequence of the # value contained inside the 1st argument to the # readline specific functions "\eOd": backward-word "\eOc": forward-word # for linux console "\e[1~": beginning-of-line "\e[4~": end-of-line "\e[5~": beginning-of-history "\e[6~": end-of-history "\e[3~": delete-char "\e[2~": quoted-insert # for xterm "\eOH": beginning-of-line "\eOF": end-of-line # for Konsole "\e[H": beginning-of-line "\e[F": end-of-line # End /etc/inputrc EOF
Shell 程序 /bin/bash (以下简称 “shell”) 使用一系列启动文件来帮助创建运行环境。每个文件都有特定的用途,并且可能会以不同的方式影响登录和交互环境。/etc目录中的文件提供全局设置。如果主目录中存在等效文件,它可能会覆盖全局设置。
在成功登录后,使用 /bin/login 启动一个交互式登录 shell,并通过读取/etc/passwd文件来实现。交互式非登录 shell 在命令行启动(例如,[提示符]$/bin/bash)。非交互式 shell 通常在 shell 脚本运行时出现。它是非交互式的,因为它正在处理脚本,而不是等待用户在命令之间输入。
要了解更多信息,请参阅 info bash 中的 Bash Startup Files and Interactive Shells 章节。
文件/etc/profile和~/.bash_profile在将 shell 作为交互式登录 shell 调用时读取。
以下的基本/etc/profile设置了一些本地语言支持所需的环境变量。正确设置它们可以实现:
程序输出翻译成当地语言
将字符正确分类为字母、数字和其他类别。这是 bash 在非英语环境中正确接受命令行中的非 ASCII 字符所必需的
该国家/地区的正确字母排序
合适的默认纸张尺寸
货币、时间和日期值的正确格式
此脚本还设置了INPUTRC环境变量,使 Bash 和 Readline 使用之前创建的/etc/inputrc文件。
将下面的 [ll] 替换为所需语言的两位字母代码(例如,“en”),并将 [CC] 替换为相应国家/地区的两位字母代码(例如,“GB”)。[charmap] 应该替换为您选择的语言环境的规范字符映射。
可以通过运行以下命令获取 Glibc 支持的所有语言环境的列表:
locale -a
语言环境可以有许多同义词,例如,“ISO-8859-1” 也被称为 “iso8859-1” 和 “iso88591”。某些应用程序无法正确处理各种同义词,因此选择特定语言环境的规范名称是最安全的。要确定规范名称,请运行以下命令,其中 [locale name] 是 locale -a 为您首选语言环境提供的输出(在我们的示例中为 “en_GB.iso88591”)。
LC_ALL=[locale name] locale charmap
对于 “en_GB.iso88591” 语言环境,上述命令将打印:
ISO-8859-1
这将导致最终的语言环境设置为 “en_GB.ISO-8859-1”。重要的是,在使用启发式方法找到的语言环境添加到 Bash 启动文件之前,对其进行测试。
LC_ALL=[locale name] locale country LC_ALL=[locale name] locale language LC_ALL=[locale name] locale charmap LC_ALL=[locale name] locale int_curr_symbol LC_ALL=[locale name] locale int_prefix
上面的命令应该打印国家和语言名称,语言环境使用的字符编码,当地货币以及在拨打电话号码之前拨打的用于进入该国家/地区的前缀。 如果上面的任何命令失败并显示类似于下面显示的消息,则表示您的语言环境要么未在第 6 章中安装,要么不受 Glibc 的默认安装支持。
locale: Cannot set LC_* to default locale: No such file or directory
如果发生这种情况,您应该使用 localedef 命令安装所需的语言环境,或考虑选择其他语言环境。以下说明假定 Glibc 没有此类错误消息。
LFS 之外的一些软件包也可能缺乏对您选择的语言环境的支持。一个例子是 X 库(X Window System 的一部分),它输出以下错误消息:
Warning: locale not supported by Xlib, locale set to C
有时可以通过删除语言环境规范的字符映射部分来解决此问题,只要这不会更改 Glibc 与语言环境关联的字符映射(可以通过在两个语言环境中运行 locale charmap 命令来检查)。例如,必须将 “de_DE.ISO-8859-15@euro” 更改为 “de_DE@euro”,才能使 Xlib 识别此语言环境。
如果语言环境名称不符合他们的期望,其他软件包也可能无法正常工作(但不一定会显示任何错误消息)。在这些情况下,调查其他 Linux 发行版如何支持您的语言环境可能会提供一些有用的信息。
确定正确的语言环境设置后,创建/etc/profile文件
cat > /etc/profile << "EOF" # Begin /etc/profile export LANG=[ll]_[CC].[charmap] export INPUTRC=/etc/inputrc # End /etc/profile EOF
“C”(默认)和 “en_US”(推荐给美国英语用户)语言环境是不同的。
设置键盘布局、屏幕字体和与语言环境相关的环境变量是支持使用普通单字节编码和从左到右书写方向的语言环境所需的唯一国际化步骤。更复杂的情况(包括基于 UTF-8 的语言环境)需要额外的步骤和额外的补丁,因为许多应用程序在这些条件下往往无法正常工作。LFS 书籍中不包含这些步骤和补丁,LFS 尚不支持此类语言环境。
localnet 脚本的部分工作是设置系统的主机名。这需要在/etc/sysconfig/network文件中使用这些名称。
通过运行以下命令来创建/etc/sysconfig/network文件中配置,并通过运行以下命令输入主机名:
echo "HOSTNAME=[lfs]" > /etc/sysconfig/network
[lfs] 需要替换为分配给计算机的名称。 请勿在此处输入完全限定域名 (FQDN)。该信息将放在下一节的/etc/hosts文件中。
如果要配置网卡,请确定将在/etc/hosts文件中使用的 IP 地址、FQDN 和可能的别名。 语法是:
<IP address> myhost.example.org aliases
除非计算机对 Internet 可见(即,存在已注册的域和有效的已分配 IP 地址块 - 大多数用户没有此权限),否则请确保 IP 地址位于专用网络 IP 地址范围内。有效范围是:
Class Networks A 10.0.0.0 B 172.16.0.0 through 172.31.0.255 C 192.168.0.0 through 192.168.255.255
有效的 IP 地址可以是 192.168.1.1。 此 IP 的有效 FQDN 可以是 www.linuxfromscratch.org(不推荐,因为这是一个有效的已注册域地址,可能会导致域名服务器问题)。
即使不使用网卡,仍然需要 FQDN。 这是某些程序正常运行所必需的。
通过运行以下命令来创建/etc/hosts通过运行
cat > /etc/hosts << "EOF" # Begin /etc/hosts (network card version) 127.0.0.1 localhost [192.168.1.1] [<HOSTNAME>.example.org] [HOSTNAME] # End /etc/hosts (network card version) EOF
对于特定用户或要求,需要更改 [192.168.1.1] 和 [<HOSTNAME>.example.org] 值(如果由网络/系统管理员分配了 IP 地址,并且该计算机将连接到现有网络)。
如果不配置网卡,请创建/etc/hosts通过运行
cat > /etc/hosts << "EOF" # Begin /etc/hosts (no network card version) 127.0.0.1 [<HOSTNAME>.example.org] [HOSTNAME] localhost # End /etc/hosts (no network card version) EOF
本节仅适用于要配置网卡的情况。
如果不使用网卡,则可能无需创建任何与网卡相关的配置文件。如果是这种情况,请删除所有运行级别目录(network)中的/etc/rc.d/rc*.d).
网络脚本启动和停止哪些接口取决于/etc/sysconfig/network-devices层次结构中的文件和目录。 此目录应包含要配置的每个接口的子目录,例如ifconfig.xyz,其中 “xyz” 是网络接口名称。在此目录中将是定义此接口属性的文件,例如其 IP 地址、子网掩码等。
以下命令创建一个示例ipv4文件,用于 eth0 设备。
cd /etc/sysconfig/network-devices && mkdir -v ifconfig.eth0 && cat > ifconfig.eth0/ipv4 << "EOF" ONBOOT=yes SERVICE=ipv4-static IP=192.168.1.1 GATEWAY=192.168.1.2 PREFIX=24 BROADCAST=192.168.1.255 EOF
必须在每个文件中更改这些变量的值,以匹配正确的设置。如果ONBOOT变量设置为 “yes”,则网络脚本将在系统启动期间启动网络接口卡 (NIC)。如果设置为除 “yes” 之外的任何内容,则网络脚本将忽略 NIC 并且不会启动。
的SERVICE变量定义用于获取 IP 地址的方法。 LFS-Bootscripts 软件包具有模块化的 IP 分配格式,并且在/etc/sysconfig/network-devices/services目录中创建其他文件允许其他 IP 分配方法。这通常用于动态主机配置协议 (DHCP),这在 BLFS 书籍中进行了介绍。
的GATEWAY变量应包含默认网关 IP 地址(如果存在)。如果没有,则完全注释掉该变量。
的PREFIX变量需要包含子网中使用的位数。IP 地址中的每个八位字节为 8 位。如果子网的子网掩码为 255.255.255.0,则它使用前三个八位字节(24 位)来指定网络号。如果子网掩码为 255.255.255.240,则它将使用前 28 位。长于 24 位的网络前缀通常由 DSL 和基于电缆的 Internet 服务提供商 (ISP) 使用。在此示例中 (PREFIX=24),子网掩码为 255.255.255.0。根据您的特定子网调整PREFIX变量。
如果系统要连接到 Internet,则需要一些域名服务 (DNS) 名称解析方法,才能将 Internet 域名解析为 IP 地址,反之亦然。最好通过将 DNS 服务器的 IP 地址(可从 ISP 或网络管理员处获得)放入/etc/resolv.conf来实现。通过运行以下命令创建文件:
cat > /etc/resolv.conf << "EOF" # Begin /etc/resolv.conf domain {[Your Domain Name]} nameserver [IP address of your primary nameserver] nameserver [IP address of your secondary nameserver] # End /etc/resolv.conf EOF
将 [名称服务器的 IP 地址] 替换为最适合设置的 DNS 的 IP 地址。 通常会有多个条目(要求有辅助服务器用于回退功能)。 如果您只需要或想要一个 DNS 服务器,请从文件中删除第二个 nameserver 行。 IP 地址也可以是本地网络上的路由器。
的/etc/fstab文件被一些程序用来确定默认情况下文件系统应挂载在何处、按什么顺序挂载,以及哪些文件系统必须在挂载之前进行检查(以确保完整性)。创建一个新的文件系统表,如下所示
cat > /etc/fstab << "EOF" # Begin /etc/fstab # file system mount-point type options dump fsck # order /dev/[xxx] / [fff] defaults 1 1 /dev/[yyy] swap swap pri=1 0 0 proc /proc proc defaults 0 0 sysfs /sys sysfs defaults 0 0 devpts /dev/pts devpts gid=4,mode=620 0 0 shm /dev/shm tmpfs defaults 0 0 # End /etc/fstab EOF
将 [xxx]、[yyy] 和 [fff] 替换为适合系统的值,例如:hda2, hda5和ext2。有关此文件中六个字段的详细信息,请参阅 man 5 fstab。
使用日志文件系统时,行尾的 1 1 应替换为 0 0,因为此类分区不需要转储或检查。
的/dev/shm的挂载点tmpfs包含是为了允许启用 POSIX 共享内存。内核必须内置支持才能使其工作(有关此的更多信息将在下一节中介绍)。请注意,目前只有很少的软件使用 POSIX 共享内存。因此,请考虑/dev/shm挂载点是可选的。有关更多信息,请参阅Documentation/filesystems/tmpfs.txt在内核源代码树中。
还可以将其他行添加到/etc/fstab文件中。一个例子是 USB 设备的行
usbfs /proc/bus/usb usbfs devgid=14,devmode=0660 0 0
只有在内核中配置了“对主机端 USB 的支持”和“USB 设备文件系统”时,此选项才有效。如果“对主机端 USB 的支持”被编译为模块,则usbcore必须在/etc/sysconfig/modules.
Linux 软件包包含 Linux 内核。
构建内核涉及几个步骤:配置、编译和安装。阅读README内核源代码树中的文件,了解本书配置内核的替代方法。
运行以下命令准备编译
make mrproper
这可确保内核树绝对干净。内核团队建议在每次内核编译之前发出此命令。请勿依赖于解压后源代码树的干净程度。
如果在第 7.6 节,“配置 Linux 控制台”中,决定将键盘映射编译到内核中,请发出以下命令
loadkeys -m /usr/share/kbd/keymaps/[path to keymap] > \ drivers/char/defkeymap.c
例如,如果使用荷兰语键盘,请使用/usr/share/kbd/keymaps/i386/qwerty/nl.map.gz.
通过菜单驱动的界面配置内核。BLFS 在 http://www.linuxfromscratch.org/blfs/view/svn/longindex.html#kernel-config-index 上提供了一些关于 LFS 之外的软件包的特定内核配置要求的信息。
make menuconfig
或者,在某些情况下,make oldconfig 可能更合适。参见README文件获取更多信息。
如果需要,可以通过复制内核配置文件来跳过内核配置,.config,从主机系统(假设可用)到解包的linux-2.6.11.12目录。但是,我们不建议使用此选项。通常最好浏览所有配置菜单并从头开始创建内核配置。
NPTL 要求使用 GCC-3.x 或更高版本(在本例中为 3.4.3)编译内核。不建议使用 GCC-2.95.x 编译内核,因为这会导致 Glibc 测试套件失败。通常,由于 LFS 不构建 GCC-2.95.x,因此不会提及这一点。不幸的是,内核文档已过时,仍然声称 GCC-2.95.3 是推荐的编译器。
编译内核镜像和模块
make
如果使用内核模块,则可能需要/etc/modprobe.conf文件。有关模块和内核配置的信息位于linux-2.6.11.12/Documentation目录中的内核文档中。另外,modprobe.conf(5)可能也很有趣。
在阅读与内核模块相关的其他文档时要非常小心,因为它通常仅适用于 2.4.x 内核。据我们所知,没有记录特定于 Hotplug 和 Udev 的内核配置问题。问题在于,只有在 Hotplug 或用户编写的脚本将相应模块插入内核时,Udev 才会创建设备节点,并且并非所有模块都可以被 Hotplug 检测到。请注意,/etc/modprobe.conf文件中的以下语句不适用于 Udev
alias char-major-XXX some-module
由于 Hotplug、Udev 和模块的复杂性,我们强烈建议从完全非模块化的内核配置开始,尤其是在第一次使用 Udev 时。
如果内核配置使用模块,则安装模块
make modules_install
内核编译完成后,需要执行其他步骤才能完成安装。一些文件需要复制到/boot目录中。
内核镜像的路径可能会因使用的平台而异。以下命令假设使用 x86 架构
cp -v arch/i386/boot/bzImage /boot/lfskernel-2.6.11.12
System.map是内核的符号文件。它映射了内核 API 中每个函数的函数入口点,以及正在运行的内核的内核数据结构的地址。发出以下命令以安装映射文件
cp -v System.map /boot/System.map-2.6.11.12
内核配置文件.config由上面的 make menuconfig 步骤生成,包含刚刚编译的内核的所有配置选项。保留此文件以供将来参考是个好主意
cp -v .config /boot/config-2.6.11.12
重要的是要注意,内核源代码目录中的文件不归 root 所有。每当一个软件包以用户 root 的身份解包时(就像我们在 chroot 中所做的那样),这些文件的用户和组 ID 都是它们在打包者计算机上的 ID。对于要安装的任何其他软件包,这通常不是问题,因为源代码树在安装后会被删除。但是,Linux 源代码树通常会保留很长时间。因此,打包者使用的任何用户 ID 都有可能分配给机器上的某个人。然后,该人将具有对内核源代码的写入访问权限。
如果要保留内核源代码树,请对linux-2.6.11.12目录运行 chown -R 0:0,以确保所有文件都归用户 root 所有。
一些内核文档建议创建一个从/usr/src/linux指向内核源代码目录的符号链接。这特定于 2.6 系列之前的内核,并且绝不能在 LFS 系统上创建,因为它可能会导致您希望在基本 LFS 系统完成后构建的软件包出现问题。
此外,系统include目录中的标头应该始终是 Glibc 编译所依据的标头,即来自 Linux-Libc-Headers 软件包的标头,因此绝不应该被内核标头替换。
您闪亮的新 LFS 系统几乎完成。最后要做的事情之一是确保系统可以正确引导。以下说明仅适用于 IA-32 架构的计算机,即主流 PC。有关其他架构的“引导加载”的信息应可在这些架构的常用资源特定位置找到。
引导加载可能是一个复杂的领域,因此需要一些警告。熟悉当前的引导加载程序以及需要可引导的硬盘驱动器上的任何其他操作系统。确保准备好紧急引导磁盘,以便在计算机变得无法使用(无法引导)时“拯救”计算机。
之前,我们编译并安装了 GRUB 引导加载程序软件,以准备此步骤。该过程涉及将一些特殊的 GRUB 文件写入硬盘驱动器上的特定位置。我们强烈建议创建一个 GRUB 引导软盘作为备份。插入空白软盘并运行以下命令
dd if=/boot/grub/stage1 of=/dev/fd0 bs=512 count=1 dd if=/boot/grub/stage2 of=/dev/fd0 bs=512 seek=1
取出软盘并将其存放在安全的地方。现在,运行 grub shell
grub
GRUB 使用自己的驱动器和分区命名结构,格式为 (hdn,m),其中 n 是硬盘驱动器号,m 是分区号,两者都从零开始。例如,分区hda1对于 GRUB 来说是 (hd0,0),而hdb3是 (hd1,2)。与 Linux 相比,GRUB 不认为 CD-ROM 驱动器是硬盘驱动器。例如,如果使用 CD 在hdb上,并在hdc上有第二个硬盘驱动器,则第二个硬盘驱动器仍然是 (hd1)。
使用以上信息,确定根分区(或引导分区,如果使用单独的分区)的适当指示符。对于以下示例,假设根分区(或单独的引导分区)是hda4.
告诉 GRUB 在哪里搜索其stage{1,2}文件。可以在任何地方使用 Tab 键使 GRUB 显示替代项
root (hd0,3)
以下命令将会覆盖当前的引导加载器。 如果您不希望这样做,例如,如果使用第三方引导管理器来管理主引导记录(MBR),请不要运行该命令。 在这种情况下,将GRUB安装到LFS分区的“引导扇区”中更有意义。 在这种情况下,接下来的命令将变为setup (hd0,3)。
告诉GRUB将其自身安装到hda:
setup (hd0)
如果一切顺利,GRUB将报告在/boot/grub中找到它的文件。 这就是全部了。 退出grub shell。
quit
创建一个“菜单列表”文件,用于定义GRUB的引导菜单
cat > /boot/grub/menu.lst << "EOF" # Begin /boot/grub/menu.lst # By default boot the first menu entry. default 0 # Allow 30 seconds before booting the default. timeout 30 # Use prettier colors. color green/black light-green/black # The first entry is for LFS. title LFS 6.1.1 root (hd0,3) kernel /boot/lfskernel-2.6.11.12 root=/dev/hda4 EOF
如果需要,为宿主机发行版添加一个条目。 它可能看起来像这样
cat >> /boot/grub/menu.lst << "EOF" title Red Hat root (hd0,2) kernel /boot/kernel-2.6.5 root=/dev/hda3 initrd /boot/initrd-2.6.5 EOF
如果双启动Windows,以下条目将允许启动它
cat >> /boot/grub/menu.lst << "EOF" title Windows rootnoverify (hd0,0) chainloader +1 EOF
如果info grub没有提供所有必要的材料,有关GRUB的更多信息位于其网站:https://gnu.ac.cn/software/grub/。
FHS 规定GRUB的menu.lst文件应该被符号链接到/etc/grub/menu.lst。 为了满足此要求,请执行以下命令
mkdir -v /etc/grub && ln -sv /boot/grub/menu.lst /etc/grub
做得好! 全新的 LFS 系统已经安装完成!祝贺您成功构建了全新的定制 Linux 系统。
创建一个/etc/lfs-release文件可能是一个好主意。 通过拥有此文件,您可以(如果您需要在某个时候寻求帮助,我们也一样)非常容易地找出系统上安装的 LFS 版本。 通过运行以下命令来创建此文件
echo 6.1.1 > /etc/lfs-release
既然您已经完成了本书,您想被视为 LFS 用户吗? 前往http://www.linuxfromscratch.org/cgi-bin/lfscounter.cgi,输入您的姓名和您使用的第一个 LFS 版本,注册成为 LFS 用户。
现在让我们重新启动进入LFS。
现在所有的软件都已安装,是时候重新启动您的计算机了。 但是,您应该意识到一些事情。 您在本书中创建的系统非常基本,并且很可能没有您能够继续前进的功能。 通过在当前 chroot 环境中安装 BLFS 书中的一些额外软件包,您可以让自己处于更好的位置,以便在重新启动到新的 LFS 安装后继续前进。 安装文本模式网络浏览器(例如 Lynx),您可以轻松地在一个虚拟终端中查看 BLFS 书籍,同时在另一个虚拟终端中构建软件包。 GPM 软件包还允许您在虚拟终端中执行复制/粘贴操作。 最后,如果您处于静态 IP 配置无法满足您的网络要求的情况,那么此时安装 Dhcpcd 或 PPP 等软件包也可能很有用。
现在我们已经说了这些,让我们开始第一次启动我们闪亮的新 LFS 安装! 首先退出 chroot 环境
logout
然后卸载虚拟文件系统
umount -v $LFS/dev/pts umount -v $LFS/dev/shm umount -v $LFS/dev umount -v $LFS/proc umount -v $LFS/sys
卸载LFS文件系统本身
umount -v $LFS
如果创建了多个分区,请在卸载主分区之前卸载其他分区,如下所示
umount -v $LFS/usr umount -v $LFS/home umount -v $LFS
现在,使用以下命令重新启动系统
shutdown -r now
假设 GRUB 引导加载程序已按照前面所述设置,则菜单设置为自动启动 LFS 6.1.1。
重新启动完成后,LFS 系统即可使用,并且可以添加更多软件以满足您的需求。
感谢您阅读这本 LFS 书。 我们希望您发现这本书对您有所帮助,并且对系统创建过程有了更多的了解。
既然 LFS 系统已经安装,您可能想知道“接下来做什么?” 为了回答这个问题,我们为您编制了一份资源列表。
维护
定期报告所有软件的错误和安全公告。 由于 LFS 系统是从源代码编译的,因此您有责任及时了解此类报告。 有几个在线资源可以跟踪此类报告,其中一些如下所示
Freshmeat.net (http://freshmeat.net/)
Freshmeat 可以通过电子邮件通知您系统上安装的软件包的新版本。
CERT(计算机紧急情况响应小组)
CERT 有一个邮件列表,用于发布有关各种操作系统和应用程序的安全警报。 订阅信息可在 http://www.us-cert.gov/cas/signup.html 获取。
Bugtraq
Bugtraq 是一个完全公开的计算机安全邮件列表。 它发布新发现的安全问题,偶尔还会发布潜在的修复程序。 订阅信息可在 http://www.securityfocus.com/archive 获取。
超越 Linux From Scratch
超越 Linux From Scratch 一书涵盖了 LFS 书籍范围之外的各种软件的安装过程。 BLFS 项目位于 http://www.linuxfromscratch.org/blfs/。
LFS 提示
LFS 提示是 LFS 社区志愿者提交的教育文档集合。 这些提示可在 http://www.linuxfromscratch.org/hints/list.html 获取。
邮件列表
如果您需要帮助、想要了解最新动态、想要为项目做贡献等等,您可以订阅几个 LFS 邮件列表。 有关更多信息,请参阅第 1 章 - 邮件列表。
Linux 文档项目
Linux 文档项目 (TLDP) 的目标是协作处理所有 Linux 文档问题。 TLDP 包含大量 HOWTO、指南和手册页。 它位于 http://www.tldp.org/。
ABI |
应用程序二进制接口 |
ALFS |
自动 Linux From Scratch |
ALSA |
高级 Linux 声音架构 |
API |
应用程序编程接口 |
ASCII |
美国信息交换标准代码 |
BIOS |
基本输入/输出系统 |
BLFS |
超越 Linux From Scratch |
BSD |
伯克利软件发行版 |
chroot |
更改根目录 |
CMOS |
互补金属氧化物半导体 |
COS |
服务类别 |
CPU |
中央处理器 |
CRC |
循环冗余校验 |
CVS |
并发版本系统 |
DHCP |
动态主机配置协议 |
DNS |
域名服务 |
EGA |
增强图形适配器 |
ELF |
可执行和可链接格式 |
EOF |
文件结束 |
EQN |
方程式 |
EVMS |
企业卷管理系统 |
ext2 |
第二扩展文件系统 |
FAQ |
常见问题解答 |
FHS |
文件系统层次结构标准 |
FIFO |
先进先出 |
FQDN |
完全限定域名 |
FTP |
文件传输协议 |
GB |
吉字节 |
GCC |
GNU 编译器集合 |
GID |
组标识符 |
GMT |
格林威治标准时间 |
GPG |
GNU Privacy Guard |
HTML |
超文本标记语言 |
IDE |
集成驱动器电子设备 |
IEEE |
电气与电子工程师协会 |
IO |
输入/输出 |
IP |
互联网协议 |
IPC |
进程间通信 |
IRC |
互联网中继聊天 |
ISO |
国际标准化组织 |
ISP |
互联网服务提供商 |
KB |
千字节 |
LED |
发光二极管 |
LFS |
Linux From Scratch(从零开始构建Linux) |
LSB |
Linux 标准库 |
MB |
兆字节 |
MBR |
主引导记录 |
MD5 |
消息摘要 5 |
NIC |
网络接口卡 |
NLS |
本机语言支持 |
NNTP |
网络新闻传输协议 |
NPTL |
本机 POSIX 线程库 |
OSS |
开放声音系统 |
PCH |
预编译标头 |
PCRE |
Perl 兼容正则表达式 |
PID |
进程标识符 |
PLFS |
纯 Linux From Scratch |
PTY |
伪终端 |
QA |
质量保证 |
QOS |
服务质量 |
RAM |
随机存取存储器 |
RPC |
远程过程调用 |
RTC |
实时时钟 |
SBU |
标准构建单元 |
SCO |
圣克鲁斯运营公司 |
SGR |
选择图形呈现 |
SHA1 |
安全散列算法 1 |
SMP |
对称多处理器 |
TLDP |
Linux 文档项目 |
TFTP |
简单文件传输协议 |
TLS |
线程本地存储 |
UID |
用户标识符 |
umask |
用户文件创建掩码 |
USB |
通用串行总线 |
UTC |
协调世界时 |
UUID |
通用唯一标识符 |
VC |
虚拟控制台 |
VGA |
视频图形阵列 |
VT |
虚拟终端 |
我们要感谢以下人员和组织对 Linux From Scratch 项目的贡献。
Gerard Beekmans <gerard AT linuxfromscratch D0T org> – LFS 创建者, LFS 项目负责人
Matthew Burgess <matthew AT linuxfromscratch D0T org> – LFS 项目负责人, LFS 技术作家/编辑, LFS 发布经理
Archaic <archaic AT linuxfromscratch D0T org> – LFS 技术文档编写者/编辑,HLFS 项目领导者,BLFS 编辑,提示和补丁项目维护者
Nathan Coulson <nathan AT linuxfromscratch D0T org> – LFS-Bootscripts 维护者
Bruce Dubbs <bdubbs AT linuxfromscratch D0T org> – BLFS 项目领导者
Manuel Canales Esparcia <manuel AT linuxfromscratch D0T org> – LFS/BLFS/HLFS XML 和 XSL 维护者
Jim Gifford <jim AT linuxfromscratch D0T org> – LFS 技术文档编写者,补丁项目领导者
Jeremy Huntwork <jhuntwork AT linuxfromscratch D0T org> – LFS 技术文档编写者,LFS LiveCD 维护者,ALFS 项目领导者
Anderson Lizardo <lizardo AT linuxfromscratch D0T org> – 网站后端脚本维护者
Ryan Oliver <ryan AT linuxfromscratch D0T org> – LFS 工具链维护者
James Robertson <jwrober AT linuxfromscratch D0T org> – Bugzilla 维护者
Tushar Teredesai <tushar AT linuxfromscratch D0T org> – BLFS 书籍编辑,提示和补丁项目领导者
无数 LFS 和 BLFS 邮件列表中的其他人员,他们通过提供建议、测试书籍以及提交错误报告、说明和安装各种软件包的经验,为本书的完成做出了贡献。
Manuel Canales Esparcia <macana AT lfs-es D0T com> – 西班牙语 LFS 翻译项目
Johan Lenglet <johan AT linuxfromscratch D0T org> – 法语 LFS 翻译项目
Anderson Lizardo <lizardo AT linuxfromscratch D0T org> – 葡萄牙语 LFS 翻译项目
Thomas Reitelbach <tr AT erdfunkstelle D0T de> – 德语 LFS 翻译项目
Scott Kveton <scott AT osuosl D0T org> – lfs.oregonstate.edu 镜像
Mikhail Pastukhov <miha AT xuy D0T biz> – lfs.130th.net 镜像
William Astle <lost AT l-w D0T net> – ca.linuxfromscratch.org 镜像
Jeremy Polen <jpolen AT rackspace D0T com> – us2.linuxfromscratch.org 镜像
Tim Jackson <tim AT idge D0T net> – linuxfromscratch.idge.net 镜像
Jeremy Utley <jeremy AT linux-phreak D0T net> – lfs.linux-phreak.net 镜像
Andres Meggiotto <sysop AT mesi D0T com D0T ar> – lfs.mesi.com.ar 镜像
Manuel Canales Esparcia <manuel AT linuxfromscratch D0T org> – lfsmirror.lfs-es.info 镜像
Eduardo B. Fonseca <ebf AT aedsolucoes D0T com D0T br> – br.linuxfromscratch.org 镜像
Barna Koczka <barna AT siker D0T hu> – hu.linuxfromscratch.org 镜像
UK Mirror Service – linuxfromscratch.mirror.ac.uk 镜像
Martin Voss <Martin D0T Voss AT ada D0T de> – lfs.linux-matrix.net 镜像
Guido Passet <guido AT primerelay D0T net> – nl.linuxfromscratch.org 镜像
Bastiaan Jacques <baafie AT planet D0T nl> – lfs.pagefault.net 镜像
Roel Neefs <lfs-mirror AT linuxfromscratch D0T rave D0T org> – linuxfromscratch.rave.org 镜像
Justin Knierim <justin AT jrknierim D0T de> – www.lfs-matrix.de 镜像
Stephan Brendel <stevie AT stevie20 D0T de> – lfs.netservice-neuss.de 镜像
Antonin Sprinzl <Antonin D0T Sprinzl AT tuwien D0T ac D0T at> – at.linuxfromscratch.org 镜像
Fredrik Danerklint <fredan-lfs AT fredan D0T org> – se.linuxfromscratch.org 镜像
Parisian sysadmins <archive AT doc D0T cs D0T univ-paris8 D0T fr> – www2.fr.linuxfromscratch.org 镜像
Alexander Velin <velin AT zadnik D0T org> – bg.linuxfromscratch.org 镜像
Dirk Webster <dirk AT securewebservices D0T co D0T uk> – lfs.securewebservices.co.uk 镜像
Thomas Skyt <thomas AT sofagang D0T dk> – dk.linuxfromscratch.org 镜像
Simon Nicoll <sime AT dot-sime D0T com> – uk.linuxfromscratch.org 镜像
Pui Yong <pyng AT spam D0T averse D0T net> – sg.linuxfromscratch.org 镜像
Stuart Harris <stuart AT althalus D0T me D0T uk> – lfs.mirror.intermedia.com.sg 镜像
Jason Andrade <jason AT dstc D0T edu D0T au> – au.linuxfromscratch.org 镜像
Christine Barczak <theladyskye AT linuxfromscratch D0T org> – LFS 书籍编辑
Timothy Bauscher
Robert Briggs
Ian Chilton
Jeroen Coumans <jeroen AT linuxfromscratch D0T org> – 网站开发者,FAQ 维护者
Alex Groenewoud – LFS 技术文档编写者
Marc Heerdink
Mark Hymers
Seth W. Klein – FAQ 维护者
Nicholas Leippe <nicholas AT linuxfromscratch D0T org> – Wiki 维护者
Simon Perreault
Scot Mc Pherson <scot AT linuxfromscratch D0T org> – LFS NNTP 网关维护者
Alexander Patrakov <semzx AT newmail D0T ru> – LFS 技术文档编写者
Greg Schafer <gschafer AT zip D0T com D0T au> – LFS 技术文档编写者
Jesse Tie-Ten-Quee – LFS 技术文档编写者
Jeremy Utley <jeremy AT linuxfromscratch D0T org> – LFS 技术文档编写者,Bugzilla 维护者,LFS-Bootscripts 维护者
Zack Winkles <zwinkles AT gmail D0T com> – LFS 技术文档编写者
Dean Benson <dean AT vipersoft D0T co D0T uk> 为多次捐款
Hagen Herrschaft <hrx AT hrxnet D0T de> 捐赠了一个 2.2 GHz P4 系统,现在以 Lorien 的名义运行
VA Software 代表 Linux.com 捐赠了一台 VA Linux 420(之前的 StartX SP2)工作站
Mark Stone 捐赠了 Belgarath,linuxfromscratch.org 服务器