6.Cross compiling temporary tools
6.1 Introduction
本章展示如何使用刚刚构建的交叉工具链对基本工具进行交叉编译。这些工具会被安装到它们的最终位置,但现在还无法使用。基本操作仍然依赖宿主系统的工具。尽管如此,在链接时会使用刚刚安装的库。
在下一章,进入“chroot”环境后,就可以使用这些工具。但是在此之前,我们必须将本章中所有的软件包构建完毕。因此现在我们还不能脱离宿主系统。
再一次地,请注意如果 LFS 环境变量设置错误,而且使用 root 用户的身份进行构建,可能导致您的电脑完全无法使用。本章应该以用户 lfs 身份完成,且环境变量应该如同第 4.4 节 “配置环境”所述设置。
6.2 M4-1.4.19
M4 软件包包含一个宏处理器。
估计构建时间: 0.1 SBU
需要硬盘空间: 31 MB
6.2.1 安装 M4
准备编译 M4:
./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)
编译该软件包:
make
安装该软件包:
make DESTDIR=$LFS install
该软件包的详细信息可以在第 8.12.2 节 “M4 的内容”找到。
6.3 Ncurses-6.4
Ncurses 软件包包含使用时不需考虑终端特性的字符屏幕处理函数库。
估计构建时间: 0.3 SBU
需要硬盘空间: 51 MB
6.3.1 安装 Ncurses
首先,保证在配置时优先查找 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-normal \
--with-cxx-shared \
--without-debug \
--without-ada \
--disable-stripping \
--enable-widec
新的配置选项的含义:
–with-manpage-format=normal
这防止 Ncurses 安装压缩的手册页面,否则在宿主发行版使用压缩的手册页面时,Ncurses 可能这样做。
–with-shared
该选项使得 Ncurses 将 C 函数库构建并安装为共享库。
–without-normal
该选项禁止将 C 函数库构建和安装为静态库。
–without-debug
该选项禁止构建和安装用于调试的库。
–with-cxx-shared
该选项使得 Ncurses 将 C++ 绑定构建并安装为共享库,同时防止构建和安装静态的 C++ 绑定库。
–without-ada
这保证不构建 Ncurses 的 Ada 编译器支持,宿主环境可能有 Ada 编译器,但进入 chroot 环境后 Ada 编译器就不再可用。
–disable-stripping
该选项防止构建过程使用宿主系统的 strip 程序。对交叉编译产生的程序使用宿主工具可能导致构建失败。
–enable-widec
该选项使得宽字符库 (例如 libncursesw.so.6.4) 被构建,而不构建常规字符库 (例如 libncurses.so.6.4)。宽字符库在多字节和传统 8 位 locale 中都能工作,而常规字符库只能在 8 位 locale 中工作。宽字符库和普通字符库在源码层面是兼容的,但二进制不兼容。
编译该软件包:
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 章中将要做的那样。
该软件包的详细信息可以在第 8.28.2 节 “Ncurses 的内容”中找到。
6.4 Bash-5.2.15
Bash 软件包包含 Bourne-Again Shell。
估计构建时间: 0.2 SBU
需要硬盘空间: 67 MB
6.4.1 安装 Bash
准备编译 Bash:
./configure --prefix=/usr \
--build=$(sh support/config.guess) \
--host=$LFS_TGT \
--without-bash-malloc
配置选项的含义:
–without-bash-malloc
该选项禁用 Bash 自己的内存分配 (malloc) 函数,因为已知它会导致段错误。这样,Bash 就会使用 Glibc 的更加稳定的 malloc 函数。
编译该软件包:
make
安装该软件包:
make DESTDIR=$LFS install
为那些使用 sh 命令运行 shell 的程序考虑,创建一个链接:
ln -sv bash $LFS/bin/sh
该软件包的详细信息可以在第 8.34.2 节 “Bash 的内容”中找到。
6.5 Coreutils-9.1
Coreutils 软件包包含各种操作系统都需要提供的基本工具程序。
估计构建时间: 0.3 SBU
需要硬盘空间: 162 MB
6.5.1 安装 Coreutils
准备编译 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/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
该软件包的详细信息可以在第 8.54.2 节 “Coreutils 的内容”中找到。
6.6 Diffutils-3.9
Diffutils 软件包包含显示文件或目录之间差异的程序。
估计构建时间: 0.2 SBU
需要硬盘空间: 26 MB
6.6.1 安装 Diffutils
准备编译 Diffutils:
./configure --prefix=/usr --host=$LFS_TGT
编译该软件包:
make
安装该软件包:
make DESTDIR=$LFS install
该软件包的详细信息可以在第 8.56.2 节 “Diffutils 的内容”中找到。
6.7 File-5.44
File 软件包包含用于确定给定文件类型的工具。
估计构建时间: 0.1 SBU
需要硬盘空间: 36 MB
6.7.1 安装 File
宿主系统 file 命令的版本必须和正在构建的软件包相同,才能在构建过程中创建必要的签名数据文件。运行以下命令,构建 file 命令的一个临时副本:
mkdir build
pushd build
../configure --disable-bzlib \
--disable-libseccomp \
--disable-xzlib \
--disable-zlib
make
popd
新的配置选项的含义:
–disable-*
如果相关的库文件存在,配置脚本企图使用宿主发行版的一些软件包。当库文件存在,但对应的头文件不存在时,这会导致编译失败。该选项防止使用这些来自宿主系统的非必要功能。
准备编译 File:
./configure --prefix=/usr --host=$LFS_TGT --build=$(./config.guess)
编译该软件包:
make FILE_COMPILE=$(pwd)/build/src/file
安装该软件包:
make DESTDIR=$LFS install
移除对交叉编译有害的 libtool 档案文件:
rm -v $LFS/usr/lib/libmagic.la
该软件包的详细信息可以在第 8.10.2 节 “File 的内容”中找到。
6.8 Findutils-4.9.0
Findutils 软件包包含用于查找文件的程序。这些程序能直接搜索目录树中的所有文件,也可以创建、维护和搜索文件数据库 (一般比递归搜索快,但在数据库最近没有更新时不可靠)。Findutils 还提供了 xargs 程序,它能够对一次搜索列出的素有文件执行给定的命令。
估计构建时间: 0.2 SBU
需要硬盘空间: 42 MB
6.8.1 安装 Findutils
准备编译 Findutils:
./configure --prefix=/usr \
--localstatedir=/var/lib/locate \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)
编译该软件包:
make
安装该软件包:
make DESTDIR=$LFS install
该软件包的详细信息可以在第 8.58.2 节 “Findutils 的内容”中找到。
6.9 Gawk-5.2.1
Gawk 软件包包含操作文本文件的程序。
估计构建时间: 0.1 SBU
需要硬盘空间: 47 MB
6.9.1 安装 Gawk
首先,确保不安装某些不需要的文件:
sed -i 's/extras//' Makefile.in
准备编译 Gawk:
./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)
编译该软件包:
make
安装该软件包:
make DESTDIR=$LFS install
该软件包的详细信息可以在第 8.57.2 节 “Gawk 的内容”中找到。
6.10 Grep-3.8
Grep 软件包包含在文件内容中进行搜索的程序。
估计构建时间: 0.2 SBU
需要硬盘空间: 25 MB
6.10.1 安装 Grep
准备编译 Grep:
./configure --prefix=/usr \
--host=$LFS_TGT
编译该软件包:
make
安装该软件包:
make DESTDIR=$LFS install
该软件包的详细信息可以在第 8.33.2 节 “Grep 的内容”中找到。
6.11 Gzip-1.12
Gzip 软件包包含压缩和解压缩文件的程序。
估计构建时间: 0.1 SBU
需要硬盘空间: 11 MB
6.11.1 安装 Gzip
准备编译 Gzip:
./configure --prefix=/usr --host=$LFS_TGT
编译该软件包:
make
安装该软件包:
make DESTDIR=$LFS install
该软件包的详细信息可以在第 8.61.2 节 “Gzip 的内容”中找到。
6.12 Make-4.4
Make 软件包包含一个程序,用于控制从软件包源代码生成可执行文件和其他非源代码文件的过程。
估计构建时间: 不到 0.1 SBU
需要硬盘空间: 15 MB
6.12.1 安装 Make
首先,修复上游发现的问题:
sed -e '/ifdef SIGPIPE/,+2 d' \
-e '/undef FATAL_SIG/i FATAL_SIG (SIGPIPE);' \
-i src/main.c
准备编译 Make:
./configure --prefix=/usr \
--without-guile \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)
新的配置选项的含义:
–without-guile
尽管我们在进行交叉编译,配置脚本如果找到宿主系统的 guile,仍然会试图使用它。这导致编译失败,因此使用该选项防止使用 guile。
编译该软件包:
make
安装该软件包:
make DESTDIR=$LFS install
该软件包的详细信息可以在第 8.65.2 节 “Make 的内容”中找到。
6.13 Patch-2.7.6
Patch 软件包包含通过应用 “补丁” 文件,修改或创建文件的程序,补丁文件通常是 diff 程序创建的。
估计构建时间: 0.1 SBU
需要硬盘空间: 12 MB
6.13.1 安装 Patch
准备编译 Patch:
./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)
编译该软件包:
make
安装该软件包:
make DESTDIR=$LFS install
该软件包的详细信息可以在第 8.66.2 节 “Patch 的内容”中找到。
6.14 Sed-4.9
Sed 软件包包含一个流编辑器。
估计构建时间: 0.2 SBU
需要硬盘空间: 19 MB
6.14.1 安装 Sed
准备编译 Sed:
./configure --prefix=/usr \
--host=$LFS_TGT
编译该软件包:
make
安装该软件包:
make DESTDIR=$LFS install
该软件包的详细信息可以在第 8.29.2 节 “Sed 的内容”中找到。
6.15 Tar-1.34
Tar 软件包提供创建 tar 归档文件,以及对归档文件进行其他操作的功能。Tar 可以对已经创建的归档文件进行提取文件,存储新文件,更新文件,或者列出文件等操作。
估计构建时间: 0.1 SBU
需要硬盘空间: 38 MB
6.15.1 安装 Tar
准备编译 Tar:
./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)
编译该软件包:
make
安装该软件包:
make DESTDIR=$LFS install
该软件包的详细信息可以在第 8.67.2 节 “Tar 的内容”中找到。
6.16 Xz-5.4.1
Xz 软件包包含文件压缩和解压缩工具,它能够处理 lzma 和新的 xz 压缩文件格式。使用 xz 压缩文本文件,可以得到比传统的 gzip 或 bzip2 更好的压缩比。
估计构建时间: 0.1 SBU
需要硬盘空间: 20 MB
6.16.1 安装 Xz
准备编译 Xz:
./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess) \
--disable-static \
--docdir=/usr/share/doc/xz-5.4.1
编译该软件包:
make
安装该软件包:
make DESTDIR=$LFS install
移除对交叉编译有害的 libtool 档案文件:
rm -v $LFS/usr/lib/liblzma.la
该软件包的详细信息可以在第 8.8.2 节 “Xz 的内容”中找到。
6.17 Binutils-2.40 - Pass 2
Binutils 包含汇编器、链接器以及其他用于处理目标文件的工具。
估计构建时间: 0.4 SBU
需要硬盘空间: 525 MB
6.17.1 安装 Binutils
Binutils 的源码包中内置了一份陈旧的 libtool 拷贝。这个版本的 libtool 没有 sysroot 支持,因此产生的二进制代码会错误地链接到宿主系统提供的库。绕过这个问题:
sed '6009s/$add_dir//' -i ltmain.sh
再次创建一个独立的构建目录:
mkdir -v build
cd build
准备编译 Binutils:
../configure \
--prefix=/usr \
--build=$(../config.guess) \
--host=$LFS_TGT \
--disable-nls \
--enable-shared \
--enable-gprofng=no \
--disable-werror \
--enable-64-bit-bfd
新的配置选项的含义:
–enable-shared
将 libbfd 构建为共享库。
–enable-64-bit-bfd
(在字长较小的宿主平台上) 启用 64 位支持。该选项在 64 位平台上可能不必要,但无害。
编译该软件包:
make
安装该软件包:
make DESTDIR=$LFS install
移除对交叉编译有害的 libtool 档案文件,同时移除不必要的静态库:
rm -v $LFS/usr/lib/lib{bfd,ctf,ctf-nobfd,opcodes}.{a,la}
该软件包的更多信息可以在第 8.18.2 节 “Binutils 的内容”中找到。
6.18 GCC-12.2.0 - Pass 2
GCC 软件包包含 GNU 编译器集合,其中有 C 和 C++ 编译器。
估计构建时间: 4.6 SBU
需要硬盘空间: 4.7 GB
6.18.1 安装 GCC
如同第一次构建 GCC 时一样,需要使用 GMP、MPFR 和 MPC 三个包。解压它们的源码包,并将它们移动到 GCC 要求的目录名:
tar -xf ../mpfr-4.2.0.tar.xz
mv -v mpfr-4.2.0 mpfr
tar -xf ../gmp-6.2.1.tar.xz
mv -v gmp-6.2.1 gmp
tar -xf ../mpc-1.3.1.tar.gz
mv -v mpc-1.3.1 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
覆盖 libgcc 和 libstdc++ 头文件的构建规则,以允许在构建它们时启用 POSIX 线程支持:
sed '/thread_header =/s/@.*@/gthr-posix.h/' \
-i libgcc/Makefile.in libstdc++-v3/include/Makefile.in
再次创建一个独立的构建目录:
mkdir -v build
cd build
在开始构建 GCC 前,记得清除所有覆盖默认优化开关的环境变量。
现在准备编译 GCC:
../configure \
--build=$(../config.guess) \
--host=$LFS_TGT \
--target=$LFS_TGT \
LDFLAGS_FOR_TARGET=-L$PWD/$LFS_TGT/libgcc \
--prefix=/usr \
--with-build-sysroot=$LFS \
--enable-default-pie \
--enable-default-ssp \
--disable-nls \
--disable-multilib \
--disable-libatomic \
--disable-libgomp \
--disable-libquadmath \
--disable-libssp \
--disable-libvtv \
--enable-languages=c,c++
新的配置选项的含义:
–with-build-sysroot=$LFS
通常,指定 –host 即可保证使用交叉编译器构建 GCC,这个交叉编译器知道它应该在 $LFS 中查找头文件和库。但是 GCC 构建系统使用其他一些工具,它们不知道这个位置。因此需要该选项,使得这些工具在 $LFS 中查找需要的文件,而不是在宿主系统中查找。
–target=$LFS_TGT
我们正在交叉编译 GCC,因此不可能用编译得到的 GCC 二进制程序构建用于目标系统的运行库 (libgcc 和 libstdc++) —— 这些二进制程序无法在宿主系统运行。GCC 构建系统在默认情况下会试图使用宿主系统提供的 C 和 C++ 编译器来绕过这个问题。但是,用不同版本的 GCC 构建 GCC 运行库不受支持,所以使用宿主系统的编译器可能导致构建失败。该选项保证使用第一遍构建的 GCC 编译运行库。
LDFLAGS_FOR_TARGET=…
允许 libstdc++ 使用即将构建的 libgcc 共享库,而不是第一遍构建 GCC 时得到的静态库。这对于 C++ 异常处理支持是必要的。
编译该软件包:
make
安装该软件包:
make DESTDIR=$LFS install
最后,还需要创建一个符号链接。许多程序和脚本运行 cc 而不是 gcc,因为前者能够保证程序的通用性,使它可以在所有 UNIX 系统上使用,无论是否安装了 GNU C 编译器。运行 cc 可以将安装哪种 C 编译器的选择权留给系统管理员:
ln -sv gcc $LFS/usr/bin/cc
该软件包的详细信息在第 8.26.2 节 “GCC 的内容”可以找到。