Linux中国 Linux中国门户站!
设为主页 设为主页
收藏本站 收藏本站
 
当前位置 :首页 ->Linux技术 ->内核研究 ->正文

CLFS2.0原理分析

来源:linuxsir 作者:youbest  时间:2007-04-22 点击: [收藏] [投稿]


  由上图我们可以看出,实际上binutils编译过程中是没有用到目标体系的内核头文件的,因此复制内核的目标体系头文件和编译binutils的顺序是无所谓的。


  接着我们就要准备开始编译GCC(不要以为我这里漏掉了glibc-2.4的headers这部分,这样安排正是为了说明glibc-2.4的headers部分为什么要在编译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将被安装到${CLFS}/cross-tools,而且只编译c语言部分,同时将${CLFS}所定义的目录作为根目录(--with-sysroot)
  这里有必要解释一下一个比较重要的概念就是“交叉编译”,交叉编译简单的讲就是在一种体系的机器上编译出运行于另一种体系的代码(两种体系也可以是相同的,但通常是以不同的体系来说明),如下图:


  这里很重要的一个部分就是编译器和链接器,这二者在这里对应的是GCC和binutils,它们即要运行于当前体系的系统下,又要能生成和处理目标体系的文件,因此称它们为交叉编译工具链。
  这里比较重要的是GCC(并不是binutils不重要,只是我们重点要说明的是GCC),那么GCC是怎么样进行编译的呢?
  这个问题要说清楚的话可以写一本书了,这里我只是从CLFS的角度来说明这个问题。GCC要编译出其它体系的代码,除了需要要编译的程序的源代码外还需要符合该体系的头文件,这里最重要的就是内核的头文件和glibc的头文件,所以作为交叉编译用的GCC,除了在编译其它程序的时候用到头文件,其自身也必须“了解”这些头文件,它必须掌握目标体系的全部细节,这已经由Linux的内核头文件给出了,另一点需要注意的是,GCC不仅可以用来在Linux 下用,也可以用在其它支持的系统上,比如BSD,而C库也不局限于glibc,有可能是其它的C库,比如uclibc,所以要能够生成在目标体系的目标系统下运行的二进制代码,那么就必须对这一切都要了解,所以在编译GCC的时候必须有目标体系及目标系统相对应的头文件,这就解释了为什么要在编译GCC之前要先编译一个glibc-2.4的头文件部分。
  下面来图解这段内容



  现在我们回过头来,编译glibc-2.4符合目标系统的头文件,这部分我感觉也是各个体系差异比较大的部分,所以我们这里参考CLFS2.0第一个完成的体系ARM来说明(我只说重点,全部内容可以参考手册说明)
tar -jxvf ../glibc-ports-2.4.tar.bz2
mv -v glibc-ports-2.4 ports
这部分实际上是为了glibc能够支持arm而安装的,标准的glibc并不支持ARM等几个体系,而glibc-ports就是为了补充这部分的支持而出现的(这里必须将其改为ports,否则编译无法找到)。
echo "libc_cv_forced_unwind=yes" > config.cache
echo "libc_cv_c_cleanup=yes" >> config.cache
echo "libc_cv_arm_tls=yes" >> config.cache
这部分实际上是强制指定一些编译时候的参数,因为目前还没有交叉编译用的GCC,所以用主系统做./configure的时候有些参数会设置一些不正确的参数,因此这里强制声明是非常必要的,到工具链中第一遍的GCC完成后就可以正确设置这些参数了,所以再编译glibc就可以不用指定这些参数。
echo "install_root=${CLFS}" > configparms
这个就是为了指定安装目录,方便以后用make install直接装到${CLFS}目录下,其实不要这句也没问题,后面的make install改为make install_root=${CLFS} install-headers就可以了。
CC=gcc ../glibc-2.4/configure --prefix=/usr \
--host=${CLFS_TARGET} --build=${CLFS_HOST} \
--with-headers=${CLFS}/usr/include --cache-file=config.cache
这个编译参数说明gcc用的是主系统的gcc,这里需要注意的是--prefix=/usr虽然指定的是/usr目录,但实际上最后安装到的是$ {install_root}/usr下,如果没有指定install_root,那自然是安装到了/usr,而因为前面指定了install_root 的目录,实际上最后安装到了${CLFS}/usr下,这里还需要注意的是--host和--build的指定(--host=$ {CLFS_TARGET} --build=${CLFS_HOST}),对比前面编译的binutils的参数(--host=${CLFS_HOST} --target=${CLFS_TARGET}),和后面GCC的参数(--host=${CLFS_HOST} --target=${CLFS_TARGET}),看到没有:

glibc-2.4 :--host=${CLFS_TARGET} --build=${CLFS_HOST}
binutils :--host=${CLFS_HOST} --target=${CLFS_TARGET}
gcc  :--host=${CLFS_HOST} --target=${CLFS_TARGET}

这里--host的指定刚好binutils和gcc相反,指定为目标体系,这点很重要,这是为了让后面即将编译的GCC能够准确的了解其要编译出的符合目标系统的二进制所需要的信息。
--with-headers指定了使用的头文件的目录,glibc唯一必须要的头文件就是内核的头文件,这点很有意义,因为glibc也是可以支持多种内核平台的,比如BSD,所以它也必须了解所服务的内核的所有特征细节,因此就不难理解为什么内核头文件必须先于glibc的头文件安装,只有这样 glibc才能“了解”到准确的内核信息。

 如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<



上一篇:使用异步 I/O 大大提高应用程序的性能   下一篇:简析Linux与FreeBSD的syscall

文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论
更多相关文章
Power by linux-cn.com 粤ICP备05006655号