LFS 搭建 2 构建临时系统
准备工作做完之后,就要开始搭建临时工具链了。
但说是工具链,其实还包括一些其他工具。
开始前的准备
首先当然是登录lfs
用户。
之后检查下$LFS
是否设置正确。
echo $LFS
之后,需要检查以下部分是否正确设置,虽然大部分都不需要刻意留意,但不排除像我这样有特殊习惯的用户会不满足以下条件。
- shell 用的是 bash。
不过目前大部分 shell 都是兼容 bash 的,比如我用的 zsh。 - sh 符号链接到 bash。
这个绝大多数发行版都满足。 /usr/bin/awk
符号链接到 gawk。
这个也不用在意/usr/bin/yacc
是到 bison 的符号链接,或者是一个执行 bison 的小脚本。
嗯,这个也是,除非你用的是 BSD(
此外,对于构建过程,不要把源码放在/mnt/lfs/tools
里,以免污染。
在没有特殊说明时,软件包的标准构建步骤如下
- 解压并 cd 到源码目录
- 根据 readme 编译,也可以 configure make make install 三连
- 离开目录,再把它删了。
现在,就正式开始构建。
构建交叉编译工具链
现在先把目录切到$LFS/sources
下。
Binutils-2.37 - 第一遍
先解压软件包
tar -xvf binutils-2.37.tar.xz
之后将 patch 放入目录并应用
1 | cp binutils-2.37-upstream_fix-1.patch ./binutils-2.37 |
现在需要确认 pty 能否在 chroot 环境里工作
expect -c "spawn ls"
如果不能显示spawn ls
的话,就说明环境没有为 pty 正常工作设置好。不过大多数情况下装expect
包就行了。
根据 Binutils 手册建议,创建build
目录:
1 | mkdir build |
进行 configure
1 | ../configure --prefix=$LFS/tools \ |
开始编译:
make
安装:
make install -j1
至于加上这个-j1
的原因,是为了规避 make 中的一个问题。
GCC 11.2.0 - 第一遍
解压
1 | tar -xvf gcc-11.2.0.tar.xz |
此处 gcc 需要 GMP,MPFR 和 MPC 软件包,将源码解压进 gcc 目录并随 gcc 一起编译
1 | tar -xf ../mpfr-4.1.0.tar.xz |
对于 x86-64 的宿主机,将 64 位库的默认目录设为lib
1 | case $(uname -m) in |
设置build
目录:
1 | mkdir build |
之后是一段巨长的 configure:
1 | ../configure \ |
毕竟是交叉编译还是第一遍,这里对gcc关闭了一堆功能,主要是避免编译依赖标准库的代码
编译:
make
安装:
make install
此处还要补上limits.h
,具体原因是在第一次编译时,$LFS/usr/include/limits.h
还不存在,因此此时 gcc 安装的是不完整的,自给自足的头文件。虽然不加对于编译 glibc 已经足够,但后续步骤需要完整的内部头文件,因此此时手动将 gcc 源码中的相关头文件抽出。
1 | cd .. |
Linux-5.13.12 API 头文件
国际惯例进行解压
1 | tar -xvf linux-5.13.12.tar.xz |
这里只需要编译 glibc 用到的头文件,因此在确保目录里没有什么奇奇怪怪的东西(比如从其他地方 copy 进去的配置什么的)
make mrproper
之后再从源码中提取头文件然后手动复制到工具链目录下
1 | make headers |
最后还是一样的删除整个目录。
Glibc-2.34
glibc 2.34 需要加一个 patch
1 | tar -xvf glibc-2.34.tar.xz |
需要创建符合 LSB 的符号链接
1 | case $(uname -m) in |
之后是创建 build 目录:
1 | mkdir -v build |
现在要确保ldconfig
和sln
被安装到了/usr/bin
echo "rootsbindir=/usr/sbin" > configparms
configure
1 | ../configure \ |
编译
make
安装
make DESTDIR=$LFS install
此处最好检查$LFS
,如果该变量是空的话 glibc 是会装的宿主机的。
此处要修复一个ldd
的硬编码错误:
sed '/RTLDLIST=/s@/usr@@g' -i $LFS/usr/bin/ldd
第一次检查
当上述包都安装完了之后,就需要检查工具链的基本功能能否正常工作。
找一个不会污染源码的目录,运行
1 | echo 'int main(){}' > dummy.c |
如果一切正常,就只会有以下输出
1 | [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] |
在 32 位机器上,解释器名字应该是/lib/ld-linux.so.2.
。
现在删除刚刚创建的文件
rm -v dummy.c a.out
现在用 gcc 的工具安装limits.h
$LFS/tools/libexec/gcc/$LFS_TGT/11.2.0/install-tools/mkheaders
虽然我在运行时会报错找不到文件,但
limits.h
确实安装到了目录include-fixed
里
GCC-11.2.0 里的 Libstdc++ - 第一遍
第一次编译 gcc 时,因为没有 glibc,因此并没有编译 libstdc++,现在安装了 glibc 后就需要编译它了。
现在解压 gcc 目录并创建 build
:
1 | tar -xvf gcc-11.2.0.tar.xz |
之后是 configure
1 | ../libstdc++-v3/configure \ |
之后就是编译安装二连
1 | make |
构建交叉编译临时工具
现在只是编译安装了基础的工具链,在此之上还要安装一些额外工具。
虽然说这些工具是在chroot
之后用的,但现在就要编译。
M4-1.4.19
1 | tar -xvf m4-1.4.19.tar.xz |
此处不需要build
目录。
configure
1 | ./configure --prefix=/usr \ |
编译和安装
1 | make |
Ncurses-6.2
1 | tar -xvf ncurses-6.2.tar.gz |
首先要确保在 configure 时要找得到gawk
sed -i s/mawk// configure
之后需要编译tic
程序
1 | mkdir build |
之后**不要进入build
**,直接开始 configure
1 | ./configure --prefix=/usr \ |
编译
make
安装
1 | make DESTDIR=$LFS TIC_PATH=$(pwd)/build/progs/tic install |
Bash-5.1.8
1 | tar -xvf bash-5.1.8.tar.gz |
configure
1 | ./configure --prefix=/usr \ |
编译和安装
1 | make |
加上sh
到bash
的符号链接
ln -sv bash $LFS/bin/sh
Coreutils-8.32
此处要加一个 patch
1 | tar -xvf coreutils-8.32.tar.xz |
configure
1 | ./configure --prefix=/usr \ |
编译安装二连
1 | make |
此处需要移动部分文件的位置以适应有些硬编码的程序
1 | mv -v $LFS/usr/bin/chroot $LFS/usr/sbin |
Diffutils-3.8
1 | tar -xvf diffutils-3.8.tar.xz |
三连
1 | ./configure --prefix=/usr --host=$LFS_TGT |
File-5.40
1 | tar -xvf file-5.40.tar.gz |
这里的file
命令需要与宿主机上的版本一致,因此需要特殊编译
1 | mkdir build |
再进行三连,同样不要进入build
1 | ./configure --prefix=/usr --host=$LFS_TGT --build=$(./config.guess) |
Findutils-4.8.0
1 | tar -xvf findutils-4.8.0.tar.xz |
configure
1 | ./configure --prefix=/usr \ |
编译和安装
1 | make |
Gawk-5.1.0
1 | tar -xvf gawk-5.1.0.tar.xz |
首先确保不安装不需要的文件
sed -i 's/extras//' Makefile.in
configure
1 | ./configure --prefix=/usr \ |
编译和安装
1 | make |
Grep-3.7
1 | tar -xvf grep-3.7.tar.xz |
configure
1 | ./configure --prefix=/usr \ |
编译和安装
1 | make |
Gzip-1.10
1 | tar -xvf gzip-1.10.tar.xz |
Make-4.3
1 | tar -xvf make-4.3.tar.gz |
configure
1 | ./configure --prefix=/usr \ |
编译和安装
1 | make |
Patch-2.7.6
1 | tar -xvf patch-2.7.6.tar.xz |
configure
1 | ./configure --prefix=/usr \ |
编译和安装
1 | make |
Sed-4.8
1 | tar -xvf sed-4.8.tar.xz |
configure
1 | ./configure --prefix=/usr \ |
编译和安装
1 | make |
Tar-1.34
1 | tar -xvf tar-1.34.tar.xz |
configure
1 | ./configure --prefix=/usr \ |
编译和安装
1 | make |
Xz-5.2.5
1 | tar -xvf xz-5.2.5.tar.xz |
configure
1 | ./configure --prefix=/usr \ |
编译和安装
1 | make |
Binutils-2.37 - 第二遍
这一次和第一次差不多,但有一些微妙的差别
1 | tar -xvf binutils-2.37.tar.xz |
configure
1 | ../configure \ |
编译
make
安装,并绕过导致libctf.so
链接到宿主发行版 zlib 的问题
1 | make DESTDIR=$LFS install -j1 |
GCC-11.2.0 - 第二遍
1 | tar -xvf gcc-11.2.0.tar.xz |
还是一样的解压 GMP, MPFR 和 MPC
1 | tar -xf ../mpfr-4.1.0.tar.xz |
还是一样的设置 64 位库的符号链接
1 | case $(uname -m) in |
建立build
目录
1 | mkdir build |
创建一个符号链接以在构建libgcc
时启用对 posix 线程的支持
1 | mkdir -pv $LFS_TGT/libgcc |
configure
1 | ../configure \ |
编译和安装
1 | make |
一样的创建cc
到gcc
的符号链接
ln -sv gcc $LFS/usr/bin/cc
至此本文就到这里,接下来就要进行 chroot 了。
11.0 的手册相较于 9.0 而言第二部分的内容实在是太多了……
不理解为什么要把 chroot 后的操作也要放在这一部分。