目录

0、本文约定

0.0. 参考内容

特别感谢Linux 中国 - LCTT - LFS 翻译小组翻译的LFS手册,该小组官网地址为https://lctt.github.io,LFS手册网址为https://lctt.github.io/LFS-BOOK

本文使用的LFS手册为该小组翻译的Linux From Scratch (简体中文版)- 9.0 - SysV HTML版

强烈建议操作过程参考HTML版的LFS手册,原因见本文1.1.节。

0.1. 输入输出样式

在Linux环境中输入的命令及输出的结果使用如下样式表示(内容与终端显示的一致):


lfs@lfs-VirtualBox:~$ echo "hello world"

0.2. 注意事项

使用如下样式表示:

这里是注意事项、

0.3. 宿主机配置

本文使用的物理机器为:

HP ZHAN 66 Pro 14 G3
CPU:i7-10510U
内存:16GB
操作系统:Windows10-64

LFS编译环境:

VirualBox-6.1 & Ubuntu20.04

LFS编译环境中的各软件版本:

bash, version 5.0.17(1)-release
/bin/sh -> /usr/bin/bash
Binutils: GNU ld (GNU Binutils for Ubuntu) 2.34
bison (GNU Bison) 3.5.1
/usr/bin/yacc -> /usr/bin/bison.yacc
bzip2, Version 1.0.8, 13-Jul-2019.
Coreutils: 8.30
diff (GNU diffutils) 3.7
find (GNU findutils) 4.7.0
GNU Awk 5.0.1, API: 2.0 (GNU MPFR 4.0.2, GNU MP 6.2.0)
/usr/bin/awk -> /usr/bin/gawk
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
(Ubuntu GLIBC 2.31-0ubuntu9.2) 2.31
grep (GNU grep) 3.4
gzip 1.10
Linux version 5.4.0-42-generic (buildd@lgw01-amd64-038) (gcc version 9.3.0 (Ubuntu 9.3.0-10ubuntu2)) #46-Ubuntu SMP Fri Jul 10 00:24:02 UTC 2020
m4 (GNU M4) 1.4.18
GNU Make 4.2.1
GNU patch 2.7.6
Perl version=‘5.30.0’;
Python 3.8.5
sed (GNU sed) 4.7
tar (GNU tar) 1.30
texi2any (GNU texinfo) 6.7
xz (XZ Utils) 5.2.4
g++ compilation OK

1、对LFS的一点理解

1.0. 关于LFS交叉编译环境

本质上是在宿主机操作系统中,编译出另一套可以在其它机器上使用的操作系统,也就是交叉编译。

复杂的地方是,需要避免编译结果受宿主机环境变量,软件版本的影响,造成编译结果的链接、环境变量等指向到宿主机,从而导致编译结果无法在其它机器上正常使用。

为了避免发生这种情况(环境污染),LFS手册所有的操作,实际上分三步走:

  • 第一步,先小心翼翼的(严格的设置了它们的符号链接、编译参数等)构建了一套工具。
  • 第二步,用这套不会造成环境污染的工具,来编译一个基本的交叉编译环境。
  • 第三步,当基本的交叉编译环境构建好了以后,LFS手册指导我们,通过chroot命令,切换到该环境中,使用该环境中最基本的编译工具,自己来编译自己所需要的其它软件。

上个图来方便理解:
在这里插入图片描述

1.1. 关于操作步骤

LFS手册中的shell代码部分(如下图),原样复制粘贴过去执行即可。但是一定要注意,如果你参考的LFS手册是PDF版的,下面的代码部分可能不带有换行符号(既linux中的\n,或Windows中的\r\n),或者某些符号无法复制(如某些章节里英文的 - 符号)。再次强烈建议操作过程参考html版的LFS手册。

在这里插入图片描述
关于LFS手册的整个操作流程,大概理解为下图:

在这里插入图片描述

2、LFS手册中要注意的几个地方

2.0. 关于软件版本检查

