从零开始搭建一个Linux系统

https://www.linuxfromscratch.org/

本文所有的内容都来自于上方的网站中,我只是手动的进行了一次操作


一直以来听到过很多发行版的Linux,像是Ubuntu、CentOS、Debian等等,但是对于Linux的内核和系统的构建过程却是一无所知。这次就来从零开始搭建一个Linux系统,了解一下Linux系统的构建过程。

1. 先决条件

  • 一台Linux系统的主机(可以是VMware,也可以是主机)
  • 有四个以上 CPU 核⼼和⾄少 8 GB 存储

2. 开始搭建

2.1. 安装Debian

预计时间:10分钟

首先我们需要安装一个Debian系统,这里我们使用VMware来安装Debian系统。首先我们需要下载Debian的ISO文件,然后在VMware中新建一个虚拟机,选择Debian的ISO文件进行安装。这里给出一张正在使用VMware安装Debian的截图。一路Continue,有需要设置账户名和root/user的密码需要设置一
下,直到安装完成。

在分区的时候我们留下一个空的分区,用于后面的LFS系统。可以按照我的截图来分区或者你自己选择。

PS: 需要注意的是在最后一步,不能直接选择Continue。需要如图所选再点击Continue。



然后系统会重启,等待一分钟即可进入系统(视性能而定)。

进入Debian

1.1. 安装必要的软件(最低要求)

下列软件必须是要在宿主系统下进行安装的。这些软件是构建LFS系统的必要软件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
•Bash-3.2 (/bin/sh 必须是到 bash 的符号链接或硬连接)
•Binutils-2.13.1 (⽐ 2.43.1 更新的版本未经测试,不推荐使⽤)
•Bison-2.7 (/usr/bin/yacc 必须是到 bison 的链接,或者是⼀个执⾏ bison 的⼩脚本)
•Coreutils-8.1
•Diffutils-2.8.1
•Findutils-4.2.31
•Gawk-4.0.1 (/usr/bin/awk 必须是到 gawk 的链接)
•GCC-5.2,包括 C++ 编译器 g++ (⽐ 14.2.0 更新的版本未经测试,不推荐使⽤)。C 和 C++ 标准库 (包
括头⽂件) 也必须可⽤,这样 C++ 编译器才能构建宿主环境的程序
•Grep-2.5.1a
•Gzip-1.3.12
•Linux Kernel-4.19
•M4-1.4.10
•Make-4.0
•Patch-2.5.4
•Perl-5.8.8
•Python-3.4
•Sed-4.1.5
•Tar-1.22
•Texinfo-5.0
•Xz-5.0.0

打开终端,并且输入nano version-check.sh, 然后粘贴以下代码即可检查环境,需要注意必须已经安装了上方所列出的所有软件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/bin/bash
# A script to list version numbers of critical development tools
# If you have tools installed in other directories, adjust PATH here AND
# in ~lfs/.bashrc (section 4.4) as well.
LC_ALL=C
PATH=/usr/bin:/bin
bail() { echo "FATAL: $1"; exit 1; }
grep --version > /dev/null 2> /dev/null || bail "grep does not work"
sed '' /dev/null || bail "sed does not work"
sort /dev/null || bail "sort does not work"
ver_check()
{
if ! type -p $2 &>/dev/null
then
echo "ERROR: Cannot find $2 ($1)"; return 1;
fi
v=$($2 --version 2>&1 | grep -E -o '[0-9]+\.[0-9\.]+[a-z]*' | head -n1)
if printf '%s\n' $3 $v | sort --version-sort --check &>/dev/null
then
printf "OK: %-9s %-6s >= $3\n" "$1" "$v"; return 0;
else
printf "ERROR: %-9s is TOO OLD ($3 or later required)\n" "$1";
return 1;
fi
}
ver_kernel()
{
kver=$(uname -r | grep -E -o '^[0-9\.]+')
if printf '%s\n' $1 $kver | sort --version-sort --check &>/dev/null
then
printf "OK: Linux Kernel $kver >= $1\n"; return 0;
else
printf "ERROR: Linux Kernel ($kver) is TOO OLD ($1 or later required)\n" "$kver";
return 1;
fi
}
# Coreutils first because --version-sort needs Coreutils >= 7.0
ver_check Coreutils sort 8.1 || bail "Coreutils too old, stop"
ver_check Bash bash 3.2
ver_check Binutils ld 2.13.1
ver_check Bison bison 2.7
ver_check Diffutils diff 2.8.1
ver_check Findutils find 4.2.31
ver_check Gawk gawk 4.0.1
ver_check GCC gcc 5.2
ver_check "GCC (C++)" g++ 5.2
ver_check Grep grep 2.5.1a
ver_check Gzip gzip 1.3.12
ver_check M4 m4 1.4.10
ver_check Make make 4.0
ver_check Patch patch 2.5.4
ver_check Perl perl 5.8.8
ver_check Python python3 3.4
ver_check Sed sed 4.1.5
ver_check Tar tar 1.22
ver_check Texinfo texi2any 5.0
ver_check Xz xz 5.0.0
ver_kernel 4.19
if mount | grep -q 'devpts on /dev/pts' && [ -e /dev/ptmx ]
then echo "OK: Linux Kernel supports UNIX 98 PTY";
else echo "ERROR: Linux Kernel does NOT support UNIX 98 PTY"; fi
alias_check() {
if $1 --version 2>&1 | grep -qi $2
then printf "OK: %-4s is $2\n" "$1";
else printf "ERROR: %-4s is NOT $2\n" "$1"; fi
}
echo "Aliases:"
alias_check awk GNU
alias_check yacc Bison
alias_check sh Bash
echo "Compiler check:"
if printf "int main(){}" | g++ -x c++ -
then echo "OK: g++ works";
else echo "ERROR: g++ does NOT work"; fi
rm -f a.out
if [ "$(nproc)" = "" ]; then
echo "ERROR: nproc is not available or it produces empty output"
else
echo "OK: nproc reports $(nproc) logical cores are available"
fi

然后按Ctrl+X,然后按Y,然后按Enter,保存文件。然后输入chmod +x version-check.sh,然后输入./version-check.sh,然后等待一会,就可以看到你的系统是否满足要求了。

在截图上可以看见输出了两个error。
Error: sh is not Bash
Error: g++ does NOT work
这两个error很好解决,第一个需要修改一下链接,第二个需要安装g++。

修改链接

在我的虚拟机中,输入ls -l /usr/bin/sh,可以看见sh指向的是dash,而不是bash。所以我们需要修改一下。输入sudo ln -sf /usr/bin/bash /usr/bin/sh

安装g++

输入sudo apt install g++

再次运行检查脚本,可以看见已经没有error了。

在进行下一步前必须要确定你的系统满足上方的所有要求。如果有不满足的,需要安装相应的软件。

2.1 分区

终端输入sydi oarted /dev/sda print free, 可以看见我还有一个空的分区没有分配,这里的空的空间是在安装系统时刻意去设置的。

记下起始位置和结束位置。接下来我们就要对这个分区进行分区。

sudo parted /dev/sda进入parted,然后输入mkpart primary ext4 16.GB 100%,这里的16GB是起始位置,然后使用100%。最后输入quit退出parted。

出现了一个information。先不用管,后面会解决。

接下来运行

1
2
3
export LFS=/mnt/lfs
mkdir -pv $LFS
mount -v -t ext4 /dev/sda3 $LFS

如果一切正常那么你会看见新的分区已经挂在在了/mnt/lfs下。

需要的操作用户为root

3. 下载需要的包

预计时间:20分钟

下载的依赖/软件需要放在一个容易找到的地方,这里我们选择放在/mnt/lfs/sources下。运行 mkdir -v $LFS/sources,然后运行 chmod -v a+wt $LFS/sources。然后我们就可以下载依赖了。

这里使用wget来下载。按照 wget --input-file=wget-list-sysv --continue --directory-prefix=$LFS/sources来进行所有的下载。

不过首先要创建一个wget-list-sysv文件,然后把所有的下载链接放进去。这里我就不一一列举了,可以参考这里

这个是上面两个链接的整合,下载这个比较好

PS: 可以使用vscode来获取所有的下载链接,正则匹配所有链接,CTRL+SHIFT+L选中所有的链接,粘贴下载即可。

下载完毕的截图

cd $LFS/sources,然后就可以看到下载完毕后的文件了。

不要忘了还要下载一些补丁,可以参考这里

