- 创建者: 虚拟的现实,上次更新时间:5月 06, 2025 需要 7 分钟阅读时间
简介
LFS是Linux From Scratch的简称,LFS 存在的一个重要原因是可以帮助人们学习 linux 系统内部是如何工作的。构建一个 LFS 系统会帮助演示是什么使 linux 运转,各种组件如何在一起互相依赖的工作。最好的事情之一通过这种学习可以获得完全根据自己的需求定制 linux 系统的能力。
LFS 的一个关键的好处是它让用户对于系统有更多的控制,而不是依赖于他人的 linux 实现。在 LFS 的世界里,你自己坐在司机的位置,掌控系统的每一个细节,比如目录布局和启动脚本配置等等。你也能掌控在哪里、为何、以及怎样安装每一个程序。有关LFS相关的资料可以去这个链接中查找:http://www.linuxfromscratch.org
环境配置
项目 | 软件 | CPU | 内存 | 硬盘 | 网络 | 备注 |
---|---|---|---|---|---|---|
虚拟机软件 | VirtualBox7.1.6 | 2 | 4 | 50+20 | NAT | 映射端口访问 |
宿主机 | Windows11 | i3-9100 | 16 | 1T | ||
虚拟机系统 | Debian12 | 最小化安装 |
- 虚拟机 50G 硬盘为 Debian12 的硬盘,20G硬盘为 LFS 的目标硬盘
- 参照 https://wiki.waringid.me/x/PgAS 完成 Debian 系统安装和镜像源配置
- 将新建用户 lf 加入 sudo 组。usermod -aG sudo lf
- 安装基础的开发组件
- 检查相关组件是否符合 LFS 项目的要求
sudo apt install -y build-essential vim sudo apt install -y autoconf automake gdb libffi-dev zlib1g-dev libssl-dev git wget
cat > version-check.sh << "EOF" #!/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 5.4 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 EOF sudo bash version-check.sh
针对上述检查结果补齐没有安装的组件
sudo apt install bison gawk texinfo
磁盘分区及格式
20G 为 LFS 的目标磁盘,共分3个区
- sdb1 规划 300M ,目标格式 ext2 用于挂载启动分区 /boot
- sdb2 规划 1G,用作交换分区
- sdb3 规划剩余的空间,分区格式:ext4,挂载根分区
sudo mkfs -v -t ext2 /dev/sdb1 sudo mkswap /dev/sdb2 sudo mkfs -v -t ext4 /dev/sdb3
下载软件包
- 创建软件包的存储目录
- 下载对应的软件包
- 软件包的下载地址文件 https://www.linuxfromscratch.org/lfs/view/stable/wget-list-sysv
- 软件包的 md5 校验文件 https://www.linuxfromscratch.org/lfs/view/stable/md5sums
- 如果存在无法下载的软件包可以参考国内镜像网站 https://mirrors.ustc.edu.cn/lfs/lfs-packages/12.3/
- 验证软件包的 md5 值,确保软件包数量一致
export LFS=/mnt/lfs echo $LFS sudo mkdir -pv $LFS sudo mount -v -t ext4 /dev/sdb3 $LFS sudo chown root:root $LFS sudo chmod 755 $LFS wget https://www.linuxfromscratch.org/lfs/view/stable/wget-list-sysv wget https://www.linuxfromscratch.org/lfs/view/stable/md5sums sudo mv md5sums $LFS/sources/ vim wget-list-sysv sudo mkdir -pv $LFS/sources sudo chmod -v a+wt $LFS/sources/ sudo wget --input-file=wget-list-sysv --continue --directory-prefix=$LFS/sources/ pushd $LFS/sources/ sudo md5sum -c md5sums popd
创建文件目录布局
以下操作通过 root 用户操作
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
添加 LFS 用户并配置用户环境
groupadd lfs useradd -s /bin/bash -g lfs -m -k /dev/null lfs passwd lfs chown -v lfs $LFS/{usr{,/*},var,etc,tools} case $(uname -m) in x86_64) chown -v lfs $LFS/lib64 ;; esac su - lfs cat > ~/.bash_profile << "EOF" exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash EOF 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 source ~/.bash_profile
- LFS_TGT=$(uname -m)-lfs-linux-gnu。LFS_TGT变量设定了一个非默认,但与宿主系统兼容的机器描述符。该描述符被用于构建交叉编译器和交叉编译临时工具链。
- set +h。set +h 命令关闭 bash 的散列功能。一般情况下,散列是很有用的 —— bash 使用一个散列表维护各个可执行文件的完整路径,这样就不用每次都在 PATH 指定的目录中搜索可执行文件。然而,在构建 LFS 时,我们希望总是使用最新安装的工具。关闭散列功能强制 shell 在运行程序时总是搜索 PATH。这样,一旦$LFS/tools/bin 中有新的工具可用,shell 就能够找到它们,而不是使用之前记忆在散列表中,由宿主发行版提供的 /usr/bin 或 /bin 中的工具。
- 将 umask 设定为 022,保证只有文件所有者可以写新创建的文件和目录,但任何人都可读取或搜索 (仅针对目录) 它们
编译交叉工具链
构建临时编译环境前需要确认 LFS 环境变量是否配置正确,并确保使用 lfs 用户登入且已经进入 sources 目录
su - lfs export LFS=/mnt/lfs echo $LFS cd $LFS/sources/ mkdir -v build
Binutils-2.44 第一遍
tar Jxvf binutils-2.44.tar.xz cd $LFS/sources/build ..//binutils-2.44/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 make make install
GCC-14.2.0 第一遍
tar Jxvf gcc-14.2.0.tar.xz cd gcc-14.2.0 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 mkdir -v build cd build ../configure \ --target=$LFS_TGT \ --prefix=$LFS/tools \ --with-glibc-version=2.41 \ --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++ 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
Linux-6.13.4 API 头文件
tar xf linux-6.13.4.tar.xz cd linux-6.13.4 make mrproper make headers find usr/include -type f ! -name '*.h' -delete cp -rv usr/include $LFS/usr
Glibc-2.41
tar xf glibc-2.41.tar.xz cd glibc-2.41 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 patch -Np1 -i ../glibc-2.41-fhs-1.patch mkdir -v build cd build echo "rootsbindir=/usr/sbin" > configparms ../configure \ --prefix=/usr \ --host=$LFS_TGT \ --build=$(../scripts/config.guess) \ --enable-kernel=5.4 \ --with-headers=$LFS/usr/include \ --disable-nscd \ libc_cv_slibdir=/usr/lib 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
如果一切正常,那么应该没有错误消息,而且最后一行命令应该输出下列格式的内容:
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
GCC-14.2.0 中的 Libstdc++
Libstdc++ 是 C++ 标准库。我们需要它才能编译 C++ 代码 (GCC 的一部分用 C++ 编写)。但在构建第一遍的 GCC时我们不得不暂缓安装它,因为 Libstdc++ 依赖于当时还没有安装到目标目录的 Glibc。
cd gcc-14.2.0 cd build ../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 rm -v $LFS/usr/lib/lib{stdc++{,exp,fs},supc++}.la
交叉编译临时工具
使用刚刚构建的交叉工具链对基本工具进行交叉编译。这些工具会被安装到它们的最终位置,但现在还无法使用。基本操作仍然依赖宿主系统的工具。尽管如此,在链接时会使用刚刚安装的库。
M4-1.4.19
tar xvf m4-1.4.19.tar.xz cd m4-1.4.19 ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) make make DESTDIR=$LFS install
Ncurses-6.5
tar xf ncurses-6.5.tar.gz cd ncurses-6.5 mkdir build pushd build ../configure AWK=gawk 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 \ AWK=gawk 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
Bash-5.2.37
tar xvf bash-5.2.37.tar.gz cd bash-5.2.37 ./configure --prefix=/usr \ --build=$(sh support/config.guess) \ --host=$LFS_TGT \ --without-bash-malloc make make DESTDIR=$LFS install ln -sv bash $LFS/bin/sh
Coreutils-9.6
tar xvf coreutils-9.6.tar.xz cd coreutils-9.6 ./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
Diffutils-3.11
tar xvf diffutils-3.11.tar.xz cd diffutils-3.11 ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(./build-aux/config.guess) make make DESTDIR=$LFS install
File-5.46
tar xvf file-5.46.tar.gz cd file-5.46 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
Findutils-4.10.0
tar xvf findutils-4.10.0.tar.xz cd findutils-4.10.0 ./configure --prefix=/usr \ --localstatedir=/var/lib/locate \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) make make DESTDIR=$LFS install
Gawk-5.3.1
tar xvf gawk-5.3.1.tar.xz cd gawk-5.3.1 sed -i 's/extras//' Makefile.in ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) make make DESTDIR=$LFS install
Grep-3.11
tar xvf grep-3.11.tar.xz cd grep-3.11 ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(./build-aux/config.guess) make make DESTDIR=$LFS install
Gzip-1.13
tar xvf gzip-1.13.tar.xz cd gzip-1.13 ./configure --prefix=/usr --host=$LFS_TGT make make DESTDIR=$LFS install
Make-4.4.1
tar xvf make-4.4.1.tar.gz cd make-4.4.1 ./configure --prefix=/usr \ --without-guile \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) make make DESTDIR=$LFS install
Patch-2.7.6
tar xvf patch-2.7.6.tar.xz cd patch-2.7.6 ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) make make DESTDIR=$LFS install
Sed-4.9
tar xvf sed-4.9.tar.xz cd sed-4.9 ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(./build-aux/config.guess) make make DESTDIR=$LFS install
Tar-1.35
tar xvf tar-1.35.tar.xz cd Tar-1.35 ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) make make DESTDIR=$LFS install
Xz-5.6.4
tar xvf xz-5.6.4.tar.xz cd Xz-5.6.4 ./configure --prefix=/usr \ --host=$LFS_TGT \ --build=$(build-aux/config.guess) \ --disable-static \ --docdir=/usr/share/doc/xz-5.6.4 make make DESTDIR=$LFS install rm -v $LFS/usr/lib/liblzma.la
Binutils-2.44 - 第二遍
tar Jxvf binutils-2.44.tar.xz cd binutils-2.44 sed '6031s/$add_dir//' -i ltmain.sh mkdir -v build cd 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}
GCC-14.2.0 - 第二遍
tar xvf gcc-14.2.0.tar.xz cd gcc-14.2.0 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 build cd 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
- 无标签