交叉编译基本工具
接下来将使用刚刚构建的交叉工具链交叉对基本工具进行交叉编译。自 10.0 开始这些工具会直接安装到最终它们应该被安装到的位置,而非 10.0 之前的版本会先安装到 tool 下。不过效果是一样的,即使构建完成,但还是不能马上使用的状态,实际的操作依赖宿主系统,只是在链接的时候使用的会是它们而已。
在这个时候率先交叉编译它们的主要原因是为了调整依赖关系,交叉编译仍然使用的是宿主系统中的对应依赖。而最后的 LFS 系统需要独立于宿主机运行,那就不得不将依赖转移到其内部。基本工具的一个特点就是被依赖的多,且本身编译器就需要依赖它们。为了构建 LFS 的时候,可以少依赖甚至不依赖宿主系统的环境,需要交叉编译这些基本工具。
3.3.1 安装 M4:宏处理器
M4 是 POSIX 标准中的一部分,对于 Unix 宏处理器的一种实现。很多软件包需求,其中 Autoconf 对其极度依赖。
- 大致构建用时: 0.1 SBU
- 所需磁盘空间: 22 MB 解压并进入软件包:
tar -xf m4-1.4.18.tar.xz
cd m4-1.4.18
对应 glibc-2.28 的需求做一些修复:
sed -i 's/IO_ftrylockfile/IO_EOF_SEEN/' lib/*.c
echo "#define _IO_IN_BACKUP 0x100" >> lib/stdio-impl.h
配置 M4 准备编译:
./configure --prefix=/tools
编译软件包:
make
安装软件包:
make DESTDIR=$LFS install
退出并清理软件包:
cd ..
rm -rf m4-1.4.18
3.3.2 安装 Ncurses:字符终端处理库
GNU Guile Ncurses 是 Guile Scheme 解释器的库,提供创建文本用户界面的函数。
- 大致构建用时: 0.7 SBU
- 所需磁盘空间: 48 MB 解压并进入软件包:
tar -xf ncurses-6.2.tar.gz
cd ncurses-6.2
首先,执行以下命令,确保在配置文件中 gawk 将会被率先找到:
sed -i s/mawk// configure
然后,在宿主系统构建 tic 程序:
mkdir build
pushd build
../configure
make -C include
make -C progs tic
popd
配置 Ncurses 准备编译:
./configure \
--prefix=/usr \
--host=$LFS_TGT \
--build=$(./config.guess) \
--mandir=/usr/share/man \
--with-manpage-format=normal \
--with-shared \
--without-debug \
--without-ada \
--without-normal \
--enable-widec
配置选项的含义:
| 参数 | 描述 |
|---|---|
--with-manpage-format=normal | 避免安装压缩的 man 手册(若宿主发行版使用压缩手册,可能会安装) |
--without-ada | 这个选项会保证禁止构建 Ada 编译器 |
--enable-widec | 这个选项会控制编译使用宽字符库(比如,libncursesw.so.6.1)而不是默认的普通库(比如,libncurses.so.6.1 )进行构建。这些宽字符库在多字节和传统的 8 位环境下都可以使用,而普通库只能用于 8 位环境。宽字符库和普通库的源代码是兼容的,但并不是二进制兼容。 |
--without-normal | 禁止多数静态库的安装 |
编译软件包:
make
安装软件包:
make DESTDIR=$LFS TIC_PATH=$(pwd)/build/progs/tic install
echo "INPUT(-lncursesw)" > $LFS/usr/lib/libncurses.so
TIC_PATH=$(pwd)/build/progs/tic
我们需要传递刚刚构建的,可以在宿主系统运行的 tic 程序的路径,以保证正确创建终端数据库。
echo "INPUT(-lncursesw)" > $LFS/usr/lib/libncurses.so
我们很快将会构建一些需要 libncurses.so 库的软件包。创建这个简短的链接脚本,正如我们在第 8 章中将要做的那样。
将共享库移动到它们应该位于的 /lib 目录中:
mv -v $LFS/usr/lib/libncursesw.so.6* $LFS/lib
由于库文件被移动到其他位置,一个符号链接现在指向不存在的文件。重新生成它:
ln -sfv ../../lib/$(readlink $LFS/usr/lib/libncursesw.so) $LFS/usr/lib/libncursesw.so
退出并清理软件包:
cd ..
rm -rf ncurses-6.2
3.3.3 安装 Bash–最常用的 shell
Bash 是 GNU 项目的 shell。这是一个与 sh 兼容的 shell,它包含了 kornshell(ksh)和 csh(csh)的有用特性。它符合 IEEE POSIX P1003.2/ISO 9945.2 外壳和工具标准。它为编程和交互使用提供了比 sh 更好的功能。此外,大多数 sh 脚本都可以由 Bash 运行而无需修改。
- 大致构建用时: 0.4 SBU
- 所需磁盘空间: 64 MB 解压并进入软件包:
tar -xf bash-5.0.tar.gz
cd bash-5.0
配置 Bash 准备编译:
./configure \
--prefix=/usr \
--build=$(support/config.guess) \
--host=$LFS_TGT \
--without-bash-malloc
配置选项的含义:
| 参数 | 描述 |
|---|---|
--without-bash-malloc | 这个选项会禁用 bash 的内存分配功能(malloc),禁用这个功能后,bash 将使用 glibc 的 malloc 函数,这样会更稳定 |
编译软件包:
make
安装软件包:
make DESTDIR=$LFS install
将可执行文件移动到正确位置:
mv $LFS/usr/bin/bash $LFS/bin/bash
为使用 sh 终端的程序创建一个软链接:
ln -sv bash $LFS/bin/sh
退出并清理软件包:
cd ..
rm -rf bash-5.0
3.3.4 安装 Coreutils–GNU 核心工具组
非常直白的命名方式 Core utils,也就是核心工具组或者工具集。
- 大致构建用时: 0.6 SBU
- 所需磁盘空间: 170 MB 解压并进入软件包:
tar -xf coreutils-8.32.tar.xz
cd coreutils-8.32
配置 Coreutils 准备编译:
./configure \
--prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess) \
--enable-install-program=hostname \
--enable-no-install-program=kill,uptime
配置选项的含义:
| 参数 | 描述 |
|---|---|
--enable-install-program=hostname | 这个选项会允许构建和、安装 hostname 程序,默认是不安装的,但是 Perl 的测试套件需要 |
编译软件包:
make
安装软件包:
make DESTDIR=$LFS install
将程序移动到它们最终安装时的正确位置。尽管在临时环境中这不必要,但我们必须这样做,因为一些程序会硬编码它们的位置:
mv -v $LFS/usr/bin/{cat,chgrp,chmod,chown,cp,date,dd,df,echo} $LFS/bin
mv -v $LFS/usr/bin/{false,ln,ls,mkdir,mknod,mv,pwd,rm} $LFS/bin
mv -v $LFS/usr/bin/{rmdir,stty,sync,true,uname} $LFS/bin
mv -v $LFS/usr/bin/{head,nice,sleep,touch} $LFS/bin
mv -v $LFS/usr/bin/chroot $LFS/usr/sbin
mkdir -pv $LFS/usr/share/man/man8
mv -v $LFS/usr/share/man/man1/chroot.1 $LFS/usr/share/man/man8/chroot.8
sed -i 's/"1"/"8"/' $LFS/usr/share/man/man8/chroot.8
退出并清理软件包:
cd ..
rm -rf coreutils-8.32
3.3.5 安装 Diffutils:一组用于显示文本文件之间的差异实用程序
GNU Diffutils 一个包含若干关于比较文件区别程序的软件包,其中包含诸如“diff”、“cmp”等常用命令。
- 大致构建用时: 0.2 SBU
- 所需磁盘空间: 26 MB 解压并进入软件包:
tar -xf diffutils-3.7.tar.xz
cd diffutils-3.7
配置 Diffutils 准备编译:
./configure --prefix=/usr --host=$LFS_TGT
编译软件包:
make
安装软件包:
make DESTDIR=$LFS install
退出并清理软件包:
cd ..
rm -rf diffutils-3.7
3.3.6 安装 File-用于判断给定文件类型的工具
用于判断给定文件类型的工具。构建后主要包含两个文件:用于区分文件类型的 file 和给 file 提供幻数(magic number)识别例程的 libmagic
- 大致构建用时: 0.1 SBU
- 所需磁盘空间: 21 MB 解压并进入软件包:
tar -xf file-5.39.tar.gz
cd file-5.37
配置 File 准备编译:
./configure --prefix=/usr --host=$LFS_TGT
编译软件包:
make
安装软件包:
make DESTDIR=$LFS install
退出并清理软件包:
cd ..
rm -rf file-5.39
3.3.7 安装 Findutils-GNU 操作系统的基本目录搜索应用程序
GNU Find Utilities 目录检索基本工具。通常会与其他命令一起使用,为其他命令提供模块化的、强大的目录搜索和文件定位功能。
- 大致构建用时: 0.2 SBU
- 所需磁盘空间: 40 MB 解压并进入软件包:
tar -xf findutils-4.7.0.tar.gz
cd findutils-4.7.0
配置 Findutils 准备编译:
./configure \
--prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)
编译软件包:
make
安装软件包:
make DESTDIR=$LFS install
将可执行文件移动到最终安装时的正确位置:
mv -v $LFS/usr/bin/find $LFS/bin
sed -i 's|find:=${BINDIR}|find:=/bin|' $LFS/usr/bin/updated
退出并清理软件包:
cd ..
rm -rf findutils-4.7.0
3.3.8 安装 Gawk-一种优秀的文本处理工具
- 大致构建用时: 0.2 SBU
- 所需磁盘空间: 46 MB 解压并进入软件包:
tar -xf gawk-5.1.0.tar.xz
cd gawk-5.1.0
首先,确保不要安装一些没有必要的文件:
sed -i 's/extras//' Makefile.in
配置 Gawk 准备编译:
./configure \
--prefix=/usr \
--host=$LFS_TGT \
--build=$(./config.guess)
编译软件包:
make
安装软件包:
make DESTDIR=$LFS install
退出并清理软件包:
cd ..
rm -rf gawk-5.1.0
3.3.9 安装 Grep-用于搜索与正则表达式匹配的行的纯文本数据集
Grep 是一个用于检索一个或多个输入文件的工具,按行匹配,并且会默认的输出符合条件的行。
- 大致构建用时: 0.2 SBU
- 所需磁盘空间: 26 MB 解压并进入软件包:
tar -xf grep-3.4.tar.xz
cd grep-3.4
配置 Grep 准备编译:
./configure \
--prefix=/usr \
--host=$LFS_TGT \
--bindir=/bin
编译软件包:
make
安装软件包:
make DESTDIR=$LFS install
退出并清理软件包:
cd ..
rm -rf grep-3.4
3.3.10 安装 Gzip-GNU 文件压缩程序
- 大致构建用时: 0.1 SBU
- 所需磁盘空间: 10 MB 解压并进入软件包:
tar -xf gzip-1.10.tar.xz
cd gzip-1.10
配置 Gzip 准备编译:
./configure --prefix=/usr --host=$LFS_TGT
编译软件包:
make
安装软件包:
make DESTDIR=$LFS install
将可执行文件移动到最终安装时的正确位置:
mv -v $LFS/usr/bin/gzip $LFS/bin
退出并清理软件包:
cd ..
rm -rf gzip-1.10
3.3.11 安装 make-自动化构建软件
Make 可以自动确认大型程序需要重新编译的部分,并发出指令重新编译这些部分。
- 大致构建用时: 0.1 SBU
- 所需磁盘空间: 16 MB 解压并进入软件包:
tar -xf make-4.3.tar.bz2
cd make-4.3
配置 make 准备编译:
./configure \
--prefix=/usr \
--without-guile \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)
配置选项的含义:
| 参数 | 描述 |
|---|---|
--without-guile | 这个选项会保证 Make-4.2.1 不会去链接宿主系统上可能存在的 Guile 库,避免构建的环境而在下一章里通过 chroot 切换环境后便不再有效了不能正常使用了 |
编译软件包:
make
安装软件包:
make DESTDIR=$LFS install
退出并清理软件包:
cd ..
rm -rf make-4.3
3.3.12 安装 Patch-根据补丁文件中包含的指令更新文本文件
- 大致构建用时: 0.1 SBU
- 所需磁盘空间: 13 MB 解压并进入软件包:
tar -xf patch-2.7.6.tar.xz
cd patch-2.7.6
配置 Patch 准备编译:
./configure \
--prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)
编译软件包:
make
安装软件包:
make DESTDIR=$LFS install
退出并清理软件包:
cd ..
rm -rf patch-2.7.6
3.3.13 安装 Sed-流编辑器
sed(streameditor)是一个非交互式的命令行文本编辑器。
- 大致构建用时: 0.1 SBU
- 所需磁盘空间: 21 MB 解压并进入软件包:
tar -xf sed-4.8.tar.xz
cd sed-4.8
配置 Sed 准备编译:
./configure \
--prefix=/usr \
--host=$LFS_TGT \
--bindir=/bin
编译软件包:
make
安装软件包:
make DESTDIR=$LFS install
退出并清理软件包:
cd ..
rm -rf sed-4.8
3.3.14 安装 Tar-GNU Tar 提供了 tar 文件的创建和管理功能
文件归档工具,常与 gzip、bzip 等压缩软件一起使用。
- 大致构建用时: 0.2 SBU
- 所需磁盘空间: 39 MB 解压并进入软件包:
tar -xf tar-1.32.tar.xz
cd tar-1.32
配置 Tar 准备编译:
./configure \
--prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess) \
--bindir=/bin
编译软件包:
make
安装软件包:
make DESTDIR=$LFS install
退出并清理软件包:
cd ..
rm -rf tar-1.32
3.3.15 安装 xz-免费的通用数据压缩软件
- 大致构建用时: 0.1 SBU
- 所需磁盘空间: 16 MB 解压并进入软件包:
tar -xf xz-5.2.5.tar.xz
cd xz-5.2.5
配置 Xz 准备编译:
./configure \
--prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess \
--disable-static \
--docdir=/usr/share/doc/xz-5.2.5
编译软件包:
make
安装软件包:
make DESTDIR=$LFS install
确保所有关键文件位于正确的目录中:
mv -v $LFS/usr/bin/{lzma,unlzma,lzcat,xz,unxz,xzcat} $LFS/bin
mv -v $LFS/usr/lib/liblzma.so.* $LFS/lib
ln -svf ../../lib/$(readlink $LFS/usr/lib/liblzma.so) \
$LFS/usr/lib/liblzma.so
退出并清理软件包:
cd ..
rm -rf xz-5.2.5
3.3.16 第二次安装 Binutils
- 大致构建用时: 1.3 SBU
- 所需磁盘空间: 497 MB 解压并进入软件包:
tar -xf binutils-2.35.tar.xz
cd binutils-2.35
再次新建一个单独的编译文件夹:
mkdir -v build
cd build
准备编译 Binutils:
../configure \
--prefix=/usr \
--build=$(../config.guess) \
--host=$LFS_TGT \
--disable-nls \
--enable-shared \
--disable-werror \
--enable-64-bit-bfd
配置选项的含义,之后的含意解释中不会重复之前解释过的内容,如表 3-5 所示。
| 参数 | 作用描述 |
|---|---|
| --enable-shared | 将 libbfd 构建为共享库。 |
| --enable-64-bit-bfd | 启用 64 位支持 (在那些字长较短的平台上)。在 64 位系统上可能并不需要,但无害。 |
编译软件包:
make
安装软件包:
make DESTDIR=$LFS install
退出并清理软件包:
cd ../..
rm -rf binutils-2.35
3.3.17 第二次安装 GCC
- 大致构建用时: 12 SBU
- 所需磁盘空间: 3.7 GB 解压并进入软件包:
tar -xf gcc-10.2.0.tar.xz
cd gcc-10.2.0
与第一次编译 GCC 相同,需求 GMP、MPFR 和 MPC 软件包。解压 tar 包并把它们重名为到所需的文件夹名称:
tar -xf ../mpfr-4.0.2.tar.xz
mv -v mpfr-4.0.2 mpfr
tar -xf ../gmp-6.1.2.tar.xz
mv -v gmp-6.1.2 gmp
tar -xf ../mpc-1.1.0.tar.gz
mv -v mpc-1.1.0 mpc
如果是在 x86_64 环境上构建,设置 64 位的库的默认目录为 lib:
case $(uname -m) in
x86_64)
sed -e '/m64=/s/lib64/lib/' -i.orig gcc/config/i386/t-linux64
;;
esac
再次创建独立的编译文件夹:
mkdir -v build
cd build
创建一个符号链接,以允许 libgcc 在构建时启用 POSIX 线程支持:
mkdir -pv $LFS_TGT/libgcc
ln -s ../../../libgcc/gthr-posix.h $LFS_TGT/libgcc/gthr-default.h
在开始构建 GCC 前,记得清除所有覆盖默认优化开关的环境变量。 准备编译 GCC:
../configure \
--build=$(../config.guess) \
--host=$LFS_TGT \
--prefix=/usr \
CC_FOR_TARGET=$LFS_TGT-gcc \
--with-build-sysroot=$LFS \
--enable-initfini-array \
--disable-nls \
--disable-multilib \
--disable-decimal-float \
--disable-libatomic \
--disable-libgomp \
--disable-libquadmath \
--disable-libssp \
--disable-libvtv \
--disable-libstdcxx \
--enable-languages=c,c++
配置选项的含义:
| 参数 | 描述 |
|---|---|
| --enable-languages=c,c++ | 这个选项确保编译了 C 和 C++ 编译器 |
| --with-build-sysroot=$LFS | 通常,使用 --host 即可保证使用交叉编译器构建 GCC,这个交叉编译器知道它应该在 $LFS 中查找头文件和库。但是,GCC 构建系统使用其他一些工具,它们不知道这个位置。因此需要该选项告诉它们在 $LFS 中查找需要的文件,而不是在宿主系统中查找。 |
| --enable-initfini-array | 该选项在使用 x86 本地编译器构建另一个本地编译器时自动启用。然而我们使用交叉编译器进行编译,因此必须显式启用它。 |
编译软件包:
make
安装软件包:
make DESTDIR=$LFS install
这里创建一个符号链接,作为画龙点睛的一笔。很多程序和脚本执行 cc 而不是 gcc 来保证程序的通用性,并且在所有的 Unix 类型的系统上都能用,而非仅局限于安装了 GCC 的 Unix 类型的系统。运行 cc 使得系统管理员无需考虑要安装那种 C 编译器:
ln -sv gcc $LFS/usr/bin/cc