LFS6.1.1构建GNU-i686工具链笔记(why to)

    技术2022-05-11  64

    1. 建议使用 Firefox浏览本文档, 以达到最好的浏览效果.IE在浏览时易发生排版显示变形. 2. 文档发布的初衷是方便大家交流学习, 欢迎转载, 并请一并标注版权. +-----------------------------------------------------------------------+ +-----------------------------------------------------------------------+ |                       第一部分 文档说明                                | +-----------------------------------------------------------------------+ 1 作用 ##########    Gnu tool chain in LFS-6.1.1    构建工具链的具体步骤参见lfs_6.1.1.note.(How to).    本文档说明相应的关键点(Why to). 2 版权 ######   版权: 聂大鹏(dozec) 3.2 作者 ======== 3.2.1 作者1 -----------    姓名: 聂大鹏    email: dozec@mail.csdn.net 4 产生时间 ##########   时间: 2007-2-9 5 版本 ######   版本: 0.1 版 6 修订过程 ########## 6.1 第0.1版 =========== +-----------------------------------------------------------------------+ |                       第二部分 文档正文                                | +-----------------------------------------------------------------------+ 1 Gnu tool china说明 #################### 1.1 实验环境 ============ 工作站: RHEL4         Linux version 2.6.14.7         gcc version 3.4.6 20060404 (Red Hat 3.4.6-3))         CPU: Pentium 1.7G         Memory: 256MB         装LFS的分区: /dev/hdd1 (hdd是一块4.3G硬盘,只有1个分区) 1.2 笔记 ========   a).在LFS-6.1.1当中一共构建了2次Gnu tool chain.      第1次是LFS-6.1.1第5章,构建了一个不依赖于宿主系统(就是我们工作站)的Gnu工具链.              然后用这个工具链来编译生成最后目标LFS系统当中的软件包.这里涉及到2点注              意,第一点是为什么要构建这个GNU工具链来编译目标LFS系统当中的软件包而非              使用宿主系统当中的工具链,原因就在于我们最终构建目标LFS系统当中的软件包              之前,会先chroot到$LFS(/就变成了/mnt/lfs), 这样宿主系统当中的工具链就无              法使用了(例如:相应的头文件,库文件,gcc,g++,ar,as,ld等). 第二点就是我们              构建的这个新的GNU工具链是用原有宿主系统当中的GNU工具链来编译生成的,有点              鸡生蛋嘛,当这个蛋长大时(就是我们新工具链GCC第一遍完成时),再用破壳而出的              鸡再生蛋.(编译第5章剩下的软件包,包括GCC第二遍以及第6章目标LFS系统的软件              包,其中又包括目标LFS的GNU工具链).       第2次是LFS-6.1.1第6章创建的目标LFS系统的Gnu tool chain.   b).构建一个不依赖于宿主系统的GNU工具链最重要的有2点:      一是Binutils中的ld: Gcc生成.o文件后, ld会将.o与库文件链接生成可执行文件.                          重点就在于ld将会到哪些路径去搜索库文件.由于第5章中构建的                          不依赖于宿主系统的GNU工具链是安装到/tools目录下,所以ld应该                          到/tools/lib下去找我们新装的Glibc的库文件,而非到/lib下去找                          宿主系统的库文件.                          查看ld的库搜索路径的命令如下:                          # ld --verbose | grep SEARCH                          调整ld的库搜索路径需要在Binutils源码当中执行如下:                          # make -C ld LIB_PATH=/tools/lib (库搜索路径为/tools/lib)      二是Glibc中的动态库加载器: 动态库加载器实为一个动态库文件ld-linux.so.2.当程序加                                 载到内存运行时,ld-linux.so.2负责完成将程序所需使用的                                 动态库映射到进程的内存空间(使用pmap可以查看一个进程的                                 内存空间分布).ld-linux.so.2的默认搜索动态库路径为/lib                                 and /usr/lib, 可以通过修改/etc/ld.so.conf文件来增加搜                                 索路径.由于第5章中构建的不依赖于宿主系统的GNU工具链是                                 安装到/tools目录下,所以用这条新工具链编译出的程序使用                                 的应该为/tools/lib/ld-linux.so.2, 而非宿主系统/lib/ld                                 -linux.so.2.                                 查看一个程序使用的动态库加载器命令如下:                                 # readelf -l 用新工具链编译的可执行文件 | grep interpreter                                 指定编译董成的程序所使用的动态库加载器需要如下:                                 # 调整Gcc的specs文件.   c).第1次构建的GNU工具链说明(LFS-6.1.1 第5章):      这个时候是用宿主系统的GNU工具链来编译生成一个不依赖于宿主系统的工具链.      c.1) 首先要说的就是编译这个GNU工具链使用的是lfs用户来完成的,其PATH环境变量如下:           PATH=/tools/bin:/bin:/usr/bin           /tools/bin优于宿主系统当中的/bin and /usr/bin, 这样当Binutils和Gcc的第1遍           编译生成后, 再编译Glibc以及Binutils和Gcc的第2遍均是使用新的GCC.      c.2) 先装Binutils到/tools目录下,因为Gcc和Glibc的configure要对as和ld进行测试.           值得注意的是最后执行了如下2条命令:           # make -C ld clean           # make -C ld LIB_PATH=/tools/lib           生成一个库搜索路径为/tools/lib的ld, 但现在不能安装这个ld,原因很简单--Glibc没装.           当Glibc装完之后,调整工具链的时候就把这个ld安装上.           注意: 此次是使用宿主系统的GCC编译生成的Binutils, 并且动态库加载器ld-linux.so.2                 使用的是宿主系统/lib下的.      c.3) 再装GCC(pass 1)到/tools目录下,第1遍只装GCC的c编译器就成.(GCC == Gnu compiler collection).           创建cc符号链接使其指向gcc.           这个时候GCC的第1遍完成, 由于PATH当中的/tools/bin在前, 所以其后编译的软件均使用           新gcc,而非宿主系统当中的gcc了.下面的任务就是要编译Glibc,但编译Glibc之前,要先把           Linux-Libc-Headers头文件先装上.           注意: 此次是使用宿主系统的GCC编译生成的我们的GCC,并且动态库加载器ld-linux.so.2                 使用的是宿主系统/lib下的.      c.4) 使用新安装的GCC来编译Glibc到/tools目录下,以下2个参数需要注意一下:           --with-binutils=/tools/bin     保证在编译Glibc时不会使用/tools/bin下的Binutils程序.                                          也就是c.2当中提到的Binutils.           --with-headers=/tools/include  前面的头文件是安装到/tools/include当中.现在就指定                                          Glibc使用这里的头文件.           注意: 使用第一遍生成的GCC编译生成Glibc.      c.5) 调整工具链:           -1: 因为Glibc已经安装完成, 所以要把在c.1当中已经编译生成的库搜索路径为/tools/lib的ld               安装生成. 这样用新GCC编译生成的程序所使用的库均为我们刚刚安装的Glibc当中的库,而               非宿主系统当中的/lib下的库.           -2: 调整GCC的specs文件,使其编译生成的程序所使用的动态库加载器均为/tools/lib/ld-linux.so.2               而非宿主系统当中的/lib/ld-linux.so.2.                      -3: 这个时候做一个合理性检查是非常有必要的,从而来确定我们上述2步工具链是否成功.      c.6) 用第1遍生成的GCC再次编译GCC(pass 2)并安装到/tools目录下,目的有二:           -1: 把c/c++编译器也一并编译.           -2: 使用经过调整的第1遍生成的GCC来第2次编译GCC, 生成的第2遍GCC动态库加载器使用的是               /tools/lib/ld-linux.so.2, 而非宿主系统的. 这样, GCC已经独立于宿主系统了.           gcc-3.4.3-specs-2.patch这个补丁它有2个功能:           -1: 省去了安装完GCC后还要再次调整specs文件,以指向我们的动态库加载器/tools/lib/ld-linux.so.2               这个步骤.           -2: 把宿主系统头文件路径/usr/include从GCC的头文件搜索路径当中删除.      c.7) 用第2遍生成的GCC再次安装Binutils(pass 2),目的就二:           -1: 使用经过调整的第1遍生成的GCC来再次编译Binutils, 生成的第2遍Binutils动态库加载器使用的是               /tools/lib/ld-linux.so.2, 而非宿主系统的. 这样, Binutils已经独立于宿主系统了.           -2: --with-lib-path=/tools/lib   指定库搜索路径为/tools/lib                                            其实这步在c.5工具链调整中做过了, 在这指定是省去了                                            安装完Binutils再另行调整的步骤.   d). 第2次构建GNU工具链说明(LFS-6.1.1 构建目标LFS的GNU工具链)       这个时候是用第1次构建的那个独立于宿主系统的GNU工具链来构建目标LFS的GNU工具链.      d.1) 首先要说的就是编译这个GNU工具链使用的是root用户来完成的,并且chroot到$LFS           也就是说: 现在的/已经是/mnt/lfs(目标LFS系统的根), 而非我们宿主系统中的根了.           并且其PATH环境变量如下:           PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin           /tools/bin位于最后,产生的行为就是向目标LFS编译安装完软件包后,即刻就使用           新的软件包,而非/tools/bin的.                d.2) 在第1次构建GNU工具链是如下顺序:           Binutils -> Gcc -> Glibc -> 调整工具链 -> Gcc(pass 2) -> Binutils(pass 2)           而第2次构建目标LFS的GNU工具链是如下顺序:           Glibc -> 调整工具链 -> Gcc -> Binutils           显然第2次比第1次少了一次编译Gcc/Binutils环节,原因就在于调整工具链上.           按照第1次构建GNU工具链, 它调整工具链调整的是独立于宿主系统的我们自己创建的工具链,                                   而宿主系统工具链仍然正常.(这就是要先装一遍GCC/Binutils的目                                   的). 这样就会出现2个完全独立的工具链:一个是宿主系统的, 一                                   个是我们自己的.           按照第2次构建的目标LFS的工具链, 它调整工具链实际上是直接把我们第1次创建的独立于                                           宿主系统的工具链给调整了. 然后在此之上完成目标LFS                                           工具链的. 这样也会出现2个工具链: 一个是目标LFS的工                                           具链, 一个是第1次创建的工具链(其中Binutils的ld和                                           GCC的specs文件中指向的ld-linux.so.2已经被调整为/lib了,                                           而非原先的/tools), 这个工具链可以说已经以依赖于目标                                           LFS系统了.如果要用该工具链再次构建目标LFS系统,需要重新                                           调整工具链.           实验如下:           [root@hellokitty lfs]# chroot "$LFS" /usr/bin/env -i /                                  HOME=/root TERM="$TERM" PS1='[/u@lfs /W]//$ ' /                                  PATH=/tools/bin /tools/bin/bash --login           [root@lfs /]$ echo 'main() {}' > dummy.c           [root@lfs /]$ cc dummy.c           [root@lfs /]$ readelf -l a.out | grep preter                   [Requesting program interpreter: /lib/ld-linux.so.2]                                                    这已经是/lib/ld-linux.so.2了               d.3). 在构建目标LFS工具链当中:            Glibc: 线程库装上了, 这在第1次构建工具链当中是没有做的.                   另外Glibc的2个比较重要的配置文件一定要注意: /etc/nsswitch.conf                                                               /etc/ld.so.conf 1.3 参考文档 ============   < LFS-6.1.1 >   < lfs_6.1.1.note > http://blog.csdn.net/dozec/  自己写的关于LFS6.1.1的笔记  

    最新回复(0)