定制自己的系统-lfs6.4

更新时间:2023-04-29 04:00:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

像大多数其他操作系统一样,LFS 通常安装在一个新的专用分区上。我们推荐您在一个空的分区上构建LFS 系统,如果您还有足够的未分区空间,也可以创建一个新的分区。当然,LFS 系统(多个LFS 系统)也可以安装在已经安装了其他操作系统的磁盘分区上,它们可以和平共处。

8d2df468561252d380eb6ec3/hints/downloads/files/lfs_next_t o_existing_systems.txt解释了怎样实现上述目标。但是本书只讨论如何在一个新的空白分区上构建LFS 系统。

建立一个最小的系统需要1.3GB 左右的分区,这样才能有足够的空间存储并编译所有的源码包。当然,如果您打算把LFS 作为您的主Linux 系统,您可能会在上面安装其它软件,那么您就需要更大的空间(2-3GB)。LFS 系统本身并不占用这么多空间,所需的空间大部分用来为软件编译提供足够的临时空间,编译软件包的时候需要使用大量的临时空间,软件包装好之后这些临时空间可以回收。

因为编译过程中内存(RAM)并不总是够用的,所以最好使用一个小的硬盘分区作为交换空间。内核使用交换空间来存放不常用到的数据,以便为正在运行的进程腾出内存空间。LFS 系统使用的交换分区与宿主系统使用的交换分区可以是同一个,因此当宿主系统已经有交换分区的时候就不必为LFS 系统再创建一个了。

启动一个磁盘分区程序,例如cfdisk或者fdisk,用即将在上面创建新分区的硬盘名字作为命令行选项,比如主IDE 硬盘名字就是/dev/hda。如果需要,创建一个交换(swap)分区。如果您还不知道如何使用这两个工具的话,请参考cfdisk(8)或

fdisk(8)。

记下新分区的命名,比如hda5,本书将其作为LFS 分区。另外记下swap分区的命名。在后面配置/etc/fstab的时候会用到。

建好空白分区之后,就可以在上面建立文件系统了。在Linux 世界里应用最广的是ext2文件系统。但是随着新的大容量硬盘的出现,日志文件系统变得越来越流行。ext3是带有日志功能的ext2升级版本,并且与E2fsprogs 工具兼容。我们将创建一个ext3文件系统。关于其他文件系统的说明请参阅

8d2df468561252d380eb6ec3/blfs/view/svn/postlfs/filesystems 。

为创建一个ext3文件系统,请运行以下命令:

用您创建的LFS 分区的名称替换(比如前面的例子中的hda5)。

注意

有些发行版的宿主系统中的文件系统创建工具(E2fsprogs)增加了某些自定义的特性。这可能导致在第九章重启进入新的LFS 系统时出现问题,因为LFS 安装的E2fsprogs 不支持这些特性。因此可能会出现类似“unsupported filesystem features, upgrade your e2fsprogs”的错误。请运行下面的命令,检查你的宿主系统是否使用了这些自定义的特性。

如果输出结果有不同于以下的特性,has_journal、ext_attr、resize_inode、

dir_index、filetype、sparse_super、large_file或needs_recovery,说明你的宿主系统可能使用了自定义的特性。这种情况下,为避免后面出现错误,请编译下载标准的E2fsprogs。然后用编译生成的工具重新安装LFS 的文件系统。

如果你的硬盘上已经有swap分区,并正在使用,就无需格式化它了。否则,新建的swap 分区需要格式化,请运行下面命令格式化它:

用你的交换分区名替换掉

新的文件系统建立以后,为了可以访问到新的分区,我们需要一个挂载点挂载它。本书假定新的文件系统挂载到/mnt/lfs,当然选择权归你。

选择一个挂载点,并运行下面命令将其指定到LFS环境变量:

接下来的命令,创建挂载点并挂载LFS 文件系统:

根据你的LFS分区命名,替换

如果想为LFS 分配多个分区(比如一个作/分区,另一个作/usr分区),请使用下面命令分别挂载:

分别替换成相应的分区名。

请确认挂载的新分区的权限不是太严格,(比如nosuid、nodev或noatime选项)。不带任何参数运行mount,如果设置了nosuid、nodev或noatime选项,则需要重新挂载该分区。

如果你使用了交换分区,使用swapon命令确保它被启用:

替换成交换分区名。

现在工作空间建立好的了,是时候下载软件包了。

本章包含了一个构建基本Linux 系统需要下载的软件包清单,列出的版本号是已知可以正常工作的版本,本书就是建立在这些软件包之上的。我们强烈建议不要使用新的版本,因为用于前一个版本的编译安装命令可能并不适用于新的版本。最新版本的软件包也许需要一个与旧版本不同的工作环境而可能会出现问题。在本书的开发版中将会建立这种新的工作环境。

