|
|
春节期间利用假期做了三次LFS系统。在VMware上,Redhat 9.0的系统,内核是2.4.20。先编了个最新的2.6.20的内核,然后又在VMware上挂了一个虚拟磁盘,作为LFS分区,开始LFS的制作。
第一次完全按照6.2的指导和建议的软件版本,可以启动LFS系统,但不能将虚拟磁盘分区独立出来启动,后来修改中不小心删除了整个LFS分区,这次算是基本成功。
第二次全部使用最新的软件构建LFS系统,最后勉勉强强可以看见login:提示,但不能登录,应该算是基本失败。
第三次吸取经验,成功用最新的软件构建了LFS系统,算是完全成功。
这篇帖子记述了制作过程中的一些体会,以及与LFS 6.2有差异的地方,和大家一起交流。
一. LFS的目的和原理
构建LFS就好比在一块空地上盖一座房屋,学会了盖一种样子的房屋,以后就能够盖各种各样的房屋,因为盖各种房屋的基本原理是一样的。通过学习LFS的构成,可以理解Linux系统各软件之间的关系,最后成为一个可以独立运行的Linux系统,以后可以根据自己的需要建立各种需要的Linux系统。
LFS的过程基本可以分为两步,第一步是建立/tools目录下的各种软件,第二步是利用/tools目录下的软件(此时已经脱离了host宿主机的环境)建立我们需要的目标系统。这就像在建房屋之间先要准备趁手的工具,这样才能建出高质量的房屋。
我想LFS的过程分为两步可能有两个原因:
1) 构建的新系统中的各种软件要符合FHS的目录设置标准,因此在路径上和目前工作的host系统产生了重叠。
2) 宿主机的环境一般比需要生成的LFS系统古老,在这个环境中工作可能需要安装新版本的软件,但这就可能破坏原来的工作环境。
二.构建LFS系统中的几个重点
1. 工具链(Toolschain)
工具链包括binutils,gcc,glibc三个软件包(LFS中还包括了linux-headers头文件包)。
Binutils主要是ld链接程序,gas汇编程序等。
Glibc提供了C的主要函数库。
Gcc是GNU的编译程序,提供C和C++的编译程序,然后会调用ld程序将用户的代码与glibc链接起来或将glibc提供的函数静态链接到用户程序中,生成最终的可执行程序。
在LFS的准备阶段(第5章),为了建立一个纯粹的工具链,gcc和binutils通常需要生成两次。第一次是利用宿主机中原有的gcc,glibc和ld等工具,建立半成品的gcc和ld。利用这半成品的编译链接程序,编译出纯净的glibc库。
然后利用半成品的gcc和成品glibc,先做了成品binutils,再做了成品的gcc。
此时整个工具链就纯净了,与宿主机中的编译程序没有了任何关系。以后利用这个工具链生成的软件也都是纯净的,也就是说这些生成的软件全部调用/tools/lib目库下的文件,与宿主机中的/lib目录没有任何关系。
在LFS的第6章也是同样道理,通过重新编译工具链,再使得生成的软件脱离/tools的干扰。
2.路径(Path)
LFS中路径的设置是非常重要的,如果忽略这个问题会给整个过程带来很大的麻烦。
我说的路径一个是环境变量$PATH,一个是软件生成过程中需要设置的路径。
环境变量$PATH在准备阶段(第4章)中设置为/tools/bin:/bin:/usr/bin,并且取消了路径的hash表查找(+h),这样如果在/tools/bin目录下生成了新的软件,就会开始使用这个新的软件,如果没有则会在老系统的/bin和/usr/bin目录下寻找。例如在生成gcc之前,使用的是宿主机中的gcc,而一旦在/tools/bin下生成了gcc,以后再编译软件包,就会使用/tools/bin下的gcc程序。
我在第一次做LFS时由于没有重视这个问题,足足被阻挡了2天才找到原因(见我在论坛写的关于forced unwind support的帖子)。
在第6章中,则将这个过程反过来,设置PATH=/bin:/usr/bin:/tools/bin,将/tools/bin目录放在查找路径的最后。
不过,这里的/bin目录和原来老系统的/bin不是同一个目录,因为利用chroot命令改变了linux系统的根目录,在执行chroot后,linux提供了一个虚拟的环境,这个环境下的根目录是原linux系统的一个子目录(/mnt/lfs)而已。在这个虚拟环境中,已经完全无法访问宿主系统的/mnt/lfs以外的目录了。这也是为什么LFS会在一开始在根目录下建立/tools软链接的原因,这样在真实环境和虚拟环境下,对/tools目录的访问是同一个目录。
软件生成过程中大部分软件通过设置prefix选项确定生成路径。准备阶段的软件路径全部以/tools目录为基准,正式生成阶段的软件路径全部以/usr目录为基准(个别软件除外)。
gcc,binutils除了需要确定自己的生成路径,还需要决定其它软件的函数库引用路径,gcc的路径是通过补丁来设置的,binutils是通过LIB_PATH选项。这步没有做好,以后所有软件的生成工作可能都白费了。
3.补丁(Patch)
LFS的过程中需要打各种补丁,这些补丁大致可以分为三类。
一类是修改软件中存在的bug,这类补丁文件的名称中通常含有fixes,这种补丁是必须要打上的,否则很可能编译时出现错误,或以后运行中出现错误。
一类是增强软件的功能,这类补丁在文件名称中会含有功能的名称。用户如果不需要这项功能,可以不安装这个补丁。
还有一类是由于特殊需要,对源代码作一些修改,但又不方便使用sed命令的,这时LFS会提供一个patch文件,方便用户修改。这类补丁也是必须要打上的,通常patch文件中会含有specs。
如果你是完全使用LFS建议得软件,那最好严格按照LFS文档的要求打上patch。
三.LFS的过程
我最终生成的LFS系统中主要软件版本如下:
Kernel 2.6.20
Binutils 2.17
Gcc 4.1.2
Glibc 2.5
Make 3.81
Bash 3.2
Bzip 1.0.4
Coreutils 6.7
Diff 2.8.1
Find 4.2.29
Gawk 3.1.5
Grep 2.5.1
Gzip 1.3.9
Patch 2.5.4
Sed 4.1.5
Tar 1.16
下面介绍编译的过程,由于大部分内容与LFS 6.2的文档相同,我就偷懒重点写有差异的地方了。
1.按照LFS文档做到第4章结束。注意不要偷懒使用root用户,也不要忘记编写4.4步的环境设置。否则如果你宿主机中的gcc或glibc版本不够,一定会在后面被卡得很难受。
2.按照5.3编译binutils 2.17,ld已经被生成了两次,第一次生成的ld放在/tools/bin目录下,供临时使用,第二次生成的ld叫ld-new,会在5.7步才正式登基,现在还没有用处。
3.按照5.4~5.5编译gcc 4.1.2,并复制linux-libc-headers
4.按照5.6编译glibc 2.3.6,注意这里使用的是2.3.6版本,不是最新的2.5的版本。如果直接编译最新的2.5版本,在编译到nscd库时会出现“未定义的__stack_chk_guard标识”。整个标识是2.4版本中新增加的功能,好像和gcc也有一些关系(也有可能是我原系统中2.2.3的gcc太古董引起的)。
所以先编译glibc 2.3.6,通常可以正确通过。
上面做出的gcc、glibc和binutils只是半成品,如果这时开始编译其它应用软件,那些编译出来的软件会使用/lib目录下的库文件,所以要调整工具链。
5.文档中5.7调整工具链,分为两段,先将ld-new程序(也就是LIB_PATH指向/tools/lib目录的那个ld程序)正名,将原来的ld程序被改成ld-old(也可以直接删除)。
6.现在编译glibc 2.5版本,应该可以顺利通过。如果有人没有不幸被挡住的话,可以发个帖子,我们讨论一下。
7.继续5.7步调整工具链的其余工作。
8.按照5.8~5.10安装测试用的软件。
9.照文档5.11编译gcc 4.1.2,除了按照文档使用sed命令修改源代码以外,文档中还使用了gcc-4.0.3-specs-1.patch的补丁文件。这个补丁是将源代码中引用/lib库的地方修改为/tools/lib。由于4.1.2的代码和4.0.3的代码要修改的地方不完全一样,因此不能直接使用gcc-4.0.3的这个补丁。有经验的朋友可以查看4.0.3的补丁来手工修改4.1.2的代码,只是代码行数上有些差异。此外我做了4.1.2的相应补丁文件,使用时去掉后面的txt后缀。
打完补丁后再编译生成。做完后最好按文档中的要求,检查一下dummy.c生成的程序是否使用了/tools/lib目录下的ld-linux.so.2,如果是指向/lib/ld-linux.so.2,那说明前面有路径没有设置正确。
10.照文档5.12编译binutils 2.17,这里又将ld编译了两次。第一次是使用新的gcc和glibc做了新的binutils。第二次做的ld已经将LIB_PATH改为/lib,这是为第6章服务的,在整个第5章中,ld-new是没有作用的。
11.此时/tools下的工具链制作完成,到这里如果顺利的话,以后应该就没有什么大事了。按照文档的指导,继续编译其余的工具软件,这些工具最好全部编译而不要偷懒,否则在正式生成LFS系统时会由于缺少工具而陷入困境。
12.按照5.13~5.30编辑其余的软件。
注意:
-- Bash 3.2已经有缺陷补丁了,在LFS的网站有下。
-- Gettext 0.16.1生成时,LFS写的
make -C lib
需要改为
make -C gnulib-lib
13.Tools目录下需要的文件已经全部产生,可以做个备份,将来可以利用这个目录的文件生成各种需要的linux系统。
14.按照6.1~6.8的步骤工作,尤其是6.4的chroot不要错过了,我觉得这是LFS很精彩的部分。
15.按6.9步骤,在2.5的库里增加glibc-libidn-2.5.tar.bz2,后面两个补丁好像可以跳过。2.5的glibc中已经更正好了。但编译时可能会出现“未定义的IDNA_SUCCESS”等错误。需要在glibc-build中建一个libidn目录,然后将glibc-libidn-2.5中的所有文件复制到libidn目录下,编译才可以通过。如果做check的话好像会出现几个错误,也许和内核有关,不过应该没有大的破坏。
16.按6.10~6.12调整工具链,并重新编译binutils和gcc。新的工具链做好,使用这个工具链生产的软件,会使用/lib下的库文件。
17.以后只要照着文档的要求一步步编译和设置就可以了。
不过当时我做到这里的时候,比较着急想知道这个能不能启动,因此所有的工作是围绕生成kernel进行的。
从6.13~6.24继续照着文档做的,因为这些工具都是很重要的,或被其它工具引用。
然后做了readline, bash, bzip, diffutils, grep, gzip, grub(grub最好还是使用0.97的版本,1.97的版本是grub2,与grub的配置不一样),file,module-init-tools, make, sed, shadow, sysvinit, udev。
这些工具做完后,就可以生成kernel了。内核的生成也是比较复杂的事情,不过已经有很多朋友说过,我就不多嘴了。
接着做了文档7.2, 7.7, 7.10, 8.2四个步骤。
最后修改/boot/grub/menu.lst配置文件,加入新做的LFS系统。由于我是在VM中挂了一个虚拟的scsi盘,来单独做LFS系统,这个新的盘是/dev/sdb,因此启动的配置如下:
Title My Lastest LFS
root (hd1,0)
kernel /boot/kernel-2.6.20 root=/dev/sdb1
保存文件,退出,重新启动,在grub中选择启动项,启动成功,工作正常。
现在启动的这个系统还很简单,没有网络,没有系统日志,没有全屏幕的编辑器,不过这些已经可以在新的环境中进行编译和生成了。
终于敲完了,希望这篇帖子可以给大家提供一点帮助,能够让朋友们在LFS时体会到更多的乐趣。 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|