最后还得要运行一下chown root:root $LFS/sources/*

3.1 最后准备工作

在终端运行

1
2
3
4
5
6
7
8
9
mkdir -pv $LFS/{etc,var} $LFS/usr/{bin,lib,sbin}
for i in bin lib sbin; do
ln -sv usr/$i $LFS/$i
done
case $(uname -m) in
x86_64) mkdir -pv $LFS/lib64 ;;
esac

mkdir -pv $LFS/tools

3.2 添加LFS用户

1
2
3
4
5
6
7
8
9
10
groupadd lfs

useradd -s /bin/bash -g lfs -m -k /dev/null lfs

passwd lfs

chown -v lfs $LFS/{usr{,/*},lib,var,etc,bin,sbin,tools}
case $(uname -m) in
x86_64) chown -v lfs $LFS/lib64 ;;
esac

如果出现找不到命令的错误,可以使用 /usr/sbin/groupadd lfs/usr/sbin/useradd -s /bin/bash -g lfs -m -k /dev/null lfs亦或者cd到目录手动运行。上面四条命令是为了创建一个lfs用户,然后把lfs用户的权限赋予给$LFS目录。

3.3. 切换到lfs用户

1
su - lfs

3.3 配置lfs用户环境

预计时间:5分钟

分别运行以下命令

1
2
3
cat > ~/.bash_profile << "EOF"
exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash
EOF
1
2
3
4
5
6
7
8
9
10
11
12
cat > ~/.bashrc << "EOF"
set +h
umask 022
LFS=/mnt/lfs
LC_ALL=POSIX
LFS_TGT=$(uname -m)-lfs-linux-gnu
PATH=/usr/bin
if [ ! -L /bin ]; then PATH=/bin:$PATH; fi
PATH=$LFS/tools/bin:$PATH
CONFIG_SITE=$LFS/usr/share/config.site
export LFS LC_ALL LFS_TGT PATH CONFIG_SITE
EOF

防止对root用户的影响,我们需要运行

[ ! -e /etc/bash.bashrc ] || mv -v /etc/bash.bashrc /etc/bash.bashrc.NOUSE

最后,不要忘记 source ~/.bash_profile。终端输入。

3.4 make -jx(可选)

提升编译速度

因为我这里使用的是虚拟机,性能不会有真机那么强大。

但是如果你的电脑性能足够强大,可以指定make -jx,这样可以加快编译速度。x为一个数字,代表你的CPU核心数。

4. 编译

预计时间:1-10小时

用户为lfs,终端输入

1
2
3
cd $LFS/sources # 进入到下载的文件夹
for file in *.tar.xz; do tar -xf "$file"; done # 解压所有的tar.xz文件

4.1. Binutils 第一遍

要在lfs用户下运行并且确保在build目录下。这个build目录是在binutils目录下创建的。

预计时间:5分钟

运行

1
2
3
4
5
6
7
8
9
10
mkdir -v build
cd build
../configure --prefix=$LFS/tools \
--with-sysroot=$LFS \
--target=$LFS_TGT \
--disable-nls \
--enable-gprofng=no \
--disable-werror \
--enable-new-dtags \
--enable-default-hash-style=gnu

如果出现错误,如下图所示,请检查前置条件是否满足。比如上方的环境检查脚本。

接下来运行

1
make && make install # 编译并安装。此前提为已经运行了上方的configure命令。并且当前目录是在build目录下。

如出现以下错误,可以运行 sudo apt install texinfo来解决。当然,这个错误理应在前面的环境检查中就已经解决了。

安装完毕后,可以看到如下图所示。

4.2. GCC

预计时间:30分钟

gcc依赖于gmp、mpfr、mpc所以要先安装这些依赖。

因为前面我们已经下载了并且解压了这三个依赖,所以我们可以直接进行编译。只需要把这三个依赖放到gcc的目录下即可。
具体方法为使用mv命令,按照mv gmp-版本号 gcc-版本号/gmp来移动gmp到gcc目录下。mpfr和mpc同理。

需要注意的是,这里的版本号是你下载的版本号,移动过去的文件是不带版本号的。只有一个gmp、mpfr、mpc的名字的文件夹。

如果你是x86_64的系统,需要运行`case $(uname -m) in
x86_64)
sed -e '/m64=/s/lib64/lib/' \
-i.orig gcc/config/i386/t-linux64
;;
esac`

接下来cd到gcc目录下(终端输入cd gcc+tab可以自动补全),然后运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
mkdir -v build
cd build

../configure \
--target=$LFS_TGT \
--prefix=$LFS/tools \
--with-glibc-version=2.40 \
--with-sysroot=$LFS \
--with-newlib \
--without-headers \
--enable-default-pie \
--enable-default-ssp \
--disable-nls \
--disable-shared \
--disable-multilib \
--disable-threads \
--disable-libatomic \
--disable-libgomp \
--disable-libquadmath \
--disable-libssp \
--disable-libvtv \
--disable-libstdcxx \
--enable-languages=c,c++

小趣事:在这里我的vmware因为内存不足需要提升一下,我重启了一下vmware,然后把内存提升到了4G。再次进入系统的时候进入lfs目录我发现我文件全没了。我突然就慌了,然后检查了一下发现原来是我没有mount分区,然后我就mount了一下,然后文件全回来了。哈哈哈

运行完上面的命令后,运行

1
2
3
4
make && make install
cd ..
cat gcc/limitx.h gcc/glimits.h gcc/limity.h > \
`dirname $($LFS_TGT-gcc -print-libgcc-file-name)`/include/limits.h # 在gcc目录下运行

成功后如下图所示。

或者使用ls $LFS/tools/bin来查看是否有gcc和g++。

4.3 Linux Api header

预计时间:1分钟

先cd到linux-6.10.5目录下,然后依次运行

1
2
3
4
make mrproper
make headers
find usr/include -type f ! -name '*.h' -delete
cp -rv usr/include $LFS/usr

4.4 Glibc

预计时间:15分钟

先运行一下下方的命令。请注意这里,非常的重要。如果前面的前置条件没有满足,下面的命令会造成系统崩溃。

建议:在运行前创建一个快照。在运行,如果出错,可以直接恢复快照。

1
2
3
4
5
6
7
case $(uname -m) in
i?86) ln -sfv ld-linux.so.2 $LFS/lib/ld-lsb.so.3
;;
x86_64) ln -sfv ../lib/ld-linux-x86-64.so.2 $LFS/lib64
ln -sfv ../lib/ld-linux-x86-64.so.2 $LFS/lib64/ld-lsb-x86-64.so.3
;;
esac

然后进入到glibc文件夹中,使用cd。

进入后输入命令 patch -Np1 -i ../glibc-2.40-fhs-1.patch即可自动完成补丁。请注意这里的补丁是在前面我们就已经下载好的文件,应该在sources文件夹下面。

在运行configure前我们的系统中应该有两个依赖包,分别是gawk bison & gettext。让我们用apt-get install 来安装它们。如果前面已经安装完毕请忽略这一步。

1
2
apt-get gawk bison
apt-get install gettext

接下来运行configure(build目录下)

1
2
3
4
5
6
7
8
../configure \
--prefix=/usr \
--host=$LFS_TGT \
--build=$(../scripts/config.guess) \
--enable-kernel=4.19 \
--with-headers=$LFS/usr/include \
--disable-nscd \
libc_cv_slibdir=/usr/lib

成功截图如下

在configure成功后,运行

1
2
make && make DESTDIR=$LFS install
sed '/RTLDLIST=/s@/usr@@g' -i $LFS/usr/bin/ldd

到此就安装好了,接下来可以检查一下是否安装成功。

echo 'int main(){}' | $LFS_TGT-gcc -xc - readelf -l a.out | grep ld-linux

结果如下图所示。

最后删除一下临时文件 rm -v a.out

4.5. Libstdc++

预计时间:1分钟
此文件是在gcc中的,所以再次进入gcc的目录下,创建一个新的文件夹,然后运行configure

运行

1
2
3
$LFS/sources/gcc-14.2.0/libstdc++-v3/configure --host=$LFS_TGT --build=$(../config.guess) --prefix=/usr --disable-multilib --disable-nls --disable-libstdcxx-pch --with-gxx-include-dir=/tools/$LFS_TGT/include/c++/14.2.0

make && make DESTDIR=$LFS install

运行成功后如下图所示。

4.6 M4

预计时间:1分钟

进入m4目录,然后运行

1
2
3
4
5
6
7
./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)

make

make DESTDIR=$LFS install

运行成功后如下图所示。

4.7. Ncurses

预计时间:5分钟

运行以下几条命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
sed -i s/mawk// configure

mkdir build
pushd build
../configure
make -C include
make -C progs tic
popd

./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

make

make DESTDIR=$LFS TIC_PATH=$(pwd)/build/progs/tic install
ln -sv libncursesw.so $LFS/usr/lib/libncurses.so
sed -e 's/^#if.*XOPEN.*$/#if 1/' \
-i $LFS/usr/include/curses.h

运行成功后如下图所示。

4.8. Bash

预计时间:5分钟

运行以下几条命令(所有的configure都是在包的目录下面才能运行)

1
2
3
4
5
6
7
8
9
10
11
./configure --prefix=/usr \
--build=$(sh support/config.guess) \
--host=$LFS_TGT \
--without-bash-malloc \
bash_cv_strtold_broken=no

make

make DESTDIR=$LFS install

ln -sv bash $LFS/bin/sh

运行成功后如下图所示。

4.9. Coreutils

预计时间:5分钟

运行以下几条命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess) \
--enable-install-program=hostname \
--enable-no-install-program=kill,uptime

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

运行成功后如下图所示。

4.10. Diffutils

预计时间:1分钟

运行以下几条命令

1
2
3
4
5
6
7
8
./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(./build-aux/config.guess)

make

make DESTDIR=$LFS install

运行成功后如下图所示。

4.11. File

预计时间:1分钟

运行以下几条命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mkdir build

pushd build
../configure --disable-bzlib \
--disable-libseccomp \
--disable-xzlib \
--disable-zlib
make
popd

./configure --prefix=/usr --host=$LFS_TGT --build=$(./config.guess)

make FILE_COMPILE=$(pwd)/build/src/file

make DESTDIR=$LFS install

rm -v $LFS/usr/lib/libmagic.la

运行成功后如下图所示。

4.12. Findutils

预计时间:1分钟

运行以下几条命令

1
2
3
4
5
6
7
8
./configure --prefix=/usr \
--localstatedir=/var/lib/locate \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)

make

make DESTDIR=$LFS install

运行成功后如下图所示。

4.13. Gawk

预计时间:1分钟

运行以下几条命令

1
2
3
4
5
6
7
sed -i 's/extras//' Makefile.in

./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)

make && make DESTDIR=$LFS install

运行成功后如下图所示。

4.14. Grep

预计时间:1分钟

运行以下几条命令

1
2
3
4
5
./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(./build-aux/config.guess)

make && make DESTDIR=$LFS install

运行成功后如下图所示。

4.15. Gzip

预计时间:1分钟

运行以下几条命令

1
2
3
./configure --prefix=/usr --host=$LFS_TGT

make && make DESTDIR=$LFS install

运行成功后如下图所示。

4.16. Make

预计时间:1分钟

运行以下几条命令

1
2
3
4
5
6
./configure --prefix=/usr \
--without-guile \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)

make && make DESTDIR=$LFS install

运行成功后如下图所示。

4.17. Patch

预计时间:1分钟

运行以下几条命令

1
2
3
4
5
./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)

make && make DESTDIR=$LFS install

运行成功后如下图所示。

4.18. Sed

预计时间:1分钟

运行以下几条命令

1
2
3
4
5
./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(./build-aux/config.guess)

make && make DESTDIR=$LFS install

运行成功后如下图所示。

4.19. Tar

预计时间:1分钟

运行以下几条命令

1
2
3
4
5
./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess)

make && make DESTDIR=$LFS install

运行成功后如下图所示。

4.20. Xz

预计时间:1分钟

运行以下几条命令

1
2
3
4
5
6
7
8
9
./configure --prefix=/usr \
--host=$LFS_TGT \
--build=$(build-aux/config.guess) \
--disable-static \
--docdir=/usr/share/doc/xz-5.6.2

make && make DESTDIR=$LFS install

rm -v $LFS/usr/lib/liblzma.la

运行成功后如下图所示。

4.21. Binutils 第二遍

预计时间:5分钟

运行以下几条命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
sed '6009s/$add_dir//' -i ltmain.sh

mkdir -v new_build
cd new_build

../configure \
--prefix=/usr \
--build=$(../config.guess) \
--host=$LFS_TGT \
--disable-nls \
--enable-shared \
--enable-gprofng=no \
--disable-werror \
--enable-64-bit-bfd \
--enable-new-dtags \
--enable-default-hash-style=gnu

make && make DESTDIR=$LFS install

rm -v $LFS/usr/lib/lib{bfd,ctf,ctf-nobfd,opcodes,sframe}.{a,la}

运行成功后如下图所示。

4.22. Gcc 第二遍

预计时间:30分钟

运行以下几条命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

tar -xf ../mpfr-4.2.1.tar.xz
mv -v mpfr-4.2.1 mpfr
tar -xf ../gmp-6.3.0.tar.xz
mv -v gmp-6.3.0 gmp
tar -xf ../mpc-1.3.1.tar.gz
mv -v mpc-1.3.1 mpc

case $(uname -m) in
x86_64)
sed -e '/m64=/s/lib64/lib/' \
-i.orig gcc/config/i386/t-linux64
;;
esac

sed '/thread_header =/s/@.*@/gthr-posix.h/' \
-i libgcc/Makefile.in libstdc++-v3/include/Makefile.in

mkdir -v new_build
cd new_build

../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-libsanitizer \
--disable-libssp \
--disable-libvtv \
--enable-languages=c,c++

make

make DESTDIR=$LFS install

ln -sv gcc $LFS/usr/bin/cc

运行成功后如下图所示。

5. 进⼊ Chroot 并构建其他临时⼯具

在进行下一步之前,我非常建议你创建一个快照。因为下一步如果出现错误,你可以直接恢复快照。相信如果你一步一步的做到这里了,你一定不想因为一个小错误而重头再来。

5.1 更改权限

在$LFS目录下的用户组是lfs。在进行后续的操作时,我们需要更改一下权限。在那之前,记得进入root用户。

1
2
3
4
chown --from lfs -R root:root $LFS/{usr,lib,var,etc,bin,sbin,tools}
case $(uname -m) in
x86_64) chown --from lfs -R root:root $LFS/lib64 ;;
esac

运行后的截图如下

5.2 准备虚拟内核⽂件系统

运行以下命令

1
2
3
4
5
6
7
8
9
10
11
12
mkdir -pv $LFS/{dev,proc,sys,run}
mount -v --bind /dev $LFS/dev
mount -vt devpts devpts -o gid=5,mode=0620 $LFS/dev/pts
mount -vt proc proc $LFS/proc
mount -vt sysfs sysfs $LFS/sys
mount -vt tmpfs tmpfs $LFS/run

if [ -h $LFS/dev/shm ]; then
install -v -d -m 1777 $LFS$(realpath /dev/shm)
else
mount -vt tmpfs -o nosuid,nodev tmpfs $LFS/dev/shm
fi

5.3 进入 Chroot 环境

终于到了这一步了,我们要进入chroot环境了。在这个环境下,我们可以在$LFS目录下进行操作,而不会影响到我们的主系统。

1
2
3
4
5
6
7
8
chroot "$LFS" /usr/bin/env -i \
HOME=/root \
TERM="$TERM" \
PS1='(lfs chroot) \u:\w\$ ' \
PATH=/usr/bin:/usr/sbin \
MAKEFLAGS="-j$(nproc)" \
TESTSUITEFLAGS="-j$(nproc)" \
/bin/bash --login

运行成功后如下图所示。

5.4 创建chroot的目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mkdir -pv /{boot,home,mnt,opt,srv}
mkdir -pv /etc/{opt,sysconfig}
mkdir -pv /lib/firmware
mkdir -pv /media/{floppy,cdrom}
mkdir -pv /usr/{,local/}{include,src}
mkdir -pv /usr/lib/locale
mkdir -pv /usr/local/{bin,lib,sbin}
mkdir -pv /usr/{,local/}share/{color,dict,doc,info,locale,man}
mkdir -pv /usr/{,local/}share/{misc,terminfo,zoneinfo}
mkdir -pv /usr/{,local/}share/man/man{1..8}
mkdir -pv /var/{cache,local,log,mail,opt,spool}
mkdir -pv /var/lib/{color,misc,locate}
ln -sfv /run /var/run
ln -sfv /run/lock /var/lock
install -dv -m 0750 /root
install -dv -m 1777 /tmp /var/tmp

5.5 创建必要的⽂件和符号链接

接下来我们要创建一些必要的文件和符号链接。然后添加一个root用户并且去除I have no name!的提示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
ln -sv /proc/self/mounts /etc/mtab
cat > /etc/hosts << EOF
127.0.0.1 localhost $(hostname)
::1 localhost
EOF

cat > /etc/passwd << "EOF"
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/dev/null:/usr/bin/false
daemon:x:6:6:Daemon User:/dev/null:/usr/bin/false
messagebus:x:18:18:D-Bus Message Daemon User:/run/dbus:/usr/bin/false
uuidd:x:80:80:UUID Generation Daemon User:/dev/null:/usr/bin/false
nobody:x:65534:65534:Unprivileged User:/dev/null:/usr/bin/false
EOF

cat > /etc/group << "EOF"
root:x:0:
bin:x:1:daemon
sys:x:2:
kmem:x:3:
tape:x:4:
tty:x:5:
daemon:x:6:
floppy:x:7:
disk:x:8:
lp:x:9:
dialout:x:10:
audio:x:11:
video:x:12:
utmp:x:13:
cdrom:x:15:
adm:x:16:
messagebus:x:18:
input:x:24:
mail:x:34:
kvm:x:61:
uuidd:x:80:
wheel:x:97:
users:x:999:
nogroup:x:65534:
EOF

localedef -i C -f UTF-8 C.UTF-8

echo "tester:x:101:101::/home/tester:/bin/bash" >> /etc/passwd
echo "tester:x:101:" >> /etc/group
install -o tester -d /home/tester

exec /usr/bin/bash --login

运行上方的命令后,你会看到如下图所示。

现在需要来初始化一些文件

1
2
3
4
touch /var/log/{btmp,lastlog,faillog,wtmp}
chgrp -v utmp /var/log/lastlog
chmod -v 664 /var/log/lastlog
chmod -v 600 /var/log/btmp

6. 安装基本系统软件

在这里说一句,如果系统重启了的话,再次进入chroot环境的时候,你需要重新mount一下。也就是再次挂载一下。这个刚上手的一天是绝对搞不好的。


终于来到这一步了,但是系统中还是有很多的命令是无法使用的,这就相当于一个刚出生的婴儿,什么都不会,你需要去教他怎么去做。当然,在这里就相当于我们给这个婴儿装上了一些基本的软件,让他能够做一些基本的事情。

6.1. Gettext

在正式开始安装之前,需要先将你前面所下载的文件包挂载到chroot环境中。比如我这里的文件包都在/mnt/lfs/sources下,所以我需要把这个文件夹挂载到chroot环境中。

1
mount -v --bind /mnt/lfs/sources "$LFS"/mnt

这样子在进入后,你就可以在/mnt下找到你的文件包了。直接进是没有任何东西的。直到现在我才知道平时简单的命令如果突然不见了,那是多么的不方便。

接下来开始编译gettext。先确认一下这个文件是否在/mnt下。

运行

1
2
3
4
5
./configure --disable-shared

make

cp -v gettext-tools/src/{msgfmt,msgmerge,xgettext} /usr/bin

这里只编译不安装。

成功后如下图所示。

6.2. Bison

运行

1
2
3
4
./configure --prefix=/usr \
--docdir=/usr/share/doc/bison-3.8.2

make && make install

成功后如下图所示。

6.3. Perl

运行

1
2
3
4
5
6
7
8
9
10
11
12
13

sh Configure -des \
-D prefix=/usr \
-D vendorprefix=/usr \
-D useshrplib \
-D privlib=/usr/lib/perl5/5.40/core_perl \
-D archlib=/usr/lib/perl5/5.40/core_perl \
-D sitelib=/usr/lib/perl5/5.40/site_perl \
-D sitearch=/usr/lib/perl5/5.40/site_perl \
-D vendorlib=/usr/lib/perl5/5.40/vendor_perl \
-D vendorarch=/usr/lib/perl5/5.40/vendor_perl

make && make install

成功后如下图所示。

6.4. Python

运行

1
2
3
4
5
./configure --prefix=/usr \
--enable-shared \
--without-ensurepip

make && make install

成功后如下图所示。

6.5. Texinfo

运行

1
2
3
./configure --prefix=/usr

make && make install

成功后如下图所示。

6.6. Util-linux

运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

mkdir -pv /var/lib/hwclock

./configure --libdir=/usr/lib \
--runstatedir=/run \
--disable-chfn-chsh \
--disable-login \
--disable-nologin \
--disable-su \
--disable-setpriv \
--disable-runuser \
--disable-pylibmount \
--disable-static \
--disable-liblastlog2 \
--without-python \
ADJTIME_PATH=/var/lib/hwclock/adjtime \
--docdir=/usr/share/doc/util-linux-2.40.2

make && make install

成功后如下图所示。

6.7. 清理

到这里,我们已经安装了基本的环境,接下来我们要清理一下临时文件

运行

1
2
3
4
5
rm -rf /usr/share/{info,man,doc}/*

find /usr/{lib,libexec} -name \*.la -delete

rm -rf /tools

最后一步,退出chroot环境(如果你选择使用命令行进行备份,如果不是,请直接在chroot环境下开始下一章的内容)

1
exit

另外不要忘了解除挂载的文件夹

1
2
3
mountpoint -q $LFS/dev/shm && umount $LFS/dev/shm
umount $LFS/dev/pts
umount $LFS/{sys,proc,run,dev}

非常建议在这里进行一次快照,如果你使用的是虚拟机。真机请用以下命令进行备份

1
2
cd $LFS
tar -cJpf $HOME/lfs-temp-tools-12.2.tar.xz .

恢复命令如下

1
2
3
cd $LFS
rm -rf ./* # 非常危险的命令,请注意LFS环境变量是正常的,不建议直接复制,而是一步一步来输入。非常危险!!
tar -xpf $HOME/lfs-temp-tools-12.2.tar.xz

7. 构建 LFS 系统

终于到了这里了。如果你是一步一步手动进行操作的,那么你一定会非常的开心,事实上我也是,终于来到这里了,前面的有很多次都忘记了进行备份,导致重头再来。想想都不想再来一次了。哈哈。

再次声明:我的操作皆是书上的操作。 建议和书在和此文一起看,会有很多的方便。很多地方只需要直接复制粘贴就可以了。

安装基本系统软件

在这里我们要安装基本的系统软件,这里的软件是我们在构建LFS系统时需要的软件。这里的软件是我们在构建LFS系统时需要的软件。这里的软件是我们在构建LFS系统时需要的软件。重要的事情说三遍。

记得使用root用户来运行。是在chroot下的root,不是真机root!!!

记得使用root用户来运行。是在chroot下的root,不是真机root!!!

记得使用root用户来运行。是在chroot下的root,不是真机root!!!

所有的软件包都在根目录下的sources文件夹中

所有的软件包都在根目录下的sources文件夹中

所有的软件包都在根目录下的sources文件夹中

7.1. Man-pages

运行

1
2
3
rm -v man3/crypt*

make prefix=/usr install

成功后如下图所示。

7.2 Iana-Etc

这里只需要复制一下文件就可以了。

运行

1
cp services protocols /etc

成功后如下图所示。

7.3. Glibc

进入到根目录下的sources目录中,先来运行一下打补丁的操作

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

如图所示

再依次运行进行编译,测试和安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mkdir -v t_build
cd t_build

echo "rootsbindir=/usr/sbin" > configparms

../configure --prefix=/usr \
--disable-werror \
--enable-kernel=4.19 \
--enable-stack-protector=strong \
--disable-nscd \
libc_cv_slibdir=/usr/lib

make

make check # 在测试中可能会出现几个错误,但是无伤大雅,下图是详细信息

7.3.1 install glibc

在进行上方的check后,接下来我们就可以运行make install了,不得不说,check的时间特别的久…

在这里可以看到check的结果。不用去管,我们来运行

sed '/test-installation/s@$(PERL)@echo not running@' -i ../Makefile

make install

7.3.2 install locale

虽然这一步可以省略,但是有可能在进行check的时候会出现错误,所以我们还是运行一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
localedef -i C -f UTF-8 C.UTF-8
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 el_GR -f ISO-8859-7 el_GR
localedef -i en_GB -f ISO-8859-1 en_GB
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_ES -f ISO-8859-15 es_ES@euro
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 is_IS -f ISO-8859-1 is_IS
localedef -i is_IS -f UTF-8 is_IS.UTF-8
localedef -i it_IT -f ISO-8859-1 it_IT
localedef -i it_IT -f ISO-8859-15 it_IT@euro
localedef -i it_IT -f UTF-8 it_IT.UTF-8
localedef -i ja_JP -f EUC-JP ja_JP
localedef -i ja_JP -f SHIFT_JIS ja_JP.SJIS 2> /dev/null || true
localedef -i ja_JP -f UTF-8 ja_JP.UTF-8
localedef -i nl_NL@euro -f ISO-8859-15 nl_NL@euro
localedef -i ru_RU -f KOI8-R ru_RU.KOI8-R
localedef -i ru_RU -f UTF-8 ru_RU.UTF-8
localedef -i se_NO -f UTF-8 se_NO.UTF-8
localedef -i ta_IN -f UTF-8 ta_IN.UTF-8
localedef -i tr_TR -f UTF-8 tr_TR.UTF-8
localedef -i zh_CN -f GB18030 zh_CN.GB18030
localedef -i zh_HK -f BIG5-HKSCS zh_HK.BIG5-HKSCS
localedef -i zh_TW -f UTF-8 zh_TW.UTF-8

make localedata/install-locales

localedef -i C -f UTF-8 C.UTF-8
localedef -i ja_JP -f SHIFT_JIS ja_JP.SJIS 2> /dev/null || true

7.3.3 配置glibc

创建/etc/nsswitch.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
cat > /etc/nsswitch.conf << "EOF"
# Begin /etc/nsswitch.conf
passwd: files
group: files
shadow: files
hosts: files dns
networks: files
protocols: files
services: files
ethers: files
rpc: files
# End /etc/nsswitch.conf
EOF

添加时区数据

1
2
3
4
5
6
7
8
9
10
11
12
tar -xf ../../tzdata2024a.tar.gz
ZONEINFO=/usr/share/zoneinfo
mkdir -pv $ZONEINFO/{posix,right}
for tz in etcetera southamerica northamerica europe africa antarctica \
asia australasia backward; do
zic -L /dev/null -d $ZONEINFO ${tz}
zic -L /dev/null -d $ZONEINFO/posix ${tz}
zic -L leapseconds -d $ZONEINFO/right ${tz}
done
cp -v zone.tab zone1970.tab iso3166.tab $ZONEINFO
zic -d $ZONEINFO -p America/New_York
unset ZONEINFO

在运行tzselect后,你会看到如下图所示。

输出了一个时区,你可以根据你的时区来选择。我这里选择的是Europe/Madrid。

在运行ln -sf /usr/share/zoneinfo/Europe/Madrid /etc/localtime后,你会看到如下图所示。

这说明我们已经为我们的lfs系统设置了时区。好耶!!

配置动态加载器

动态加载器是一个用于加载共享库的程序。我们需要配置一下。

1
2
3
4
5
6
7
8
9
10
11
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

下图是一张安装glibc后的我们能使用的命令。

到此为止,我们已经完成了glibc的安装。好耶!!!!

7.4. Zlib

用来解压缩文件的。

运行

1
2
3
4
5
6
7
./configure --prefix=/usr

make

make check

make install

make check的结果如下图所示。

make install的结果如下图所示。

删除一下无用的文件。

1
rm -fv /usr/lib/libz.a

7.5. Bzip2

也是用来解压缩文件的。

运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
patch -Np1 -i ../bzip2-1.0.8-install_docs-1.patch # 打补丁

sed -i 's@\(ln -s -f \)$(PREFIX)/bin/@\1@' Makefile # 确认安装的符号链接是相对

sed -i "s@(PREFIX)/man@(PREFIX)/share/man@g" Makefile

make -f Makefile-libbz2_so
make clean

make # 编译Bzip2

make PREFIX=/usr install # 安装Bzip2

cp -av libbz2.so.* /usr/lib
ln -sv libbz2.so.1.0.8 /usr/lib/libbz2.so # 共享库

cp -v bzip2-shared /usr/bin/bzip2
for i in /usr/bin/{bzcat,bunzip2}; do
ln -sfv bzip2 $i
done

rm -fv /usr/lib/libbz2.a # 删除静态库

成功后如下图所示。

下图是Bzip2的命令。

7.6. Xz

还是用来解压缩文件的。

运行

1
2
3
4
5
./configure --prefix=/usr \
--disable-static \
--docdir=/usr/share/doc/xz-5.6.2

make && make check && make install

成功后如下图所示。

命令如下

7.7 lz4

一种压缩算法。

运行

1
2
3
4
5
make BUILD_STATIC=no PREFIX=/usr

make -j1 check

make BUILD_STATIC=no PREFIX=/usr install

成功后如下图所示。

7.8. Zstd

一种实时压缩算法

运行

1
2
3
4
5
6
7
make prefix=/usr

make check # 可能会出现failed的情况,不用管。又不是fail

make prefix=/usr install # 安装

rm -v /usr/lib/libzstd.a # 删除静态库

成功后如下图所示。

7.9. File

用来检查文件类型的。

运行

1
2
3
4
5
6
7
./configure --prefix=/usr

make

make check

make install

成功后如下图所示。

7.10. Readline

运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
sed -i '/MV.*old/d' Makefile.in
sed -i '/{OLDSUFF}/c:' support/shlib-install

sed -i 's/-Wl,-rpath,[^ ]*//' support/shobj-conf