下载地址并不是总是可用的,如果在本书出版之后,软件包的下载地址变了,Google (8d2df468561252d380eb6ec3/)提供了强大的搜索引擎帮我们寻找绝大多数的软件包。如果搜索不到,试试

8d2df468561252d380eb6ec3/lfs/packages#packages上介绍的其他下载方式。

下载好的软件包和补丁需要放在一个构建过程中便于访问的目录,还要一个用于解压和编译源码包的目录。$LFS/sources可同时满足这两个要求。使用这个目录让所有需要的部件都在LFS 分区上,且构建过程中的所有步骤都可以访问到。

要创建该目录,在下载前用root用户运行下面的命令:

把该目录设置为所有用户可写和sticky 模式,“Sticky”表示虽然多个用户对该目录有写的权限,但是只有文件的所有者才能删除。下面的命令将该目录设置可写和sticky 模式:

环境变量LFS在全书中会被使用很多次。保证它总是已定义是很重要的,它应该被设置为LFS 分区的挂载点。用下面的命令检查LFS变量的设置是否恰当:

请确认输出的是LFS 分区挂载点的路径,如果您遵循我们的例子,则应该是/mnt/lfs。如果输出结果不正确,用下述命令设置它:

设置这个环境变量的好处是您以后可以按照原样输入形如mkdir $LFS/tools的命令,shell会自动用“/mnt/lfs”(或者该环境变量所设定的值)替换“$LFS”。

当您离开然后重新进入当前工作环境的时候(像su到root或者其他用户),不要忘记检查$LFS是否设置正确。

第五章中编译的所有程序都将安装到$LFS/tools目录下,以便与第六章中编译的程序隔离开来。这里编译的程序只是临时使用的工具,不是最终LFS 系统的组成部分。把这些程序放到一个单独的目录下,在使用过之后简单的删除掉就可以了。这样做也可以防止这些程序与宿主系统中相同的程序混淆(在第五章一不小心就会混淆)。

以root身份运行下列命令以创建所需的目录:

接下来就是在宿主系统裳创建一个/tools符号链接。它指向刚刚在LFS 分区裳创建的目录。以root身份执行下面的命令:

注意

上述命令是正确的,ln命令的语法有了一点变化。如果您认为发现了一个错误,在报告它之前,先用info coreutils ln和ln(1)命令查看手册页。

创建的符号链接使得将要编译的工具链总是引用/tools,从而使得编译器、汇编器和链接器在本章(此时我们仍然使用宿主系统的一些工具)和下一章(我们已经“chrooted”到LFS 分区)都能很好的工作。

以root用户登录的时候,一个错误就足以损坏甚至摧毁系统,因此我们推荐使用一个非特权用户来完成本章软件包的编译工作。你可以使用你自己的用户名,但为了建立一个干净的编译环境,建立一个lfs用户,使它隶属于一个新的用户组(也命名为lfs),在安装过程中使用这个用户。使用root用户运行以下命令添加该用户:

命令行选项说明:

-s /bin/bash

使用bash作为lfs Shell。

-g lfs

添加lfs用户到lfs组。

-m

为lfs用户创建home 目录。

-k /dev/null

这个参数通过修改输入位置为特殊的空设备来防止从框架目录(默认为

/etc/skel)拷贝文件。

lfs

创建的用户和用户组的名字。

为了使用lfs用户登入,必须先为lfs用户设置一个密码(与从root用户切换到lfs用户不同,这种切换不需要lfs用户有一个密码):

把lfs用户设置为$LFS/tools目录的所有者来赋予lfs用户对该目录

的完全访问权限:

如果按照我们建议创建了独立的工作目录,同样把其所有权赋予lfs用户:

接下来,作为lfs用户登入,可以通过启动一个虚拟控制台,或者下面的切

换用户的命令:

参数“-”告诉su开启一个新的登入Shell 而不是一个非登入Shell 。

两者之间的差别请参阅bash(1)和info bash。

通过给bash shell 创建两个新的启动文件可以设置一个良好的工作环境。以lfs用户登入,输入下面的命令创建新的.bash_profile文件:

当以lfs用户登入时,会使用前面设定的Bash Shell,它会首先读取宿主系统的

/etc/profile文件(通常包含一些设置和环境变量),然后读取.bash_profile文件来完成初始化。.bash_profile中的exec env -i.../bin/bash命令用完全空的环境(除了HOME、TERM和PS1变量外)来启动Shell。这样能保证我们的编译环境不会被宿主系统中不必要的或者有潜在危险的环境变量所影响,从而确保获得一个干净的工作环境。

