6.9. Glibc-2.21

Glibc 软件包包含了主要的 C 函数库。这个库提供了分配内存、搜索目录、打开关闭文件、读写文件、操作字符串、模式匹配、基础算法等基本程序。

大概编译时间: 16.3 SBU
所需磁盘空间: 1.1 GB

6.9.1. 安装 Glibc

[Note]

注意

有些 LFS 之外的软件包会建议安装 GNU libiconv 来转换不同编码的文字。根据项目主页(http://www.gnu.org/software/libiconv/)上的说法这个库会提供函数 iconv() 的实现,应用于那些没有这个函数的系统,或者函数实现中不支持 Unicode 转换的系统。 Glibc 提供了函数 iconv() 的实现而且支持 Unicode 转换,所以对于 LFS 系统来说并不需要 libiconv 库。

有些 Glibc 程序会用到和 FHS 不兼容的 /var/db 目录来存储它们的运行时数据。打上如下的补丁让这些程序在 FHS 兼容的位置存储它们的运行时数据。

patch -Np1 -i ../glibc-2.21-fhs-1.patch

Glibc 的编译系统是自包含的,可以完美安装,尽管编译器的配置文件和链接器仍然指向 /tools。这在 Glibc 安装前没法调整,因为如果调整的话 Glibc 的 autoconf 测试将会提示错误,不符合我们实现一个干净构建的目标。

修正软件包里的一个会影响到 32 位架构系统的正则表达式:

sed -e '/ia32/s/^/1:/' \
    -e '/SSE2/s/^1://' \
    -i  sysdeps/i386/i686/multiarch/mempcpy_chk.S

Glibc 文档里建议在 Glibc 源代码目录之外的特定编译目录下编译:

mkdir -v ../glibc-build
cd ../glibc-build

配置 Glibc 准备编译:

../glibc-2.21/configure    \
    --prefix=/usr          \
    --disable-profile      \
    --enable-kernel=2.6.32 \
    --enable-obsolete-rpc

新出现的 configure 选项参数的含义:

--enable-obsolete-rpc

安装 NIS 和 RPC 相关的头文件,默认是不安装的;重新编译 Glibc 时以及一些 BLFS 软件包需要这些头文件。

编译软件包:

make
[Important]

重要

在本小节里,运行 Glibc 的测试套件是很关键的。在任何情况下都不要跳过这个测试。

通常会有一些测试不能通过,但是一般你可以忽略任何下面列出来的失败项。现在开始测试编译结果:

make check

你可能会看到一些失败的测试项。Glibc 的测试套件对宿主系统有一定的依赖。下面是当前版本 LFS 里最常见的问题:

  • 测试项 tst/tst-cputimer1rt/tst-cpuclock2 已知是通不过的。具体原因还不清楚,不过一些细微的时间问题可能导致这些测试失败。

  • 如果你系统的 CPU 不是相对较新的 Genuine Intel 或 Authentic AMD 处理器,数学运算测试有时候会失败。

  • 因为测试的时候还没有网络,测试项 posix/tst-getaddrinfo4 和 posix/tst-getaddrinfo5 将总是失败。

  • 其它已知的在某些架构平台上会失败的测试项是 malloc/tst-malloc-usable 和 nptl/tst-cleanupx4。

在安装 Glibc 时会抱怨找不到 /etc/ld.so.conf 文件,这只是无关紧要的输出信息。下面的方式可以避免这个警告:

touch /etc/ld.so.conf

安装软件包:

make install

nscd 安装配置文件并创建运行时目录:

cp -v ../glibc-2.21/nscd/nscd.conf /etc/nscd.conf
mkdir -pv /var/cache/nscd

nscd 安装系统支持文件:

install -v -Dm644 ../glibc-2.21/nscd/nscd.tmpfiles /usr/lib/tmpfiles.d/nscd.conf
install -v -Dm644 ../glibc-2.21/nscd/nscd.service /lib/systemd/system/nscd.service

上面的命令并没有安装可以让你的电脑用不同语言响应的语言环境。语言环境并不是必须的,只是如果有些语言环境缺失,后续的测试套件可能会跳过一些重要测试用例。

单独的语言环境可以用 localedef 程序安装。例如,下面第一个 localedef 命令将 /usr/share/i18n/locales/cs_CZ 字符无关的语言环境定义和 /usr/share/i18n/charmaps/UTF-8.gz 字符表定义组合在一起,并将结果附加到 /usr/lib/locale/locale-archive 文件末尾。下面的命令将安装能完美覆盖测试所需语言环境的最小集合:

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

另外,安装适合你自己国家、语言和字符集的语言环境。

或者,也可以一次性安装在 glibc-2.21/localedata/SUPPORTED 文件里列出的所有语言环境(包括以上列出的所有语言环境以及其它更多),执行下面这个非常耗时的命令:

make localedata/install-locales

你需要的语言环境几乎不大可能没列在 glibc-2.21/localedata/SUPPORTED 文件中,但如果真的没有可以使用 localedef 命令创建和安装。

6.9.2. 配置 Glibc

尽管 Glibc 在文件 /etc/nsswitch.conf 丢失或损坏的情况下会创建一个默认的,但是我们需要手动该创建文件,因为 Glibc 的默认文件在网络环境下工作时有问题。另外,也需要设置一下时区。

运行下面的命令创建一个新文件 /etc/nsswitch.conf

cat > /etc/nsswitch.conf << "EOF"
# Begin /etc/nsswitch.conf

passwd: files
group: files
shadow: files

hosts: files dns myhostname
networks: files

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

# End /etc/nsswitch.conf
EOF

安装时区数据:

tar -xf ../tzdata2015a.tar.gz

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

for tz in etcetera southamerica northamerica europe africa antarctica  \
          asia australasia backward pacificnew 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 zone1970.tab iso3166.tab $ZONEINFO
zic -d $ZONEINFO -p America/New_York
unset ZONEINFO

zic 命令的含义:

zic -L /dev/null ...

这会创建没有时间补偿的 posix 时区数据。一般将它们同时放在 zoneinfozoneinfo/posix 目录下。另外需要将 POSIX 时区数据放到 zoneinfo 目录下,否则很多测试套件会报错。在嵌入式平台,如果存储空间紧张而且你也不准备更新时区,也可以不用 posix 目录从而节省 1.9MB,但是一些应用程序或测试套件也许会出错。

zic -L leapseconds ...

这会创建包含时间补偿的 right 时区数据。在嵌入式平台,空间比较紧张而且你也不打算更新时区或者不需要准确时间,你可以忽略 right 目录从而节省 1.9MB。

zic ... -p ...

这会创建 posixrules 文件。我们使用纽约是因为 POSIX 要求夏令时规则与 US 标准一致。

一种确定本地时区的方式是运行下面的脚本:

tzselect

在询问了几个关于位置的问题后,脚本会输出所在时区的名字(比如 America/Edmonton)。在 /usr/share/zoneinfo 文件中也有其它一些可用时区,比如 Canada/EasternEST5EDT,这些时区并没有被脚本列出来但也是可以使用的。

然后运行下面的命令创建 /etc/localtime 文件:

ln -sfv /usr/share/zoneinfo/<xxx> /etc/localtime

将命令中的 <xxx> 替换成你所在实际时区的名字(比如 Canada/Eastern)。

6.9.3. 配置动态库加载器

默认情况下,动态库加载器(/lib/ld-linux.so.2)会搜索目录 /lib/usr/lib 查找程序运行时所需的动态库文件。不过,如果库文件不在 /lib/usr/lib 目录下,需要把它所在目录加到 /etc/ld.so.conf 文件里,保证动态库加载器能找到这些库。通常有两个目录包含额外的动态库,/usr/local/lib/opt/lib,把这两个目录加到动态库加载器的搜索路径中。

运行下面的命令创建一个新文件/etc/ld.so.conf

cat > /etc/ld.so.conf << "EOF"
# Begin /etc/ld.so.conf
/usr/local/lib
/opt/lib

EOF

如果需要的话,动态库加载器也可以查找目录并包含里面配置文件的内容。通常在这个包含目录下的文件只有一行字指向库目录。运行下面的命令增加这个功能:

cat >> /etc/ld.so.conf << "EOF"
# Add an include directory
include /etc/ld.so.conf.d/*.conf

EOF
mkdir -pv /etc/ld.so.conf.d

6.9.4. Glibc 软件包内容

安装的程序: catchsegv, gencat, getconf, getent, iconv, iconvconfig, ldconfig, ldd, lddlibc4, locale, localedef, makedb, mtrace, nscd, pcprofiledump, pldd, rpcgen, sln, sotruss, sprof, tzselect, xtrace, zdump, 和 zic
安装的库: ld-2.21.so, libBrokenLocale.{a,so}, libSegFault.so, libanl.{a,so}, 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, 和 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/locale, /usr/libexec/getconf, /usr/share/i18n, /usr/share/zoneinfo, /var/cache/nscd, 和 /var/lib/nss_db

简要介绍

catchsegv

可以在程序因为段错误终止的时候创建栈调用历史

gencat

生成消息条目

getconf

显示文件系统相关的系统配置变量的值

getent

获取系统数据库的内容

iconv

字符集转换

iconvconfig

创建 iconv 快速加载模块配置文件

ldconfig

配置动态链接器的运行时环境

ldd

报告某个程序或动态库所依赖的动态库。

lddlibc4

协助 ldd 处理某些目标文件。

locale

输出当前语言环境的大量信息

localedef

编译语言环境规格

makedb

根据输入的文本创建简单数据库

mtrace

读取并解析内存跟踪文件,然后用方便人阅读的格式显示一个摘要

nscd

一个后台服务程序,提供最常用名字服务请求的缓存

pcprofiledump

输出个人电脑分析时生成的信息

pldd

列出运行中进程正在使用的动态共享目标

rpcgen

生成实现远端进程调用(RPC)协议的 C 语言代码

sln

一个静态链接的 ln 程序

sotruss

跟踪指定命令里的动态库函数调用

sprof

读取并显示共享目标分析数据

tzselect

询问用户该系统的地理位置并给出相应的时区描述

xtrace

跟踪程序执行过程并打印当前执行的函数

zdump

时区数据输出工具

zic

时区数据编译工具

ld-2.21.so

用于动态库执行的辅助程序

libBrokenLocale

Glibc 内部的一个粗暴破解用来修复损坏程序(比如,一些 Motif 应用)。查看文件 glibc-2.21/locale/broken_cur_max.c 里的注释来了解更多信息

libSegFault

段错误信号处理函数,catchsegv会用到

libanl

一个异步名字查找库

libc

主要的 C 库

libcidn

Glibc 内部用于在函数 getaddrinfo() 中处理国际化域名

libcrypt

密码学函数库

libdl

动态链接接口函数库

libg

不包含函数的一个空库。以前是 g++ 的运行时库

libieee

链接该模块会强制使用电气与电子工程师协会(IEEE) 定义的数学函数错误处理规则。默认的是 POSIX.1 错误处理。

libm

数学运算函数库

libmcheck

链接这个库后会打开内存分配检查

libmemusage

memusage 命令用它来协助收集应用程序里内存使用信息

libnsl

网络服务函数库

libnss

名称服务切换函数库,包含了解析主机名、用户名、组名、别称、服务、协议等等的函数。

libpcprofile

包含一些分析函数,用于跟踪特定源代码里的 CPU 时间占用情况

libpthread

POSIX 线程函数库

libresolv

包含了创建、发送和解析互联网域名服务器封包的函数

librpcsvc

包含了提供杂项 RPC 服务的函数

librt

包含了实现 POSIX.1b 实时扩展里规定的大部分接口的函数

libthread_db

包含了方便构建多线程程序调试工具的函数

libutil

包含各种 Unix 应用程序中用到的标准 函数的代码