+-----------------------------------------------------------------------------+
| 第一部分 文档说明 |
+-----------------------------------------------------------------------------+
1 作用
##########
Gnu tool chain in LFS-6.1.1
构建工具链的具体步骤参见lfs_6.1.1.note.(How to).
本文档说明相应的关键点(Why to).
2 版权
######
版权: 聂大鹏(dozec)
3 组织与作者
############
3.1 作者
========
3.1.1 作者1
-----------
姓名: 聂大鹏
email: dozec@mail.csdn.net
4 产生时间
##########
时间: 2007-2-9
5 版本
######
版本: 0.1 版
6 修订过程
##########
7 目录
######
1 实验环境
2 工具链构建说明
+-----------------------------------------------------------------------------+
| 第二部分 文档正文 |
+-----------------------------------------------------------------------------+
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硬盘)
swap分区: /dev/hdd2
/dev/hdd1 1 427 3429846 83 Linux
/dev/hdd2 428 524 779152+ 82 Linux swap
2 工具链构建说明
################
2.1 在LFS-6.1.1当中一共构建了2次Gnu tool chain
==============================================
在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的笔记
| 第一部分 文档说明 |
+-----------------------------------------------------------------------------+
1 作用
##########
Gnu tool chain in LFS-6.1.1
构建工具链的具体步骤参见lfs_6.1.1.note.(How to).
本文档说明相应的关键点(Why to).
2 版权
######
版权: 聂大鹏(dozec)
3 组织与作者
############
3.1 作者
========
3.1.1 作者1
-----------
姓名: 聂大鹏
email: dozec@mail.csdn.net
4 产生时间
##########
时间: 2007-2-9
5 版本
######
版本: 0.1 版
6 修订过程
##########
7 目录
######
1 实验环境
2 工具链构建说明
+-----------------------------------------------------------------------------+
| 第二部分 文档正文 |
+-----------------------------------------------------------------------------+
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硬盘)
swap分区: /dev/hdd2
/dev/hdd1 1 427 3429846 83 Linux
/dev/hdd2 428 524 779152+ 82 Linux swap
2 工具链构建说明
################
2.1 在LFS-6.1.1当中一共构建了2次Gnu tool chain
==============================================
在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的笔记