./configure --prefix=/usr \
--disable-static \
--with-curses \
--docdir=/usr/share/doc/readline-8.2.13

make SHLIB_LIBS="-lncursesw"

make SHLIB_LIBS="-lncursesw" install

install -v -m644 doc/*.{ps,pdf,html,dvi} /usr/share/doc/readline-8.2.13

7.11. M4

运行

1
2
3
./configure --prefix=/usr

make && make check && make install

成功后如下图所示。

7.12. Bc

运行

1
2
3
CC=gcc ./configure --prefix=/usr -G -O3 -r

make && make test && make install

成功后如下图所示。

7.13. Flex

运行

1
2
3
4
5
6
7
8
./configure --prefix=/usr \
--docdir=/usr/share/doc/flex-2.6.4 \
--disable-static

make && make check && make install

ln -sv flex /usr/bin/lex
ln -sv flex.1 /usr/share/man/man1/lex.1

成功后如下图所示。

7.14. tcl

Tcl 软件包包含⼯具命令语⾔,它是⼀个可靠的通⽤脚本语⾔

运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
SRCDIR=$(pwd)
cd unix
./configure --prefix=/usr \
--mandir=/usr/share/man \
--disable-rpath

make
sed -e "s|$SRCDIR/unix|/usr/lib|" \
-e "s|$SRCDIR|/usr/include|" \
-i tclConfig.sh
sed -e "s|$SRCDIR/unix/pkgs/tdbc1.1.7|/usr/lib/tdbc1.1.7|" \
-e "s|$SRCDIR/pkgs/tdbc1.1.7/generic|/usr/include|" \
-e "s|$SRCDIR/pkgs/tdbc1.1.7/library|/usr/lib/tcl8.6|" \
-e "s|$SRCDIR/pkgs/tdbc1.1.7|/usr/include|" \
-i pkgs/tdbc1.1.7/tdbcConfig.sh
sed -e "s|$SRCDIR/unix/pkgs/itcl4.2.4|/usr/lib/itcl4.2.4|" \
-e "s|$SRCDIR/pkgs/itcl4.2.4/generic|/usr/include|" \
-e "s|$SRCDIR/pkgs/itcl4.2.4|/usr/include|" \
-i pkgs/itcl4.2.4/itclConfig.sh
unset SRCDIR

make test

make install

chmod -v u+w /usr/lib/libtcl8.6.so

make install-private-headers

ln -sfv tclsh8.6 /usr/bin/tclsh

mv /usr/share/man/man3/{Thread,Tcl_Thread}.3

cd ..
tar -xf ../tcl8.6.14-html.tar.gz --strip-components=1
mkdir -v -p /usr/share/doc/tcl-8.6.14
cp -v -r ./html/* /usr/share/doc/tcl-8.6.14

成功后如下图所示。

7.15. Expect

Expect 软件包包含通过脚本控制的对话,⾃动化 telnet,ftp,passwd,fsck,rlogin,以及
tip 等交互应⽤的⼯具。Expect 对于测试这类程序也很有⽤,它简化了这类通过其他⽅式很难完成的⼯
作。DejaGnu 框架是使⽤ Expect 编写的

运行

1
python3 -c 'from pty import spawn; spawn(["echo", "ok"])' # 检测环境是否正常

应该输出OK,如图所示。如果输出不是OK,那么请检查是否已经正确了挂载devpts文件系统。

接下来运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
patch -Np1 -i ../expect-5.45.4-gcc14-1.patch

./configure --prefix=/usr \
--with-tcl=/usr/lib \
--enable-shared \
--disable-rpath \
--mandir=/usr/share/man \
--with-tclinclude=/usr/include

make

make test

make install
ln -svf expect5.45.4/libexpect5.45.4.so /usr/lib

7.16. DejaGNU

运行

1
2
3
4
5
6
7
8
9
10
11
12
13
mkdir -v build
cd build

../configure --prefix=/usr
makeinfo --html --no-split -o doc/dejagnu.html ../doc/dejagnu.texi
makeinfo --plaintext -o doc/dejagnu.txt ../doc/dejagnu.texi

make check

make install
install -v -dm755 /usr/share/doc/dejagnu-1.6.3
install -v -m644 doc/dejagnu.{html,txt} /usr/share/doc/dejagnu-1.6.3

7.17 pkg-config

运行

1
2
3
4
5
./configure --prefix=/usr \
--disable-static \
--docdir=/usr/share/doc/pkgconf-2.3.0

make && make install

7.18 Binutils

运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

mkdir -v build
cd build

../configure --prefix=/usr \
--sysconfdir=/etc \
--enable-gold \
--enable-ld=default \
--enable-plugins \
--enable-shared \
--disable-werror \
--enable-64-bit-bfd \
--enable-new-dtags \
--with-system-zlib \
--enable-default-hash-style=gnu

make tooldir=/usr

make -k check

make tooldir=/usr install

7.19. GMP

运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
./configure --prefix=/usr \
--enable-cxx \
--disable-static \
--docdir=/usr/share/doc/gmp-6.3.0

make
make html

make check 2>&1 | tee gmp-check-log

awk '/# PASS:/{total+=$3} ; END{print total}' gmp-check-log # 至少要有199个通过

make install
make install-html

7.20. MPFR

运行

1
2
3
4
5
6
7
8
9
10
11
12
./configure --prefix=/usr \
--disable-static \
--enable-thread-safe \
--docdir=/usr/share/doc/mpfr-4.2.1

make
make html

make check

make install
make install-html

7.21. MPC

运行

1
2
3
4
5
6
7
8
9
10
11
12

./configure --prefix=/usr \
--disable-static \
--docdir=/usr/share/doc/mpc-1.3.1

make
make html

make check

make install
make install-html

7.22. Attr

运行

1
2
3
4
5
6
7
8
9
10
./configure --prefix=/usr \
--disable-static \
--sysconfdir=/etc \
--docdir=/usr/share/doc/attr-2.5.2

make

make check

make install

7.23. Acl

运行

1
2
3
4
5
6
7
./configure --prefix=/usr \
--disable-static \
--docdir=/usr/share/doc/acl-2.3.2

make

make install

7.24. Libcap

运行

1
2
3
4
5
6
7
sed -i '/install -m.*STA/d' libcap/Makefile

make prefix=/usr lib=lib

make test

make prefix=/usr lib=lib install

7.25 Libxcrypt

运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
./configure --prefix=/usr \
--enable-hashes=strong,glibc \
--enable-obsolete-api=no \
--disable-static \
--disable-failure-tokens

make

make check

make install

make distclean
./configure --prefix=/usr \
--enable-hashes=strong,glibc \
--enable-obsolete-api=glibc \
--disable-static \
--disable-failure-tokens
make
cp -av --remove-destination .libs/libcrypt.so.1* /usr/lib

7.26 Shadow

运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
sed -i 's/groups$(EXEEXT) //' src/Makefile.in
find man -name Makefile.in -exec sed -i 's/groups\.1 / /' {} \;
find man -name Makefile.in -exec sed -i 's/getspnam\.3 / /' {} \;
find man -name Makefile.in -exec sed -i 's/passwd\.5 / /' {} \;

sed -e 's:#ENCRYPT_METHOD DES:ENCRYPT_METHOD YESCRYPT:' \
-e 's:/var/spool/mail:/var/mail:' \
-e '/PATH=/{s@/sbin:@@;s@/bin:@@}' \
-i etc/login.defs

touch /usr/bin/passwd
./configure --sysconfdir=/etc \
--disable-static \
--with-{b,yes}crypt \
--without-libbsd \
--with-group-name-max-length=32

make

make exec_prefix=/usr install
make -C man install-man

7.26.1 配置Shadow

启用加密

1
2
3
4
5
pwconv # 对⽤⼾密码启用加密
grpconv # 对组密码启⽤加密

mkdir -p /etc/default
useradd -D --gid 999

然后输入passwd root来设置root密码。如图所示

7.29 Gcc

我在这里系统重启了一下,所以需要重新挂载一下。如果你没有重启,那么你可以直接跳过这一步。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mount -v --bind /dev $LFS/dev
mount -vt devpts devpts -o gid=5,mode=0620 $LFS/dev/pts
mount -vt proc proc $LFS/proc
mount -vt sysfs sysfs $LFS/sys
mount -vt tmpfs tmpfs $LFS/run

if [ -h $LFS/dev/shm ]; then
install -v -d -m 1777 $LFS$(realpath /dev/shm)
else
mount -vt tmpfs -o nosuid,nodev tmpfs $LFS/dev/shm
fi #

chroot "$LFS" /usr/bin/env -i \
HOME=/root \
TERM="$TERM" \
PS1='(lfs chroot) \u:\w\$ ' \
PATH=/usr/bin:/usr/sbin \
MAKEFLAGS="-j$(nproc)" \
TESTSUITEFLAGS="-j$(nproc)" \
/bin/bash --login # 进入chroot环境

运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
case $(uname -m) in
x86_64)
sed -e '/m64=/s/lib64/lib/' \
-i.orig gcc/config/i386/t-linux64
;;
esac

mkdir -v t_build
cd t_build

../configure --prefix=/usr \
LD=ld \
--enable-languages=c,c++ \
--enable-default-pie \
--enable-default-ssp \
--enable-host-pie \
--disable-multilib \
--disable-bootstrap \
--disable-fixincludes \
--with-system-zlib

make # 这里可以添加一个-j参数,加快编译速度,比如make -j4

ulimit -s -H unlimited

sed -e '/cpython/d' -i ../gcc/testsuite/gcc.dg/plugin/plugin.exp
sed -e 's/no-pic /&-no-pie /' -i ../gcc/testsuite/gcc.target/i386/pr113689-1.c
sed -e 's/300000/(1|300000)/' -i ../libgomp/testsuite/libgomp.c-c++-common/pr109062.c
sed -e 's/{ target nonpic } //' \
-e '/GOTPCREL/d' -i ../gcc/testsuite/gcc.target/i386/fentryname3.c

chown -R tester .
su tester -c "PATH=$PATH make -k check"

../contrib/test_summary

make install # 这里可以加上time,来查看编译的时间,比如time make install.

install的结果如下图所示。

接下来改变一下目录的所有权为root

使用ls -ld命令可以看到所有权目前为tester,我们需要改变为root。

1
2
3
4
ls -ld /usr/lib/gcc/$(gcc -dumpmachine)/14.2.0/include{,-fixed} # 查看所有权

chown -v -R root:root \
/usr/lib/gcc/$(gcc -dumpmachine)/14.2.0/include{,-fixed} # 改变所有权

在接下来需要链接一下文件

运行

1
2
3
4
5
6
ln -svr /usr/bin/cpp /usr/lib

ln -sv gcc.1 /usr/share/man/man1/cc.1

ln -sfv ../../libexec/gcc/$(gcc -dumpmachine)/14.2.0/liblto_plugin.so \
/usr/lib/bfd-plugins/

如果一切正常,那么在运行测试的时候你会看见如下图所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
echo 'int main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'

grep -E -o '/usr/lib.*/S?crt[1in].*succeeded' dummy.log

grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'

grep -B4 '^ /usr/include' dummy.log

grep found dummy.log

grep "/lib.*/libc.so.6 " dummy.log

一切正常,删除一些无用的文件。

1
rm -v dummy.c a.out dummy.log

移动一个文件到正确的位置。

1
2
mkdir -pv /usr/share/gdb/auto-load/usr/lib
mv -v /usr/lib/*gdb.py /usr/share/gdb/auto-load/usr/lib

**至此,我们已经完成了gcc的安装。好耶!!
**

7.3 Ncurses

运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
./configure --prefix=/usr \
--mandir=/usr/share/man \
--with-shared \
--without-debug \
--without-normal \
--with-cxx-shared \
--enable-pc-files \
--with-pkg-config-libdir=/usr/lib/pkgconfig

make

make DESTDIR=$PWD/dest install
install -vm755 dest/usr/lib/libncursesw.so.6.5 /usr/lib
rm -v dest/usr/lib/libncursesw.so.6.5
sed -e 's/^#if.*XOPEN.*$/#if 1/' \
-i dest/usr/include/curses.h
cp -av dest/* /

for lib in ncurses form panel menu ; do
ln -sfv lib${lib}w.so /usr/lib/lib${lib}.so
ln -sfv ${lib}w.pc /usr/lib/pkgconfig/${lib}.pc
done

ln -sfv libncursesw.so /usr/lib/libcurses.so

成功后如下图所示。

7.31 Sed

运行

1
2
3
4
5
6
7
8
9
10
./configure --prefix=/usr

make && make html

chown -R tester .
su tester -c "PATH=$PATH make check"

make install
install -d -m755 /usr/share/doc/sed-4.9
install -m644 doc/sed.html /usr/share/doc/sed-4.9

7.32 Psmisc

运行

1
2
3
./configure --prefix=/usr

make && make install

7.33 Gettext

运行

1
2
3
4
5
6
7
8
./configure --prefix=/usr \
--disable-static \
--docdir=/usr/share/doc/gettext-0.22.5

make

make install
chmod -v 0755 /usr/lib/preloadable_libintl.so

7.34 Bison

运行

1
2
3
4
5
6
7
./configure --prefix=/usr --docdir=/usr/share/doc/bison-3.8.2

make

make check # 如果你想要进行测试的话

make install

7.35 Grep

运行

1
2
3
4
5
sed -i "s/echo/#echo/" src/egrep.sh

./configure --prefix=/usr

make && make install

7.36 Bash

运行

1
2
3
4
5
6
7
8
9
10

./configure --prefix=/usr \
--without-bash-malloc \
--with-installed-readline \
bash_cv_strtold_broken=no \
--docdir=/usr/share/doc/bash-5.2.32

make && make install

exec /usr/bin/bash --login

7.37 Libtool

运行

1
2
3
4
5
./configure --prefix=/usr

make && make install

rm -fv /usr/lib/libltdl.a

7.38 GDBM

运行

1
2
3
4
5
./configure --prefix=/usr \
--disable-static \
--enable-libgdbm-compat

make && make install

7.39 Gperf

运行

1
2
3
./configure --prefix=/usr --docdir=/usr/share/doc/gperf-3.1

make && make install

7.40 Expat

1
2
3
4
5
./configure --prefix=/usr \
--disable-static \
--docdir=/usr/share/doc/expat-2.6.2

make && make install

7.41 Inetutils

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sed -i 's/def HAVE_TERMCAP_TGETENT/ 1/' telnet/telnet.c

./configure --prefix=/usr \
--bindir=/usr/bin \
--localstatedir=/var \
--disable-logger \
--disable-whois \
--disable-rcp \
--disable-rexec \
--disable-rlogin \
--disable-rsh \
--disable-servers

make
make install

mv -v /usr/{,s}bin/ifconfig

7.42 less

1
2
3
./configure --prefix=/usr --sysconfdir=/etc

make && make install

7.43 Perl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
export BUILD_ZLIB=False
export BUILD_BZIP2=0

sh Configure -des \
-D prefix=/usr \
-D vendorprefix=/usr \
-D privlib=/usr/lib/perl5/5.40/core_perl \
-D archlib=/usr/lib/perl5/5.40/core_perl \
-D sitelib=/usr/lib/perl5/5.40/site_perl \
-D sitearch=/usr/lib/perl5/5.40/site_perl \
-D vendorlib=/usr/lib/perl5/5.40/vendor_perl \
-D vendorarch=/usr/lib/perl5/5.40/vendor_perl \
-D man1dir=/usr/share/man/man1 \
-D man3dir=/usr/share/man/man3 \
-D pager="/usr/bin/less -isR" \
-D useshrplib \
-D usethreads

make
make install
unset BUILD_ZLIB BUILD_BZIP2

7.44 XML::Parser

1
2
3
perl Makefile.PL

make && make install

7.45 Intltool

1
2
3
4
5
6
7
sed -i 's:\\\${:\\\$\\{:' intltool-update.in

./configure --prefix=/usr

make
make install
install -v -Dm644 doc/I18N-HOWTO /usr/share/doc/intltool-0.51.0/I18N-HOWTO

7.46 Autoconf

1
2
3
./configure --prefix=/usr

make && make install

7.47 Automake

1
2
3
4
./configure --prefix=/usr --docdir=/usr/share/doc/automake-1.17

make
make install

7.48 openssl

1
2
3
4
5
6
7
8
9
10
11
12
13
./config --prefix=/usr \
--openssldir=/etc/ssl \
--libdir=lib \
shared \
zlib-dynamic

make

sed -i '/INSTALL_LIBS/s/libcrypto.a libssl.a//' Makefile
make MANSUFFIX=ssl install

mv -v /usr/share/doc/openssl /usr/share/doc/openssl-3.3.1
cp -vfr doc/* /usr/share/doc/openssl-3.3.1

7.49 Kmod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
./configure --prefix=/usr \
--sysconfdir=/etc \
--with-openssl \
--with-xz \
--with-zstd \
--with-zlib \
--disable-manpages

make
make install

for target in depmod insmod modinfo modprobe rmmod; do
ln -sfv ../bin/kmod /usr/sbin/$target
rm -fv /usr/bin/$target
done

7.50 Elfutils

1
2
3
4
5
6
7
8
9
./configure --prefix=/usr \
--disable-debuginfod \
--enable-libdebuginfod=dummy

make

make -C libelf install
install -vm644 config/libelf.pc /usr/lib/pkgconfig
rm /usr/lib/libelf.a

7.51 Libffi

1
2
3
4
5
6
./configure --prefix=/usr \
--disable-static \
--with-gcc-arch=native

make
make install

7.52 python

1
2
3
4
5
6
7
./configure --prefix=/usr \
--enable-shared \
--with-system-expat \
--enable-optimizations

make
make install

如果想要禁止一些pip3的信息,可以使用来进行

1
2
3
4
5
cat > /etc/pip.conf << EOF
[global]
root-user-action = ignore
disable-pip-version-check = true
EOF

7.53 Flit-core

1
2
3
pip3 wheel -w dist --no-cache-dir --no-build-isolation --no-deps $PWD

pip3 install --no-index --no-user --find-links dist flit_core

7.54 wheel

1
2
3
pip3 wheel -w dist --no-cache-dir --no-build-isolation --no-deps $PWD

pip3 install --no-index --find-links=dist wheel

7.55 setuptools

1
2
3
pip3 wheel -w dist --no-cache-dir --no-build-isolation --no-deps $PWD

pip3 install --no-index --find-links dist setuptools

7.56 Ninja

1
2
3
4
5
python3 configure.py --bootstrap

install -vm755 ninja /usr/bin/
install -vDm644 misc/bash-completion /usr/share/bash-completion/completions/ninja
install -vDm644 misc/zsh-completion /usr/share/zsh/site-functions/_ninja

7.57 Meson

1
2
3
4
5
pip3 wheel -w dist --no-cache-dir --no-build-isolation --no-deps $PWD

pip3 install --no-index --find-links dist meson
install -vDm644 data/shell-completions/bash/meson /usr/share/bash-completion/completions/meson
install -vDm644 data/shell-completions/zsh/_meson /usr/share/zsh/site-functions/_meson

7.58 Coreutils

Coreutils 在make的时候要求aclocal的版本为1.16,但是前面在安装automake的时候安装的是1.17。这里应该就是书中的错误了。所以我们需要重新安装automake,这里是1.16的网址,先退出chroot环境在进入root环境下的LFS目录下的sources中用wget下载,在进入chroot就能看见了。

重新安装automake1.16

1
2
3
./configure --prefix=/usr --docdir=/usr/share/doc/automake-1.16
make
make install

下面是安装coreutils的命令

patch -Np1 -i ../coreutils-9.5-i18n-2.patch # 这个补丁好像是有一个bug,我这里尝试构建了好几次但是都没有成功,后来我想着不打这个补丁试试,结果成功了。

1
2
3
4
5
6
7
8
9
10
11
12
autoreconf -fiv
FORCE_UNSAFE_CONFIGURE=1 ./configure \
--prefix=/usr \
--enable-no-install-program=kill,uptime

make

make install

mv -v /usr/bin/chroot /usr/sbin
mv -v /usr/share/man/man1/chroot.1 /usr/share/man/man8/chroot.8
sed -i 's/"1"/"8"/' /usr/share/man/man8/chroot.8

7.59 Check

1
2
3
4
5
./configure --prefix=/usr --disable-static

make

make docdir=/usr/share/doc/check-0.15.2 install

7.60 Diffutils

1
2
3
4
5
./configure --prefix=/usr

make

make install

7.61 Gawk

1
2
3
4
5
6
sed -i 's/extras//' Makefile.in
./configure --prefix=/usr

make
rm -f /usr/bin/gawk-5.3.0
make install

7.62 Findutils

1
2
3
4
5
./configure --prefix=/usr --localstatedir=/var/lib/locate

make

make install

7.63 Groff

1
2
3
4
5
6

PAGE=A4 ./configure --prefix=/usr

make

make install

7.64 GRUB

1
2
3
4
5
6
7
8
9
10
11
12
13
unset {C,CPP,CXX,LD}FLAGS

echo depends bli part_gpt > grub-core/extra_deps.lst

./configure --prefix=/usr \
--sysconfdir=/etc \
--disable-efiemu \
--disable-werror

make

make install
mv -v /etc/bash_completion.d/grub /usr/share/bash-completion/completions

7.65 gzip

1
2
3
4
5
./configure --prefix=/usr

make

make install

7.66 IPRoute2

1
2
3
4
5
6
sed -i /ARPD/d Makefile
rm -fv man/man8/arpd.8

make NETNS_RUN_DIR=/run/netns

make SBINDIR=/usr/sbin install

7.67 Kbd

1
2
3
4
5
6
7
8
9
10
patch -Np1 -i ../kbd-2.6.4-backspace-1.patch

sed -i '/RESIZECONS_PROGS=/s/yes/no/' configure
sed -i 's/resizecons.8 //' docs/man/man8/Makefile.in

./configure --prefix=/usr --disable-vlock

make

make install

7.68 libpipeline

1
2
3
4
5
./configure --prefix=/usr

make

make install

7.69 Make

1
2
3
4
5
./configure --prefix=/usr

make

make install

7.70 patch

1
2
3
4
5
./configure --prefix=/usr

make

make install

7.71 tar

1
2
3
4
5
6
7
FORCE_UNSAFE_CONFIGURE=1 \
./configure --prefix=/usr

make

make install
make -C doc install-html docdir=/usr/share/doc/tar-1.35

7.72 Texinfo

1
2
3
4
5
./configure --prefix=/usr

make

make install

7.73 vim

1
2
3
4
5
6
7
8
9
10
11
12
13
14
echo '#define SYS_VIMRC_FILE "/etc/vimrc"' >> src/feature.h

./configure --prefix=/usr

make

make install

ln -sv vim /usr/bin/vi
for L in /usr/share/man/{,*/}man1/vim.1; do
ln -sv vim.1 $(dirname $L)/vi.1
done # 这里是为了让vi也能使用vim的man手册