这个新创建的bash 是非登入Shell,它不读取/etc/profile或.bash_profile

文件,而是读取.bashrc文件。用下面命令创建.bashrc:

set +h命令关闭了bash的哈希功能,哈希功能通常是一个有用的功能——bash用一个哈希表来记录可执行文件的完整路径,从而在避免反复搜索系统的PATH变量来寻找同一个可执行文件。但是,我们需要在新编译好的工具安装好后立刻使用它。关闭哈希功能,当需要运行一个软件的时候,Shell 总是会在PATH里搜索。因此当一个程序可用时,Shell 可以在$LFS/tools里立即搜索到,而不是使用哈希表里记忆的在其它目录下的同一个程序。

将用户文件创建掩码(umask)设置为022 保证了新生成的文件和目录只对其所有者可写,但其它人都可读和可执行。(假定open(2)系统调用使用默认模式,新文件权限模式为644,目录为755)。

LFS变量应当设置为所选择的挂载点。

LC_ALL变量控制着某些程序的本地化,使其显示的信息复合指定国家(地区)的规范。如果宿主系统使用早于2.2.4 版本的Glibc,LC_ALL使用除“POSIX”或“C”外其它的值可能导致在退出chroot 环境再返回继续时出现问题。

将/tools/bin置于PATH变量的开头,可以使在第五章中安装的程序安装后立即被shell 使用。再加上关闭shell 哈希功能,在第五章的环境中,使得宿主系统中的相同名字的程序被使用的可能降到最小。

最后,为了完全准备好构建临时工具的环境,导入刚才生成的配置文件:

许多人都想知道编译和安装一个软件包预计需要多长时间。因为Linux From Scratch 可以在多种不同的系统上创建,准确估计所需的时间是不可能的。最快的系统上编译安装最大的软件包(Glibc)大约需要20 分钟,但在很慢的系统上可能耗费长达三天时间。我们不提供准确时间,代之以标准编译时间单位(SBU)来度量。

SBU 度量具体说明如下,本书中第一个编译的软件包是第五章中静态编译的Binutils。编译这个软件包所花费的时间就作为标准编译时间单位(SBU)。所有其它软件的编译时间都用这个时间来衡量。

例如,对于一个编译时间为 4.5 SBU 的软件包,这意味着如果一个系统静态编译安装Binutils 需要花费10 分钟,那么编译这个软件包将大约需要45 分钟。幸运的是,大多数软件包编译安装所需的时间都比Binutils 所需的时间要短。

通常,SBU 并不十分精确,因为它依赖于许多因素,包括宿主系统GCC 的版本。另外,在基于对称多处理器(SMP)的机器上,SBU 更加不准确。我们提供SBU,仅仅是给出安装一个软件包所需时间的大概估计,在某些情况下实际花费的时间与预估计的时间之间可能有数十分钟的差异。

要查看在一些特定机器上的实际编译安装时间,我们推荐您查看LinuxFromScratch SBU 的主页8d2df468561252d380eb6ec3/

大多数软件包提供了测试套件。编译完一个软件包之后立即运行一下它提供的测试程序是个好主意,因为测试程序将进行一次“健全检查”来确认所有的代码是否都正确编译了。通过了测试套件的一系列检查,通常意味着软件包在按照开发者的预期工作,但是这并不保证这个软件包就完全没有bug 了。

某些软件包的测试程序是极为重要的,例如核心工具链软件包—GCC、Binutils、Glibc—的测试程序,这是因为这些软件包在一个良好工作的系统里的处于核心角色。GCC 和Glibc 的测试程序需要运行很长时间,尤其在速度慢的硬件上,但我们仍然强烈建议您运行这些测试程序。

注意

经验显示,运行第五章的测试套件收获很小。宿主系统会不可避免的对该章中的测试造成影响,经常会有不能解释的错误。因为第五章中编译的工具是临时的,会最终被丢弃,因此我们推荐一般水平的读者不需再做该章的测试。这些测试程序的指令是为开发和测试人员准备的,它们不是必需的。

Binutils 和GCC 的测试程序一个常见的问题就是没有可用的伪终端(PTY),这样可能会出现大量的测试失败。可能的原因有几个,但最可能的原因是宿主系统没有正确的设置好devpts文件系统,这个问题会在第五章详细讨论。

某些软件包测试程序可能会出错,但是开发者了解到这些,这些出错关系不是很大。请参考LFS Wiki(地址为8d2df468561252d380eb6ec3/lfs/build-logs/6.4/)查看这些出错是否在预料之中。这个站点的内容适用于本书所有的测试。

