我正在尝试理解Linux From Scratch的概念,并想知道为什么有多个传递用于构建binutils
,gcc
等。
为什么我们需要分别使用pass1和pass2?为什么我们无法在第1版中构建工具,然后使用它们来构建gcc
,glibc
,libstdc++
等。
答案 0 :(得分:10)
目标是确保您的构建是一致的,无论您使用哪个编译器来编译编译器(以及编译器具有哪些错误)。
假设您正在使用gcc 3.2构建gcc 4.1(我将称之为gcc 3.2“stage-0”)。使用gcc 4.1以外的任何编译器构建的用于gcc 4.1的QA的人没有测试它是否正常工作 - 因此,需要首先构建stage-1 gcc,然后使用该stage-1编译stage-2编译器,以防止stage-0编译器中的任何错误影响最终结果。
然后,gcc的默认编译过程使用stage-2编译器构建stage-3编译器,并比较两个二进制文件:它们之间的任何差异都可以用作存在的证明一个错误。
(当然,这只是避免非预期错误的有效机制;请参阅经典的Ken Thompson论文Reflections on Trusting Trust,讨论预期的错误可以在这种措施中存活下来。)
这超越了gcc到整个工具链,因为相同的原则贯穿始终:如果在运行glibc-xy的系统和运行glibc-x的系统上构建glibc-xy之间的结果有任何差异。(y-1并且你不做额外的通行证以确保你在目标环境的匹配中建立,然后再生这些错误(和测试建议的修复)比其他方式更难是这样的:没有你没有(通常是未公开的)构建环境的人都必须重新创建这个bug!
答案 1 :(得分:1)
我知道这个查询有点陈旧,但我有一些东西可以添加到答案中:澄清'bootstrap'的含义。
多阶段构建的主要原因是从生成的软件中消除构建主机的程序/配置/库的每个痕迹。编制新软件是不够的。您还必须避免对主机库,主机的内核接口(内核头文件),主机的pkg版本以及主机系统上的所有其他此类依赖项的任何和所有引用。
假设你碰巧是一个受虐狂,并想在Fedora 27上构建Debian 4(应该可能)。简单地构建软件将引入27个库和其他东西。并且您的结果系统将无法运行,因为在安装最终系统时这些内容不可用。
LFS通过在阶段1中构建简单的x86到x86 binutils和gcc交叉工具,然后安装要在最终系统中使用的内核的头文件,然后安装glibc来简化该过程。第2阶段(binutils和gcc)使用交叉工具构建,这保证了主机的程序/ libs / config根本不被使用。工具链的其余部分(我称之为第3阶段)是使用第2阶段的工具构建的。现在可以构建最终阶段(通过一些小的调整),确保不会引用或使用构建主机的任何部分,并且不会引用或使用工具链的任何部分。最后阶段是使用类似PATH = / bin:/ usr / bin:/ tools / bin的路径构建的;因此,在构建最终工具时,将使用它们而不是工具链中的工具。
构建工具链不适合不耐烦。我花了几个月的时间来更新Smoothwall Express的构建系统和使用的pkgs,因为构建工具链充满了危险。我和许多龙,巴洛克和矮人作战。我经常引用LFS来弄清楚他们是如何做到的。结果是一个自动重入构建系统,它构建整个发行版而不引用主机系统。我主要是在Debian 8上构建它,但是它已经知道构建在Gentoo上,并且它应该能够自行构建。