ln -sv ../vim/vim91/doc /usr/share/doc/vim-9.1.0660

7.731 配置vim

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cat > /etc/vimrc << "EOF"
" Begin /etc/vimrc
" Ensure defaults are set before customizing settings, not after
source $VIMRUNTIME/defaults.vim
let skip_defaults_vim=1
set nocompatible
set backspace=2
set mouse=
syntax on
if (&term == "xterm") || (&term == "putty")
set background=dark
endif
" End /etc/vimrc
EOF

7.74 MarkupSafe

1
2
3
pip3 wheel -w dist --no-cache-dir --no-build-isolation --no-deps $PWD

pip3 install --no-index --no-user --find-links dist Markupsafe

7.75 Jinja2

1
2
3
pip3 wheel -w dist --no-cache-dir --no-build-isolation --no-deps $PWD

pip3 install --no-index --no-user --find-links dist Jinja2

7.76 Systemd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
sed -i -e 's/GROUP="render"/GROUP="video"/' \
-e 's/GROUP="sgx", //' rules.d/50-udev-default.rules.in

sed '/systemd-sysctl/s/^/#/' -i rules.d/99-systemd.rules.in

sed '/NETWORK_DIRS/s/systemd/udev/' -i src/basic/path-lookup.h

mkdir -p build
cd build
meson setup .. \
--prefix=/usr \
--buildtype=release \
-D mode=release \
-D dev-kvm-mode=0660 \
-D link-udev-shared=false \
-D logind=false \
-D vconsole=false # 在安装这个时候会有个报错,这时候要先安装Util-linux(7.79)再返回安装这个

