NakanoMiku39
Articles17
Tags31
Categories3

Categories

Archive

构造基于x86_64的LFS(1)

构造基于x86_64的LFS(1)

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

环境配置

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

准备宿主系统

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

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
81
82
83
84
85
86
87
88
89
90
#!/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

运行结果如下:

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
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的问题可以手动更改

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

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

1
sudo mkfs -v -t ext4 /dev/sdc1

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

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

检查文件系统是否为ext4

1
df -T

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

1
export LFS=/mnt/LFS

软件包和补丁

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

1
mkdir -v $LFS/sources

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

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

1
sudo chmod -v a+wt $LFS/sources

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

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

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

1
2
3
pushd $LFS/sources
md5sum -c md5sums
popd

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

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

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

最后的准备工作

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

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

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

1
2
3
4
5
6
7
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

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

1
sudo mkdir -pv $LFS/tools

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

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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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用于编译软件包,这可以保证建立一个干净的工作环境

1
2
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目录的所有者

1
2
3
4
5
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

检查更改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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登录

1
sudo su - lfs

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

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

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

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

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

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

设置编译时使用的核心数

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

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

1
source ~/.bash_profile
Author:NakanoMiku39
Link: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 协议进行许可