正在查看旧版本。 查看 当前版本.

与当前比较 查看页面历史记录

版本 2 下一个 »

简介

LFS是Linux From Scratch的简称,LFS 存在的一个重要原因是可以帮助人们学习 linux 系统内部是如何工作的。构建一个 LFS 系统会帮助演示是什么使 linux  运转,各种组件如何在一起互相依赖的工作。最好的事情之一通过这种学习可以获得完全根据自己的需求定制 linux 系统的能力。

LFS 的一个关键的好处是它让用户对于系统有更多的控制,而不是依赖于他人的 linux 实现。在 LFS  的世界里,你自己坐在司机的位置,掌控系统的每一个细节,比如目录布局和启动脚本配置等等。你也能掌控在哪里、为何、以及怎样安装每一个程序。有关LFS相关的资料可以去这个链接中查找:http://www.linuxfromscratch.org

环境配置

项目软件CPU内存硬盘网络备注
虚拟机软件VirtualBox7.1.62450+20NAT映射端口访问
宿主机Windows11i3-9100161T

虚拟机系统Debian12



最小化安装
  • 虚拟机 50G 硬盘为 Debian12 的硬盘,20G硬盘为 LFS 的目标硬盘

  1. 参照 https://wiki.waringid.me/x/PgAS 完成 Debian 系统安装和镜像源配置
  2. 将新建用户 lf 加入 sudo 组。usermod -aG sudo lf
  3. 安装基础的开发组件
  4. 检查相关组件是否符合 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

下载软件包

  1. 创建软件包的存储目录
  2. 下载对应的软件包
    1. 软件包的下载地址文件 https://www.linuxfromscratch.org/lfs/view/stable/wget-list-sysv
    2. 软件包的 md5 校验文件 https://www.linuxfromscratch.org/lfs/view/stable/md5sums
    3. 如果存在无法下载的软件包可以参考国内镜像网站 https://mirrors.ustc.edu.cn/lfs/lfs-packages/12.3/
  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 第一遍

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 第一遍

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



  • 无标签