网管联盟 | 网管论坛 | 网管u家 | 网管博客 | 网管软件 | 网管求职 | 小游戏 | 网管搜索 | 网管原创 | 网管聚合 | 网管读摘 | 网管焦点 | 世界素材 | 会员投稿 | 会员中心 
中国网管联盟
Windows Linux Cisco 网络技术 数据库 黑客攻防 DotNet Java PHP 认证 新闻资讯 服务器 存储资讯 网络设备 网管学堂 技术专题 焦点 网吧频道
 当前位置: > bitsCN.com > linux > 系统管理 > 内核技术 > 内核研究 :CLFS2.0原理分析  

内核研究 :CLFS2.0原理分析

2006-10-16  作者:网管整理  来源:bitsCN.com  点评 投稿 收藏

到目前为止只有在编译glibc的时候用到了交叉版本的binutils,其它部分的链接都是由主系统的binutils来完成的。
  现在对工具链中gcc的两次编译的目的和原因差不多搞清楚了,我们来看一下gcc两次编译参数的对比
第一次:
../gcc-4.1.1/configure --prefix=${CLFS}/cross-tools \
--host=${CLFS_HOST} --target=${CLFS_TARGET} --disable-multilib \
--with-sysroot=${CLFS} --disable-nls --disable-shared \
--enable-languages=c
第二次:
../gcc-4.1.1/configure --prefix=${CLFS}/cross-tools \
--host=${CLFS_HOST} --target=${CLFS_TARGET} --disable-multilib \
--with-sysroot=${CLFS} --disable-nls --enable-shared \
--enable-languages=c,c++ --enable-__cxa_atexit \
--enable-c99 --enable-long-long --enable-threads=posix
  看来没什么特别需要说明的,非交叉编译用的参数基本上和LFS没什么太大区别,反正最重要的就是这个--with-sysroot,好了,三次--with-sysroot都出现了,虽然前面对这个参数也说明了一下,但不够详细,下面我就来说说对这个关键参数的理解
  我们在做LFS的过程中了解到gcc在编译过程中是默认从/usr/include中找头文件的来编译的,而binutils中的工具ld是从 /lib /usr/lib、LD_LIBRARY_PATH、/etc/ld.so.conf等设置中所指定的路径搜索动态库或者静态库进行链接操作的,而要改变这种默认情况则可以通过参数指定、打补丁等方式来达到目的,但是这样非常烦琐,所以就产生了LFS中工具链的方法,通过先做一个能自我编译的工具链,但这些工具链中的程序都是连接到类似/tools/lib这样的目录下的库中,而且也是通过参数指定或者打补丁的方式来实现的,并不符合标准的/lib /usr/lib,所以后面在chroot后再用这个工具链来生成目标系统。

网管有家bitscn.net

  而现在我们用CLFS2.0的方法不需要再建立这个完整的工具链了,只是建立一个交叉用的工具链,而这个工具链中的程序都是链接到/lib和 /usr/lib里的库的,这样一个工具链是不能chroot,但现在我们要利用这个“不健全”的工具链来完成目标体系平台,就必须要用到更改默认路径的方式,这个方式就是--with-sysroot。
  一个简单的理解就是,默认的路径实际上都是{--with-sysroot}/usr {--with-sysroot}/usr/lib {--with-sysroot}/usr/include这样的形式,只是在默认的情况下{--with-sysroot}表示的是空字符串,这样就变成了/usr /usr/lib /usr/include,而如果我们指定了--with-sysroot,比如--with-sysroot=/mnt/clfs,则默认路径就变成了 /mnt/clfs/usr /mnt/clfs/usr/lib /mnt/clfs/usr/include,这样我们在编译时查找头文件以及在链接时查找动态或静态库就自动到--with-sysroot指定的路径下来完成。这个就是--with-sysroot参数的目的。
  这里需要注意的是,--with-sysroot默认是只支持交叉编译的情况的,我们可以从代码中印证
  在gcc-core解压后的Makefile.in文件(你可以理解为是Makefile的一个摸板文件)中有一段代码
网管bitscn_com

代码:
# Default native SYSTEM_HEADER_DIR, to be overridden by targets. NATIVE_SYSTEM_HEADER_DIR = /usr/include # Default cross SYSTEM_HEADER_DIR, to be overridden by targets. CROSS_SYSTEM_HEADER_DIR = @CROSS_SYSTEM_HEADER_DIR@

中国网管论坛bbs.bitsCN.com

而对于CROSS_SYSTEM_HEADER_DIR的赋值在
configure中有如下代码
网管有家bitscn.net

代码:
CROSS_SYSTEM_HEADER_DIR='$(TARGET_SYSTEM_ROOT)$(NATIVE_SYSTEM_HEADER_DIR)'

网管联盟bitsCN@com

而同在configure中对TARGET_SYSTEM_ROOT的赋值
网管有家bitscn.net

代码:
TARGET_SYSTEM_ROOT=$with_sysroot