5.1. 本章介绍

本章介绍如何构建一个极小的Linux 系统,这个系统将仅包含用于构建第六章的LFS 系统的必要的工具和一个足够便利的工作环境。

构建这个环境分两个步骤。第一步建立一个新的依赖于宿主系统的工具链,包括编译器、汇编器、链接器、库文件和一些实用工具;第二步是利用这些工具链构建其它的必要工具。

本章中编译安装的文件将安装在$LFS/tools目录下。这样可以与下一章将要安装的软件以及宿主系统区分开来。这些软件包编译出来是起临时作用的,我们不希望这些软件和即将建立的LFS 系统混杂在一起。

本节阐述了整个构建方法的一些基本原理和技术细节,您不必马上就理解本节中的所有内容。在您实际操作之后,就会了解大多数的东西,您可以在任何时候回顾本节。

第五章的总体目标是提供一个临时环境,您可以通过chroot进入到这个环境,在里面构建一个第六章的干净、没有问题的目标LFS 系统。为了尽量的与宿主系统分开,我们一步步构建了一个自包含、自依赖的工具链。这个构建过程对于新手而言犯错误的风险已被降到最低,同时它也提供了尽量大的学习价值。

重要

在继续之前,要先知道工作平台的名称,就是所谓的目标三元组(“target triplet”)。通常情况下,目标三元组可能是i686-pc-linux-gnu。确定该名字的简单办法就是运行许多源码包中都含有的config.guess脚本,解压Binutils 包运行./config.guess并注意输出结果。

另外,注意工作平台的动态连接器名称,通常指的是动态加载器(不要与Binutils 里面的标准连接器ld相混淆)。动态连接器由Glibc 提供,用来找到并加载一个程序运行时所需的共享库,在做好程序运行的准备之后,运行这个程序。动态连接器的名称通常是

ld-linux.so.2。在不怎么流行的平台上则可能是ld.so.1,而在新的64 位平台上更可能是别的完全不同的名称。通过查看宿主系统的/lib目录可以确定动态连接器的名字。确定这个名称还有一个必杀技,就是在宿主系统上随便找一个二进制文件,运行readelf -l | grep interpreter并查看输出的内容。涵盖所有平台的权威参考请查看Glibc 源码根目录里的shlib-versions文件。

以下是关于第五章中构建方法的一些技术要点:

?这个过程在原理上与交叉编译类似,通过安装在同一个目录的工具的协同工作,它还利用了一点GNU 的“魔术”。

?小心处理标准连接器的库文件搜索路径,确保程序仅连接到指定的库上。

?小心处理gcc的specs文件,告诉编译器要使用哪个动态连接器。

首先安装的是Binutils ,因为GCC 和Glibc 的configure脚本要在汇编器和连接器上执行各种各样的特性测试,以确定软件的哪些功能要启用或禁用。这样做比你想像的还要重要,配置不正确的GCC 或者Glibc 会导致工具链出现微妙的错误,这样的错误造成的影响可能直到整个系统快要编译完成的时候才显现出来。测试程序通常会在其它的许多工作进行之前给出错误警告(以避免其后的无效劳动)。

Binutils 的汇编器和连接器安装在两个位置:/tools/bin和

/tools/$TARGET_TRIPLET/bin。其中一个程序是另外一个的硬连接。连接器的一个重要方面是它的库搜索顺序,将--verbose选项传递给ld可以获得详细的信息。比如:ld --verbose | grep SEARCH将显示当前搜索路径和顺序。要显示ld连接的是哪个文件,可以编译一个伪(dummy)程序并把--verbose传递给连接器。例如:gcc dummy.c -Wl,--verbose 2>&1 | grep succeeded将显示所有连接成功的文件。

接下来安装的是GCC 。下面是运行GCC 的configure脚本时,输出内容的一个实例:

基于上面提到过的原因,这是重要的步骤,它同时证明了GCC 的配置脚本并不是搜索PATH 里的目录来寻找要使用哪个工具的,而且在gcc的实际操作中也不一定会使用相同的搜索路径。想要知道gcc将会使用哪个标准连接器,请运行gcc

-print-prog-name=ld。

通过在编译一个伪程序传递参数-v给gcc可以获得详细的信息。举例来说,gcc -v dummy.c将会给出在预处理、编译和汇编各个阶段的详细信息,包括gcc包含的搜索路径及其顺序。