ninja udevadm systemd-hwdb \
$(ninja -n | grep -Eo '(src/(lib)?udev|rules.d|hwdb.d)/[^ ]*') \
$(realpath libudev.so --relative-to .) \
$udev_helpers

install -vm755 -d {/usr/lib,/etc}/udev/{hwdb.d,rules.d,network}
install -vm755 -d /usr/{lib,share}/pkgconfig
install -vm755 udevadm /usr/bin/
install -vm755 systemd-hwdb /usr/bin/udev-hwdb
ln -svfn ../bin/udevadm /usr/sbin/udevd
cp -av libudev.so{,*[0-9]} /usr/lib/
install -vm644 ../src/libudev/libudev.h /usr/include/
install -vm644 src/libudev/*.pc /usr/lib/pkgconfig/
install -vm644 src/udev/*.pc /usr/share/pkgconfig/
install -vm644 ../src/udev/udev.conf /etc/udev/
install -vm644 rules.d/* ../rules.d/README /usr/lib/udev/rules.d/
install -vm644 $(find ../rules.d/*.rules \
-not -name '*power-switch*') /usr/lib/udev/rules.d/
install -vm644 hwdb.d/* ../hwdb.d/{*.hwdb,README} /usr/lib/udev/hwdb.d/
install -vm755 $udev_helpers /usr/lib/udev
install -vm644 ../network/99-default.link /usr/lib/udev/network

tar -xvf ../../udev-lfs-20230818.tar.xz
make -f udev-lfs-20230818/Makefile.lfs install

tar -xf ../../systemd-man-pages-256.4.tar.xz \
--no-same-owner --strip-components=1 \
-C /usr/share/man --wildcards '*/udev*' '*/libudev*' \
'*/systemd.link.5' \
'*/systemd-'{hwdb,udevd.service}.8
sed 's|systemd/network|udev/network|' \
/usr/share/man/man5/systemd.link.5 \
> /usr/share/man/man5/udev.link.5
sed 's/systemd\(\\\?-\)/udev\1/' /usr/share/man/man8/systemd-hwdb.8 \
> /usr/share/man/man8/udev-hwdb.8
sed 's|lib.*udevd|sbin/udevd|' \
/usr/share/man/man8/systemd-udevd.service.8 \
> /usr/share/man/man8/udevd.8
rm /usr/share/man/man*/systemd*

