构造基于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 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 } 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.outif [ "$(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/shsudo 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/LFSsudo mount /dev/sdc1 /mnt/LFS
检查文件系统是否为ext4
接下来设置环境变量$LFS,这个变量指向了构建LFS时使用的目录 ,在我的情况中则是/mnt/LFS,可以用echo $LFS来检查环境变量是否被正确设置了 注意:可以通过向.bashrc(或其他类似功能文件)中添加下面的命令来确保环境变量$LFS正确
软件包和补丁 接下来是下载软件包和补丁,首先创建一个目录用于存放软件包和补丁
然后更改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 sudo useradd -s /bin/bash -g lfs -m -k /dev/null 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 -ldrwxr-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登录
登录后,先为lfs配置一下环境
1 2 3 cat > ~/.bash_profile << "EOF" exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bashEOF
命令的详细含义可以阅读4.4. 配置环境 ,注意LFS变量的路径要设置正确,也就是$LFS的路径
1 2 3 4 5 6 7 8 9 10 11 12 cat > ~/.bashrc << "EOF" set +humask 022LFS=/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_SITEEOF
一些商业发行版未做文档说明地将 /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
运行以确保上面的所有更改能现在就被应用