网管朋友网www_bitscn_net

  现在明白了吧,对于交叉方式,是默认支持--with-sysroot的,而普通的编译方式是不行的,但也不是说我们就没办法了,其实办法说起来也很简单,就是改代码、打补丁。

  我们来看三次使用--with-sysroot的作用和目的
  第一次,binutils下使用,目的是让binutils在查找库的时候到--with-sysroot指定的地方查,接着的glibc-headers和gcc都没有用到这个binutils,我们先放一下,看第二次使用;
  第二次,第一次编译gcc下使用,目的是让这个gcc在编译的时候默认到{--with-sysroot}/usr/include下找头文件。
  接着我们就开始编译目标体系平台下的glibc了,这个时候交叉版本的binutils和第一次编译的gcc都用上了,则我们也就清楚了,在编译这个 glibc的时候是到${CLFS}/usr/include里找头文件,到${CLFS}/lib等目录下链接库的,不过glibc是目标系统的第一个软件包,因此,他并不需要到${CLFS}/lib等目录下的库链接,但交叉版本的binutils还是顺利的完成了glibc编译目录下自己众多库文件的链接工作。这里binutils的--with-sysroot没有体现出来,但gcc的--with-sysroot已经发挥作用了。
  第三次,实际上这次是为了替换掉第一次编译的gcc而“重复”的(原因前面已经讲过了),所以可以理解和第二次使用--with-sysroot是一样的。 网管bitscn_com
  到现在为止,gcc中的--with-sysroot已经体现出其作用了,但binutils什么时候才能发挥作用呢?
  不要着急,很快就到了它的用武之地了。

  现在我们就完成了交叉工具链了……(画外音:等等,还有两个包没说呢,怎么工具链就完成了?)
  这里我们先把--with-sysroot的问题放下,现在出现了另外一个问题,在LFS过程中我们知道工具链除了binutils和gcc外还有很多大量的工具包,而在CLFS2.0中就只有file和groff两个包,是什么意思呢?
  这里我们要全面了解工具链的作用以及这些工具包的作用,在LFS中的工具链的目的不光是为了能编译,而且是为了能够成为一个完整的自已自足的“系统”,再进入(chroot)这个“系统”后,能够利用这种自已自足的能力创造新系统,而这个过程中,大量的工具包是少不了的,这也就是为什么LFS的方法中需要在工具链阶段里加入大量的工具包。
  而在CLFS2.0之所以没有加入大量的包是因为,CLFS2.0的方法里没有chroot这个环节,所以使用主系统的工具就可以了,因此只需要 gcc和binutils就可以完成任务了,而file和groff其实我觉得也是没有必要的,只要主系统中的file和groff是符合要求的版本就可以了,如果没有符合的版本编译一个也是可以的,这里要注意的是file和groff是用主系统的gcc和binuitls完成编译链接的并依赖于主系统的glibc

网管网www.bitscn.com


  好了,下面我们就要开始编译目标系统的文件了。
  之前我们已经在第五章的部分完成了glibc的编译,所以我们就可以直接编译各个包了,从CLFS2.0的手册来看,似乎还是遵循着LFS的先编译binutils和gcc,然后再编译其它的包,但这里又是和LFS的方法有着本质上的区别,下面我们就来对照一下看看。
  在LFS中,我们在完成了工具链后,利用工具链来编译目标系统的glibc,之后是编译binutils,然后利用刚刚编译的binutils和工具链中的gcc来编译目标系统中的gcc,之后就利用刚刚编译的binutils和gcc来编译后面的部分,而之后每编译一个包,在后面的编译过程中需要用到这个包就是用刚刚编译好的,而不是工具链中的,直到把工具链中的所有包都替换成目标系统中的包,工具链就算完成目的了。比如在编译sed包之前,使用的是工具链中的sed命令,而当sed包编译完成之后,再用sed命令的时候,就是用刚刚编译好的目标系统中的sed命令了。
  而在CLFS2.0中,我们知道现在用的是交叉版本的工具链,所以编译出来的是目标体系平台的代码,那么是不能在当前的体系平台下运行的,因此,也不会出现LFS中的替换过程,所以在CLFS2.0的方法中,还以sed命令为例,在交叉工具链编译目标体系平台的sed包前用的是主系统的sed命令,而编译完sed后,再用sed命令时,依然用的还是主系统的sed命令,因为刚刚编译的sed根本就不能在当前体系平台上运行。

网管bitscn_com


  现在我们就清楚了,我们也得出了几个结论:
  1、第六章编译的包都是运行于目标体系平台的,所以不可以在当前体系平台上运行。
  2、在CLFS2.0中第六章部分的binutils和gcc不是必须编译的,除非你需要在这个系统完成后移植到目标体系的机器中运行并要继续编译其它程序才需要编译binutils和gcc(这点和我以前写的《体积小巧、功能单一的LFS》思路是一样的);
  3、第六章的包编译顺序是不需要这么严格的,特别是只有命令的包,是可以随便摆放顺序的,比如coreutils这个包,在手册中是位于gcc之后就编译了,但实际上即使放在最后一个包编译也没问题,因为这个包编译出来的命令根本就在这里用不上,部分命令如果觉得在目标系统中根本不用,即使不编译都可以,比如你不打算在目标体系平台中用patch 命令,你就可以不安装这个命令,这是不会影响编译效果的。
  4、不是所有的包都可以随意改变编译顺序的,对于有动态或者静态库的文件,如果有其它的包需要,那么就必须先于依赖于它的包编译,比如ncurses和readline,因为readline要链接ncurses的库,所以ncurses必须比readline先编译,否则会导致编译问题。

网管论坛bbs_bitsCN_com


  5、在整个第六章的过程中都是由主系统中的工具包和交叉编译工具链来完成编译的,这个时候binutils和gcc的--with-sysroot发挥着重要的作用(binutils中的--with-sysroot终于开始用上了),因为这个参数,使得整个第六章的编译过程在没有路径补丁的情况下变的相对“顺利”起来。
TAGs   原理   分析   研究   编译   CLFS   gcc   工具   系统   CLFS_TARGET      
 上一篇:开源的力量:为什么我们要使用LAMP   下一篇:使用异步 I/O 大大提高应用程序的性能
内核研究 :CLFS2.0原理分析 评论:
loading.. 评论加载中…
评论:请自觉遵守互联网相关政策法规,评论不得超过250字。

验证码: 注册用户
本类热门排行:
最新推荐文章:
网管论坛交流: