折腾了两天 LFS
我自认为一向是很不感冒Linux那些东东的,也不知道为什么,前两天突然就心血来潮去搞一番LFS。于是很有纪念意义,特此记录。
起先准备搞的是 LFS 6.1,因为只有 6.1 有官方中文手册。但是我的宿主系统是 Arch Linux 2010.05,也许太新了,刚开始编译 gcc 4.0.3 就过不了。后来就放弃了,换 6.7 的玩。
说到底这是件很无聊的事情。打过的最多的命令就是
tar -xzvf ...
tar -xvjf ...
./configure ...
make
make install
rm -rf ...
这么一套操作重复个百来下,加上无休止的等待,就成了。
以为成了,结果出状况了:
似乎好像大概可能它找不到硬盘,而且我明明要 sda2 的,它却找了 sdb2。
第一,在 8.4.2 grub-mkconfig -o /boot/grub/grub.cfg 的时候,grub的配置文件是利用它的命令自动生成的,结果它找错了。可能是因为我一开始装的时候拿块硬盘是sdb,它就认sdb了。或者是之前那条命令 grub-install --grub-setup=/bin/true /dev/sda 我自作聪明地以为它要实际操作,把最后的sda换成了sdb的缘故吧。
第二是因为我在 VMWare 上跑,虚拟硬盘是 SCSI 的,编译内核之前没配置对。后来看到了 http://www.cnblogs.com/benben7466/archive/2009/04/01/1427404.html,于是把 fusion mpt 中的全选上了(文章中的 Fusion MPT (base + ScsiHost) drivers 我没找到,于是全选了= =),重新编译内核,启动成功。
谨以此截图留念:
流水账结束了。正文开始。
我想谈谈对 LFS 中的工具链切换的理解。请允许我把 binutil 和 gcc 简称为编译系统,把 glibc 简称为运行库。用下面这张图简单表示一下:
首先,利用宿主系统的编译系统编译出一个依赖于宿主运行库的新的编译系统(Pass1),和独立的新的运行库(Pass1)。然后再利用运行在宿主运行库上的新的编译系统(Pass1)编译出依赖于新的运行库(Pass1)的新的编译系统(Pass2)。这样,产生了一个脱离宿主的编译环境,利用这个编译环境编译出其他工具,一起作为临时系统使用。
再在临时系统中,编译出目标系统中要用的运行库(Pass2)和依赖于目标运行库(Pass2)的编译系统(Pass3)。目标系统中的编译环境搭建完毕。最后使用这个编译环境编译出目标系统上的其他软件。
不知道这个陈述有没有问题?如果没说错的话,问题来了。其实,得到的临时系统,已经是一个不依赖于宿主的系统了,何不把这个作为 LFS 的目标系统呢?理由似乎只有“使它更纯净”之类的了。如果追求纯净,多搞一遍是不够的,还是不纯净的;既然反正不纯净,为啥多做一遍呢?
由此,我想到了挺久以前我一直压抑在心里的问题:同一个环境下的编译器的升级问题。加入已经有了 1.0 版的编译器执行文件和 2.0 版的编译器源代码,要如何产生 2.0 版的编译器的执行文件呢?是拿 1.0 版的去编译 2.0 的源代码,然后直接发布?还是再用新的 2.0 版的编译器再编译一遍(两遍、三遍)?6.1 版的 LFS 手册部分解决了这个疑问,它提到了在 gcc pass1 的时候做 bootstrap,即编译一次后用产生的新编译器编译第二遍,再用产生的新的编译器编译第三遍,比较第二遍与第三遍结果是否相同。(LFS 6.7无此要求。)不知道这里的相同是指逐字节相同吗?如果是,这在理论上可能吗?我的想法是,已有的1.0版可能存在一个固有问题(或者不称为问题,叫“特征”吧),它可能将影响到后面的一切,2.0 的编译器不管自举几遍,或许总是无法完全消灭来自 1.0 的某些影响?
不知道现在理论上是怎样回答这个问题的。工程上又是如何对待这个问题的呢?
这也许是个比较深层次的问题。抑或只是一个很肤浅的问题,只是我心生执念罢了。期待解惑 ~_~