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

CLFS2.0原理分析

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

--cache-file则没什么好说的,就是让./configure对于--cache-file指定的文件中设置的参数强制使用。
make install-headers
到这里,我们还不需要一个完整的glibc,其实也无法进行编译的,因为目前的交叉编译用的GCC还没有,所以是无法编译的,但编译一个交叉编译的GCC又必须要一组C库的头文件,好在安装目标平台的glibc的头文件并不需要交叉编译器,所以这里直接安装头文件即可。
cp -v ../glibc-2.4/ports/sysdeps/unix/sysv/linux/arm/nptl/bits/pthreadtypes.h \
${CLFS}/usr/include/bits
这个是为了安装支持NPTL的头文件,这部分根据不同的平台复制的文件是不一样的,文章的附录中将介绍PowerPC和MIPS两种体系需要复制的文件,可作为参考。
如果你前面没有仔细看,我提个醒,上面提到的glibc-headers部分和GCC第一次编译部分是反过来讲的,因此和书上没有冲突。

  好了,到目前为止已经有了一个交叉编译用的GCC和一个交叉链接用的binutils,以及一组目标平台和目标系统用的库文件,现在就可以正式的开始编译Linux平台的基础部分——C库(glibc)
  在编译glibc的时候,同样指定了两个参数
  echo "libc_cv_forced_unwind=yes" > config.cache
  echo "libc_cv_c_cleanup=yes" >> config.cache
  这两个参数于体系无关,而第三个参数
  echo "libc_cv_arm_tls=yes" >> config.cache
  则省略了,因为交叉编译环境已经完全了解你要编译的目标体系,所以可以自行检测出来。

  这里着重需要明白的是glibc的编译参数
BUILD_CC="gcc" CC="${CLFS_TARGET}-gcc" \
AR="${CLFS_TARGET}-ar" RANLIB="${CLFS_TARGET}-ranlib" \
../glibc-2.4/configure --prefix=/usr --libexecdir=/usr/lib/glibc \
--host=${CLFS_TARGET} --build=${CLFS_HOST} \
--disable-profile --enable-add-ons \
--with-tls --enable-kernel=2.6.0 --with-__thread \
--with-binutils=${CLFS}/cross-tools/bin --with-headers=${CLFS}/usr/include \
--cache-file=config.cache
  BUILD_CC所指定的是用来建立在编译过程中需要运行的程序用什么gcc来编译,这个很重要,可以看出BUILD_CC指定的是主系统的gcc,主系统的gcc是一个运行于i386,编译出i386体系的编译器,因此它编译出来的程序可以在当前系统下运行,因为在编译过程中会编译一些临时使用的程序,而这些程序是编译完后就马上要用的,所以这些程序必须能在当前体系的平台上运行,因此必须以一个运行于当前体系平台,又编译出当前体系平台的编译器来完成,所以主系统的gcc自然成了最合适的选择。而CC所指定的是${CLFS_TARGET}-gcc,很明显是交叉编译用的GCC,原因很简单,最后编译出来的glibc的二进制库都是要在目标体系平台上运行的。AR和RANLIB是binutils中的工具,它们也是在编译过程中需要用到的,而且是用来处理目标平台的二进制文件,所以它们也是使用交叉编译用的版本。
  --prefix和--libexecdir已经在前面编译glibc-headers部分说明过了,不要被表面现象所“迷惑”,最后安装到的是${install_root}/usr和${install_root}/usr/lib/glibc下。
  --host指定也表明这里最后编译出来的库是用在目标体系平台下的。
  --with-binutils则是为了表明在需要使用binutils的时候使用交叉版本所在的目录(这里不会影响BUILD_CC编译的临时程序,因为交叉版本在交叉工具链阶段是有前缀的)。
  --with-headers和--cache-file解释同glibc-headers部分。
  其余参数于LFS中含义相同,这里就不做解释了。
  后面的make和make install自然没什么好说明的,只是这里因为前面设置了install_root的原因,在make install阶段会安装到install_root下。
  下面按道理应该要安装locales了,但这里运行make localedata/install-locales并不能正确完成,原因很简单localedef是目标体系平台的程序,所以无法在本阶段完成,这里需要和前面说明的BUILD_CC编译的是可以在当前体系平台运行的临时程序分开看,因为localedef并不是一个临时用的文件,而是glibc的标准程序,所以这里也可以算是一个未解决的问题。我的建议是暂时跳过安装localedata部分
  在完成了glibc的编译和设置后,我们要进行第二次编译交叉版本的GCC了。
这里我想说明一下为什么要进行两次GCC编译的目的,这里和我们已经熟知的LFS中工具链里的两次GCC编译有着不同的原理。这一部分也算是CLFS2.0中的重点部分,我将以我的理解来说明这个问题:
  在LFS里,工具链中第一遍编译gcc,是为了编译工具链中的glibc而编译的,而且为了能够保证编译器的正确则使用了make bootstrap来编译,在编译完glibc后,则再编译一遍gcc,目的是为了让这个gcc使用刚刚在工具链中编译好的glibc,为了是在后面完成工具链后chroot时保证工具链的可用,并且可以用来编译目标系统的glibc和LFS其他需要的软件。
  而在CLFS2.0中,第一遍编译gcc,也确实为了编译glibc,而这个glibc却不是工具链中要用的,这是目标系统用的(这一点也可以通过第六章中没有编译glibc的部分来间接验证),并不是为了第二次编译gcc,让gcc链接到这个glibc用的,而且gcc也不能链接到这个glibc 上,因为第一遍编译的交叉版本的gcc来编译出的glibc必然是目标体系平台的代码,所以在当前的体系平台上是运行不起来的,如果第二次编译的gcc链接到这个glibc上,那么这个gcc也就不能在当前的体系平台上运行了,所以CLFS2.0在工具链阶段的两次编译gcc,不是为了让gcc连接到新编译的glibc上。
  那么究竟是什么原因呢?
  我们先来看CLFS2.0第一编译GCC,没有使用make bootstrap来编译,而是使用make all-gcc来编译,也就是只编译了一次,这是合情合理的,要知道这个gcc是交叉版本,也就是说它再编译出来的是目标体系平台的二进制文件,虽然可以完成make bootstrap的第二步,但第三步是无法进行的,因为目标体系平台无法在当前平台上运行(make bootstrap,就是用第一遍编译的gcc来编译第二遍的gcc,再用第二遍的gcc编译第三遍的gcc,然后比较第二遍和第三遍的gcc,来确定编译是否正确),因此这里只需要也只能编译一遍。
  在LFS里,第一遍gcc只编译了c语言部分,是因为编译glibc只需要c语言就行了,你当然也可以编译其它的语言支持,但没有什么意义,因为第一遍的gcc会被第二遍替换掉,而且第一遍是依赖于主系统glibc的,所以在chroot后就不能用了。

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



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

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