NakanoMiku
文章10
标签12
分类3
构造基于x86_64的LFS(1)

构造基于x86_64的LFS(1)

今天老师要求我构造一个基于x86_64架构的LFS,于是在此记录一下构建过程。
LFS手册链接:https://lfs.xry111.site/zh_CN/

环境配置

强烈建议仔细读LFS手册,手册内容还是很简单明了的
这里就直入主题了,我的宿主机配置如下:

准备宿主系统

我将从2.2. 宿主系统需求开始,首先需要检查宿主机的软件包情况,脚本如下:

#!/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

运行结果如下:

OK:    Coreutils 9.4    >= 8.1
OK:    Bash      5.2.32 >= 3.2
OK:    Binutils  2.43.1 >= 2.13.1
OK:    Bison     3.8.2  >= 2.7
OK:    Diffutils 3.10   >= 2.8.1
OK:    Findutils 4.10.0 >= 4.2.31
OK:    Gawk      5.2.1  >= 4.0.1
OK:    GCC       14.2.0 >= 5.2
OK:    GCC (C++) 14.2.0 >= 5.2
OK:    Grep      3.11   >= 2.5.1a
OK:    Gzip      1.12   >= 1.3.12
OK:    M4        1.4.19 >= 1.4.10
OK:    Make      4.3    >= 4.0
OK:    Patch     2.7.6  >= 2.5.4
OK:    Perl      5.38.2 >= 5.8.8
OK:    Python    3.12.6 >= 3.4
OK:    Sed       4.9    >= 4.1.5
OK:    Tar       1.35   >= 1.22
OK:    Texinfo   7.1.1  >= 5.0
OK:    Xz        5.6.2  >= 5.0.0
OK:    Linux Kernel 6.10.9 >= 4.19
OK:    Linux Kernel supports UNIX 98 PTY
Aliases:
OK:    awk  is GNU
OK:    yacc is Bison
OK:    sh   is Bash
Compiler check:
OK:    g++ works
OK: nproc reports 24 logical cores are available

如果出现sh is not Bash的问题可以手动更改

sudo rm /bin/sh
sudo ln -s /bin/bash /bin/sh

完成环境检查后,接下来是为LFS准备一个分区,手册建议分区的大小为30GB,我这里将使用一个32G的USB作为LFS分区,分区名为/dev/sdc1,因为USB已经存在了一个FAT32分区,所以这里可以直接省略掉用fdisk工具进行分区的操作,直接格式化,将其变为ext4。如果不存在一个分区,,或者想要创建多个分区,则需要用如fdisk之类的分区工具首先进行分区处理

sudo mkfs -v -t ext4 /dev/sdc1

完成格式化后挂载该分区
手册中还给出了多个分区的方案,例如一个分区作为/,另一个作为/home,那么这步需要将这两个分区依次挂载,更详细的内容可以参考2.7. 挂载新的分区

sudo mkdir /mnt/LFS
sudo mount /dev/sdc1 /mnt/LFS

检查文件系统是否为ext4

df -T

接下来设置环境变量$LFS,这个变量指向了构建LFS时使用的目录,在我的情况中则是/mnt/LFS可以用echo $LFS来检查环境变量是否被正确设置了
注意:可以通过向.bashrc(或其他类似功能文件)中添加下面的命令来确保环境变量$LFS正确

export LFS=/mnt/LFS

软件包和补丁

接下来是下载软件包和补丁,首先创建一个目录用于存放软件包和补丁

mkdir -v $LFS/sources

然后更改sources的权限,为该目录添加写入权限和 sticky 标志。

“Sticky” 标志使得即使有多个用户对该目录有写入权限,也只有文件所有者能够删除其中的文件

sudo chmod -v a+wt $LFS/sources

手册提供了一个包括了所有所需软件包的下载列表wget-list-sysv,下载这个文件,然后将这个文件作为wget的输入,把所有软件包下载到$LFS/sources

sudo wget --input-file=wget-list-sysv --continue --directory-prefix=$LFS/sources

手册还提供了一个用于检查所下载软件包正确性的md5sums,下面是一个检查正确性的脚本,确保md5sums$LFS/sources目录下

pushd $LFS/sources
  md5sum -c md5sums
popd

手册强烈建议以root用户执行这些操作,如果已经以非root用户创建了文件夹或下载了软件包和补丁,可以修改它们的所有者