unset udev_helpers

7.77 Man-DB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
./configure --prefix=/usr \
--docdir=/usr/share/doc/man-db-2.12.1 \
--sysconfdir=/etc \
--disable-setuid \
--enable-cache-owner=bin \
--with-browser=/usr/bin/lynx \
--with-vgrind=/usr/bin/vgrind \
--with-grap=/usr/bin/grap \
--with-systemdtmpfilesdir= \
--with-systemdsystemunitdir=

make

make install

7.78 Procps-ng

1
2
3
4
5
6
7
8
./configure --prefix=/usr \
--docdir=/usr/share/doc/procps-ng-4.0.4 \
--disable-static \
--disable-kill

make

make install

7.79 Util-linux

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
./configure --bindir=/usr/bin \
--libdir=/usr/lib \
--runstatedir=/run \
--sbindir=/usr/sbin \
--disable-chfn-chsh \
--disable-login \
--disable-nologin \
--disable-su \
--disable-setpriv \
--disable-runuser \
--disable-pylibmount \
--disable-liblastlog2 \
--disable-static \
--without-python \
--without-systemd \
--without-systemdsystemunitdir \
ADJTIME_PATH=/var/lib/hwclock/adjtime \
--docdir=/usr/share/doc/util-linux-2.40.2

make
make install

7.80 E2fsprogs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mkdir -v build
cd build

../configure --prefix=/usr \
--sysconfdir=/etc \
--enable-elf-shlibs \
--disable-libblkid \
--disable-libuuid \
--disable-uuidd \
--disable-fsck

make

make install

rm -fv /usr/lib/{libcom_err,libe2p,libext2fs,libss}.a

gunzip -v /usr/share/info/libext2fs.info.gz
install-info --dir-file=/usr/share/info/dir /usr/share/info/libext2fs.info

7.81 Sysklogd

1
2
3
4
5
6
7
8
./configure --prefix=/usr \
--sysconfdir=/etc \
--runstatedir=/run \
--without-logger

make

make install
1
2
3
4
5
6
7
8
9
10
11
12
13
cat > /etc/syslog.conf << "EOF"
# Begin /etc/syslog.conf
auth,authpriv.* -/var/log/auth.log
*.*;auth,authpriv.none -/var/log/sys.log
daemon.* -/var/log/daemon.log
kern.* -/var/log/kern.log
mail.* -/var/log/mail.log
user.* -/var/log/user.log
*.emerg *
# Do not open any internet ports.
secure_mode 2
# End /etc/syslog.conf
EOF

7.82 Sysvinit

1
2
3
4
5
patch -Np1 -i ../sysvinit-3.10-consolidated-1.patch

make

make install

到此为止,我们已经结束了所有软件包的安装,接下来我们很快就可以进入我们的系统了!!