下一个安装的包是Glibc。编译Glibc 的时候,最需要注意的地方是编译器、Binutils 和内核头文件。编译器一般不是问题,因为Glibc 总是使用在PATH目录里找到的gcc;Binutils 和内核头文件要复杂点。因此,为慎重起见,明确使用配置开关(选项)来强制进行正确的选择。在运行configure脚本之后,检查在glibc-build目录下的config.make文件,注意所有重要的细节信息。CC="gcc -B/tools/bin/"控制着使用哪一个Binutils,而用选项-nostdinc和-isystem用来控制编译器的库文件的搜索路径。这些说明了Glibc 的一个重要方面——在编译方法上它是高度自给自足的,通常不依赖于工具链的默认值。

在安装完Glibc 之后,需要做一些调整来保证/tools是唯一的搜索和连接路径。安装一个调整好的ld它的硬链接搜索路径限制在/tools/lib。接下来修正gcc的specs 文件,使它指向新的位于/tools/lib的动态连接器。最后一步对于整个过程至关重要,正如先前提及的,指向动态连接器的硬链接路径被嵌入到每个共享ELF 可执行文件里。这可以通过readelf -l | grep interpreter来查看。修正gcc 的specs 文件确保了现在开始到本章结束编译的所有程序都会使用位于/tools/lib

下的新动态连接器。

在第二遍编译GCC 时,也需要修改其源码使GCC 使用新生成的动态连接器。不这样做的结果是GCC 会把宿主系统/lib目录下动态连接器的名字嵌入进来,这样有悖于与宿主系统隔离的目标。

在编译软件包时有一些假定,说明如下:

?有些软件包在编译之前需要打补丁,但是仅仅在需要修正一个问题的时候才会打该补丁。一个补丁可能在本章和下一章都需要,但有时会只在这章或下章需要,因此会发现已经下载了的补丁在编译时没有应用,此时不必有太多顾虑。在应用某个补丁时可能会出现offset或fuzz的警告信息,不要在意这些警告,这些补丁仍能成功被应用。?在编译大多数软件包的时候,会出现一些警告信息。这是很正常的,可以安全的忽略掉。这些警告大都分是关于警告 C 或C++ 使用了不推荐(deprecated)但仍有效的语法。C 语言的标准会经常更改,某些软件包使用了旧的标准,这不算问题,但是会给出警告信息。

?重要

在每个软件包安装好以后,删除它的源码和编译目录,另有特殊说明除外。删除源码可以防止同一个软件包再次编译安装时配置出错。

确认输出结果为LFS 分区的挂载点,在我们的配置中是/mnt/lfs。

?最后一个重要的事项要着重指出:

?重要

在安照说明编译安装软件包之前,每个源码包应该作为lfs用户解压,而且进入(cd)到新生成的目录中。编译说明假设使用bash Shell。

在第二遍编译Binutils 时,我们可以利用参数--with-lib-path来控制ld的库文件搜索路径。如前面所指出的,核心工具链是自给自足的,第五章剩余部分的所有软件包在编译时都会使用位于/tools目录下的新Glibc。

基于上述Glibc 自给自足的特性,当我们进入chroot 虚拟环境之后,在第六章中首先安装就是Glibc。一旦安装好Glibc 到/usr,马上更改工具链的默认值,然后继续构建目标LFS 系统的剩余部分。

5.4. Binutils-2.18 - 第一遍

Binutils 是一组开发工具,包括连接器、汇编器和其他用于目标文件和档案的工具。

预计编译时间: 1 SBU

所需磁盘空间: 213 MB

5.4.1. 安装Binutils

首先安装的第一个软件包是Binutils ,这非常重要。因为Glibc 和GCC 会针对可用的连接器和汇编器进行多种测试,以决定是否打开某些特性。

Binutils 不能识别高于4.9 版本的Texinfo。应用下面的补丁修正这个问题:

Binutils 的文档推荐用一个新建的目录来编译它,而不是在源码目录中:

注意

如果你想使用本书余下部份列出的SBU 值,那么现在就要测量一下编译本软件包的时间。你可以用类似下面这样的time 命令来测量:time { ./configure ... && make && make install; }

现在开始准备编译:

配置选项的含义:

CC="gcc -B/usr/bin/"

该选项强制gcc使用宿主系统中/usr/bin目录下的连接器。这样做的必要是因为新生成的ld可能与某些宿主系统的gcc不兼容。

--prefix=/tools

这个参数告诉配置脚本,应该把Binutils 软件包中的程序安装到/tools目录中。

--disable-nls

这个参数禁用国际化(通常简称i18n),临时工具不需要国际化的特性。

--disable-werror

该参数防止编译工作在使用某些宿主系统的编译器给出警告信息时停止。

接下来编译它:

现在编译完成了。通常我们会运行测试套件,但是目前测试套件(Tcl、Expect 和

DejaGNU)尚未安装。而且在这里运行测试也没什么用处,因为第一遍安装的