chown root:root $LFS/sources/*
ls -l # 检查是否更改

如果以非 root 用户身份下载了软件包和补丁,则下载的文件会属于该用户。文件系统使用 UID 记录文件所有者,而宿主系统中普通用户的 UID 在 LFS 中未被分配。因此,这些文件保留到最终的 LFS 系统后,会属于一个没有命名的 UID 。

最后的准备工作

在LFS分区中创建一个目录树

cd $LFS
mkdir -pv $LFS/{etc,var} $LFS/usr/{bin,lib,sbin}

然后在$LFS目录下创建一个脚本,加入下列命令并运行

for i in bin lib sbin; do
  sudo ln -sv usr/$i $LFS/$i
done

case $(uname -m) in
  x86_64) sudo mkdir -pv $LFS/lib64 ;;
esac

为交叉编译器编译程序等工具创建一个专用目录,与其他程序分离

sudo mkdir -pv $LFS/tools

最后的目录结构应该如下所示

tree $LFS

/mnt/LFS
├── bin -> usr/bin
├── etc
├── lib -> usr/lib
├── lib64
├── lost+found  [error opening dir]
├── sbin -> usr/sbin
├── sources
│   ├── acl-2.3.2.tar.xz
│   ├── attr-2.5.2.tar.gz
│   ├── autoconf-2.72.tar.xz
│   ├── automake-1.17.tar.xz
│   ├── bash-5.2.32.tar.gz
│   ├── bc-6.7.6.tar.xz
│   ├── binutils-2.43.1.tar.xz
│   ├── bison-3.8.2.tar.xz
│   ├── bzip2-1.0.8-install_docs-1.patch
│   ├── bzip2-1.0.8.tar.gz
│   ├── check-0.15.2.tar.gz
│   ├── coreutils-9.5-i18n-2.patch
│   ├── coreutils-9.5.tar.xz
│   ├── dejagnu-1.6.3.tar.gz
│   ├── diffutils-3.10.tar.xz
│   ├── e2fsprogs-1.47.1.tar.gz
│   ├── elfutils-0.191.tar.bz2
│   ├── expat-2.6.2.tar.xz
│   ├── expect-5.45.4-gcc14-1.patch
│   ├── expect5.45.4.tar.gz
│   ├── file-5.45.tar.gz
│   ├── findutils-4.10.0.tar.xz
│   ├── flex-2.6.4.tar.gz
│   ├── flit_core-3.9.0.tar.gz
│   ├── gawk-5.3.0.tar.xz
│   ├── gcc-14.2.0.tar.xz
│   ├── gdbm-1.24.tar.gz
│   ├── gettext-0.22.5.tar.xz
│   ├── glibc-2.40-fhs-1.patch
│   ├── glibc-2.40.tar.xz
│   ├── gmp-6.3.0.tar.xz
│   ├── gperf-3.1.tar.gz
│   ├── grep-3.11.tar.xz
│   ├── groff-1.23.0.tar.gz
│   ├── grub-2.12.tar.xz
│   ├── gzip-1.13.tar.xz
│   ├── iana-etc-20240806.tar.gz
│   ├── inetutils-2.5.tar.xz
│   ├── intltool-0.51.0.tar.gz
│   ├── iproute2-6.10.0.tar.xz
│   ├── jinja2-3.1.4.tar.gz
│   ├── kbd-2.6.4-backspace-1.patch
│   ├── kbd-2.6.4.tar.xz
│   ├── kmod-33.tar.xz
│   ├── less-661.tar.gz
│   ├── lfs-bootscripts-20240825.tar.xz
│   ├── libcap-2.70.tar.xz
│   ├── libffi-3.4.6.tar.gz
│   ├── libpipeline-1.5.7.tar.gz
│   ├── libtool-2.4.7.tar.xz
│   ├── libxcrypt-4.4.36.tar.xz
│   ├── linux-6.10.5.tar.xz
│   ├── lz4-1.10.0.tar.gz
│   ├── m4-1.4.19.tar.xz
│   ├── make-4.4.1.tar.gz
│   ├── man-db-2.12.1.tar.xz
│   ├── man-pages-6.9.1.tar.xz
│   ├── MarkupSafe-2.1.5.tar.gz
│   ├── meson-1.5.1.tar.gz
│   ├── mpc-1.3.1.tar.gz
│   ├── mpfr-4.2.1.tar.xz
│   ├── ncurses-6.5.tar.gz
│   ├── ninja-1.12.1.tar.gz
│   ├── openssl-3.3.1.tar.gz
│   ├── patch-2.7.6.tar.xz
│   ├── perl-5.40.0.tar.xz
│   ├── pkgconf-2.3.0.tar.xz
│   ├── procps-ng-4.0.4.tar.xz
│   ├── psmisc-23.7.tar.xz
│   ├── python-3.12.5-docs-html.tar.bz2
│   ├── Python-3.12.5.tar.xz
│   ├── readline-8.2.13.tar.gz
│   ├── sed-4.9.tar.xz
│   ├── setuptools-72.2.0.tar.gz
│   ├── shadow-4.16.0.tar.xz
│   ├── sysklogd-2.6.1.tar.gz
│   ├── systemd-256.4.tar.gz
│   ├── systemd-man-pages-256.4.tar.xz
│   ├── sysvinit-3.10-consolidated-1.patch
│   ├── sysvinit-3.10.tar.xz
│   ├── tar-1.35.tar.xz
│   ├── tcl8.6.14-html.tar.gz
│   ├── tcl8.6.14-src.tar.gz
│   ├── texinfo-7.1.tar.xz
│   ├── tzdata2024a.tar.gz
│   ├── udev-lfs-20230818.tar.xz
│   ├── util-linux-2.40.2.tar.xz
│   ├── vim-9.1.0660.tar.gz
│   ├── wheel-0.44.0.tar.gz
│   ├── XML-Parser-2.47.tar.gz
│   ├── xz-5.6.2.tar.xz
│   ├── zlib-1.3.1.tar.gz
│   └── zstd-1.5.6.tar.gz
├── tools
├── usr
│   ├── bin
│   ├── lib
│   └── sbin
└── var

创建一个新的用户lfs用于编译软件包,这可以保证建立一个干净的工作环境

sudo groupadd lfs # 创建一个组lfs
sudo useradd -s /bin/bash -g lfs -m -k /dev/null lfs # 创建一个用户lfs

命令行中各选项的含义:
-s /bin/bash
设置 bash 为用户 lfs 的默认 shell。
-g lfs
添加用户 lfs 到组 lfs。
-m
为用户 lfs 创建一个主目录。
-k /dev/null
将模板目录设置为空设备文件,防止从默认模板目录 (/etc/skel) 复制文件到新的主目录。
lfs
这是新用户的名称。

lfs设为$LFS目录的所有者

sudo chown -v lfs $LFS/{usr{,/*},lib,var,etc,bin,sbin,tools}

case $(uname -m) in
  x86_64) sudo chown -v lfs $LFS/lib64 ;;
esac

检查更改

ls $LFS -l

drwxr-xr-x 9 root root  4096 Sep 27 20:26 .
drwxr-xr-x 3 root root  4096 Sep 26 23:37 ..
lrwxrwxrwx 1 root root     7 Sep 27 20:13 bin -> usr/bin
drwxr-xr-x 2 lfs  root  4096 Sep 27 20:10 etc
lrwxrwxrwx 1 root root     7 Sep 27 20:13 lib -> usr/lib
drwxr-xr-x 2 lfs  root  4096 Sep 27 20:13 lib64
drwx------ 2 root root 16384 Sep 26 23:40 lost+found
lrwxrwxrwx 1 root root     8 Sep 27 20:13 sbin -> usr/sbin
drwxrwxrwt 2 root root  4096 Sep 27 20:08 sources
drwxr-xr-x 2 lfs  root  4096 Sep 27 20:19 tools
drwxr-xr-x 5 lfs  root  4096 Sep 27 20:10 usr
drwxr-xr-x 2 lfs  root  4096 Sep 27 20:10 var

最后以lfs登录

sudo su - lfs

登录后,先为lfs配置一下环境

cat > ~/.bash_profile << "EOF"
exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash
EOF

命令的详细含义可以阅读4.4. 配置环境注意LFS变量的路径要设置正确,也就是$LFS的路径

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

一些商业发行版未做文档说明地将 /etc/bash.bashrc 引入 bash 初始化过程。该文件可能修改 lfs 用户的环境,并影响 LFS 关键软件包的构建。为了保证 lfs 用户环境的纯净,检查 /etc/bash.bashrc 是否存在,如果它存在就将它移走。以 root 用户身份,运行:

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

设置编译时使用的核心数

cat >> ~/.bashrc << "EOF"
export MAKEFLAGS=-j$(nproc)
EOF

运行以确保上面的所有更改能现在就被应用

source ~/.bash_profile
本文作者:NakanoMiku
本文链接:http://nakanomiku39.github.io/2024/09/26/%E6%9E%84%E9%80%A0%E5%9F%BA%E4%BA%8Ex86-64%E7%9A%84LFS%EF%BC%881%EF%BC%89/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可