交叉编译基本工具

接下来将使用刚刚构建的交叉工具链交叉对基本工具进行交叉编译。自 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

配置选项的含义:

表 3-1 Ncurses 配置选项
参数描述
--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

配置选项的含义:

表 3-1 Bash 配置选项
参数描述
--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

配置选项的含义:

表 3-1 Coreutils 配置选项
参数描述
--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)

配置选项的含义:

表 3-1 make 配置选项
参数描述
--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 所示。

表 3-2 Binutils 配置选项(第二次)
参数作用描述
--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++

配置选项的含义:

表 3-3 GCC 配置选项(第二次)
参数描述
--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