程序很快就会被第二遍的程序所覆盖。

安装它:

下面为后面“调整工具链”做准备:

make 选项的含义:

-C ld clean

告诉make 程序删除所有ld子目录中编译生成的文件。

-C ld LIB_PATH=/tools/lib

这个选项重新编译ld子目录中的所有文件。在命令行中指定Makefile 的LIB_PATH变量值,使它明确指向临时工具目录,以覆盖默认值。这个变量的值指定了连接器的默认库搜索路径,它在这一章的稍后部分会用到。

5.5. GCC-4.3.2 - 第一遍

GCC 软件包包含GNU 编译器,其中有C 和C++ 编译器。

预计编译时间: 22 SBU

所需磁盘空间: 1.1 GB

5.5.1. 安装GCC

该版本的GCC 需要GMP 和MPFR 软件包,你的宿主系统上可能没有安装这两个软件包,它们将一起编译进GCC。

GCC 的安装指南推荐用一个新建的目录来编译它,而不是在源码目录中:

准备编译GCC:

配置选项的含义:

CC="gcc -B/usr/bin/"

该选项强制gcc使用宿主系统中/usr/bin目录下的连接器。这样做的必要是因为上一节新生成的ld可能与某些宿主系统的gcc不兼容。

--with-local-prefix=/tools

这个参数的目的是把/usr/local/include目录从gcc的头文件搜索路径里删除。这并不是绝对必要,但能尽量减小宿主系统的影响。

--disable-shared

该开关强制GCC 静态链接中间库,这样做是为了避免宿主系统可能带来的错误。

--disable-libssp

该开关是为了防止和旧版本的glibc 的冲突,该冲突可能导致编译失败。

--enable-languages=c

该选项确保只编译 C 语言的编译器,现在我们只需要C。

下面的命令会不只一次的编译GCC,它会使用第一遍编译的程序来编译第二

次,再利用第二次的结果进行第三次编译。然后对第二次和第三次的结果进行

比较,确保能完全无差错的编译自身。这被称作“bootstrapping”。这样编

译GCC 可以保证其正确性。有了软件包的配置文件,运行下面命令进行下一

步的编译:

编译完成之后,按通常情况要运行测试程序,但是如前面所述,测试框架还没

有就位。在这里运行测试没什么用处,因为第一遍安装的程序很快就会被第二

遍的程序所覆盖。

安装软件包:

使用参数--disable-shared意味着文件libgcc_eh.a不会被编译和

安装,而在编译Glibc 时,由于使用了参数-lgcc_eh,这会依赖

libgcc_eh.a库。我们可以创建一个到libgcc.a的符号链接来满足这一

依赖关系,因为该文件中通常包含了libgcc_eh.a中的内容。

最后,我们创建一个必要的符号连接。因为许多程序和脚本运行cc而不是

gcc,这是为了保持程序的通用性,使得在一些没有安装GCC 的UNIX 系

统上也能运行。运行cc可以使系统管理员自由选择使用系统中不同的C 语

言编译器。

5.6. Linux-2.6.27.4 API 头文件

Linux API Headers 是将内核的应用程序编程接口(API)提供给Glibc 使用。

预计编译时间: 0.1 SBU

所需磁盘空间: 341 MB

5.6.1. Linux API 头文件的安装

Linux 内核需要向系统C 语言库(LFS 中为Glibc)使用的应用程序接口(API)。我们通过安装Linux 内核源码包中的C 语言头文件来实现。

首先,确认使没有上次使用留下来的过时的文件和依赖关系。

现在测试并提取源码包中的用户可见内核头文件,它们被放置在一个本地的中间目录,然后复制到所需的位置。整个提取过程会移动目标目录的任何文件。

关于这个软件包的详细资料位于第 6.7.2 节“Linux API Headers 的内容”。

5.7. Glibc-2.8-20080929

Glibc 包含了主要的C 语言库。这个库提供了基本例程,用于分配内存、搜索目录、打开关闭文件、读写文件、字串处理、模式匹配、数学计算等等。

预计编译时间: 7.6 SBU

所需磁盘空间: 407 MB

5.7.1. Glibc 的安装

如果宿主系统使用/etc/ld.so.preload,运行下面命令修正可能会出现的问题。

Glibc 文档推荐在源码目录之外的一个专门的编译目录下进行编译:

由于Glibc 不再支持i386,Glibc 的开发者提示在为X86 机器构建时使用编译选项

-march=i486,尽管其他方法也能做到,但是测试显示,最好的办法是将它传递给参数“CFLAGS”。为了不完全覆盖Glibc 内部构建系统使用的CFLAGS,使用特殊文件configparms将所需新选项附加到其原内容之后。由于设置了参数-march,参数

