根据《Linux From Scratch 版本 20200901-systemd,中文翻译版》构建 LFS systemd 10.0 的归纳总结。

LFS 简介

LFS 项目主要是从源码一步一步构建一个定制的 Linux 系统。具体内容可以访问项目主页

LFS 构建过程

  1. 阅读官方手册。
  2. 宿主机环境检查,安装相应软件包,完成相关配置。
  3. 新建分区。
  4. 下载需要的软件包和补丁。
  5. 配置工作环境,主要包括创建目录布局、添加 lfs 用户、完成 lfs 用户的环境配置。
  6. 编译交叉工具链。
  7. 用编译好的交叉工具链,交叉编译基本工具,用于构建其他软件包。
  8. 进入 Chroot 环境,构建一些额外工具,用于后续构建和测试。
  9. 构建完整的 LFS 系统。
  10. 完成系统的基本设置。
  11. 配置内核和引导加载器。
  12. 收尾工作。

常见问题及个人理解

构建 LFS 系统的意义

如果是为了构建自己使用 Linux 系统,我真的不推荐 LFS,除非你有不得不用 LFS 系统的理由,不然用现成的 Linux 发行版比较靠谱。

那么对于大部分人来说,构建 LFS 的意义肯定不是自己使用了,而是体验一步一步从源码构建的过程。这个过程,能让我们熟悉如何从源码安装软件包,了解一个系统包括哪些必要的组件,以及在一定程度上知晓它们的依赖关系。这对今后使用其他 Linux 发行版是有好处的,至少在一定程度上具备了从源码自己构建相关软件包的能力。

当前,这一切的前提,是理解了构建 LFS 的大部分指令的含义,而不是复制粘贴完成构建。

多次构建工具链的意义

这也是 LFS 作者重点讨论的内容。来看手册上描述的三个阶段:

阶段BuildHostTarget操作描述
1pcpclfspc 上使用 cc-pc 构建交叉编译器 cc1
2pclfslfspc 上使用 cc1 构建 cc-lfs
3lfslfslfslfs 上使用 cc-lfs 重新构建并测试它本身

根据官方手册,抛开用于验证的第三阶段,我们构建了两遍工具链,不妨来反向思考这个问题。

最终我们希望用工具链 cc-lfs 来构建完整的 LFS 系统,所以我们需要构建 cc-lfs

现在我们需要在宿主机上构建 cc-lfs,如果直接用宿主机自带的 cc-pc,那么构建的 cc-lfs 将依赖于我们的宿主系统,这显然不是我们想要的结果,所以必须使用交叉编译工具链 cc1 来避免这种依赖,这就是第二遍构建——用 cc1 构建 cc-lfs

现在要在宿主机上构建交叉编译工具链 cc1,自然是使用宿主机自带的工具链 cc-pc,这就是第一次构建——用 cc-pc 构建交叉编译器 cc1

多次切换环境的意义

在构建 LFS 的过程中,我们进行了多次环境的切换,下面列出所有可能的环境切换:

  1. 从普通用户切换到 root 用户。
  2. root 用户切换到 lfs 用户。
  3. lfs 用户返回到 root 用户。
  4. root 用户切换到 Chroot 环境。
  5. 从 Chroot 环境返回到 root 用户。
  6. root 用户返回到普通用户。

第一次切换和第六次对应,是为了用 root 权限执行一些指令。

第二次切换和第三次切换对应,这个切换不是强制要求的,因为用 root 权限进行操作存在较大风险,所以通过切换到 lfs 用户来降低这种风险,同时创建一个新用户也能更容易地建立干净的工作环境。

第四次切换和第五次切换对应,因为我们希望在一个与宿主机隔离的环境中构建 LFS,确保尽可能不受宿主系统影响,所以进入了 Chroot 这个临时环境。

工具链编译顺序的问题

这部分内容 LFS 作者给出了完整的介绍,简单概括如下:

我们首先安装 Binutils。这是由于 GCC 和 Glibc 的 configure 脚本首先测试汇编器和链接器的一些特性,以决定启用或>禁用一些软件特性。

下一步安装 GCC。

下一步安装“净化的” (sanitized) Linux API 头文件。这允许 C 标准库 (Glibc) 与 Linux 内核提供的各种特性交互。

下一步安装 Glibc。在构建 Glibc 时需要着重考虑编译器,二进制工具,以及内核头文件。

接下来构建 C++ 标准库,然后是第 6 章中那些需要自身才能构建的程序后。

在第 6 章一节的末尾,构建 lfs 本地编译器。首先使用和其他程序相同的 DESTDIR 第二次构建 binutils,然后第二次> 构建 GCC,构建时忽略 libstdc++ 和其他不重要的库。

在第 7 章中,进入 chroot 环境后,首先安装 libstdc++。之后临时性地安装工具链的正常工作所必须的程序。还要构建测试其他程序时必须的程序。此后,核心工具链成为自包含的本地工具链。在第 8 章中,构建、测试并最后一次安装所有软件包,它们组成功能完整的系统。

自动构建 LFS

官方的 ALFS 项目,是利用 shell 或 Python 脚本解析 LFS 手册的 XML 代码,生成相应的构建脚本完成全自动构建。但这个项目似乎很久没人维护了,目前依然停留在较早版本。这是一个非常智能的构建脚本,但技术要求相对较高。

本人基于官方手册,抱着写着玩的心态,写了一个自动构建 LFS 的项目,该项目使用 shell 脚本编写,可以自动构建 LFS systemd 10.0 到一个虚拟磁盘文件,项目地址如下:https://github.com/FreeFlyingSheep/lfs

原本准备用 Python 重构一个脚本,但感觉实际意义不大,又耗时,就鸽了……