随笔-89  评论-944  文章-0  trackbacks-0

我自认为一向是很不感冒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 简称为运行库。用下面这张图简单表示一下:

image

首先,利用宿主系统的编译系统编译出一个依赖于宿主运行库的新的编译系统(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 的某些影响?

不知道现在理论上是怎样回答这个问题的。工程上又是如何对待这个问题的呢?

这也许是个比较深层次的问题。抑或只是一个很肤浅的问题,只是我心生执念罢了。期待解惑 ~_~

posted on 2010-10-19 00:59 溪流 阅读(2560) 评论(13)  编辑 收藏 引用 所属分类: Linux

评论:
# re: 折腾了两天 LFS 2010-10-19 03:16 | 唐僧
第一遍是编译内核,第二遍是编译可以在内核上跑的开发环境。
gcc 之类的编译器编译成功的标志是可以“自己编译出自己”,事实上也就是单一平台上做lfs第二遍编译的时候只重新做了个gcc。
我也不清楚这个“重新编译出自己”是怎么保证的……  回复  更多评论
  
# re: 折腾了两天 LFS 2010-10-19 09:34 | 溪流
@唐僧
第一遍不是编译内核,谢谢,LFS里内核只在最后被编译一遍而已。
这里我想说的不是内核的问题,而是编译环境的自我进化问题。
自己能编否译出自己取决于那门语言的定义,我的问题是自己编译出的自己纯净不纯净。  回复  更多评论
  
# re: 折腾了两天 LFS 2010-10-19 10:10 | xxoo
Ken Thompson就曾这么干过,在最早的编译器里留下后门,导致其所编译的所有编译器都有后门,而这些新的编译器代码都是没有问题的,后门只存在二进制文件中。
http://cm.bell-labs.com/who/ken/trust.html  回复  更多评论
  
# re: 折腾了两天 LFS 2010-10-19 10:44 | 陈梓瀚(vczh)
@溪流
纯净和不纯净都是对用户没有关系的  回复  更多评论
  
# re: 折腾了两天 LFS 2010-10-19 12:44 | 溪流
@陈梓瀚(vczh)
也许大多数情况下是没关系的
但是否存在你楼上的情况,有一个来自原始版本的bug,就像遗传一样,不管如何改源代码,永远也无法磨灭呢?  回复  更多评论
  
# re: 折腾了两天 LFS 2010-10-19 16:09 | 溪流
@xxoo
那后来他们知道这个后门后,有办法不改动原始编译器,只更改源代码来修正吗?  回复  更多评论
  
# re: 折腾了两天 LFS 2010-10-19 17:11 | 陈梓瀚(vczh)
@溪流
显然一个编译器不可能知道一份源代码是不是C编译器的,只是靠那几个pattern……只要你用全新的方法重新写一个,就不会了  回复  更多评论
  
# re: 折腾了两天 LFS 2010-10-19 17:20 | xxoo
@溪流
知道后门后要修正很容易,只要避开后门所用的那几个pattern。
但是要知道后门的存在可不是一件容易的事情,你得查看二进制文件,但是如果二进制文件查看器也被编译器插入后门了呢?而你看源代码的话又看不出任何问题。  回复  更多评论
  
# re: 折腾了两天 LFS 2010-10-19 20:55 | 溪流
@陈梓瀚(vczh)
也许编译结果中有某些数据,是源代码不能决定的呢?  回复  更多评论
  
# re: 折腾了两天 LFS 2010-10-19 20:58 | 溪流
@xxoo
那你认为 bootstrap 是不是总是可以做到的呢?  回复  更多评论
  
# re: 折腾了两天 LFS 2010-10-20 00:06 | 陈梓瀚(vczh)
@溪流
只要你尝试写一个有后门的编译器,你就明白了……  回复  更多评论
  
# re: 折腾了两天 LFS 2010-10-20 00:40 | 溪流
@陈梓瀚(vczh)
你在诱使我做一件有点点遥远事情啊。。。等我搞过单正则表达式查询、多正则表达式查询后,一定试试。我总觉得,来自静态库,或者动态库,或者编译器本身的某些东西会很微妙。  回复  更多评论
  
# re: 折腾了两天 LFS 2010-10-20 10:26 | 陈梓瀚(vczh)
@溪流
单正则和多正则是差不多的……正则分为两种,一种可以用DFA表达,一种不能。能用DFA表达的有算法组合,不能的根本没办法- -b就写成捕获+或的形式好了。具体怎么做我主页有文章哈。  回复  更多评论
  

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理