-mtune也会发生改变,使用-mtune=native将其设置为一个合理的值。

接下来,配置Glibc 为编译做准备:

配置选项的含义:

--disable-profile

该设置去掉了程序性能分析相关的库文件编译。如果需要在临时工具上做程序概要

分析,就省掉这个参数。

--enable-add-ons

该选项告诉Glibc 使用NPTL(本地POSIX 线程库)作为其线程库。

--enable-kernel=2.6.0

告诉Glibc 在编译库文件时支持Linux 2.6.x 内核。

--with-binutils=/tools/bin

这个参数并不是必需的。但它们能保证在编译Glibc 时不会用错Binutils 程序。

--without-gd

这个参数保证不生成memusagestat程序,这个程序会顽固地连接到宿主系统的库文件(libgd、libpng 和libz 等等)。

--with-headers=/tools/include

这个参数指示Glibc 按照前面刚刚安装到tools 目录中的内核头文件编译自己,从而精确的知道内核的特性以根据这些特性对自己进行最佳化编译。

--without-selinux

当从一个含有SELinux 特性的宿主系统(如Fedora Core 3)编译时,Glibc 将会将SELinux 支持编译进来。由于LFS 工具链并不包含SELinux 支持,所以一个含有SELinux 特性的Glibc 将会导致许多操作失败。所以这里明确禁用它。

在此过程中可能出现下面的警告信息:

msgfmt程序的缺失或不兼容没有什么大问题,但是在运行测试程序时,

有时可能出问题。msgfmt是宿主系统中Gettext 软件应提供的一部

分,如果安装了msgfmt却不兼容,升级宿主系统的Gettext。如果测

试套件运行没有问题也可以不去管它。

编译软件包:

该包提供了测试套件,但由于我们还没有C++ 的编译器,现在还不能

运行。

安装Glibc 的过程会出现一个/tools/etc/ld.so.conf文件缺失

的警告,这没有什么危害,可以运行下面的命令消除掉:

安装:

不同的国家和文化,使用不同的习俗来交流。这样的习俗很多,从比较简

单的时间和日期格式,到非常复杂的语言发音。GNU 程序的

“internationalization”(国际化,又称“i18n”,18表示中间的18

个字母)是以locale 来实现的。

注意

如果没有运行测试套件(正如我们推荐的),现在就没有必要安装

locales。在下一章我们会安装合适的locales,如果想要现在安装,请

参考第 6.9 节“Glibc-2.8-20080929”里的说明。

现在,安装好了 C 语言的临时库,本章中剩余章节所有要编译的工具都要链接到这些库文件上。为此,需要调整连接器和编译器的工程设计(specs)文件。

在第一遍编译Binutils 结束时已经调整过的连接器,现在需要被重新命名以便可以被正确的找到和使用。首先备份原来的连接器,然后用调整过的连接器来替代,最后还要创建一个指向/tools/$(gcc -dumpmachine)/bin中连接器副本的连接。

从现在开始,所有的程序都将链接到/tools/lib目录下的库文件。

下面的任务是修改GCC 的“specs”文件,使GCC 可以默认指向新的动态链接器。一个简单的sed代换就可以做到:

为了准备起见,推荐使用复制粘贴的办法来应用下面的命令。请亲眼确认下specs 文件,保证每一处“/lib/ld-linux.so.2”都被替换成了“/tools/lib/ld-linux.so.2”:

重要

如果你的系统平台上的动态链接器名字不是ld-linux.so.2,请将下面命令中的

“ld-linux.so.2”替换为相应的动态链接器名称。如果需要,请参阅第 5.2 节“工具链技术说明”。

在编译过程中,GCC 会运行fixincludes 脚本来扫描系统头文件目录,并找出需要修正的头文件(比如包含语法错误),然后把修正后的文件放到GCC 专属头文件目录里。因此,它可能会找出宿主系统中需要修正的头文件,并将修正后的结果放到GCC 专属头文件目录里。由于本章的剩余部分仅需要使用当前已经安装好的GCC 和Glibc 的头文件,所以任何“修正后的”头文件都可以被安全的删除。并且这样做也有助于避免宿主系统中的头文件污染编译环境。运行下面的命令删除GCC 专属头文件目录中的头文件(由于命令较长,推荐你拷贝和粘贴命令,而不是手动输入):

小心

现在,有必要停下来检查新工具链能够完成预期功能(编译和链接),运行下面命令完成合理的检查:

如果工作一切正常,应该不会出错,最后一个命令的输出应该是:

注意,/tools/lib应该是动态链接器的前缀。

