为什么多次构buildLinux从零开始(LFS)?

我正在尝试理解Linux From Scratch的概念,并想知道为什么有多个构buildbinutilsgcc等的通行证。

为什么我们需要分别使用pass1和pass2? 为什么我们不能在pass 1中构build工具,然后使用它们来构buildgccglibclibstdc++

目标是确保你的构建是一致的,不管你使用哪个编译器编译你的编译器(以及编译器有哪些错误)。

假设你正在用gcc 3.2来编译gcc 4.1(我打算叫那个gcc 3.2“stage-0”)。 对gcc 4.1进行QA的人在用gcc 4.1以外的任何编译器构建时没有测试它是否能正常工作 – 因此,需要先构建一个stage-1 gcc, 然后使用该stage-1编译stage-2编译器 ,以防止0阶段编译器中的任何错误影响最终结果。

然后,gcc的默认编译过程使用stage-2编译器构建一个stage-3编译器, 并比较这两个二进制文件 :它们之间的任何差异都可以用作存在bug的证明。

(当然,这只是一个有效的机制,可以避免无意的错误;请参阅Ken Thompson的“ Trust Trust on Trust ”一文,讨论如何使用这种措施来预防错误)。


这超出了gcc到整个工具链,因为相同的原则适用于整个:如果在运行glibc-xy的系统和运行glibc-x。(y-1)的系统之间建立glibc-xy的结果有差异不要做额外的通行证,以确保你的目标环境匹配,然后复制这些错误(以及测试建议的修复)要比其他情况困难得多:没有人没有你的(通常是未公开的)构建环境可能会重新创建错误!

我知道这个查询有点旧了,但是我还有一些东西需要补充:“bootstrap”的含义。

多阶段构建的主要原因是从结果软件中消除构建主机的程序/配置/库的每一个痕迹。 有新的软件编译是不够的。 您还必须避免对主机的库,主机的内核接口(内核头文件),主机的pkg版本以及主机系统上的所有其他此类相关性的任何和所有引用。

假设你碰巧是一个受虐狂,想要在Fedora 27上构建Debian 4( 应该是可以的)。 简单地构建软件会引用27个库和其他东西。 并且你的结果系统不会运行,因为这些东西在最终系统安装时不可用。

LFS通过在阶段1中构建简单的x86-to-x86 binutils和gcc交叉工具,然后安装在最终系统中使用的内核的标题,然后安装glibc,简化了这个过程。 阶段2(binutils和gcc)是使用交叉工具构建的,它保证主机的程序/ libs / config根本不被使用。 工具链的其余部分(我称之为阶段3)是使用阶段2中的工具构建的。现在可以构建最后阶段(只需进行一些小的调整),保证不会构建主机的任何部分被引用或使用,而且工具链的任何部分都不会被引用或使用。 最后一个阶段是使用类似于PATH = / bin:/ usr / bin:/ tools / bin的路径构建的。 因此当最终的工具被建立时,它们将被用来代替工具链中的工具。

建立一个工具链并不是不耐烦的。 花了几个月的时间来更新Smoothwall Express的构建系统和pkgs,因为构建工具链充满了危险。 我和许多龙,沙滩和矮人作战。 我经常引用LFS来弄清楚他们是如何做到的。 其结果是一个自动重构构建系统,它构建了整个发行版,而不涉及主机系统。 我主要是在Debian 8上构建它,但是我们知道它是建立在Gentoo之上的,它应该能够建立在自己的基础之上。