7.83 清理垃圾

1
2
3
4
rm -rf /tmp/{*,.*}
find /usr/lib /usr/libexec -name \*.la -delete
find /usr -depth -name $(uname -m)-lfs-linux-gnu\* | xargs rm -rf
userdel -r tester

8 配置系统

8.1 安装lfs-bootscripts

make install

8.2 配置系统主机名

1
echo "LFS" > /etc/hostname

8.3 配置 SysVinit

在linux系统进行开机的时候,会首先运行init程序,然后init程序会根据/etc/inittab文件的内容来启动系统的各种服务。在LFS中,我们使用的是SysVinit,所以我们需要配置一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
cat > /etc/inittab << "EOF"
# Begin /etc/inittab
id:3:initdefault:
si::sysinit:/etc/rc.d/init.d/rc S
l0:0:wait:/etc/rc.d/init.d/rc 0
l1:S1:wait:/etc/rc.d/init.d/rc 1
l2:2:wait:/etc/rc.d/init.d/rc 2
l3:3:wait:/etc/rc.d/init.d/rc 3
l4:4:wait:/etc/rc.d/init.d/rc 4
l5:5:wait:/etc/rc.d/init.d/rc 5
l6:6:wait:/etc/rc.d/init.d/rc 6
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
su:S06:once:/sbin/sulogin
s1:1:respawn:/sbin/sulogin
1:2345:respawn:/sbin/agetty --noclear tty1 9600
2:2345:respawn:/sbin/agetty tty2 9600
3:2345:respawn:/sbin/agetty tty3 9600
4:2345:respawn:/sbin/agetty tty4 9600
5:2345:respawn:/sbin/agetty tty5 9600
6:2345:respawn:/sbin/agetty tty6 9600
# End /etc/inittab
EOF

8.4 配置时区

输入hwclock如果出现的是当前时间,那么就不需要配置时区,虚拟机已经为我们准备好了,但是如果想要修改的话,可以使用下面的命令。

UTC=1表示硬件时钟是UTC时间,你也可以修改为其他值

1
2
3
4
5
6
7
8
cat > /etc/sysconfig/clock << "EOF"
# Begin /etc/sysconfig/clock
UTC=1
# Set this to any options you might need to give to hwclock,
# such as machine hardware clock type for Alphas.
CLOCKPARAMS=
# End /etc/sysconfig/clock
EOF

8.5 配置系统Locale

本地语⾔⽀持需要⼀些环境变量。正确设定它们可以带来以下好处:

  • 程序输出被翻译成本地语⾔

  • 字符被正确分类为字⺟、数字和其他类别,这对于使 bash 正确接受命令⾏中的⾮ ASCII 本地⾮英⽂字符来说是必要的

  • 根据所在地区惯例排序字⺟

  • 适⽤于所在地区的默认纸张尺⼨

  • 正确格式化货币、时间和⽇期值

这里我将使用zh_CN.UTF-8作为我的locale,你可以根据自己的需要进行修改。(locale -a可以查看系统支持的locale)

1
2
3
4
5
LC_ALL=zh_CN.UTF-8 locale charmap
LC_ALL=zh_CN.UTF-8 locale language
LC_ALL=zh_CN.UTF-8 locale charmap
LC_ALL=zh_CN.UTF-8 locale int_curr_symbol
LC_ALL=zh_CN.UTF-8 locale int_prefix

再运行

1
2
3
4
5
6
7
8
9
10
11
12
cat > /etc/profile << "EOF"
# Begin /etc/profile
for i in $(locale); do
unset ${i%=*}
done
if [[ "$TERM" = linux ]]; then
export LANG=C.UTF-8
else
export LANG=en_US.UTF-8
fi
# End /etc/profile
EOF

8.6 创建 /etc/inputrc ⽂件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
cat > /etc/inputrc << "EOF"
# Begin /etc/inputrc
# Modified by Chris Lynn <[email protected]>
# Allow the command prompt to wrap to the next line
set horizontal-scroll-mode Off
# Enable 8-bit input
set meta-flag On
set input-meta On
# Turns off 8th bit stripping
set convert-meta Off
# Keep the 8th bit for display
set output-meta On
# none, visible or audible
set bell-style none
# All of the following map the escape sequence of the value
# contained in the 1st argument to the readline specific functions
"\eOd": backward-word
"\eOc": forward-word
# for linux console
"\e[1~": beginning-of-line
"\e[4~": end-of-line
"\e[5~": beginning-of-history
"\e[6~": end-of-history
"\e[3~": delete-char
"\e[2~": quoted-insert
# for xterm
"\eOH": beginning-of-line
"\eOF": end-of-line
# for Konsole
"\e[H": beginning-of-line
"\e[F": end-of-line
# End /etc/inputrc
EOF

8.7 创建 /etc/shells ⽂件

1
2
3
4
5
6
cat > /etc/shells << "EOF"
# Begin /etc/shells
/bin/sh
/bin/bash
# End /etc/shells
EOF

9 系统引导

9.1 创建 /etc/fstab ⽂件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cat > /etc/fstab << "EOF"
# Begin /etc/fstab
# 文件系统 挂载点 类型 选项 转储 检查顺序
/dev/sda3 / ext4 defaults 1 1
/dev/sda5 swap swap pri=1 0 0
proc /proc proc nosuid,noexec,nodev 0 0
sysfs /sys sysfs nosuid,noexec,nodev 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
tmpfs /run tmpfs defaults 0 0
devtmpfs /dev devtmpfs mode=0755,nosuid 0 0
tmpfs /dev/shm tmpfs nosuid,nodev 0 0
cgroup2 /sys/fs/cgroup cgroup2 nosuid,noexec,nodev 0 0
# End /etc/fstab
EOF

9.2 配置内核

9.2.1 安装内核

建议先保存快照,一步做错从头再来。

我要开始了,注意每一个字,都非常的重要

如果sources目录中含有linux-版本号文件夹,删掉,重新解压,再cd进去。
进入之后,先运行make defconfig, 再运行make menuconfig,然后再运行make,最后再运行make modules_install

这里有一个点非常的重要,因为我们的LFS是安装在虚拟机上面的,所以我们的内核配置要修改一下下。下方是需要修改的地方。此界面在运行make menuconfig之后会出现。

除了上方的修改之外,还需要修改下方的地方。一般来讲,只要先运行了make defconfig后,只需要再修改一下下方的地方就可以了。如果出现错误,建议重新设置。

  • Device Drivers, Generic Driver Options, Maintain a devtmpfs filesystem to mount at /dev

  • Device Drivers, Network device support, Ethernet Driver support, AMD PCnet32 PCI support

  • Device Drivers, Fusion MPT device support (select the three drivers for SPI, FC, SAS)

  • Device Drivers, SCSI device support, SCSI low-level drivers

  • File Systems, Ext3 Journaling file system support

修改好了之后,我们就可以运行make了,这个过程会非常的漫长,所以请耐心等待。

运行完了之后,我们就可以运行make modules_install了,这个过程会非常的快,所以不用担心。再之后需要运行

1
2
3
4
cp -iv arch/x86/boot/bzImage /boot/vmlinuz-6.10.5-lfs-12.2
cp -iv System.map /boot/System.map-6.10.5
cp -iv .config /boot/config-6.10.5
cp -r Documentation -T /usr/share/doc/linux-6.10.5

上方的命令是将内核的一些文件复制到了/boot目录下,这样我们就可以引导了。

9.2.2 Grub

之后开始修改引导文件,也就是grub

grub-install /dev/sda 在运行完这条命令后,会覆盖当前的引导,也就是系统在启动页面不会有宿主系统的引导了,只有LFS的引导了。

复制下方的命令,然后运行,这样就可以修改grub的引导了。如果你是跟着我一步一步来的,那么这个引导文件就是你的引导文件了。反之,你需要修改root的值。因为我的root是在sda3上的,所以我这里的root是/dev/sda3,你需要根据自己的情况来修改。

1
2
3
4
5
6
7
8
9
10
11
cat > /boot/grub/grub.cfg << "EOF"
# Begin /boot/grub/grub.cfg
set default=0
set timeout=5
insmod part_gpt
insmod ext2
set root=(hd0,3)
menuentry "GNU/Linux, Linux 6.10.5-lfs-12.2" {
linux /boot/vmlinuz-6.10.5-lfs-12.2 root=/dev/sda3 ro
}
EOF

一般到这步就可以直接重启了,蛮激动人心的不是吗?但是如果你想要进行一些额外的配置可以运行下方的命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
echo 12.2 > /etc/lfs-release

cat > /etc/lsb-release << "EOF"
DISTRIB_ID="Linux From Scratch"
DISTRIB_RELEASE="12.2"
DISTRIB_CODENAME="Liu_Yangfeng"
DISTRIB_DESCRIPTION="Linux From Scratch"
EOF

cat > /etc/os-release << "EOF"
NAME="Linux From Scratch"
VERSION="12.2"
ID=lfs
PRETTY_NAME="Linux From Scratch 12.2"
VERSION_CODENAME="Liu_Yangfeng"
HOME_URL="https://www.linuxfromscratch.org/lfs/"
EOF

最后重启就能直接进入LFS了。用户名是root,密码是你设置的密码。

10 结束语

到此为止,我们已经完成了整个LFS的安装,这个过程非常的漫长,但是也非常的有趣。在这个过程中,我们学到了很多的知识,也锻炼了我们的耐心。从小就听到Linux,但是一直不知道Linux是怎么来的,现在我们通过LFS的安装,我们知道了Linux是怎么来的,也知道了Linux是怎么运行的。这个过程非常的有趣,也非常的有意义。


从零开始搭建一个Linux系统
http://example.com/2024/09/22/从零开始搭建一个Linux系统/
作者
OneWhiteThree
发布于
2024年9月22日
许可协议