如果输出和上面的不一样,或者根本没有输出,就一定是出错了。返回前面的步骤查找问题所在,在纠正这个问题之前不要继续往下做。首先,重新做上一个检查,但用gcc替换cc,如果这次输出正确了,说明链接到cc的符号链接有问题,返回第 5.5 节“GCC-4.3.2 - 第一遍”创建符号链接。下一步,确保PATH变量的正确,这可以通过运行echo $PATH,验证/tools/bin是否在输出列表的最开头。如果PATH变量出错,可能是因为你不是作为lfs用户登入,也可能是在做第 4.4 节“设置编译环境”时出错了。另外一个原因可能是上面修正specs 文件时出错,如果这样,重新修改specs 文件,复制粘贴时要小心仔细。

一切正常之后,清理测试文件:

注意

下一节编译Tcl 时为了验证工具链构建正确而做的附加检验工具。如果Tcl 编译失败,错误出在Binutils、GCC、或者Glibc 的安装,而不是Tcl 本身。

5.9. Tcl-8.5.5

Tcl 软件包包含工具命令语言(Tool Command Language)。

预计编译时间: 0.5 SBU

所需磁盘空间: 36 MB

5.9.1. Tcl 的安装

这个软件包和接下来的两个(Expect 和DejaGNU)的安装用于支持运行GCC 和Binutils 的测试程序。仅仅为了测试目的安装三个软件包看起来显得多余,虽然不是必须的,但是为了最重要的工具能正常工作,这样做会更让人放心。即使现在不会运行这些测试程序,第六章中的测试也会需要这些。

准备编译Tcl:

编译它

现在编译完成了,如前所述,在本章为了一个临时工具运行测试程序不是强制的。如果要测试它,运行下面命令:

现在还不完全清楚为什么Tcl 的测试程序在某些宿主系统上会遭遇失败。因此,如果测试失败了也不要紧,这并不是关键。参数TZ=UTC将时区设置为协调通用时间(UTC),也就是格林尼治时间(GMT),但仅仅在测试时。这保证了时钟测试的正确性。关于环境变量TZ的详细信息请参阅第七章。

安装软件包:

将安装的库文件设置为可写,以便后面剔除调试信息:

安装Tcl 的头文件,安装下一个软件包(Expect)时会用到。

添加必要的符号链接:

5.9.2. Tcl 的内容

安装的程序: tclsh(链接到tclsh8.5)和tclsh8.5

安装的库: libtcl8.5.so

简要描述

tclsh8.5Tcl 命令行Shell

tclsh到tclsh8.5 的链接

libtcl8.5.so Tcl 库

5.10. Expect-5.43.0

Expect 提供了一个与其他交互式程序提供脚本接口的工具。

预计编译时间: 0.1 SBU

所需磁盘空间: 4 MB

5.10.1. 安装Expect

首先修正一个导致运行GCC 测试程序失败的bug:

接着修正由于近期Tcl 更新产生的bug:

接下来,强制Expect 配置脚本使用/bin/stty,而不是使用可能在宿主系统中的/usr/local/bin/stty。这保证我们的测试套件对于最终构造的工具链仍然稳健。

现在可以准备编译:

配置选项的含义:

--with-tcl=/tools/lib

这能确保配置脚本能找到临时系统目录下安装的Tcl,而不是宿主系统可能安装的。

--with-tclinclude=/tools/include

这明确指出了Tcl 内部头文件的位置。这能防止由于configure不能自动寻找到Tcl 内部头文件导致的配置失败。

--with-x=no

告诉配置脚本不去搜索Tk (Tcl 的图形界面组件)或X Window 系统库,两者可能存在于宿主系统,但在临时环境中不存在。

编译它:

编译完成之后,如前所述,在本章为了一个临时工具运行测试程序不是强制的。如

果要测试Expect,运行下面命令:

请注意,已知Expect 的测试程序会在某些不在我们控制范围内的宿主系统下出现测试失败。因此,测试失败也并不奇怪,这不是关键所在。

安装软件包:

配置选项的含义:

SCRIPTS=""

这个选项防止安装Expect 补充的一些并不需要的脚本。

5.10.2. Expect 的内容

安装的程序: expect

安装的库: libexpect-5.43.a

简单描述

expect按照一个脚本与其它交互式程序通信。

libexpect-5.43.a此库文件包含的函数可以让Expert 作为一个Tcl 扩

展来使用,或直接被C 或C++使用(不通过Tcl)。

5.11. DejaGNU-1.4.4

DejaGNU 包含为测试其他程序的一个框架。

本文来源:https://www.bwwdw.com/article/qz3q.html

Top