在LFS手册的《2.2. 宿主系统要求》章节中,给出的软件版本检查脚本不能正确的在ubuntu20.04下显示Binutils的版本,需要修改其脚本内容,删掉下图中黄色荧光笔标注部分即可(即,删除原文的 | cut -d" " -f3- )。否则输出的Binutils版本为:“Binutils: GNU”,修改后输出的版本为:“Binutils: GNU ld (GNU Binutils for Ubuntu) 2.34”。

在这里插入图片描述

2.1. 关于分区

在LFS手册的《2.4. 创建新分区》章节中,对于构建LFS系统建议使用新的分区,并建议创建交换分区、/boot分区等分区,本文并未如此操作,而是挂载了一块50GB的新硬盘/dev/sdb,并为其创建了一整个主分区/dev/sdb1,然后使用ext4格式将其格式化。

2.2. 关于编译安装软件包

特别强调

  • 编译安装软件包时,需要先进入$LFS/sources目录下。
  • 每次编译软件时,先使用tar命令将目标软件解压缩(xz文件使用tar -xf,bz2文件使用tar -jxf,gz文件使用tar -zxf)。
  • 然后使用cd命令进入该软件源代码目录。
  • 然后按照LFS提示进行操作。
  • 最后,待操作完成后,使用cd …或cd …/…命令返回$LFS/sources目录,使用rm -rf 命令移除该软件源代码目录(若LFS手册没有明示需要保留的情况下)。
  • clear命令清除屏幕显示(实操过程中编译到第六章时,疑似因为内容太多导致Terminal崩溃
  • LFS手册翻页
  • 从《6.7. Linux-5.2.8 API 头文件》章节开始,请使用cd命令进入$LFS/sources目录下进行操作
  • 已知《6.80. 清理》章节的如下命令无法正确执行
logout

chroot "$LFS" /usr/bin/env -i          \
    HOME=/root TERM="$TERM"            \
    PS1='(lfs chroot) \u:\w\$ '        \
    PATH=/bin:/usr/bin:/sbin:/usr/sbin \
    /bin/bash --login

这是因为本文使用的是ubuntu-desktop的desktop系统登录,然后在桌面系统中打开了一个Terminal来执行命令,当前执行命令的shell不是一个登录shell,所以会报错,退出失败进一步导致找不到$LFS环境变量及其对应的目录:

(lfs chroot) root:/usr/lib# logout
bash: logout: not login shell: use `exit'
(lfs chroot) root:/usr/lib# 
(lfs chroot) root:/usr/lib# chroot "$LFS" /usr/bin/env -i          \
>     HOME=/root TERM="$TERM"            \
>     PS1='(lfs chroot) \u:\w\$ '        \
>     PATH=/bin:/usr/bin:/sbin:/usr/sbin \
>     /bin/bash --login
chroot: cannot change root directory to '': No such file or directory

所以我们需要使用“exit”命令来代替logout命令。修改后的命令如下:

exit

chroot "$LFS" /usr/bin/env -i          \
    HOME=/root TERM="$TERM"            \
    PS1='(lfs chroot) \u:\w\$ '        \
    PATH=/bin:/usr/bin:/sbin:/usr/sbin \
    /bin/bash --login

2.3. 关于安装linux头文件

在LFS手册原文中的《5.6. Linux-5.2.8 API 头文件》和《6.7. Linux-5.2.8 API 头文件》章节里,并未描写准备操作步骤(如下图)。

在这里插入图片描述

其实此处和本文2.2.节相同,先解压linux内核源码包,然后进入其中,再执行即可。代码如下:

lfs@lfs-VirtualBox:/mnt/lfs/sources$ tar -xf linux-5.2.8.tar.xz
lfs@lfs-VirtualBox:/mnt/lfs/sources$ cd linux-5.2.8

2.5. 关于《7.7. Bash Shell 启动文件》章节本地字符集支持

使用以下命令可以查看支持的字符集:

locale -a

本文只能查看到zh\_CN.gb18030,故,LFS手册原文创建/etc/profile的脚本修改如下:

cat > /etc/profile << "EOF"
# Begin /etc/profile

export LANG=zh_CN.gb18030

# End /etc/profile
EOF

2.6. 《8.2. 创建 /etc/fstab 文件》章节创建fstab文件

由于本文使用单个分区,故8.2.章节中创建fstab文件的脚本修改为如下:

cat > /etc/fstab << "EOF"
# Begin /etc/fstab

# file system  mount-point  type     options             dump  fsck
#                                                              order

/dev/sdb1     /            <fff>    defaults            1     1
proc           /proc        proc     nosuid,noexec,nodev 0     0
sysfs          /sys         sysfs    nosuid,noexec,nodev 0     0
devpts         /dev/pts     devpts   gid=5,mode=620      0     0
tmpfs          /run         tmpfs    defaults            0     0
devtmpfs       /dev         devtmpfs mode=0755,nosuid    0     0

# End /etc/fstab
EOF

2.7. 《8.4. 使用 GRUB 设置启动过程》章节启动设置

根据LFS手册描述(如下图)
在这里插入图片描述

本文中使用的/dev/sdb1,应该在grub中设置为(hd1,1),并且root指向/dev/sdb1。

原文创建/boot/grub/grub.cfg文件的脚本修改如下:

cat > /boot/grub/grub.cfg << "EOF"
# Begin /boot/grub/grub.cfg
set default=0
set timeout=5

insmod ext2
set root=(hd1,1)

menuentry "GNU/Linux, Linux 5.2.8-lfs-9.0" {
        linux   /boot/vmlinuz-5.2.8-lfs-9.0 root=/dev/sdb1 ro
}
EOF

2.8. 关于测试套件失败的情况

2.8.1. 《6.9. Glibc-2.30》章节

参照本文进行LFS编译,在LFS手册《6.9. Glibc-2.30》章节操作时,会发现LFS中描述的已知测试失败项目inet/tst-idna\_name\_classify和misc/tst-ttyname,并同时出现了LFS手册中没有描述到的测试失败nptl/tst-mutex10 。但在后续实际操作时,并未产生致命影响,此处提出,以观后效。

具体测试结果输出如下:

UNSUPPORTED: elf/tst-audit10
UNSUPPORTED: elf/tst-avx512
UNSUPPORTED: elf/tst-ldconfig-bad-aux-cache
UNSUPPORTED: elf/tst-pldd
XPASS: elf/tst-protected1a
XPASS: elf/tst-protected1b
FAIL: inet/tst-idna_name_classify
UNSUPPORTED: math/test-double-libmvec-alias-avx512
UNSUPPORTED: math/test-double-libmvec-alias-avx512-main
UNSUPPORTED: math/test-double-libmvec-sincos-avx512
UNSUPPORTED: math/test-float-libmvec-alias-avx512
UNSUPPORTED: math/test-float-libmvec-alias-avx512-main
UNSUPPORTED: math/test-float-libmvec-sincosf-avx512
UNSUPPORTED: misc/tst-pkey
FAIL: misc/tst-ttyname
UNSUPPORTED: nptl/test-cond-printers
UNSUPPORTED: nptl/test-condattr-printers
UNSUPPORTED: nptl/test-mutex-printers
UNSUPPORTED: nptl/test-mutexattr-printers
UNSUPPORTED: nptl/test-rwlock-printers
UNSUPPORTED: nptl/test-rwlockattr-printers
FAIL: nptl/tst-mutex10
UNSUPPORTED: nss/tst-nss-db-endgrent
UNSUPPORTED: nss/tst-nss-db-endpwent
UNSUPPORTED: nss/tst-nss-files-hosts-long
UNSUPPORTED: nss/tst-nss-test3
UNSUPPORTED: resolv/tst-resolv-ai_idn
UNSUPPORTED: resolv/tst-resolv-ai_idn-latin1
Summary of test results:
      3 FAIL
   6070 PASS
     23 UNSUPPORTED
     17 XFAIL
      2 XPASS
make[1]: *** [Makefile:412: tests] Error 1
make[1]: Leaving directory '/sources/glibc-2.30'
make: *** [Makefile:9: check] Error 2

2.8.2. 《6.21. GCC-9.2.0》章节

LFS手册《6.21. GCC-9.2.0》章节中描述已知6处失败,本文出现8处失败,但是在后续的验证中得到了正确的验证结果[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2],根据LFS的描述及其它的一些信息来看,这些失败可能是由于语言环境,时间问题,CPU指令集问题等原因造成的所以暂不追究这个问题。另外,本章节总计用时4小时,需要耐心等待。测试报告如下:

(lfs chroot) root:/sources/gcc-9.2.0/build# ../contrib/test_summary
gawk: cmd. line:36: warning: regexp escape sequence `\=' is not a known regexp operator
cat <<'EOF' |
LAST_UPDATED: Obtained from SVN: tags/gcc_9_2_0_release revision 274275

Native configuration is x86_64-pc-linux-gnu

        === g++ tests ===


Running target unix

        === g++ Summary ===

# of expected passes        134787
# of expected failures        527
# of unsupported tests        5921
/sources/gcc-9.2.0/build/gcc/xg++  version 9.2.0 (GCC) 

        === gcc tests ===


Running target unix
FAIL: gcc.target/i386/pr57193.c scan-assembler-times movdqa 2
FAIL: gcc.target/i386/pr90178.c scan-assembler-times xorl[\\\\t ]*\\\\%eax,[\\\\t ]*%eax 1

        === gcc Summary ===

# of expected passes        139439
# of unexpected failures    2
# of expected failures        527
# of unsupported tests        2151
/sources/gcc-9.2.0/build/gcc/xgcc  version 9.2.0 (GCC) 

        === libatomic tests ===


Running target unix

        === libatomic Summary ===

# of expected passes        54
        === libgomp tests ===


Running target unix

        === libgomp Summary ===

# of expected passes        2316
# of expected failures        2
# of unsupported tests        210
        === libitm tests ===


Running target unix

        === libitm Summary ===

# of expected passes        42
# of expected failures        3
# of unsupported tests        1
        === libstdc++ tests ===


Running target unix
FAIL: 22_locale/time_get/get_time/char/2.cc execution test
FAIL: 22_locale/time_get/get_time/char/wrapped_env.cc execution test
FAIL: 22_locale/time_get/get_time/char/wrapped_locale.cc execution test
FAIL: 22_locale/time_get/get_time/wchar_t/2.cc execution test
FAIL: 22_locale/time_get/get_time/wchar_t/wrapped_env.cc execution test
FAIL: 22_locale/time_get/get_time/wchar_t/wrapped_locale.cc execution test
FAIL: experimental/net/internet/resolver/ops/lookup.cc execution test
FAIL: experimental/net/internet/resolver/ops/reverse.cc execution test

        === libstdc++ Summary ===

# of expected passes        12892
# of unexpected failures    8
# of expected failures        78
# of unsupported tests        380

Compiler version: 9.2.0 (GCC) 
Platform: x86_64-pc-linux-gnu
configure flags: --prefix=/usr --enable-languages=c,c++ --disable-multilib --disable-bootstrap --with-system-zlib
EOF
Mail -s "Results for 9.2.0 (GCC) testsuite on x86_64-pc-linux-gnu" [email protected] &&
mv /sources/gcc-9.2.0/build/./gcc/testsuite/g++/g++.sum /sources/gcc-9.2.0/build/./gcc/testsuite/g++/g++.sum.sent &&
mv /sources/gcc-9.2.0/build/./gcc/testsuite/gcc/gcc.sum /sources/gcc-9.2.0/build/./gcc/testsuite/gcc/gcc.sum.sent &&
mv /sources/gcc-9.2.0/build/./x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.sum /sources/gcc-9.2.0/build/./x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.sum.sent &&
mv /sources/gcc-9.2.0/build/./x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.sum /sources/gcc-9.2.0/build/./x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.sum.sent &&
mv /sources/gcc-9.2.0/build/./x86_64-pc-linux-gnu/libitm/testsuite/libitm.sum /sources/gcc-9.2.0/build/./x86_64-pc-linux-gnu/libitm/testsuite/libitm.sum.sent &&
mv /sources/gcc-9.2.0/build/./x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.sum /sources/gcc-9.2.0/build/./x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.sum.sent &&
mv /sources/gcc-9.2.0/build/./gcc/testsuite/g++/g++.log /sources/gcc-9.2.0/build/./gcc/testsuite/g++/g++.log.sent &&
mv /sources/gcc-9.2.0/build/./gcc/testsuite/gcc/gcc.log /sources/gcc-9.2.0/build/./gcc/testsuite/gcc/gcc.log.sent &&
mv /sources/gcc-9.2.0/build/./x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.log /sources/gcc-9.2.0/build/./x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.log.sent &&
mv /sources/gcc-9.2.0/build/./x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.log /sources/gcc-9.2.0/build/./x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.log.sent &&
mv /sources/gcc-9.2.0/build/./x86_64-pc-linux-gnu/libitm/testsuite/libitm.log /sources/gcc-9.2.0/build/./x86_64-pc-linux-gnu/libitm/testsuite/libitm.log.sent &&
mv /sources/gcc-9.2.0/build/./x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.log /sources/gcc-9.2.0/build/./x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.log.sent &&
true

验证结果如下:

(lfs chroot) root:/sources/gcc-9.2.0/build# echo 'int main(){}' > dummy.c
(lfs chroot) root:/sources/gcc-9.2.0/build# cc dummy.c -v -Wl,--verbose &> dummy.log
(lfs chroot) root:/sources/gcc-9.2.0/build# readelf -l a.out | grep ': /lib'
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

3、实操环境的搭建及注意事项

3.0. 虚拟机操作系统安装

  • 安装Oracle VitrualBox
  • 下载ubuntu20.04-desktop的ISO文件
  • VXBOX添加新虚拟机ubuntu20.04,内存设置8GB,CPU4核,第一块硬盘10GB,第二块硬盘50GB
  • 选择英文安装(避免后续可能出现的一切关于语言的系统错误
  • 选择最小化安装(尽量避免非要的软件带来系统错误
  • 系统安装到10G硬盘(/dev/sda)
  • ubuntu安装完成
  • fdisk -l查看可用硬盘(50GB硬盘当为/dev/sdb,且此时不存在文件系统)
  • fdisk /dev/sdb 创建分区(n回车,一路默认值回车,完成后w回车保存退出)
  • mkfs.ext4 /dev/sdb1 格式化分区
  • 创建/mnt/lfs目录
  • 修改/etc/fstab文件,添加挂载信息,50G硬盘/dev/sdb1挂载到/mnt/lfs
  • 安装gcc,make,perl等安装VXBOX增强功能必须的依赖软件
  • 安装VXBOX增强功能(必须装,使用虚拟终端可能会出现各种不可知的情况,本文将在虚拟机中直接操作编译过程,确保无重启、无tty断连等干扰情况。同时,LFS手册在物理主机中打开,并使用VXBOX的增强功能,将物理主机中的命令粘贴到虚拟机的Terminal中
  • 物理机控制面板->硬件和声音->电源选项->更改计划设置->接通电源->从不关闭显示器,从不睡眠 -> 更改高级电源设置 ->电源按钮和盖子 ->合上盖子的操作 ->接通电源 ->不采取任何操作 -> 确定 -> 保存修改
  • ubuntu虚拟机->Settings ->Privacy-> Screen Lock ->Blank Screen Delay -> Never
  • 如果临时有事需要暂停编译,请等待当前软件包编译或安装的步骤结束后,使用VXbox的镜像功能,先备份一个当前镜像,然后在ubuntu虚拟机右上角点关闭按钮,弹出的确认页面选择挂起功能,以避免重启可能会带来的失败风险。

3.0. 虚拟机备份

建议在如下章节完成后,使用vxbox的快照功能对当前编译环境进行备份:

  • 《2.2. 宿主系统要求》章节的要求通过以后
  • 《5.10. GCC-9.2.0 - 第 2 遍》章节完成以后
  • 《5.36. 改变属主》章节完成以后
  • 《6.21. GCC-9.2.0》章节完成以后
  • 《6.77. Eudev-3.2.8》章节完成以后

4、LFS操作过程记录

在LFS手册中,CTRL+C
切换至ubuntu环境下,CTRL+V
然后,结果如下:
在这里插入图片描述
在这里插入图片描述

标签: Linux, 编译, 章节, Scratch, LFS, lfs, UNSUPPORTED, tst

相关文章推荐

添加新评论,含*的栏目为必填