Chinaunix首页 | 论坛 | 博客
  • 博客访问: 201356
  • 博文数量: 62
  • 博客积分: 725
  • 博客等级: 上士
  • 技术积分: 746
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-09 17:07
个人简介

exyz

文章分类

全部博文(62)

分类: LINUX

2013-06-05 10:40:08


点击(此处)折叠或打开  

  1. 第六章        安装系统的基本软件
  2.  
  3. ===================================
  4. 6.1    概述
  5. ===================================
  6. 我们要学习是什么使得一个Linux系统如果的工作的关键是懂得每一个包是用来干嘛的,然后你为什么在这个系统中使用它。

  7. 不建议使用优化,因为它可能在运行程序的时候导致复杂的问题。如果优化出现了问题,可以尝试不适用优化再编译它。
  8. 第一次LFS构造建议不适用自定义优化,产生的系统照样会快而稳的运行。
  9. 接下来的包要严格确保没有程序硬接线需要指向路径 /tools 。同样的原因,不要并行编译单独的包。

  10. 在安装指导之前,每一个安装页面都会提供包的信息,关于包里含有什么,它大约要花多久来构造,多大的空间它会占用.

  11. ===================================
  12. 6.2    准备虚拟内核文件系统
  13. ===================================

  14. 由内核导出的各种各样的文件系统和内核本身是用来沟通的。
  15. 这些文件系统是虚拟的,它们被用来在任何的磁盘空间上。这些文件系统中的内容是贮存在内存中的。

  16. /* 通过创建这个文件系统将要挂载的目录开始 */
  17. #mkdir -v $LFS/{dev,proc,sys}

  18.  6.2.1    创建初始设备结点
  19. 当内核引导系统时,它需要一些设备节点,特别是 console和null设备。
  20. 这些设备结点必须创建在硬盘上,这样它在udevd已经启动的时候就会已经存在,此外Linux用 init=/bin/bash 创建这些设备用下面的命令:

  21. #mknod -m 600 $LFS/dev/console c 5 1
  22. #mknod -m 666 $LFS/dev/null c 1 3

  23.  6.2.2    挂载和填充 /dev

  24. 推荐的填充 /dev 目录的方式是在 /dev 目录上挂载一个虚拟文件系统(比如 tmpfs),这样能让设备当被检测和接入时在虚拟文件系统中能动态的创建。设备创建会在Udev引导过程中完成。
  25. 由于这个新系统还没有Udev和被引导,需要手动的挂载和填充/dev目录。这通过绑定挂载到安装主机系统的/dev目录完成。监听挂载是一种特殊的挂载方式,它能让你创建一个目录或其它位置的挂载点的镜像。
  26. 使用下面的命令实现:
  27. #mount -v --bind /dev $LFS/dev

  28.  6.2.3    挂载虚拟内核文件系统

  29. /* 挂载剩余的虚拟内核文件系统 */
  30. #mount -vt devpts devpts $LFS/dev/pts
  31. #mount -vt proc proc $LFS/proc
  32. #mount -vt sysfs sysfs $LFS/sys

  33. /* 在一些宿主系统中,/dev/shm是一个到/run/shm的链接。在chroot环境中,这个符号链接在挂载成一个临时的文件系统前需要改成一个正常临时目录 */
  34. #if [ -h /dev/shm ]; then
  35.    rm -f $LFS/dev/shm
  36.    mkdir $LFS/dev/shm
  37. fi
  38. #mount -vt tmpfs shm $LFS/dev/shm
  39.  

  40. ===================================
  41. 6.3    包管理
  42. ===================================
  43. 包管理是LFS中必要的内容。一个包管理器能够追踪文件的安装位置,这样能够容易删除和更新这个包。
  44. 就像二进制文件和类库文件,一个包管理器也会处理安装的配置文件。
  45. 这里不推荐包管理器,只讲述更多的流行技术的综述和它们是怎样工作的。这里提及的问题在升级包的时候会很受用。

  46. 6.3.1    升级问题
  47. 一个包管理器应该是能够让一个包新的版本发布之后能够容易的升级。下面是升级一个包需要注意的事项,尤其是一个运行着的系统:
  48. 如果一个toolchain包(Glibc、GCC 或 Binutils)需要升级到一个次要版本,重新构造LFS是为了使得系统更安全。
  49.     ~    尽管你能够按照依赖顺序编译所有的包,但是不建议。例如,如果glibc-2.2.x 需要更新到 glibc-2.3.x,重构造是更安全的。
  50.     对于更小版本的升级,一个小的重安装也会有作用。例如,glibc-2.3.4 更新到 glibc-2.3.5 通常不会出现任何问题。
  51.     ~    如果一个包含的共享的类库更新了,如果这个类库的名字更小了,那么所有动态的链接此包类库需要重新编译以链接到更新的类库。
  52.     (记住包版本和类库的名字之间没有对应的关系) 如包 foo-1.2.3 安装了一个共享类名,名为 libfoo.so.1。那么你把包更新到foo-1.2.4时,
  53.     会安装一个新的共享类库,名为libfoo.so.2 。这样的话,所有包动态链接到libfoo.so.1 需要重新编译以链接到 libfoo.so.2。
  54.     

  55. 6.3.2    包管理技术

  56.   6.3.2.1. It is in my head !
  57.     很多人不会去探寻包管理的技术,认为它们是与包自身紧密结合的。甚至有人觉得包有变化时,就会重新去安装系统。o(╯□╰)    

  58.   6.3.2.2. 安装在一个单独目录中
  59.     这种方式不需要更多的包去管理这些安装。每一个包安装在一个单独的目录。
  60.     如,foo-1.1 是安装在/usr/pkg/foo-1.1 和一个从 /usr/pkg/foo 链接到 /usr/pkg/foo-1.1。
  61.     当安装新版本 foo-1.2 ,它会安装在 /usr/pkg/foo-1.2 和之前的符号链接被新的版本更换了。

  62.     环境变量如 PATH, LD_LIBRARY_PATH, MANPATH, INFOPATH 和 CPPFLAGS 需要有扩展包含到 /usr/pkg/foo.
  63.     对于一些包,这种管理方式是不适合的。

  64.   6.3.2.3. 符号链接型管理
  65.     这是之前的包管理方式的变异。包的安装方式和之前的一样。但不是创建符号链接,每一个文件是链接到 /usr 阶层。
  66.     这样就解决了扩展环境变量的问题。尽管这种符号链接能让用户自己创建,但是大多数包管理器默认已经使用了这种方式,包含Stow, Epkg, Graft, 和 Depot.
  67.     
  68.     这种安装方式是伪造的,它使得看起来包被安装在/usr中,但是实际上它是安装在/usr/pkg目录中。这种安装方式不是很复杂,如你在安装 libfoo-1.1的话,使用:
  69.     #./configure --prefix=/usr/pkg/libfoo/1.1
  70.     #make
  71.     #make install
  72.     这种安装方式能工作,但是不是我们需要的链接。这种方式链接到/usr/pkg/libfoo/1.1/lib/libfoo.so.1 而不是 /usr/lib/libfoo.so.1。
  73.     正确的方式是使用 DESTDIR策略来伪装包的安装。如:
  74.     #./configure --prefix=/usr
  75.     #make
  76.     #make DESTDIR=/usr/pkg/libfoo/1.1 install
  77.     
  78.     大部分包支持这种安装方式,但是也有些不支持。
  79.     对于不需要编译的包,需要手动的安装的话,可以将它放置在 /opt 目录中。

  80.   6.3.2.4. 基于时间戳
  81.     这中技术中,一个文件在安装之前是有个时间戳的。在安装之后,使用find命令加上适当的选项可以产生所有含时间戳的文件的日志。
  82.     这种包管理器的写入方式就是安装日志。
  83.     这种方案的优点是简单,但它含有2个缺点。如果在安装的时候,安装的文件是基于其它的时间而不是当前的时间,那么这些文件将不会被追踪到。
  84.     同时这种方案只适用于一个包仅能安装一次的情况。如果两个包在两个不同的终端上安装的话,日志就不可靠了。

  85.   6.3.2.5. 追踪安装脚本
  86.     在这种方式中,安装脚本的命令执行会被记录下来。这里有两个技术要点需要记住的:
  87.     LD_PRELOAD 环境变量可在安装之前预设置到一个类库的挂载点。在安装的时候,类库追踪包通过安装执行的cp、install、mv等各种可执行文件追踪系统修改文件系统的调用。
  88.     这种工作的方式,所有的可执行文件需要动态的链接而没有设置suid或者sgid位。预载类库在安装的时候可能导致不需要的副作用。
  89.     因此,进行执行测试以确保包管理器不会破坏任何的东西和日志等相关的文件
  90.     
  91.     第二种技术是使用strace,它会记录在执行安装脚本时所有的系统调用。

  92.    6.3.2.6. 创建包的档案
  93.     这种方案中,包安装会像符号链接风格的包管理一样伪装成一个单独的树。在安装之后,一个包档案是使用已安装的文件。
  94.     此归档可以用来安装包,无论是在本地机器上还是在其他的机器上。
  95.     这种方式被大多数商业发行版所使用。其中一个就是RPM(顺便提下,它是被LSBS ,Linux Standard Base Specification,所需要),pkg-utils, Debian's apt,和Gentoo's Portage 系统。
  96.     
  97.     Slackware 是基于tar的包归档系统。这个系统不需要去处理包依赖的问题。这种包管理细节,可前往:http://www.slackbook.org/html/package-management.html.
  98.   
  99.    6.3.2.7. 基于用户的管理
  100.     这种方式是LFS独有的。这种方式中,每一个包的安装是基于不同的用户安装到标准位置。属于一个包的文件能够很容易的通过检查用户的ID来验证。
  101.     这种方式的特征和缺点在这里描述起来是很复杂的,更多的在:http://www.linuxfromscratch.org/hints/downloads/files/more_control_and_pkg_man.txt.

  102. 6.3.3.    在多个系统上部署LFS

  103.     LFS系统的一个优势是它的文件不依赖文件在磁盘系统上的位置。
  104.     克隆一个LFS构造版到一个相同架构的机子上作为基本系统相当于在包含root目录(没有压缩的LFS构造系统大约250 MB)的LFS分区中使用tar命令,通过网络传输或者CD-ROM复制问到新的系统然后扩展它。
  105.     从那点开始,一些配置文件将会发生改变。需要更新的配置文件包含:/etc/hosts, /etc/fstab, /etc/passwd, /etc/group, /etc/shadow, /etc/ld.so.conf,
  106.     /etc/sysconfig/rc.site, /etc/sysconfig/network, and /etc/sysconfig/ifconfig.eth0.
  107.     一个通用的内核需要重新构造因为这个心的系统以来系统中的硬件和原来的内核配置。

  108. ===================================
    6.4. 进入chroot环境
    ===================================
  1. 是时候进入chroot环境然后开始构造和安装最后的LFS系统了。
    /* 使用root用户,运行下面的命令来进入此时已填充了临时工具的的领域 */
    #chroot "$LFS" /tools/bin/env -i \
        HOME=/root                  \
        TERM="$TERM"                \
        PS1='\u:\w\$ '              \
        PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin \
        /tools/bin/bash --login +h

    env命令加上 -i 选项将会清除chroot的所有环境变量。这样,只有HOME, TERM, PS1, 和 PATH 会被重新设置。
    这个TERM=$TERM 变量将会设置TERM在chroot内的变量值和chroot外的值一样。这个变量会被 vim 和 less 正常运行所需要。
    如果其它的变量需要设置,比如 CFLAGS 或者 CXXFLAGS ,那么现在就可以重新设置它们了。
    从这时候开始,基本不再需要 LFS 这个环境变量了,因为所有的工作会限制在LFS文件系统中。因为现在Bash shell已经知道 $LFS 就是根目录(/).
    记住 /tools/bin 最终在 PATH 的最后面,这意味着这个临时的工具目录一旦其最终版本安装完成就会被抛弃了,不再使用了。
    出现这种情况是shell没有记住可执行二级制文件的位置——对于这个原因,是因为hashing功能会被 bash 加上 +h 关闭掉。
    记住 bash 提示说“I have no name!”。这是正常的,因为 /etc/passwd 文件还没有被创建。    
    ++++++++++++++++++++++++++++++++++++++++++
  1. 注意:这章之后的内容都会在 chroot 环境中运行。如果你离开了这个环境,比如重启(尼玛,我经常重启!!!,有必要将它加入/etc/profile中去了),务必确保你的虚拟内核文件系统被成功的挂载了。 
  2. 可使用下面的命令来确保:
  3. /* 创建设备结点console、null到硬盘上,测试检查,该项已产生 */
    mknod -m 600 $LFS/dev/console c 5 1
    mknod -m 666 $LFS/dev/null c 1 3

    /* 挂载和填充 /dev ,挂载剩余的虚拟内核文件系统  */
    mount -v --bind /dev $LFS/dev
    mount -vt devpts devpts $LFS/dev/pts
    mount -vt proc proc $LFS/proc
    mount -vt sysfs sysfs $LFS/sys


    /* /dev/shm可能是到/run/shm的链接,确保/dev/shm为空,然后再挂载 */
    if [ -h /dev/shm ]; then
         rm -f $LFS/dev/shm
        mkdir $LFS/dev/shm
     fi
    mount -vt tmpfs shm $LFS/dev/shm

  4. /* 使用root用户,运行下面的命令来进入此时已填充了临时工具的的领域 */
    chroot "$LFS" /tools/bin/env -i \
        HOME=/root                  \
        TERM="$TERM"                \
        PS1='\u:\w\$ '              \
        PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin \
        /tools/bin/bash --login +h

  5. install -dv -m 0750 /root
    install -dv -m 1777 /tmp /var/tmp

    /* 每次重启系统需要重新运行以上命令 */
  1. ++++++++++++++++++++++++++++++++++++++++++
  2.  

  3. ===================================
    6.5. 创建目录
    ===================================
    /* 是时候创建LFS系统中的一些结构了。下面是用来创建标准的目录树的 */
    mkdir -pv /{bin,boot,etc/{opt,sysconfig},home,lib,mnt,opt,run}
    mkdir -pv /{media/{floppy,cdrom},sbin,srv,var}
    install -dv -m 0750 /root
    install -dv -m 1777 /tmp /var/tmp
    mkdir -pv /usr/{,local/}{bin,include,lib,sbin,src}
    mkdir -pv /usr/{,local/}share/{doc,info,locale,man}
    mkdir -v  /usr/{,local/}share/{misc,terminfo,zoneinfo}
    mkdir -pv /usr/{,local/}share/man/man{1..8}
    for dir in /usr /usr/local; do
     ln -sv share/{man,doc,info} $dir
    done
    case $(uname -m) in
    x86_64) ln -sv lib /lib64 && ln -sv lib /usr/lib64 ;;
    esac
    mkdir -v /var/{log,mail,spool}
    ln -sv /run /var/run
    ln -sv /run/lock /var/lock
    mkdir -pv /var/{opt,cache,lib/{misc,locate},local}

    解释:
        目录的默认权限是755,不是所有的目录都应该是这样子的。在上面的命令中,发生了2个改变——一个是root用户的家目录,另一个是临时文件的目录。
        第一个模式改变的是确保不是任何人都可以进入 /root 目录中,同样的适用于其它普通用户的家目录。
        第二个模式改变的是确保任何人都能过写 /tmp 和 /var/tmp 目录,但是不能够从中移除其他用户的文件。后面的是由黏着位实现的,最高位置(1),在默认掩码1777中。

      6.5.1. 文件层次系统标准的合规性
        这个目录树是基于 Filesystem Hierarchy Standard (FHS) ,可参考:。
        多于FHS,我们创建了更多的兼容性的符号链接,如man、doc、info,
  4.     因为许多的包会尝试安装它们的文档到 /usr/ 或 /usr/local/ 相对于/usr/share/ 或 /usr/local/share/.
        FHS 同时也规定了/usr/local/games 和 /usr/share/games 目录的存在。因为 FHS 没有仔细规定 /usr/local/share 子目录的结构,因此,我们只创建我们需要的目录。
        但是,如果你想更符合 FHS 标准的话,你可以自由的创建这些目录。
  5.  
  6.  
  7.  
  8. ===================================
  9. 6.6. 创建基本的文件和符合链接
  10. ===================================
  11. 一些程序使用一些不存在的程序的硬连接路径。为满足这些个程序,在这章中,在软件安装完成之后创建的一些符号链接会被真实文件替代。
    ln -sv /tools/bin/{bash,cat,echo,pwd,stty} /bin
    ln -sv /tools/bin/perl /usr/bin
    ln -sv /tools/lib/libgcc_s.so{,.1} /usr/lib
    ln -sv /tools/lib/libstdc++.so{,.6} /usr/lib
    sed 's/tools/usr/' /tools/lib/libstdc++.la > /usr/lib/libstdc++.la
    ln -sv bash /bin/sh

  12. 一个正确的Linux系统维护的文件系统列表存放在 /etc/mtab 文件中。一般来说,这个文件呢会在我们挂载一个新的系统的时候会创建。
    因为我们不会在 chroot 环境中挂载任何文件系统,创建一个空文件以期望 /etc/mtab 文件的存在:
    #touch /etc/mtab
    为了让 root 用户能够登录进来,和 "root" 能够被记住,那么必须在 /etc/passwd 和 /etc/group 文件中有相应的条目。

  13. /* 创建 /etc/passwd 文件 */
    #cat > /etc/passwd << "EOF"
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/dev/null:/bin/false
    nobody:x:99:99:Unprivileged User:/dev/null:/bin/false
    EOF

  14. root 的真实密码(这个 "x" 在这里只是一个占位符而已)在稍后设置.
    /* 创建 /etc/group 文件 */
    #cat > /etc/group << "EOF"
    root:x:0:
    bin:x:1:
    sys:x:2:
    kmem:x:3:
    tape:x:4:
    tty:x:5:
    daemon:x:6:
    floppy:x:7:
    disk:x:8:
    lp:x:9:
    dialout:x:10:
    audio:x:11:
    video:x:12:
    utmp:x:13:
    usb:x:14:
    cdrom:x:15:
    mail:x:34:
    nogroup:x:99:
    EOF

  15. 这里创建的组不是任何标准的一部分,它是在这章中Udev配置需求所决定的,同时也是遵循一些现有发型版的共同约定。
    LSB 只是建议拥有 GID 为0的root组和 GID 为1的bin组存在即可。 其它的组名和GIDs自由由管理员选择,因为写的很好的程序依赖的是 GID 的数字,而不是 组的名字。

  16. 为了移除 "I have no name!" 提示,可以开始一个新的shell。因为一个完整的 Glibc在第五章已经安装好了,/etc/passwd 和 /etc/group 已经创建了,用户名和用户组组决断将可以工作了:
    #exec /tools/bin/bash --login +h
  17. 注意: +h 这个指示的用法。它告诉bash不要使用它内部的路径hashing。没有这个指示了,bash将会记住它执行过的二进制文件的路径。
    为了确保最新的编译安装的二进制文件能被使用到,+h 这个指示在本章中一直会使用到。


    login, agetty, 和 init 程序(以及其它的)会用一些日志文件记录一些想谁和在什么时候登陆了这个系统的信息。但是,这些程序如果不存在的话不会将这些写入日志文件中。
    初始化这些日志文件,然后给他们一个适当的权限:
    touch /var/log/{btmp,lastlog,wtmp}
    chgrp -v utmp /var/log/lastlog
    chmod -v 664  /var/log/lastlog
    chmod -v 600  /var/log/btmp
    /var/log/wtmp 文件记录登陆和登出的信息。/var/log/lastlog 记录每一个用户最后一次登陆的信息。/var/log/btmp 文件记录坏的登录尝试。
    注意: /run/utmp 文件记录当前用户登录的信息。它是在开机脚本中动态创建的。

    ********** written at 2013-06-05 21:27 ************
  18.  
  19.  
  20. ===================================
    7. Linux-3.5.2 API 头文件
    ===================================
  21. 它包含了 Glibc 使用的内核的 API 。


      7.1. 它的安装
    Linux内核需要为系统的C类库(在 LFS 中使用的是 Glibc )使用提供接口。这通过净化各种在Linux内核源码包运行的 C 头文件实现的。

  22. /* 确保没有陈旧的文件和对之前活动的依赖 */
    #make mrproper

    现在测试和解压来自源码用户可见的内核头部。它们放置在一个中间的本地目录然后复制到需要的位置,因为解压的过程会移除任何在目标目录中的任何文件。
    同时也有一些隐藏的为内核开发者使用的文件,但是在 LFS 中不需要的在中间目录中移除的文件。
    #make headers_check
    #make INSTALL_HDR_PATH=dest headers_install
    #find dest/include \( -name .install -o -name ..install.cmd \) -delete
    #cp -rv dest/include/* /usr/include

      7.2. 安装的内容
    已安装的头文件:/usr/include/asm/*.h, /usr/include/asm-generic/*.h, /usr/include/drm/*.h, /usr/include/linux/*.h, 
    /usr/include/mtd/*.h, /usr/include/rdma/*.h, /usr/include/scsi/*.h, /usr/include/sound/*.h, /usr/include/video/*.h, /usr/include/xen/*.h
    已安装的目录:/usr/include/asm, /usr/include/asm-generic, /usr/include/drm, /usr/include/linux, /usr/include/mtd,
    /usr/include/rdma, /usr/include/scsi, /usr/include/sound, /usr/include/video, /usr/include/xen
    简短的描述:
    /usr/include/asm/*.h Linux API ASM 头文件
    /usr/include/asm-generic/*.h Linux API ASM 通用头文件
    /usr/include/drm/*.h Linux API DRM 头文件
    /usr/include/linux/*.h Linux API Linux 头文件
    /usr/include/mtd/*.h Linux API MTD 头文件
    /usr/include/rdma/*.h Linux API RDMA 头文件
    /usr/include/scsi/*.h Linux API SCSI 头文件
    /usr/include/sound/*.h Linux API Sound 头文件
    /usr/include/video/*.h Linux API Video 头文件
    /usr/include/xen/*.h Linux API Xen 头文件

    ===================================
    8. Man-pages-3.42
    ===================================
    它包含超过 1,900 多个man页面!

      8.1. 它的安装
    /* 安装 */
    #make install

      8.2. 安装的内容
    已安装的文件:各种man页面 
    简短的描述:
    man pages 描述 C 语言程序函数,重要的设备文件和配置文件的意义。

    ===================================
     9. Glibc-2.16.0
    ===================================
    Glibc 包含了主要的 C 类库。这个类库提供了基本为分配内存,搜索目录,打开和关闭文件,读和写文件,字符串处理,正则表达式,算术等的基本分配。

      9.1. 它的安装
    注意:一些在 LFS 之外的包建议安装 GNU libiconv(在Unicode和其他的传统编码之间转换的库)为了实现将数据的一种编码方式转换成另外一种。
          这个项目的主页()表示这个类库提供一个 iconv() 的实现,是为了在系统上没有改转换或者其它的方式不能够会被转换或者转换到 Unicode 的。
          Glibc 提供了一个 iconv() 能够进行到或者从 Unicode 的 转换,因此 libiconv 在LFS 系统中是不需要的。
    Glibc构造系统是子包含的,将会完全的安装,即使它的编译规格文件和链接器还挂载在 /tools 上。
    这个规格和链接器在 Glibc 安装之前不能够进行调整,因为 Glibc 的autoconf 测试将会导致是失败,同时不能够获得一个干净的编译目标。

    /* 修补一个在 LFS 环境导致构造失败的问题 */
    #sed -i 's##"rpc/types.h"#' sunrpc/rpc_clntout.c

    /* 在 Glibc 执行 make install 的时候会执行一个  test-installation.pl 的完整性测试的脚本。但是它包含一个可能导致失败的脚本,阻止它 */
    # sed -i '/test-installation.pl/d' Makefile

    /* 这个 ldd  脚本包含 Bash 特有的语法。将它的默认程序转换成 /bin/bash 以防止另一个 /bin/sh 的安装 */
    #sed -i 's|@BASH@|/bin/bash|' elf/ldd.bash.in


    /* 修补一个一些应用程序不能够使用域名服务器而导致崩溃的问题 */
    #patch -Np1 -i ../glibc-2.16.0-res_query_fix-1.patch

    /* 编译安装前的准备 */
    #mkdir -v ../glibc-build
    #cd ../glibc-build

    /* Glibc 文档建议在源代码目录之外的一个专门的目录中进行构造 */
    #../glibc-2.16.0/configure  \
        --prefix=/usr          \
        --disable-profile      \
        --enable-add-ons       \
        --enable-kernel=2.6.25 \
        --libexecdir=/usr/lib/glibc

    解释:
        --libexecdir=/usr/lib/glibc
        将 pt_chown 程序的默认位置/usr/libexec 改为 /usr/lib/glibc .

  23. /* 编译 */
    #make
    重要: 这时候进行测试是非常关键的,在任何情况下都不要忽略它。
            一般会有一些歌测试没有通过,但是你只可以忽略下面列出的错误情况!

    /* 现在测试 */
    #make -k check 2>&1 | tee glibc-check-log
    #grep Error glibc-check-log

    测试出现问题可能是宿主机的原因,下面是一些可以理解的测试失败:
    @   nptl/tst-clock2, nptl/tst-attr3, tst/tst-cputimer1, 和 rt/tst-cpuclock2 可能测试失败,原因是没有完全理解,但是,迹象表明小的计时问题会导致这些个问题。
    @   在系统运行时数学测试有时出现问题,可能是因为 CPU 不是一个相对较新的真正的Intel或正宗的AMD处理器。
    @   在运行在一个老的和更慢的硬件上或者系统负载过大的情况下,一些测试可能导致失败是因为测试超时。修正 make check 命令来设置 TIMEOUTFACTOR 以消除这些错误。
        (eg:TIMEOUTFACTOR=16 make -k check)
    @   其它的测试未知问题是因为在 posix/bug-regex32, misc/tst-writev, elf/check-textrel, nptl/tst-getpid2, 和 stdio-common/bug22 架构上。

    /* 尽管它是一个无关紧要的信息,Glibc 的安装将会报告缺失 /etc/ld.so.conf .防止警告的办法是 */
    #touch /etc/ld.so.conf

    /* 安装 */
    #make install

    /* 安装 NIS 和 RPC 相关的头文件不是默认的;它需要重新构造 glibc 通过一些 BLFS 包 */
    #cp -v ../glibc-2.16.0/sunrpc/rpc/*.h /usr/include/rpc
    #cp -v ../glibc-2.16.0/sunrpc/rpcsvc/*.h /usr/include/rpcsvc
    #cp -v ../glibc-2.16.0/nis/rpcsvc/*.h /usr/include/rpcsvc

    通过上面的命令,未安装的语言环境可以是系统在不同的本地环境使用不同的语言。没有一个语言环境是必须的,但是如果它们其中的一些个丢失了,未来的软件包的测试套件会跳过重要的测试用例。
  24. 单独的本地语言可以通过 localedef 程序安装。例如下面第一个 localedef 命令将 /usr/share/i18n/locales/cs_CZ 字符集独立语言环境与  /usr/share/i18n/charmaps/UTF-8.gz 字符
    映射定义包结合一起到   /usr/lib/locale/locale-archive 文件中。

  25. 下列的命令将会最小化安装必要的语言包为最佳的测试范围。
    mkdir -pv /usr/lib/locale
    localedef -i cs_CZ -f UTF-8 cs_CZ.UTF-8
    localedef -i de_DE -f ISO-8859-1 de_DE
    localedef -i de_DE@euro -f ISO-8859-15 de_DE@euro
    localedef -i de_DE -f UTF-8 de_DE.UTF-8
    localedef -i en_GB -f UTF-8 en_GB.UTF-8
    localedef -i en_HK -f ISO-8859-1 en_HK
    localedef -i en_PH -f ISO-8859-1 en_PH
    localedef -i en_US -f ISO-8859-1 en_US
    localedef -i en_US -f UTF-8 en_US.UTF-8
    localedef -i es_MX -f ISO-8859-1 es_MX
    localedef -i fa_IR -f UTF-8 fa_IR
    localedef -i fr_FR -f ISO-8859-1 fr_FR
    localedef -i fr_FR@euro -f ISO-8859-15 fr_FR@euro
    localedef -i fr_FR -f UTF-8 fr_FR.UTF-8
    localedef -i it_IT -f ISO-8859-1 it_IT
    localedef -i it_IT -f UTF-8 it_IT.UTF-8
    localedef -i ja_JP -f EUC-JP ja_JP
    localedef -i ru_RU -f KOI8-R ru_RU.KOI8-R
    localedef -i ru_RU -f UTF-8 ru_RU.UTF-8
    localedef -i tr_TR -f UTF-8 tr_TR.UTF-8
    localedef -i zh_CN -f GB18030 zh_CN.GB18030

  1. 另外,安装在 glibc-2.16.0/localedata/SUPPORTED(它包含更多的语言包!!) 中的所有的文件的话,
  2. 使用下面的命令:
    #make localedata/install-locales

       
  3. 9.2 配置 Glibc
    首先要创建 /etc/nsswitch.conf 文件,尽管 Glibc 在这个文件丢失或者错误的时候会提供。

    默认的文件,但是 Glibc 在一个有网络的环境中默认不会工作的很好。当然也要配置时间区域。
    命令如下:
  4. ------------------------------------------------------------------------
    cat > /etc/nsswitch.conf << "EOF"
    # Begin /etc/nsswitch.conf


    passwd: files
    group: files
    shadow: files


    hosts: files dns
    networks: files


    protocols: files
    services: files
    ethers: files
    rpc: files


    # End /etc/nsswitch.conf
    EOF
    ------------------------------------------------------------------------

    安装时区数据:
    ------------------------------------------------------------------------
    #tar -xf ../tzdata2012e.tar.gz


    ZONEINFO=/usr/share/zoneinfo
    mkdir -pv $ZONEINFO/{posix,right} 


    for tz in etcetera southamerica northamerica europe africa antarctica  \
              asia australasia backward pacificnew solar87 solar88 solar89 \
              systemv; do
        zic -L /dev/null   -d $ZONEINFO       -y "sh yearistype.sh" ${tz} 
        zic -L /dev/null   -d $ZONEINFO/posix -y "sh yearistype.sh" ${tz} 
        zic -L leapseconds -d $ZONEINFO/right -y "sh yearistype.sh" ${tz}
    done


    cp -v zone.tab iso3166.tab $ZONEINFO
    zic -d $ZONEINFO -p America/New_York
    unset ZONEINFO
    ------------------------------------------------------------------------

    zic 命令意思:
        zic -L /dev/null ...
            它创建了可移植的时区而没有任何闰秒的误差。它通常防止 zoneinfo 和 zoneinfo/posix 中 。把 POSIX 时区放在 zoneinfo 中是为了防止在各种测试事宜中报错。在一个嵌入式系统中,它的空
            间是紧凑的,没有必要和需要去更新时区,这样可以不用 posix 目录而节约 1.9MB 的空间,但是一些应用程序和测试工具套不会给好的结果。
        zic -L leapseconds ...
            它创建了正确的时区,包括闰秒。嵌入式系统中,是一个紧密的空间,没必要去更新时区或者关心时间,可以节约 1.9MB 的空间通过忽略 right 目录。
        zic ... -p ...
            它创建了 posixrules 文件。使用纽约时间是因为 POSIX 标准是遵循美国的标准时间。

  5. 一种决定本地时区的方式是运行脚本:
    #tzselect
        在回答了一系列关于位置的问题之后,该脚本会自动为你输出你的时区。同样有一些其它可用的时区在 /usr/share/zoneinfo 中比如 Canada/Eastern 或者 EST5EDT 可以使用,虽然脚本没有识别
    但是仍然可用。

  6. 创建 /etc/localtime  文件:
    #cp -v --remove-destination /usr/share/zoneinfo/ \
        /etc/localtime

  7. 替换成相应的时区,如 Canada/Eastern。
    cp 命令解释:
    --remove-destination
    它需要用来对已经存在的符号链接进行强制移除。复制文件而不是使用符号链接的原因是为覆盖 /usr 在一个单独的分区的事实。这在系统进入了单用户模式的时候是非常重要的。

  8.  9.3 配置动态加载器
      默认动态加载器(/lib/ld-linux.so.2)会在 /lib 和 /usr/lib 搜索程序运行时需要的动态类库。但是其它的类库不在这两个目录中的话,它们需要加入到 /etc/ld.so.conf 文件中让动态加载器能够找得到它们。2个通常会额外包含在其中的目录是 /usr/local/lib 和 /opt/lib ,因此现在将它们加入到动态加载器的搜索路径中。

  9. /* 创建 /etc/ld.so.conf 文件 */
    cat > /etc/ld.so.conf << "EOF"
    # Begin /etc/ld.so.conf
    /usr/local/lib
    /opt/lib
    EOF

  10. 如果需要的话,动态加载器也能够搜索目录和包含找到的文件。通常在这个包含的目录中的文件中是一行行的具体需要的类库路径。
    /* 运行下面的命令以增加兼容性 */
    cat >> /etc/ld.so.conf << "EOF"
    # Add an include directory
    include /etc/ld.so.conf.d/*.conf
    EOF
    mkdir /etc/ld.so.conf.d
  11.  
     

    ② Glibc 的内容
        已安装的程序:
            catchsegv, gencat, getconf, getent, iconv, iconvconfig, ldconfig, ldd, lddlibc4, locale, localedef, mtrace, nscd, pcprofiledump, pt_chown, rpcgen, sln, 
            sotruss, sprof, tzselect, xtrace, zdump, and zic
        已安装的类库:
            ld.so, libBrokenLocale.{a,so}, libSegFault.so, libanl.{a,so}, libbsd-compat.a, libc.{a,so}, libc_nonshared.a, libcidn.so, libcrypt.{a,so}, libdl.{a,so}, 
            libg.a, libieee.a, libm.{a,so}, libmcheck.a, libmemusage.so, libnsl.{a,so}, libnss_compat.so, libnss_dns.so, libnss_files.so, libnss_hesiod.so,
            libnss_nis.so, libnss_nisplus.so, libpcprofile.so, libpthread.{a,so}, libpthread_nonshared.a, libresolv.{a,so}, librpcsvc.a, librt.{a,so}, 
            libthread_db.so, and libutil.{a,so}
        已安装的目录:
            /usr/include/arpa, /usr/include/bits, /usr/include/gnu, /usr/include/net, /usr/include/netash, /usr/include/netatalk, /usr/include/netax25,
            /usr/include/neteconet, /usr/include/netinet, /usr/include/netipx, /usr/include/netiucv, /usr/include/netpacket, /usr/include/netrom, 
            /usr/include/netrose, /usr/include/nfs, /usr/include/protocols, /usr/include/rpc, /usr/include/rpcsvc, /usr/include/sys, /usr/lib/audit, 
            /usr/lib/gconv, /usr/lib/glibc, /usr/lib/locale, /usr/share/i18n, /usr/share/zoneinfo
        简单描述:
    catchsegv 当程序因为段错误可以进行堆栈跟踪。
    gencat 生成消息目录
    getconf 配置系统配置文件系统的特定变量值
    getent 从管理数据库中获取条目
    iconv 执行字符集转换
    iconvconfig 创建 fastloading 的 iconv 模块配置文件
    ldconfig 配置动态链接器的运行时绑定
    ldd 共享库报告所需要求的每一个给定的程序或共享库
    lddlibc4 支持 ldd 的对象文件
    locale 打印关于当前本地的变量信息
    localedef 编译本地规范
    mtrace 内存追踪文件读取和解释,并显示出一个适合读的格式
    nscd 一个守护进程,提供了一个最常见的名称服务请求缓存
    pcprofiledump PC分析产生的转储信息
    pt_chown grantpt 设置用户、组和伪终端的可访问权限的助手程序
    rpcgen 产生 C 代码来完成RPC(远程过程调用)协议
    sln 静态链接的程序 ln
    sotruss 追踪共享库过程调用指定的命令
    sprof 读取和显示共享的对象资源数据
    tzselect 询问用户系统的地址然后报告出想要2的区域描述
    xtrace 追踪程序的执行通过打印当前的执行函数
    zdump 时区翻转
    zic 时区编译器
    ld.so 助手 prog ram 共享库的可执行文件
    libBrokenLocale Glibc做为一个总的技巧来破坏运行中的程序作为内部使用。(如.一些 Motif 程序).查看 glibc-2.16.0/locale/broken_cur_max.c 中的评论查看更多信息。
    libSegFault catchsegv 使用的段错误信号处理程序
    libanl 一个同步域名查询类库
    libbsd-compat 提供必要的可移植性以运行在 Linux 下的 BSD(Berkeley Software Distribution) 程序
    libc 主 C 类库
    libcidn Glibc 内部使用来处理在 getaddrinfo() 的国际化域名
    libcrypt 加密技术类库
    libdl 动态链接接口类库
    libg 无函数的假类库。之前是 g++ 的运行时类库
    libieee 链接在这个模块中强制使用 IEEE 学术定义的数学函数的错误处理规则。默认的是使用 POSTIX.1  错误处理
    libm 数学类库
    libmcheck 链接到的时候会打开内存分配检查
    libmemusage memusage 用来搜集一个程序的内存使用信息
    libnsl 网络服务类库
    libnss 名称服务转换类库,含处理主机名、用户名、组名、别名、服务、协议等名的功能。
    libpcprofile 含分析函数用来追踪在特定源代码行中的 CPU 花费时间
    libpthread POSIX 线程类库
    libresolv 含创建、发送和中断到网络域名服务器的包的功能
    librpcsvc 含提供杂 RPC 服务的功能
    librt 含提供由 POSIX.1b 即时扩展指定大部分的接口的功能
    libthread_db 含为多线程程序构造调试的有用函数
    libutil 含在大多不同 Unix 工具中使用的 "标准" 函数
  12. ===================================
  13. 10. 调整 Toolchain
  14. ===================================

  15. 现在最终的 C 类库已经安装完成,该调整 toolchain 了让新编译的程序链接到这些新的类库。
    首先,备份 /tools 链接,然后将它替换成已调整好的链接。它的副本会保存在 /tools/$(gcc -dumpmachine)/bin:
    mv -v /tools/bin/{ld,ld-old}
    mv -v /tools/$(gcc -dumpmachine)/bin/{ld,ld-old}
    mv -v /tools/bin/{ld-new,ld}
    ln -sv /tools/bin/ld /tools/$(gcc -dumpmachine)/bin/ld

    接着,修改 GCC 的规格文件让它指向新的动态链接器。简单的删除所有在 “/tools” 下面的实例应该留下到动态链接器的正确路径。同时调整规

    格文件这样 GCC 知道去哪找的正确的头文件和 Glibc 的启动文件。
    gcc -dumpspecs | sed -e 's@/tools@@g' \
        -e '/\*startfile_prefix_spec:/{n;s@.*@/usr/lib/ @}' \
        -e '/\*cpp:/{n;s@$@ -isystem /usr/include@}' > \
        `dirname $(gcc --print-libgcc-file-name)`/specs

    现在要确保基本的功能(编译和链接)来调整 toochain 能够正常工作。
    /* 需要运行下面合理的检查 */
    echo 'main(){}' > dummy.c
    cc dummy.c -v -Wl,--verbose &> dummy.log
    readelf -l a.out | grep ': /lib'
    如果一切正常的话,那么就不会显示错误,最后一个命令的输出(允许特定平台的不同动态链接名称):
    [Requesting program interpreter: /lib/ld-linux.so.2]

  16. 注意现在 /lib 是动态链接器的前缀了。
  17. /* 现在确保有设置到正确的启动文件 */
    grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log
    如果一切正常的话,现在应该没有问题了,最后输出的命令行会是:
  18. /usr/lib/crt1.o succeeded
    /usr/lib/crti.o succeeded
    /usr/lib/crtn.o succeeded

  19. /* 验证编译器有搜索正确的头文件 */
    grep -B1 '^ /usr/include' dummy.log
    返回的成功命令输出应该是:
    #include <...> search starts here:
     /usr/include

  20. /* 接下来,验证新的链接器有使用正确的搜索路径 */
    grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
    如果一切正常的话,应该没有错误,最后的输出行(允许特定平台的不同)应该是:
    SEARCH_DIR("/tools/i686-pc-linux-gnu/lib")
    SEARCH_DIR("/usr/lib")
    SEARCH_DIR("/lib");

  21. /* 现在确保我们在使用正确的 libc */
    grep "/lib.*/libc.so.6 " dummy.log
    如果一切正常的话,应该没有错误,最后的输出(允许在64位的宿主机上有 lib64 目录)应该是:
    attempt to open /lib/libc.so.6 succeeded

  22. /* 最后,确保 GCC 是使用正确的动态链接器 */
    grep found dummy.log
    如果一切正常的话,应该是没有错误的,命令行的输出会是(允许平台的的动态链接器的名称不同 和 64位的宿主机上有一个 lib64 目录):
    found ld-linux.so.2 at /lib/ld-linux.so.2

  23. 如果输出并不是像上面的显示的那样或者根本没有显示,那么肯定某些地方出错了。考察和追究步骤来找到问题所在,然后修正它。
    大部分的原因是因为规格文件调整出问题了。任何在这些过程中出现的问题在继续之前需要解决掉!

  24. /* 如果所有的工作正常的话,清理测试文件 */
    rm -v dummy.c a.out dummy.log

  25. ===================================
    11. Zlib-1.2.7
    ===================================
    一些程序正常所需的压缩和解压缩。

    ./configure --prefix=/usr
    make
    make check
    make install

    /* 共享类库需要移到 /lib,因此在 /usr/lib 中的 .so 文件会被重新创建 */
    mv -v /usr/lib/libz.so.* /lib
    ln -sfv ../../lib/libz.so.1.2.7 /usr/lib/libz.so

    Zlib 的内容
    已安装的类库: libz.{a,so}

    ===================================
    12. File-5.11
    ===================================
    决定一个给定的文件的类型。
    ./configure --prefix=/usr
    make
    make check
    make install

    File 的内容:
    已安装的程序:file
    已安装的类库: libmagic.{a,so}
    简短描述:
    file 尝试去为每一个文件归类,它完成这个是通过执行一些测试-文件系统测试,神奇的数字测试,和语言测试。
    libmagic 包含神奇的数字识别常规,被 file 程序使用

    ===================================
    13.  Binutils-2.22
    ===================================
    含一个链接器,一个链接器,和其它的处理对象文件的工具。

    ①安装
    验证 PTYs 在 chroot 环境中可以正常工作,测试下:
    expect -c "spawn ls"
    输出的命令应该如下:
    spawn ls


    如果输出的内容是下面的话,那么表示 PTY 的操作环境没有设置好。这个问题需要在运行 Binutils 和 GCC 的测试之前解决掉:
    The system has no more ptys.
    Ask your system administrator to create more.

  26. /* 抵制一个过时的 stanards.info 文件安装以后安装一个新的 Autoconf 说明 */
    rm -fv etc/standards.info
    sed -i.bak '/^INFO/s/standards.info //' etc/Makefile.in

  27. /* 应用一个补丁防止使用编译器优化时出现失败 */
    patch -Np1 -i ../binutils-2.22-build_fix-1.patch
    mkdir -v ../binutils-build
    cd ../binutils-build
    ../binutils-2.22/configure --prefix=/usr --enable-shared
    make tooldir=/usr
        /* 解释 */
            tooldir=/usr
            通常,tooldir(可执行文件的最终目录)需要设置到  $(exec_prefix)/$(target_alias) 。例如,x86_64 机器会将它扩展到/usr/x86_64-unknown-linux-gnu 。因为它是一个通用的系统,在 /usr 中的具体目标目录是不需要的。 $(exec_prefix)/$(target_alias) 会被使用如果这个系统用来进行交叉编译(例如,在 Intel 机器上编译一个包产生的代码在 PowerPC 的机器上能够被执行)。

  28. 重要:测试事宜在这里是相当的重要,无论如何都不要跳过。

  29. make -k check
    make tooldir=/usr install
    /* 安装一些包需要的 libiberty 头文件 */
    cp -v ../binutils-2.22/include/libiberty.h /usr/include

    ②Binutils 的内容
    已安装的程序:
    addr2line, ar, as, c++filt, elfedit, gprof, ld, ld.bfd, nm, objcopy, objdump, ranlib, readelf, size, strings, 和 strip
    已安装的类库:
    libiberty.a, libbfd.{a,so}, and libopcodes.{a,so}
    已安装的目录:
    /usr/lib/ldscripts
    简短描述:
        addr2line      将程序地址翻译成文件名和行数;给定一个地址和可执行文件的名字,它使用可执行文件的调试信息决定哪个资源文件和行数是和这个地址相关的
        ar     创建、修改和提取归档文件
        as      一个将 gcc 的输出汇编到对象文件的汇编器
        c++filt     链接器用来过滤 C++ 和 Java 符号和用来防止重载函数造成的冲突。
        elfedit     更新 ELF 文件的头文件
        gprof     显示程序调用数据
        ld      一个链接器,它将一系列对象文件和归档文件结合到一个单独的文件,迁移它们的数据和占用符号引用。
        ld.bfd     到 ld 的硬符号链接
        nm      列出在一个给定的对象文件中的符号
        objcopy      将一种对象文件的类型转换成其它一种
        objdump      显示给定对象文件的信息,附带控制选项来显示特定的信息;这些信息对工作使用编译工具的程序员是有用的。
        ranlib     产生一个归档文件的内容的索引;这个索引列出了所有归档数字的符号定义,这些归档数字是可重定位的对象文件。
        readelf      关于 ELF 类型的二进制文件的信息
        size      列出给定对象文件的部分大小和总大小
        strings      输出,对于每一个给定的文件,可打印的字符的顺序至少有一定的长度(默认是4);对于对象文件,它的输出,默认只用来自初始化和载入区域,而对于其它类型的文件,它扫描整个文件。
        strip      丢弃来自对象文件的符号
        libiberty      含各种 GNU 程序的常规,包含 getopt, obstack, strerror, strtol, 和 strtoul
        libbfd      二进制文件描述类库
        libopcodes     用来处理操作码—处理器的说明的“可读文本”;它用来构造工具,像 objdump .


    ===================================
    14.  GMP-5.0.5
    ===================================
    含数学类库。为精确的数学计算提供有用的函数。
    ①安装

  30. 注意:如果你在构造 32位的 x86 系统,如果你的 CPU 兼容运行 64位的代码同时你在 CFLAGS 环境中已经定义过,配置脚本会试着为 64 位

  31. 配置然后发生失败。避免这种情况就是用下面的命令调用配置命令:
        ABI=32 ./configure ...

  32. ./configure --prefix=/usr --enable-cxx --enable-mpbsd
        /* 解释选项 */
  33.         --enable-cxx
                这个参数表示支持C++
            --enable-mpbsd
                这个构造Berkeley MP 兼容类库
    make
    make check 2>&1 | tee gmp-check-log

  34. /* 确保166个测试有通过,检查下面命令的结果 */
    awk '/tests passed/{total+=$2} ; END{print total}' gmp-check-log
    make install
    mkdir -v /usr/share/doc/gmp-5.0.5

  35. /* 需要的话,安装下文档 */
    cp    -v doc/{isa_abi_headache,configuration} doc/*.html \
             /usr/share/doc/gmp-5.0.5

    ②GMP 的内容
    已安装的类库:
                libgmp.{a,so}, libgmpxx.{a,so}, and libmp.{a,so}
    已安装目录:
                /usr/share/doc/gmp-5.0.5
    简短描述:
                libgmp     包含精确的数学函数
                libgmpxx     包含 C++ 精确的数学函数
                libmp     包含Berkeley MP 数学函数

    ===================================
    15.  MPFR-3.1.1
    ===================================
    含多精度的数学函数。

    ①安装
    ./configure  --prefix=/usr        \
                 --enable-thread-safe \
                 --docdir=/usr/share/doc/mpfr-3.1.1
    make

  36. 重要:测试事宜在这里是相当的重要,无论如何都不要跳过。

    make check
    make install
    /* 安装文档 */
    make html
    make install-html

    ②MPFR 的内容
    已安装的类库:
                libmpfr.{a,so}
    已安装的目录:
                /usr/share/doc/mpfr-3.1.1
    简短描述:
                libmpfr 含多精度的数学函数

    ===================================
    16.  MPC-1.0
    ===================================
    一个为复杂和高精准度的的数学计算,以及正确的四舍五入的数学类库。

    ① 安装
    ./configure --prefix=/usr
    make
    make check
    make install

    ② MPC的内容
    已安装的类库:
                libmpc.{a,so}
    简短描述:
                libmpc 含复杂的数学函数

    ===================================
    17.  GCC-4.7.1
    ===================================
    GNU 编译器集合,包含 C 和 C++ 的编译器。

    ① 安装

    /* 应用一个 sed 脚本来抑制 libiberty.a 的安装。这个由 Binutils 提供 libiberty.a 的版本将会被替代: */
    sed -i 's/install_to_$(INSTALL_DEST) //' libiberty/Makefile.in

  37. /* 应用下面的 sed 脚本强制使用 -fomit-frame-pointer 编译标识来构造,确保一致的编译器进行构造: */
    case `uname -m` in
      i?86) sed -i 's/^T_CFLAGS =$/& -fomit-frame-pointer/' gcc/Makefile.in ;;
    esac

  38. /*  同时修复一个在检查 Makefiles 中的错误: */
    sed -i -e /autogen/d -e /check.sh/d fixincludes/Makefile.in

  39. /* 构造开始 */
    mkdir -v ../gcc-build
    cd ../gcc-build
    ../gcc-4.7.1/configure --prefix=/usr            \
                           --libexecdir=/usr/lib    \
                           --enable-shared          \
                           --enable-threads=posix   \
                           --enable-__cxa_atexit    \
                           --enable-clocale=gnu     \
                           --enable-languages=c,c++ \
                           --disable-multilib       \
                           --disable-bootstrap      \
                           --with-system-zlib


    注意,对于其它语言,一些先决条件是不存在的。参照 BLFS 指导书去构造一个所有语言都支持的 GCC 。
    /* 解释选项 */
            --with-system-zlib
                这个开关告诉 GCC 链接到系统已安装复制的 Zlib 类库,而不是它自己内部的复制。
    make

  40. 重要:测试事宜在这里是相当的重要,无论如何都不要跳过。

    /* GCC 测试套中有一个排气堆栈,现在增加堆栈的大小优先级来运行测试 */
    ulimit -s 32768

  41. /* 测试结果,但不要错误时停止 */
    make -k check

  42. /* 为接受测试套结果的总结,运行 */
    ../gcc-4.7.1/contrib/test_summary

  43. 若只要总结,将输出通过 grep -A7 Summ 进行管道。
    结果对比可以参照: 和 。
    有一些无法预料的错误并不是能够避免的。GCC 的开发者有一直意识到这些问题,但是还没能够去解决它们。特别是 libmudflap 测试是一个很有问题的结果,作为一个 bug 在 GCC() 中。除非测试结果与上面的 URL 中的内容有很大的不同之外,那么可以安全的继续。

  44. /* 安装包 */
    make install

  45. /* 除了 C 预处理器以外的一些包会安装在 /lib 目录中。为支持这些包,创建链接 */
    ln -sv ../usr/bin/cpp /lib
  46.  
  47. /* 许多包使用 cc 来调用 C 连一起,为满足这些包要创建一个符合链接: */
    ln -sv gcc /usr/bin/cc
    /* 现在最后的 toolchain 已经就位,现在当务之急的事就是确保编译和链接能够正常工作。通过完整性检查来执行检验: */
    echo 'main(){}' > dummy.c
    cc dummy.c -v -Wl,--verbose &> dummy.log
    readelf -l a.out | grep ': /lib'

  48. 如果一切正常的话,应该没有出现错误,命令行输出的最后一行应该是(允许特定平台上动态链接器的名字的不同):
    [Requesting program interpreter: /lib/ld-linux.so.2]


    /* 现在确保设置了正确的启动文件:*/
    grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log
    如果一切工作正常的话,应该没有错误,输出的结束命令行应该是:
    /usr/lib/gcc/i686-pc-linux-gnu/4.7.1/../../../crt1.o succeeded
    /usr/lib/gcc/i686-pc-linux-gnu/4.7.1/../../../crti.o succeeded
    /usr/lib/gcc/i686-pc-linux-gnu/4.7.1/../../../crtn.o succeeded

    在不同架构的机器上,上面的结果可能会稍微的不同,不同之处通常是/usr/lib/gcc后面的目录名字。如果你的机器是64位的系统,你也许会看到有个目录以 lib64 结尾的。
  49. 重要的事情就是 gcc 已经找到在 /usr/lib 目录下所有的3个 crt*.o 文件。

  50. /* 验证编译器是搜索正确的头文件: */
    grep -B4 '^ /usr/include' dummy.log
    成功的返回输出命令应该是:
    #include <...> search starts here:
     /usr/local/include
     /usr/lib/gcc/i686-pc-linux-gnu/4.7.1/include
     /usr/lib/gcc/i686-pc-linux-gnu/4.7.1/include-fixed
     /usr/include

    再次,注意到你的架构名称后面的目录名会不同,它由你机子的体系结构决定的。
    注意: 版本4.3.0 ,GCC 会无条件的安装 limits.h 文件搭配私有的 include-fixed 目录,那个目录需要被替换掉。

  51. /* 接着,验证新的链接器有使用正确的搜索路径: */
    grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
    如果一切都工作正常的话,应该没有错误,最后输出的命令应该(允许特定平台不同的架构)会是:
    SEARCH_DIR("/usr/i686-pc-linux-gnu/lib")
    SEARCH_DIR("/usr/local/lib")
    SEARCH_DIR("/lib")
    SEARCH_DIR("/usr/lib");
    一个64位的系统也许会看到更多的目录。例如,这里有来自 x86_64 机器的输出:
    SEARCH_DIR("/usr/x86_64-unknown-linux-gnu/lib64")
    SEARCH_DIR("/usr/local/lib64")
    SEARCH_DIR("/lib64")
    SEARCH_DIR("/usr/lib64")
    SEARCH_DIR("/usr/x86_64-unknown-linux-gnu/lib")
    SEARCH_DIR("/usr/local/lib")
    SEARCH_DIR("/lib")
    SEARCH_DIR("/usr/lib");

    /* 接着确保有使用正确的 libc:*/
    grep "/lib.*/libc.so.6 " dummy.log
    如果所有的一切都工作正常的话,应该没有错误,最后输出的命令行(在64位的宿主机上运行一个 lib64 目录)应该是:
    attempt to open /lib/libc.so.6 succeeded

    /* 最后,确保 GCC 使用了正确的动态链接器: */
    grep found dummy.log
    如果,所有的一切都工作正常的话,应该没有错误输出,最后的命令行输出应该(允许特定平台的动态链接器的名称不同和一个在64位宿主机上的 lib64 目录)是:
    found ld-linux.so.2 at /lib/ld-linux.so.2

    如果输出显示的不像上面的那样或者没有任何的输出,一定有地方出了问题。调查和追踪每一步找到哪里出了问题,然后修正它。
    最可能的原因就是规格文件调整时出了问题。在继续下面的处理工作之前,任何出现的问题必须要解决。

  52. /* 一旦所有的工作都正常,清除测试文件:*/
    rm -v dummy.c a.out dummy.log
    /* 最后,移动一个错位的文件: */
    mkdir -pv /usr/share/gdb/auto-load/usr/lib
    mv -v /usr/lib/*gdb.py /usr/share/gdb/auto-load/usr/lib

    ② GCC 的内容
        已安装的程序:
                c++, cc (link to gcc), cpp, g++, gcc, gccbug, and gcov
        已安装的类库:
                libgcc.a, libgcc_eh.a, libgcc_s.so, libgcov.a, libgomp.{a,so}, liblto_plugin.so, libmudflap.{a,so}, libmudflapth.{a,so}, libquadmath.{a,so}, libssp.{a,so}            , libssp_nonshared.a, libstdc++.{a,so} and libsupc++.a
        已安装的目录:
                /usr/include/c++, /usr/lib/gcc, /usr/share/gcc-4.7.1
        简短描述:
    c++     C++ 编译器
    cc      C 编译器
    cpp     C 预处理器;编译器用它来扩展 #include ,#define 和类似的在资源文件中的语句
    g++      C++ 编译器
    gcc     C编译器
    gccbug      一种shell 脚本用来帮助创建有用的bug报告
    gcov      一个覆盖测试工具;它用来分析程序来决定哪里的优化是最有效的
    libgcc      含运行时支持gcc
    libgcov     当GCC被指示启用剖析时这个类库会链接到一个程序
    libgomp      GNU多平台共享内存并行C/C++ 和 Fortran 程序的OpenMP API
    liblto_plugin     GCC的链接时间优化(LTO)插件,它允许GCC 在交叉汇编单元时执行优化。
    libmudflap     含支持 GCC 边界检查功能的正常范例
    libquadmath     GCC四路精密数学库API
    libssp      含支持 GCC 的堆栈包含功能的事务
    libstdc++     标准的 C++ 类库
    libsupc++     为 C++ 编程语言提供支持 

    ===================================
    18.    Sed-4.2.1
    ===================================
    一个流编辑器。

    ①安装
    首先,修补回归测试:
    patch -Np1 -i ../sed-4.2.1-testsuite_fixes-1.patch

  53. ./configure --prefix=/usr --bindir=/bin --htmldir=/usr/share/doc/sed-4.2.1
    /* 解释选项 */
        --htmldir
        这个设置了 HTML 文档的安装位置
    make
    make html
    make check
    make install
    make -C doc install-html

    ②Sed 的内容
        已安装的程序:
                sed
        已安装的目录:
                /usr/share/doc/sed-4.2.1
        简短描述:
    sed 通过在一个单一的过滤器和转换文本文件

  54. ===================================
     19.   Bzip2-1.0.6
    ===================================
    用于压缩和解压缩。用 bzip2 压缩文本文件的效率比 gzip 的高。

    /* 应用一个补丁,将安装此包的文档: */
    patch -Np1 -i ../bzip2-1.0.6-install_docs-1.patch

  55. /* 确保安装的符号链接是相对的: */
    sed -i 's@\(ln -s -f \)$(PREFIX)/bin/@\1@' Makefile

  56. /* 确保 man 页面的安装位置正确: */
    sed -i "s@(PREFIX)/man@(PREFIX)/share/man@g" Makefile

  57. /* 为 Bzip2 编译准备: */
    make -f Makefile-libbz2_so
    make clean

  58. /* 选项解释 */
        -f Makefile-libbz2_so
            这使得 Bzip2 使用一个不同的 Makefile 文件来构造,就是使用文件 Makefile-libbz2_so,将会创建一个动态的 libbz2.so 类库和到 Bzip2 工具的链接。
    make
    make PREFIX=/usr install

  59. /* 安装 二进制 bzip2 的共享类库到 /lib 目录,设置一些必要的符号链接,然后清除: */
    cp -v bzip2-shared /bin/bzip2
    cp -av libbz2.so* /lib
    ln -sv ../../lib/libbz2.so.1.0 /usr/lib/libbz2.so
    rm -v /usr/bin/{bunzip2,bzcat,bzip2}
    ln -sv bzip2 /bin/bunzip2
    ln -sv bzip2 /bin/bzcat


    ② Bzip2 的内容
        已安装的程序:
  60.         bunzip2 (link to bzip2), bzcat (link to bzip2), bzcmp (link to bzdiff), bzdiff, bzegrep (link to bzgrep), bzfgrep (link to bzgrep), bzgrep, 
  61.         bzip2, bzip2recover, bzless (link to bzmore), and bzmore
        已安装的类库:
            libbz2.{a,so}
        已安装的目录:
            /usr/share/doc/bzip2-1.0.6
    简短描述:
        bunzip2 解压缩 bzip 压缩的文件
        bzcat 解压缩到标准输出
        bzcmp 在 bzip 压缩的文件上运行 cmp
        bzdiff 在 bizp 压缩的文件上运行 diff
        bzegrep 在 bizp 压缩的文件上运行 egrep 
        bzfgrep 在 bizp 压缩的文件上运行 fgrep 
        bzgrep 在 bizp 压缩的文件上运行 grep 
        bzip2 压缩文件使用 Burrows-Wheeler(块排序压缩) 变换加上 Huffman(哈夫曼) 算法整理文本;压缩率比商业版压缩机使用的“Lempel-Ziv”(无损数据压缩算法) 算法的更高,比如zip.
        bzip2recover 试着从损坏的 bzip 压缩的文件修复数据
        bzless 在 bizp 压缩的文件上运行 less
        bzmore 在 bizp 压缩的文件上运行 more
        libbz2* 这个类库完成无损、快排序数据压缩、使用 块排序压缩 算法

    ===================================
     20.   Pkg-config-0.27
    ===================================
    含在配置和执行文件时传递 include 路径或者类库路径到构造工具中的一工具。

  62. ./configure --prefix=/usr         \
                --with-internal-glib  \
                --docdir=/usr/share/doc/pkg-config-0.27
    make
    make check
    make install
    已安装的程序:
            pkg-config
    已安装的目录:
            /usr/share/doc/pkg-config-0.26
    简短描述:
            pkg-config     为特定的类库和包返回元信息

    ===================================
     21.   Ncurses-5.9
    ===================================
    含终端依赖字符处理类库。
    ./configure --prefix=/usr --mandir=/usr/share/man --with-shared \
                --without-debug --enable-widec
    /* 解释选项 */
        --enable-widec
                这个选项导致宽字符类库(如 libncursesw.so.5.9)会被构造而不是正常的(如 libncurses.so.5.9)。这些宽字符类库在多位和传统的8 位语言环境中很有用的,
                因为正常的类库只在8 位语言环境中工作。宽字符和正常的类库是源兼容的,但是二进制不兼容的。
    make

    /* 这个包有个测试套,但是只能在它完成安装之后进行。测试在 test/ 目录下。可以查看那个目录中的 README 文件找更多的细节 */
    make install

    /* 移动共享类库到 /lib 目录: */
    mv -v /usr/lib/libncursesw.so.5* /lib

    /* 因为类库已经被移动了,有个符号链接会指向一个不存在的文件。重新创建它: */
    ln -sfv ../../lib/libncursesw.so.5 /usr/lib/libncursesw.so

    /* 许多应用程序希望链接器能够找到无宽字符的 Ncurses 类库。可以通过符号链接和链接器脚本来欺骗这些应用链接到宽字符类库: */
    for lib in ncurses form panel menu ; do \
        rm -vf /usr/lib/lib${lib}.so ; \
        echo "INPUT(-l${lib}w)" >/usr/lib/lib${lib}.so ; \
        ln -sfv lib${lib}w.a /usr/lib/lib${lib}.a ; \
    done
    ln -sfv libncurses++w.a /usr/lib/libncurses++.a

    /*  最后,确保以前的应用在构造的时候寻找 -lcurses 时仍然可以构造: */
    rm -vf /usr/lib/libcursesw.so
    echo "INPUT(-lncursesw)" >/usr/lib/libcursesw.so
    ln -sfv libncurses.so /usr/lib/libcurses.so
    ln -sfv libncursesw.a /usr/lib/libcursesw.a
    ln -sfv libncurses.a /usr/lib/libcurses.a

    /* 如果需要安装 Ncurses 的文档: */
    mkdir -v       /usr/share/doc/ncurses-5.9
    cp -v -R doc/* /usr/share/doc/ncurses-5.9

    注意:上面的指导不会创建无宽字符的 Ncurses 类库因为没有从源码编译安装的包会在运行时链接到它们。如果你因为有一些只支持二进制的应用或为了符合 LSB 而需要这样的类库的话,可以再构造一次包:
  63. make distclean
    ./configure --prefix=/usr --with-shared --without-normal \
          --without-debug --without-cxx-binding
    make sources libs
    cp -av lib/lib*.so.5* /usr/lib

    ②Ncurses 的内容



    ===================================
     22.   Util-linux-2.21.2
    ===================================
    含实用程序的杂项。它们中有处理文件系统、终端、分区和消息的。

    * FHS 符合笔记 *
    FHS 推荐实用 /var/lib/hwclock 目录而不是通常的 /etc 目录作为 adjtime 文件位置。为了 hwclock 程序 符合 HFS,运行:
    sed -i -e 's@etc/adjtime@var/lib/hwclock/adjtime@g' \
        $(grep -rl '/etc/adjtime' .)
    mkdir -pv /var/lib/hwclock

    ./configure
    make
    make install

    ② Util-linux 的内容
    已安装的程序:
            addpart, agetty, blkid, blockdev, cal, cfdisk, chcpu, chkdupexe, chrt, col, colcrt, colrm, column, ctrlaltdel, cytune, delpart, dmesg, fallocate, fdformat, fdisk, findfs, findmnt, flock,         fsck, fsck.cramfs, fsck.minix, fsfreeze, fstrim, getopt, hexdump, hwclock, i386, ionice, ipcmk, ipcrm, ipcs, isosize, ldattach, linux32, linux64, logger, look, losetup, lsblk, lscpu,
  64.          mcookie, mkfs, mkfs.bfs, mkfs.cramfs, mkfs.minix, mkswap, more, mount, mountpoint, namei, partx, pg, pivot_root, prlimit, raw, readprofile, rename, renice, rev, rtcwake, script, 
  65.         scriptreplay, setarch, setsid, setterm, sfdisk, swaplabel, swapoff (link to swapon), swapon, switch_root, tailf, taskset, tunelp, ul, umount, unshare, uuidd, uuidgen, wall, 
  66.         whereis, wipefs, and x86_64
    已安装的类库:
            libblkid.{a,so}, libmount.{a,so}, libuuid.{a,so}
    已安装的目录:
            /usr/include/blkid, /usr/include/libmount, /usr/include/uuid, /usr/share/getopt, /var/lib/hwclock
    简短描述:
    addpart 告知Linux 内核新的分区
    agetty 开启一个 tty 端口,提示要求一个用户名,然后调用登陆程序
    blkid 一个命令行实用程序用来定位和打印块设备属性
    blockdev 允许用户从命令行调用块设备的ioctls (ioctl是用于控制I/O设备)
    cal 显示一个简单的日历
    cfdisk 操作一个给定的设备的分区表
    chcpu 修改 CPUs 的状态
    chkdupexe 查找重复的可执行文件
    chrt 操作一个程序的即时属性
    col 过滤掉反向换行符
    colcrt 为终端过滤 nroff 输出但是欠缺兼容性,比如加粗和半线
    colrm 过滤掉给定的列
    column 一个给定文件格式化为多行
    ctrlaltdel 将 Ctrl+Alt+Del  组合键的功能的设置结合到一个硬或软复位
    cytune 为 Cyclades 卡调串行驱动的参数
    delpart 请求Linux 内核移动一个分区
    dmesg 转储内核的  引导 信息
    fallocate 为一个文件预分配空间
    fdformat 低格一个软盘
    fdisk 操作一个给定的设备的分区表
    findfs 通过标签或者通用唯一标识符(UUID)找到一个文件系统
    findmnt 是一个到 libmount 类库的命令行接口,与 mountinfo 、fstab 和 mtab 文件一起工作
    flock 获得一个文件锁然后用持有的锁执行一个命令
    fsck 用来检查和选择性的修复文件系统
    fsck.cramfs 在一个给定的设备上的 Cramfs 文件系统执行一个永久性的检查
    fsck.minix 在一个给定的设备上的 Minix 文件系统执行一个永久性的检查
    fsfreeze 是一个简单的围绕 FIFREEZE/FITHAW ioctl内核驱动操作的简单包装
    fstrim 在一个没有挂载的文件系统上丢弃未使用的块
    getopt 在一个给定的命令行解析选项
    hexdump 转储一个给定的文件为16进制或者其它的格式
    hwclock 读取或者设置系统的硬时钟,也叫做 时时时钟(RTC)或者基本输入输出系统(BIOS)时钟
    i386 到 setarch 的符号链接
    ionice 为一个程序获取或者设置 io 调度类和优先级
    ipcmk 创建各种 IPC 资源
    ipcrm 移除给定的 进程间通信(IPC) 资源
    ipcs 提供 IPC 状态信息
    isosize 报告 一个 iso9660 文件格式的大小
    ldattach 附加一行规矩到一个串行线
    linux32 到 setarch 的符号链接
    linux64 到 setarch 的符号链接
    logger 讲给定的消息写入到系统日志
    look 显示以给定字符开头的行
    losetup 设置和控制环设备
    lsblk 以树状列出关于所有或者选定的块设备的信息
    lscpu 打印 CPU 架构信息
    mcookie 为 xauth 生成魔法cookie(128位的随机16进制数)(magic cookie 简称为 cookie)
    mkfs 在一个设备(通常是一个硬盘分区)上构造一个文件系统
    mkfs.bfs 创建一个 圣克鲁斯业务(SCO) bsf 文件系统
    mkfs.cramfs 创建一个 cramfs 文件系统
    mkfs.minix 创建一个 Minix 文件系统
    mkswap 初始化给定的设备或者文件作为 swap 区域
    more 一个过滤器用来在一个屏幕上文本翻页
    mount 将给定的设备上附加文件系统到文件系统数中指定的目录
    mountpoint 检查目录是否是一个挂载点
    namei 对一个给定的路径名显示符号链接
    partx 告诉内核磁盘上分区的存在和数量
    pg 在屏幕上一次显示一个文本文件
    pivot_root 使得一个给定的文件系统作为当前进程的新根文件系统
    prlimit 获取或者设置一个进程的资源限制
    raw Linux 的原始字符设备绑定到一个块设备
    readprofile 读取内核分析信息
    rename 对一个给定的文件重命名,替换为另一个给定的字符串
    renice 调整运行着的进程的优先级
    rev 反转给定文件的行
    rtcwake 用来进入系统的休眠状态直到特定唤醒世界
    script 对终端会话制作 typescript(一种多重视窗管理程序)
    scriptreplay 使用定时信息播放打字稿
    setarch 在一个新的程序环境改变报告架构和设置私有的标识
    setsid 在新的会话中运行给定的程序
    setterm 设置终端属性
    sfdisk 一个磁盘分区表操作工具
    swaplabel 允许修改 swap 分区的 UUID 和标识
    swapoff 关闭设备和文件的换页和交换
    swapon 启用设备和文件的换页和交换同时显示当前使用中的设备和文件
    switch_root 将另外一个文件系统转为挂载树的根目录
    tailf 追踪一个日志文件的增加。显示一个日志文件的最后10行,同时这个日志文件中当任何新的条目创建时继续显示
    taskset 检索和设置一个进程的 CPU 亲和
    tunelp 协调行式打印机的参数
    ul 一个过滤器用来翻译下划线为终端使用的转义序列显示的下划线
    umount 断开系统文件树种的一个文件系统
    unshare 运行一个程序使用不从父的命名空间
    uuidd 一个守护程序所使用的UUID库在安全和存在保证唯一的方式生成基于时间的UUID。
    uuidgen 创建新的 UUIDs。 每一个新的 UUID 在所有 UUIDs 创建的时候是唯一的,在本地系统和其它的系统中,在过去的和未来的
    wall 显示一个文件的内容或者默认为它的标准输出,到所有在终端中当前已登录系统的用户
    whereis 报告二进制文件、源码和 man 页面的位置给指定的命令
    wipefs 讲一个设备的文件系统签名擦除
    x86_64 到 setarch 的符号链接
    libblkid 包含设备鉴定和标识萃取例程
    libuuid 包含生成唯一标识符的对象,可能是超出了本地系统访问的例程


    ===================================
     23.   Psmisc-22.19
    ===================================
    含显示运行程序信息的程序。

    ./configure --prefix=/usr
    make
    maek install
    /* 将 killall 和 fuser 程序安装 FHS 指定的位置移动: */
    mv -v /usr/bin/fuser /bin
    mv -v /usr/bin/killall /bin

    ② Psmisc 的内容
    已安装的程序:
    fuser, killall, peekfd, prtstat, pstree, and pstree.x11 (link to pstree)
    简短描述:
       fuser     报告一个进程 ID(PIDs) 使用给定的文件或文件系统的进程
        killall     通过 名字 杀掉进程;它会给任何给定命令的所有进程一个信号
        peekfd     偷看一个运行着的文件描述,给它一个 PID
        prtstat     打印一个进程的信息
        pstree     以树的形式显示运行着的进程
        pstree.x11     有些像 pstree ,除了它在退出之前会等待确认信息
  67. ********** written at 2013-06-17 19:22 ************
  68. ********** modified at 2013-06-19 21:24 ************
  69. ********** modified at 2013-06-20 23:53 ************
  70. ********** modified at 2013-06-21 10:43 ************
  71. 鉴于,本文长度太长,另开一文




阅读(3136) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~