1 Star 0 Fork 11

coder_lw / wiki

forked from deepinwiki / wiki 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
创建自己的linux发行版.md 98.50 KB
一键复制 编辑 原始数据 按行查看 历史
htqx 提交于 2023-08-02 00:14 . 图片地址修改为本地

创建自己的linux发行版

前言

linux发行版很多,个人没有必要去创建一个发行版,因为要维护一个发行版是一件可想而知的麻烦事。因此,我认为创建这个主要是为了加深对linux系统的理解。

FHS

FHS 制定了linux文件组织层次结构的通用标准。

制定准则:

  1. 静态:由系统管理员修改
  2. 可变:非静态
  3. 共享:多主机可访问
  4. 私有:非共享
性质 共享 私有
静态 /usr /etc
静态 /opt /boot
可变 /var/mail /var/run
可变 /var/spool/news /var/lock

/ 根

功能:

  1. 引导
  2. 还原
  3. 恢复
  4. 修复

内容:

  1. bin 基本命令
  2. boot 引导
  3. dev 设备文件
  4. etc 主机特定配置
    1. opt 附加软件包的配置
    2. X11 X Window系统配置(可选)
    3. sgml SGML配置(可选)
    4. XML XML配置(可选)
  5. lib 基本共享库和内核模块
  6. media 移动媒体挂载点
  7. mnt 临时挂载点
  8. opt 附加软件包
  9. run 运行数据
  10. sbin 管理命令
  11. srv 运行的服务的数据
  12. tmp 临时文件
  13. usr 下一层级(静态)
  14. var 可变数据
  15. home 用户主目录(可选)
  16. lib* 备用共享库(可选)
  17. root 管理员主目录(可选)
  18. proc 内核信息(虚拟文件系统,建议)
  19. sys 新款内核信息(建议)

/bin 基本命令

必备命令:

  1. cat 连接到标准输出
  2. chgrp 更改文件所有者组
  3. chmod 更改文件权限
  4. wn 更改文件所有者和组
  5. cp 复制
  6. date 打印和设置日期
  7. dd 转换和复制文件内容
  8. df 磁盘空间
  9. dmesg 打印内核消息缓冲区
  10. echo 显示一行文本
  11. false 失败
  12. hostname 显示和设置主机名
  13. kill 发送信号到进程
  14. ln 链接
  15. login 登录会话
  16. ls 列出目录内容
  17. mkdir 创建目录
  18. mknod 创建设备文件
  19. more 分页显示
  20. mount 挂载文件系统
  21. mv 移动
  22. ps 显示进程
  23. pwd 显示工作目录
  24. rm 删除
  25. rmdir 删除空目录
  26. sed 字符串流处理
  27. sh shell
  28. stty 打印和更改终端
  29. su 切换登录用户
  30. sync 刷新文件系统缓冲区,达到同步
  31. true 成功
  32. umount 卸载文件系统
  33. uname 打印系统信息
  34. csh(可选) c shell
  35. ed(可选) ed编辑器
  36. tar(可选) tar归档
  37. cpio(可选) cpio压缩
  38. gzip(可选) 压缩
  39. gunzip(可选) 解压缩
  40. zcat(可选) 解压缩
  41. netstat(可选) 网络统计
  42. ping(可选) 网络测试

/boot 引导

内容:

  1. 内核
  2. 引导程序

/etc 配置

可选内容:

序号 文件 说明
1 csh.login c shell初始化
2 exports NFS文件系统访问控制表
3 fstab 文件系统静态信息
4 ftpusers FTP守护程序访问控制表
5 gateways 网关
6 group 用户组
7 host.conf 域名解释
8 hosts 主机名
9 hosts.allow TCP通过主机
10 hosts.deny TCP拒绝主机
11 hosts.equiv TCP受信主机
12 hosts.lpd lpd受信主机
13 inetd.conf inetd配置
14 inittab 系统初始化
15 issue 登录前信息
16 ld.so.conf 共享库搜索目录
17 motd 登录后信息
18 mtab 文件系统动态信息(历史原因,现一般只是个链接:/proc/mounts)
19 mtools.conf mtools配置
20 networks 网络名称
21 passwd 密码文件
22 printcap lpd打印机数据
23 profile sh shell初始化
24 protocols IP协议列表
25 resolv.conf 域名服务器
26 rpc RPC协议列表
27 securetty 安全终端访问控制
28 services 网络服务端口名称
29 shells 有效登录shell的路径
30 syslog.conf syslogd配置
31 X11/xorg.conf X window配置
32 X11/Xmodmap 键盘配置

/lib 共享库

  1. libc.so.* c库
  2. ld* 链接加载器
  3. modules 内核模块(可选)
  4. cpp c预处理器(链接)

/opt

管理员:

  1. bin
  2. doc
  3. include
  4. info
  5. lib
  6. man

用户:

  1. 包名
    1. bin
    2. share/man
  2. 服务名

外部组织:

  1. /etc/opt
  2. /var/opt

/sbin 管理命令

  1. shutdown(必备) 关机
  2. fastboot 重启不检查磁盘
  3. fasthalt 关机不检查磁盘
  4. fdisk 分区
  5. fsck 检查和修复磁盘
  6. fsck.* 同上,特定文件系统
  7. getty 创建终端并设置模式
  8. halt 关机
  9. ifconfig 配置网络接口
  10. init 系统初始化
  11. mkfs 格式化
  12. mkfs.* 同上,特定文件系统
  13. mkswap 格式化交换分区
  14. reboot 重启
  15. route IP路由表
  16. swapon 启用交换分区
  17. swapoff 关闭交换分区
  18. update 刷新文件系统缓冲区
  19. ldconfig 配置动态链接库
  20. sln 静态链接
  21. ssync 静态同步
  22. ctrlaltdel 设置ctrl+alt+del组合键作用
  23. kbdrate 配置键盘传输比特率

/sbin 和/usr/sbin、/usr/local/sbin的区别:

  1. /sbin 启动和恢复系统时必备的
  2. /usr/sbin 系统安装的其他管理工具
  3. /usr/local/sbin 管理员安装的管理工具

/usr 下一层次(静态)

  1. bin
    1. perl 语言
    2. python 语言
    3. tclsh Tcl shell
    4. wish Tcl 窗口
    5. expect 交互式对话程序
  2. lib
  3. local 再下一层级(静态)
  4. sbin
  5. share 静态数据
    1. man 帮助文档
      1. man1 普通命令
      2. man2 系统调用
      3. man3 库函数
      4. man4 特殊文件
      5. man5 配置格式
      6. man6 游戏
      7. man7 其他
      8. man8 管理命令
    2. misc 其他
  6. games 游戏
  7. include 头文件
    1. bsd 兼容bsd
    2. asm 标准内核asm
    3. linux 标准内核
  8. libexec 二进制文件
  9. lib* 备用库
  10. src 源代码

/usr/local 本地层

  1. bin
  2. etc
  3. games
  4. include
  5. lib
  6. man(不建议使用)
  7. sbin
  8. share
  9. src

/var 动态数据

  1. cache 缓存
  2. lib 动态状态
    1. misc 杂项
  3. local /usr/local层级的动态数据
  4. lock 锁定
  5. opt /opt的动态数据
  6. run 进程数据(链接:/run)
  7. spool 脱机数据
  8. tmp 重新引导保留的临时文件
  9. log 日志
    1. lastlog 上次登录记录
    2. messages syslogd记录
    3. wtmp 所有登录记录
  10. backups 备份(不推荐)
  11. account 记账(可选)
  12. crash 故障转储(可选)
  13. games 游戏(可选)
  14. mail 邮箱(可选)
  15. yp NIS网络黄页(可选)

LSB

LSB 制定了库的标准。

核心库(架构相关)

运行时
libc libc.so.6
libm libm.so.6
proginterp /lib64/ld-lsb-x86-64.so.3

核心库

运行时
libcrypt libcrypt.so.1
libdl libdl.so.2
libgcc_s libgcc_s.so.1
libncurses libncurses.so.5
libncursesw libncursesw.so.5
libnspr4 libnspr4.so
libnss3 libnss3.so
libpam libnss3.so
libpthread libpthread.so.0
librt librt.so.1
libssl3 libssl3.so
libstdcxx libstdc++.so.6
libutil libutil.so.1
libz libz.so.1

成像库

运行时
libcups   libcups.so.2
libcupsimage libcupsimage.so.2
libsane libsane.so.1

语言运行时库

运行时
libxml2 libxml2.so.2
libxslt libxslt.so.1

桌面库

运行时
libGL libGL.so.1
libGLU libGLU.so.1
libICE libICE.so.6
libQtCore libQtCore.so.4
libQtGui libQtGui.so.4
libQtNetwork libQtNetwork.so.4
libQtOpenGL libQtOpenGL.so.4
libQtSql libQtSql.so.4
libQtSvg libQtSvg.so.4
libQtXml libQtXml.so.4
libSM libSM.so.6
libX11 libX11.so.6
libXext libXext.so.6
libXft libXft.so.2
libXi libXi.so.6
libXrender libXrender.so.1
libXt libXt.so.6
libXtst libXtst.so.6
libasound libasound.so.2
libatk-1.0 libatk-1.0.so.0
libcairo libcairo.so.2
libcairo-gobject libcairo-gobject.so.2
libcairo-script-interpreter libcairo-script-interpreter.so.2
libfontconfig libfontconfig.so.1
libfreetype libfreetype.so.6
libgdk-x11-2.0 libgdk-x11-2.0.so.0
libgdk_pixbuf-2.0 libgdk_pixbuf-2.0.so.0
libgdk_pixbuf_xlib-2.0 libgdk_pixbuf_xlib-2.0.so.0
libgio-2.0 libgio-2.0.so.0
libglib-2.0 libglib-2.0.so.0
libgmodule-2.0 libgmodule-2.0.so.0
libgobject-2.0 libgobject-2.0.so.0
libgthread-2.0 libgthread-2.0.so.0
libgtk-x11-2.0 libgtk-x11-2.0.so.0
libjpeg libjpeg.so.62
libpango-1.0 libpango-1.0.so.0
libpangocairo-1.0 libpangocairo-1.0.so.0
libpanoft2-1.0 libpangoft2-1.0.so.0
libpangoxft-1.0 libpangoxft-1.0.so.0
libpng12 libpng12.so.0
libtiff libtiff.so.5
libxcb libxcb.so.1

LFS 基础包

LFS是自己建立发行版的教育项目。

核心包:

  1. bash : shell
  2. bc : 数值计算
  3. binutils : 链接器、汇编器等构建工具
  4. coreutils : 查看操作文件和目录的基本工具
  5. diffutils :
  6. file : 文件类型
  7. findutils : 查找文件
  8. gawk : awk文本处理器
  9. grep :
  10. gzip :压缩解压缩gz
  11. m4 :通用的文本宏处理器
  12. man-db :
  13. ncurses :
  14. procps :
  15. psmisc :
  16. sed :文本处理器
  17. shadow :管理密码文件
  18. tar : 打包归档
  19. util-linux :
  20. zlib :压缩解压缩

语言运行时包:

  1. perl : 程序语言

可选:

  1. acl : 访问控制
  2. attr : 扩展属性
  3. autoconf :自动配置
  4. automake : 自动构建
  5. bison :yacc编译器
  6. bzip2 :压缩、解压缩
  7. check :校验
  8. dejagnu :测试程序框架
  9. diffutils :差异工具
  10. e2fsprogs :处理ext2系列文件系统的工具
  11. eudev :设备管理器
  12. expat :xml解析库
  13. expect :交互式脚本
  14. flex : lex词法分析器
  15. gcc :c、c++编译器集合
  16. gdbm :数据库管理器库
  17. gettext :国际化、本地化文本工具
  18. glibc :c标准库
  19. gmp :数学库
  20. gperf :哈希函数
  21. grep:搜索文本
  22. groff :格式化文本
  23. grub :引导管理器
  24. iana-etc :网络服务和协议
  25. inetutils :网络管理
  26. intltool :提取可翻译字符串
  27. iproute2 :网络工具包
  28. kbd :键盘表
  29. kmod :管理内核模块
  30. less :文本分页查看
  31. libcap :用户空间接口
  32. libelf :elf文件工具
  33. libffi :高级编程接口
  34. libpipeline :管道
  35. libtool :通用库工具
  36. linux kernel :内核
  37. make :构建工具
  38. man-pages :man帮助内容包
  39. meson :构建工具
  40. mpc :复数运算
  41. mpfr :多精度运算
  42. ninja :构建工具
  43. openssl :加密管理
  44. patch :补丁工具
  45. pkg-config :包配置
  46. procps-ng :监视过程
  47. psmisc :进程信息
  48. python3 :程序语言
  49. readline :命令行编辑和历史记录
  50. sysklogd :记录守护进程信息
  51. sysvinit :初始化
  52. tcl :测试工具
  53. texinfo :读取、写入、转换信息
  54. util-linux :实用工具包
  55. vim :编辑器
  56. xml::parser :expat交互perl模块
  57. xz utils :压缩解压缩xz

BLFS 基础包

相对LFS,BLFS内容更多。

核心包:

  1. at
  2. batch
  3. cpio
  4. ed
  5. fcrontab
  6. initd-tools
  7. lsb_release
  8. nspr
  9. nss
  10. pam
  11. pax
  12. sendmail(postfix或exim)
  13. time

桌面包:

  1. alsa
  2. atk
  3. cairo
  4. desktop-file-utils
  5. freetype
  6. fontconfig
  7. gdk-pixbuf
  8. glib2
  9. gtk+2
  10. icon-naming-utils
  11. libjpeg-turbo
  12. libpng
  13. libtiff
  14. libxml2
  15. mesalib
  16. pango
  17. xdg-utils
  18. xorg
  19. qt5(备选)

成像包:

  1. cups
  2. cups-filters
  3. ghostscript
  4. sane

图形包:

  1. gtk+3

LFS 建立步骤

  1. 基于现有发行版(debian、openmandriva、fedora、opensuse)构建
  2. 建立分区和文件系统
  3. 准备安装包
  4. 环境设置
  5. 安装、构建一个临时系统
  6. chroot进入临时系统
  7. 设置系统配置
  8. 设置内核和引导加载程序
  9. 完成

〇、准备宿主系统

cat > version-check.sh << "EOF"
#!/bin/bash
# Simple script to list version numbers of critical development tools
export LC_ALL=C
bash --version | head -n1 | cut -d" " -f2-4
MYSH=$(readlink -f /bin/sh)
echo "/bin/sh -> $MYSH"
echo $MYSH | grep -q bash || echo "ERROR: /bin/sh does not point to bash"
unset MYSH
echo -n "Binutils: "; ld --version | head -n1 | cut -d" " -f3-
bison --version | head -n1
if [ -h /usr/bin/yacc ]; then
echo "/usr/bin/yacc -> `readlink -f /usr/bin/yacc`";
elif [ -x /usr/bin/yacc ]; then
echo yacc is `/usr/bin/yacc --version | head -n1`
else
echo "yacc not found"
fi
bzip2 --version 2>&1 < /dev/null | head -n1 | cut -d" " -f1,6-
echo -n "Coreutils: "; chown --version | head -n1 | cut -d")" -f2
diff --version | head -n1
find --version | head -n1
gawk --version | head -n1
if [ -h /usr/bin/awk ]; then
echo "/usr/bin/awk -> `readlink -f /usr/bin/awk`";
elif [ -x /usr/bin/awk ]; then
echo awk is `/usr/bin/awk --version | head -n1`
else
echo "awk not found"
fi
gcc --version | head -n1
g++ --version | head -n1
ldd --version | head -n1 | cut -d" " -f2- # glibc version
grep --version | head -n1
gzip --version | head -n1
cat /proc/version
m4 --version | head -n1
make --version | head -n1
patch --version | head -n1
echo Perl `perl -V:version`
python3 --version
sed --version | head -n1
tar --version | head -n1
makeinfo --version | head -n1 # texinfo version
xz --version | head -
echo 'int main(){}' > dummy.c && g++ -o dummy dummy.c
if [ -x dummy ]
then echo "g++ compilation OK";
else echo "g++ compilation failed"; fi
rm -f dummy.c dummy
EOF

# 测试准备情况,如果没有安装对应的包,自行安装和配置(关键!!!)
chmod +x version-check.sh
./version-check.sh
版本要求(大于或等于):
Bash-3.2 (/bin/sh 应该是 bash 的符号链接或硬链接)
Binutils-2.25 (不建议使用 2.32 以后的版本,尚未经过测试)
Bison-2.7 (/usr/bin/yacc 应该是指向 bison 或执行 bison 的小型脚本的链接)
Bzip2-1.0.4
Coreutils-6.9
Diffutils-2.8.1
Findutils-4.2.31
Gawk-4.0.1 (/usr/bin/awk 应该是 gawk 的链接)
GCC-6.2 包括 C++ 编译器,g++ (9.2.0 以后的版本不建议使用,尚未经过测试)
Glibc-2.11 (2.30 以后的版本不建议使用,尚未经过测试)
Grep-2.5.1a
Gzip-1.3.12
Linux Kernel-3.2
M4-1.4.10
Make-4.0
Patch-2.5.4
Perl-5.8.8
Python-3.4
Sed-4.1.5
Tar-1.22
Texinfo-4.7
Xz-5.0.0
flex

一、建立分区和文件系统

#创建构建的目录结构,构建名为ddu的linux发行版。
mkdir -p ddu/mnt/{root,boot}
cd ddu

#创建映像盘文件
dd if=/dev/zero of=ddu.img bs=1G count=10 status=progress
# 格式化,gpt分区表,300M的efi启动分区,剩余ext4根分区
fdisk ddu.img
#省略操作过程....自行百度解决

# 加载loop设备,生成两个虚拟磁盘/dev/loop0p1,/dev/loop0p2
sudo losetup -Pf ddu.img

lsblk #确认磁盘信息

# 格式化
sudo mkfs.vfat /dev/loop0p1
sudo mkfs.ext4 /dev/loop0p2

# 挂载到 ./mnt/root 和./mnt/boot
sudo mount -t vfat /dev/loop0p1 mnt/boot
sudo mount -t ext4 /dev/loop0p2 mnt/root

# 设置LFS变量指向构建目标的根分区
export LFS=$(pwd)/mnt/root

# 注意确认LFS是否正确
echo $LFS

二、准备安装包

准备好下载的源码包链接:

# 创建存放包的文件夹
sudo mkdir $LFS/sources
# 赋予权限:可写并只有所有者可以删除
sudo chmod a+wt $LFS/sources

cd $LFS/sources

自行下载以下包(本文后面参考里面有链接):

acl attr autoconf automake bash bc binutils bison bzip2 check coreutils dejagnu diffutils e2fsprogs elfutils e2fsprogs elfutils expat file findutils flex gawk gcc gettext gperf grep groff gzip intltool iproute2 kbd kmod less libtool m4 make man-db meson mpc openssl patch perl pkg-config procps psmisc sed tar tcl texinfo tzdata util-linux vim nano

eudev gdbm glibc gdbm gmp grub2 Iana-Etc Inetutils LFS-Bootscripts libcap libffi libpipeline linuxkernel man-papes mpfr ninja Ncurses python3 readline shadow sysklogd sysvinit udev-lfs xml::parser xz zlib
# 创建临时工具链目录
sudo mkdir $LFS/tools
# 在用户的宿主系统中创建一个指向工具目录的链接
# 这很重要,因为编译的工具需要一个相对路径符号
sudo ln -sv $LFS/tools /
# 修改目录所有者为当前用户,这样就不需要用root权限写入了
sudo chown -v $USER $LFS/tools
cd $LFS/tools

# 创建环境变量文件
cat << EOF >.bashrc
# 关闭bash的命令记忆功能,每次都搜索路径上最新的命令
set +h
# 关闭新建目录和文件的写权限
umask 022
c0='\[\e[0m\]' #默认颜色
c1='\[\e[31m\]' #红色
c2='\[\e[32m\]' #绿色
c3='\[\e[33m\]' #黄色
c4='\[\e[34m\]' #蓝色
c5='\[\e[35m\]' #紫色
c6='\[\e[36m\]' #青色
c7='\[\e[37m\]' #白色
# 设置指示符
PS1="(\${c1}lfs\${c0})\${c2}\u\${c0}:\${c6}\w\${c0}\\$"
# 设置根目录
LFS=$(readlink -f "../")
LC_ALL=POSIX
LFS_TGT=$(uname -m)-lfs_ddu-linux-gnu
# 设置搜索路径
TOOLS=/tools
PATH=$TOOLS/bin:$PATH
export LFS LC_ALL LFS_TGT PATH
EOF

# 读取变量设置
. .bashrc

三、构建临时系统

库的三大要素:

  1. 平台名称(三元组):x86_64-pc-linux-gnu
    • ./config.guess
  2. 动态链接器:ld-linux-x86-64.so.2
  3. 动态链接名
    • readelf -l xxx | grep interpreter

编译步骤:

  1. 解压缩源码
  2. 在另一个文件夹编译

构造编译系统最关键的一环是搞懂路径。目标是构建一个和宿主系统无关的编译系统,因此它就不能使用宿主的路径。而应该使用能脱离宿主的路径表示。

因此提前构建了目标目录,并且构建了一个相对路径可以访问该目录:

  1. $LFS/tools
  2. /tools -> $LFS/tools
# 打印编译器使用的链接器
gcc -print-prog-name=ld

3.1 binutils

binutils包含了最基本的汇编和链接工具。因此成为第一个编译的包。

cd $LFS/sources
# 下载包,并解压
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/binutils/binutils-2.32.tar.xz
tar binutils-2.32.tar.xz
# 创建一个用来编译的文件夹
mkdir binutils
cd binutils

../binutils-2.32/config.guess #查看当前架构
# 注意 \ 结尾立即回车表示换行
# --prefix 安装路径
# --with-sysroot 交叉编译查找的目标系统根路径
# --with-lib-path 链接器搜索库路径
# --target 目标标识,构建交叉链接器
# --disable-nls 禁用国际化i18n
# --disable-werror 不要因为警告停止编译
../binutils-2.32/configure \
--prefix=$TOOLS \
--with-sysroot=$LFS \
--with-lib-path=$TOOLS/lib \
--target=$LFS_TGT \
--disable-nls \
--disable-werror
# 编译
# -j4 用四个线程并行编译
make -j4
# 创建目标lib文件夹
case $(uname -m) in
x86_64) mkdir -v $TOOLS/lib && ln -sv lib $TOOLS/lib64 ;;
esac
# 安装
make install
简略内容:
|-- bin
|   |-- x86_64-lfs_ddu-linux-gnu-addr2line
|   |-- x86_64-lfs_ddu-linux-gnu-ar
|   |-- x86_64-lfs_ddu-linux-gnu-as
|   |-- x86_64-lfs_ddu-linux-gnu-c++filt
|   |-- x86_64-lfs_ddu-linux-gnu-elfedit
|   |-- x86_64-lfs_ddu-linux-gnu-gprof
|   |-- x86_64-lfs_ddu-linux-gnu-ld
|   |-- x86_64-lfs_ddu-linux-gnu-ld.bfd
|   |-- x86_64-lfs_ddu-linux-gnu-nm
|   |-- x86_64-lfs_ddu-linux-gnu-objcopy
|   |-- x86_64-lfs_ddu-linux-gnu-objdump
|   |-- x86_64-lfs_ddu-linux-gnu-ranlib
|   |-- x86_64-lfs_ddu-linux-gnu-readelf
|   |-- x86_64-lfs_ddu-linux-gnu-size
|   |-- x86_64-lfs_ddu-linux-gnu-strings
|   `-- x86_64-lfs_ddu-linux-gnu-strip
`-- x86_64-lfs_ddu-linux-gnu
    |-- bin
    |   |-- ar
    |   |-- as
    |   |-- ld
    |   |-- ld.bfd
    |   |-- nm
    |   |-- objcopy
    |   |-- objdump
    |   |-- ranlib
    |   |-- readelf
    |   `-- strip
#$ 命令输出
$$LFS_TGT-ld --verbose |grep SEARCH

SEARCH_DIR("=/tools/x86_64-lfs_ddu-linux-gnu/lib64"); SEARCH_DIR("/tools/lib"); SEARCH_DIR("=/tools/x86_64-lfs_ddu-linux-gnu/lib");

$$LFS_TGT-readelf -l $TOOLS/bin/$LFS_TGT-ld | grep interpreter

      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

结论: 构建x86_64-lfs_ddu-linu-gnu目标平台的链接器和二进制工具。最重要的链接器ld的库搜索目录已经设置为/tools目录,即脱离了原平台。但是动态链接器还是指向/lib64,这个原平台的路径。这将在第二次编译时解决此问题。

3.2 gcc

gcc是一个编译器套件。gcc需要gcc、gmp、mpfr、mpc包。

cd $LFS/sources
# 下载
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/gcc/gcc-9.2.0/gcc-9.2.0.tar.xz
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/gmp/gmp-6.1.2.tar.xz
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/mpfr/mpfr-4.0.2.tar.xz
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/mpc/mpc-1.1.0.tar.gz
# 解压缩
tar -xvf gcc-9.2.0.tar.xz
tar -xvf gmp-6.1.2.tar.xz
tar -xvf mpfr-4.0.2.tar.xz
tar -xvf mpc-1.1.0.tar.gz
# 创建快捷方式来组合层次结构
ln -srv gmp-6.1.2 gcc-9.2.0/gmp
ln -srv mpfr-4.0.2 gcc-9.2.0/mpfr
ln -srv mpc-1.1.0 gcc-9.2.0/mpc 

# 修改gcc配置
cd gcc-9.2.0
# 以下代码将路径从默认的/lib{,64}/ld 改为/tools/lib{,64}/ld,将/usr改为/tools/usr
#
for file in gcc/config/{linux,i386/linux{,64}}.h
do
cp -uv $file{,.orig}
sed -e "s@/lib\(64\)\?\(32\)\?/ld@$TOOLS&@g" \
-e "s@/usr@$TOOLS@g" $file.orig > $file
echo "
#undef STANDARD_STARTFILE_PREFIX_1
#undef STANDARD_STARTFILE_PREFIX_2
#define STANDARD_STARTFILE_PREFIX_1 \"$TOOLS/lib/\"
#define STANDARD_STARTFILE_PREFIX_2 \"\"" >> $file
touch $file.orig
done

case $(uname -m) in
x86_64)
sed -e '/m64=/s/lib64/lib/' \
-i.orig gcc/config/i386/t-linux64
;;
esac
# 创建编译文件夹

cd ..
mkdir gcc
cd gcc

# 编译
# --with-newlib 禁止编译libc相关代码
# --without-headers  禁止查找标准头文件
# --with-local-prefix 搜索宿主主目录
# --with-native-system-header-dir 搜索目标头文件
../gcc-9.2.0/configure \
--target=$LFS_TGT \
--prefix=$TOOLS \
--with-glibc-version=2.3 \
--with-sysroot=$LFS \
--with-newlib \
--without-headers \
--with-local-prefix=$TOOLS \
--with-native-system-header-dir=$TOOLS/include \
--disable-nls \
--disable-shared \
--disable-multilib \
--disable-decimal-float \
--disable-threads \
--disable-libatomic \
--disable-libgomp \
--disable-libquadmath \
--disable-libssp \
--disable-libvtv \
--disable-libstdcxx \
--enable-languages=c,c++ 

make -j4

# 安装
make install
内容简略:
|-- bin
|   |-- x86_64-lfs_ddu-linux-gnu-c++
|   |-- x86_64-lfs_ddu-linux-gnu-cpp
|   |-- x86_64-lfs_ddu-linux-gnu-g++
|   |-- x86_64-lfs_ddu-linux-gnu-gcc
|   |-- x86_64-lfs_ddu-linux-gnu-gcc-9.2.0
|   |-- x86_64-lfs_ddu-linux-gnu-gcc-ar
|   |-- x86_64-lfs_ddu-linux-gnu-gcc-nm
|   |-- x86_64-lfs_ddu-linux-gnu-gcc-ranlib
|   |-- x86_64-lfs_ddu-linux-gnu-gcov
|   |-- x86_64-lfs_ddu-linux-gnu-gcov-dump
|   `-- x86_64-lfs_ddu-linux-gnu-gcov-tool
|-- libexec
|   `-- gcc
|       `-- x86_64-lfs_ddu-linux-gnu
|           `-- 9.2.0
|               |-- cc1
|               |-- cc1plus
|               |-- collect2
|               |-- install-tools
|               |   |-- fixinc.sh
|               |   |-- fixincl
|               |   |-- mkheaders
|               |   `-- mkinstalldirs
|               |-- liblto_plugin.la
|               |-- liblto_plugin.so -> liblto_plugin.so.0.0.0
|               |-- liblto_plugin.so.0 -> liblto_plugin.so.0.0.0
|               |-- liblto_plugin.so.0.0.0
|               |-- lto-wrapper
|               |-- lto1
|               `-- plugin
|                   `-- gengtype
|-- lib
|   |-- gcc
|   |   `-- x86_64-lfs_ddu-linux-gnu
|   |       `-- 9.2.0
|   |           |-- libgcc.a
|   |           |-- libgcov.a
|   |           `-- plugin
|   |               |-- libcc1plugin.la
|   |               |-- libcc1plugin.so -> libcc1plugin.so.0.0.0
|   |               |-- libcc1plugin.so.0 -> libcc1plugin.so.0.0.0
|   |               |-- libcc1plugin.so.0.0.0
|   |               |-- libcp1plugin.la
|   |               |-- libcp1plugin.so -> libcp1plugin.so.0.0.0
|   |               |-- libcp1plugin.so.0 -> libcp1plugin.so.0.0.0
|   |               `-- libcp1plugin.so.0.0.0
|   |-- libcc1.la
|   |-- libcc1.so -> libcc1.so.0.0.0
|   |-- libcc1.so.0 -> libcc1.so.0.0.0
|   `-- libcc1.so.0.0.0
# 命令输出
$cat <<EOF >dummy.c
//#include <stdio.h>
int main(void){
  //printf("hi ddu.\n");
  return 0;
}
EOF
$$LFS_TGT-gcc dummy.c -Wl,--verbose 2>&1 | grep succeeded

attempt to open .../tools/lib/../lib/crt1.o succeeded
attempt to open .../tools/lib/../lib/crti.o succeeded
attempt to open .../ddu/bin/../lib/gcc/x86_64-lfs_ddu-linux-gnu/9.2.0/crtbegin.o succeeded
attempt to open /tmp/ccJIBgUq.o succeeded
attempt to open .../ddu/bin/../lib/gcc/x86_64-lfs_ddu-linux-gnu/9.2.0/libgcc.a succeeded
attempt to open .../tools/lib/../lib/libc.so succeeded
attempt to open .../tools/lib/libc.so.6 succeeded
attempt to open .../tools/lib/libc_nonshared.a succeeded
attempt to open .../tools/lib/ld-linux-x86-64.so.2 succeeded
attempt to open .../ddu/bin/../lib/gcc/x86_64-lfs_ddu-linux-gnu/9.2.0/libgcc.a succeeded
attempt to open .../ddu/bin/../lib/gcc/x86_64-lfs_ddu-linux-gnu/9.2.0/crtend.o succeeded
attempt to open .../tools/lib/../lib/crtn.o succeeded

$$LFS_TGT-readelf -l a.out | grep interpreter

      [Requesting program interpreter: /tools/lib64/ld-linux-x86-64.so.2]

$$LFS_TGT-readelf -l $(which $LFS_TGT-gcc) |grep interpreter

      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

结论: 同样的方法,构建了新目标平台的gcc编译器,但是gcc是需要修改源代码内的配置,才能正确指定搜索库的,因为一部分路径已经是写死在代码中,不被构建参数和环境所影响。编译完成的gcc,已经将被其编译的程序的动态链接器地址指向/tools. 但其自身的动态链接器还是/lib64,因此必须通过第二轮编译gcc来改变。

3.3 linux headers

linux 内核头文件,是很多编译项目需要的基础。

# 下载解压
# 注意,内核不要超过5.2!!!
cd $LFS/sources
wget https://mirrors.tuna.tsinghua.edu.cn/kernel/v5.x/linux-5.2.21.tar.xz
tar -xvf linux-5.2.21.tar.xz

# 创建编译目录
mkdir linux
cd linux

# 编译输出头文件到dest目录
make -f ../linux-5.2.21/Makefile mrproper
make -f ../linux-5.2.21/Makefile INSTALL_HDR_PATH=dest headers_install

# 复制到目标
mkdir -v $TOOLS/include
cp -rv dest/include/* $TOOLS/include

3.4 glibc

c标准库,绝大部分命令都会链接和使用这个库。

交叉编译glibc,$LFS_TGT-gcc需要这个库支持来编译。

# 下载解压
cd $LFS/sources
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/glibc/glibc-2.30.tar.xz
tar -xvf glibc-2.30.tar.xz
# 打FHS兼容补丁
wget http://www.linuxfromscratch.org/patches/lfs/9.0/glibc-2.30-fhs-1.patch
cd glibc-2.30
patch -p1 -i ../glibc-2.30-fhs-1.patch
# 修复内核问题
sed -i '/asm.socket.h/a# include <linux/sockios.h>' \
sysdeps/unix/sysv/linux/bits/socket.h
cd ..
# 创建编译目录
mkdir glibc
cd glibc

# 编译
# --host 编译主机
# --build 编译目标
# --enable-kernel 支持的内核最低版本
# --with-headers 内核头文件
../glibc-2.30/configure \
--prefix=$TOOLS \
--host=$LFS_TGT \
--build=$(../glibc-2.30/scripts/config.guess) \
--enable-kernel=4.19 \
--with-headers=$TOOLS/include

make -j4

# 安装
make install
内容概要:
bin/
|-- catchsegv
|-- gencat
|-- getconf
|-- getent
|-- iconv
|-- ldd
|-- locale
|-- localedef
|-- makedb
|-- mtrace
|-- pcprofiledump
|-- pldd
|-- sotruss
|-- sprof
|-- tzselect
`-- xtrace
sbin/
|-- iconvconfig
|-- ldconfig
|-- nscd
|-- sln
|-- zdump
`-- zic
lib/
|-- ld-2.30.so
|-- ld-linux-x86-64.so.2 -> ld-2.30.so
|-- libc-2.30.so
|-- libc.a
|-- libc.so
|-- libc.so.6 -> libc-2.30.so
# $ 命令输出:
$$LFS_TGT-gcc dummy.c
$$LFS_TGT-readelf -l locale |grep interpreter

      [Requesting program interpreter: /tools/lib/ld-linux-x86-64.so.2]

$ldconfig -v

../sbin/ldconfig: Warning: ignoring configuration file that cannot be opened: /tools/etc/ld.so.conf: No such file or directory
../sbin/ldconfig: Can't stat /tools/lib64: No such file or directory
../sbin/ldconfig: Can't stat /tools/libx32: No such file or directory
/tools/lib:
        libnss_files.so.2 -> libnss_files-2.30.so
        libSegFault.so -> libSegFault.so
        libBrokenLocale.so.1 -> libBrokenLocale-2.30.so
        libresolv.so.2 -> libresolv-2.30.so
        libmemusage.so -> libmemusage.so
        libutil.so.1 -> libutil-2.30.so
        libpcprofile.so -> libpcprofile.so
        libthread_db.so.1 -> libthread_db-1.0.so
        libcc1.so.0 -> libcc1.so.0.0.0
        libnss_compat.so.2 -> libnss_compat-2.30.so
        libnss_dns.so.2 -> libnss_dns-2.30.so
        libc.so.6 -> libc-2.30.so
        libpthread.so.0 -> libpthread-2.30.so
        ld-linux-x86-64.so.2 -> ld-2.30.so
        libnsl.so.1 -> libnsl-2.30.so
        libdl.so.2 -> libdl-2.30.so
        libcrypt.so.1 -> libcrypt-2.30.so
        libnss_hesiod.so.2 -> libnss_hesiod-2.30.so
        libm.so.6 -> libm-2.30.so
        librt.so.1 -> librt-2.30.so
        libnss_db.so.2 -> libnss_db-2.30.so
        libanl.so.1 -> libanl-2.30.so
        libmvec.so.1 -> libmvec-2.30.so

结论: 这一步使用新的ggc编译器交叉编译生成对应的动态链接器和c标准库,该动态链接器搜索/tools目录。

3.5 libstdc++

c++的标准库,它是gcc的一部分

cd $LFS/sources/gcc
mkdir c++
cd c++

# 编译
../gcc-9.2.0/libstdc++-v3/configure \
--host=$LFS_TGT \
--prefix=$TOOLS \
--disable-multilib \
--disable-nls \
--disable-libstdcxx-threads \
--disable-libstdcxx-pch \
--with-gxx-include-dir=$TOOLS/$LFS_TGT/include/c++/9.2.0

make  -j4

# 安装
make install

3.6 binutils 第二遍

用生成的工具链重新编译一次。

cd $LFS/sources/binutils
rm -fr *

# 编译
# 使用之前编译的工具进行原生编译
../binutils-2.32/configure \
CC=$LFS_TGT-gcc \
AR=$LFS_TGT-ar \
RANLIB=$LFS_TGT-ranlib \
--prefix=$TOOLS \
--disable-nls \
--disable-werror \
--with-lib-path=$TOOLS/lib \
--with-sysroot 

make -j4

# 安装
make install

# 准备新的链接器
make -C ld clean
# 库地址要添加/tools/lib否则报错:
# undefined reference to `pthread_setspecific@GLIBC_2.2.5'
make -C ld LIB_PATH=/usr/lib:/lib
cp -v ld/ld-new $TOOLS/bin
# 注意,链接器有问题会产生错误:
# lib/crti.o: unable to initialize decompress status for section .debug_aranges
#ln -sv ld-new $TOOLS/bin/ld
内容概要:
bin/
|-- addr2line
|-- ar
|-- as
|-- c++filt
|-- elfedit
|-- gprof
|-- ld
|-- ld.bfd
|-- nm
|-- objcopy
|-- objdump
|-- ranlib
|-- readelf
|-- size
|-- strings
|-- strip
x86_64-pc-linux-gnu/
|--
# $ 命令输出
$readelf -l $(which ld) | grep interpreter      

[Requesting program interpreter: /tools/lib64/ld-linux-x86-64.so.2]

$ld --verbose |grep SEARCH

SEARCH_DIR("=/tools/x86_64-pc-linux-gnu/lib64"); SEARCH_DIR("/tools/lib"); SEARCH_DIR("=/tools/x86_64-pc-linux-gnu/lib");

$ld-new --verbose |grep SEARCH

SEARCH_DIR("=/tools/x86_64-pc-linux-gnu/lib64"); SEARCH_DIR("/usr/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("=/tools/x86_64-pc-linux-gnu/lib");

结论: 生成了没有前缀的链接器和汇编器,而且,也正确的链接到目标平台的动态链接器上。同时,为下一阶段准备一个新的链接器,搜索目标平台的/usr/lib:/lib

3.7 gcc 第二遍

cd $LFS/sources

# 修改gcc配置
cd gcc-9.2.0

#补充完整的gcc头文件,产生完整版gcc
mkdir -pv $TOOLS/lib/gcc/$LFS_TGT/9.2.0/include-fixed/

cat gcc/limitx.h gcc/glimits.h gcc/limity.h > \
$TOOLS/lib/gcc/$LFS_TGT/9.2.0/include-fixed/limits.h

# 修改默认动态链接器位置
for file in gcc/config/{linux,i386/linux{,64}}.h ; do 
cp -uv $file{,.orig}; 
# 从/lib*/ld* 替换到 /tools/lib*/ld*
sed -e "s@/lib\(64\)\?\(32\)\?/ld@$TOOLS&@g" \
-e "s@/usr@$TOOLS@g" $file.orig > $file; 
# 搜索库前缀/tools/lib/
echo "
#undef STANDARD_STARTFILE_PREFIX_1
#undef STANDARD_STARTFILE_PREFIX_2
#define STANDARD_STARTFILE_PREFIX_1 \"$TOOLS/lib/\"
#define STANDARD_STARTFILE_PREFIX_2 \"\"" >> $file; 

touch $file.orig; 
done

# 编译
cd ../gcc
rm -rf *
../gcc-9.2.0/configure \
CC=$LFS_TGT-gcc \
CXX=$LFS_TGT-g++ \
AR=$LFS_TGT-ar \
RANLIB=$LFS_TGT-ranlib \
--prefix=$TOOLS \
--with-local-prefix=$TOOLS \
--with-native-system-header-dir=$TOOLS/include \
--enable-languages=c,c++ \
--disable-libstdcxx-pch \
--disable-multilib \
--disable-bootstrap \
--disable-libgomp 

#多线程编译可能偶尔会出错,再尝试即可
time make -j4

# 安装
make install
ln -sv gcc $TOOLS/bin/cc

3.8 tcl

tcl、expect、dejagnu 三个包是测试用的。

安装内容:

  1. tclsh8.6
  2. tclsh 链接
  3. libtcl8.6.so
  4. libtclstub8.6.a
# 下载解压缩
cd $LFS/sources
wget https://downloads.sourceforge.net/tcl/tcl8.6.9-src.tar.gz
tar -xvf tcl8.6.9-src.tar.gz

# 创建构建目录
mkdir tcl
cd tcl

# 编译
../tcl8.6.9/unix/configure --prefix=$TOOLS
make -j4

# 测试(可略过)
TZ=UTC make test

# 安装
make install
chmod -v u+w $TOOLS/lib/libtcl8.6.so
ln -sv tclsh8.6 $TOOLS/bin/tclsh

3.9 expect

安装内容:

  1. expect
  2. libexpect-5.45.so
# 下载解压缩
cd $LFS/sources
wget https://prdownloads.sourceforge.net/expect/expect5.45.4.tar.gz
tar -xvf expect5.45.4.tar.gz 

# 修改配置
cd expect5.45.4
cp -v configure{,.orig}
# 将默认的/usr/local/bin/stty 替换为/bin/stty
sed 's:/usr/local/bin:/bin:' configure.orig >configure
cd ..

# 创建构建目录
mkdir expect
cd expect

# 编译
../expect5.45.4/configure \
--prefix=$TOOLS \
--with-tcl=$TOOLS/lib \
--with-tclinclude=$TOOLS/include 

time make -j4

# 安装
make SCRIPTS="" install

3.10 dejagnu

安装内容:

  1. runtest
# 下载解压
cd $LFS/sources
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/dejagnu/dejagnu-1.6.2.tar.gz
tar -xvf dejagnu-1.6.2.tar.gz

# 创建构建目录
mkdir dejagnu
cd dejagnu

# 编译
../dejagnu-1.6.2/configure --prefix=$TOOLS
time make -j4

# 安装
make install

3.11 m4

宏处理器

# 下载解压
cd $LFS/sources
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/m4/m4-1.4.18.tar.xz
tar -xvf m4-1.4.18.tar.xz

# 修改配置
cd m4-1.4.18
# 必须修改,否则报错:
# m4-1.4.18/lib/freadahead.c:92:3: error: #error "Please port gnulib freadahead.c
sed -i 's/IO_ftrylockfile/IO_EOF_SEEN/' lib/*.c
echo "#define _IO_IN_BACKUP 0x100" >> lib/stdio-impl.h
cd ..
# 创建构建目录
mkdir m4
cd m4

# 编译
../m4-1.4.18/configure --prefix=$TOOLS
time make -j4

# 安装
make install

3.12 ncurses

用于字符屏幕处理。

# 下载解压
cd $LFS/sources
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/ncurses/ncurses-6.1.tar.gz

# 修改配置
cd ncurses-6.1
sed -i s/mawk// configure
cd ..

# 构建目录
mkdir ncurses
cd ncurses
# 编译
../ncurses-6.1/configure \
--prefix=$TOOLS \
--with-shared \
--without-debug \
--without-ada \
--enable-widec \
--enable-overwrite

time make -j4
# 安装
make install 
ln -sv libncursesw.so $TOOLS/lib/libncurses.so

3.13 bash

bash shell

# 下载解压
cd $LFS/sources
tar -xvf bash-5.0.tar.gz 

# 创建构建目录
mkdir bash
cd bash
# 编译
../bash-5.0/configure --prefix=$TOOLS --without-bash-malloc
time make -j4
# 安装
make install
ln -sv bash $TOOLS/bin/sh

3.14 bison

语法生成器

# 下载解压
cd $LFS/sources
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/bison/bison-3.4.1.tar.xz
tar -xvf bison-3.4.1.tar.xz 

# 创建构建目录
mkdir bison
cd bison
# 编译
../bison-3.4.1/configure --prefix=$TOOLS
time make -j4
# 安装
make install

3.15 bzip

压缩解压缩

# 下载解压
cd $LFS/sources
wget  https://www.sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz
tar -xvf bzip2-1.0.8.tar.gz 

# 编译
cd bzip2-1.0.8/
make -j4
# 安装
make PREFIX=$TOOLS install

3.16 coreutils

包含显示设置基本系统特性的工具

# 下载解压
cd $LFS/sources
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/coreutils/coreutils-8.31.tar.xz
tar -xvf coreutils-8.31.tar.xz 

# 创建构建目录
mkdir coreutils
cd coreutils
# 编译
../coreutils-8.31/configure --prefix=$TOOLS \
--enable-install-program=hostname
time make -j4
# 安装
make install

3.17 diffutils

显示内容差异

# 下载解压
cd $LFS/sources
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/diffutils/diffutils-3.7.tar.xz
tar -xvf diffutils-3.7.tar.xz
# 创建构建目录
mkdir diffutils
cd diffutils
# 编译
../diffutils-3.7/configure --prefix=$TOOLS
time make -j4
# 安装
make install

3.18 file

判定文件类型

# 下载解压
cd $LFS/sources
wget ftp://ftp.astron.com/pub/file/file-5.37.tar.gz
md5sum file-5.37.tar.gz && echo 80c29aca745466c6c24d11f059329075
tar -xvf file-5.37.tar.gz
# 创建构建目录
mkdir file
cd file
# 编译
../file-5.37/configure  --prefix=$TOOLS
time make -j4
# 安装
make install

3.19 findutils

查找文件

# 下载解压
cd $LFS/sources
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/findutils/findutils-4.6.0.tar.gz
tar -xvf findutils-4.6.0.tar.gz
# 修改配置
cd findutils-4.6.0/
sed -i 's/IO_ftrylockfile/IO_EOF_SEEN/' gl/lib/*.c
sed -i '/unistd/a #include <sys/sysmacros.h>' gl/lib/mountlist.c
echo "#define _IO_IN_BACKUP 0x100" >> gl/lib/stdio-impl.h
cd ..
# 创建构建目录
mkdir findutils
cd findutils
# 编译
../findutils-4.6.0/configure --prefix=$TOOLS
time make -j4
# 安装
make install

3.20 gawk

操作文本的程序

# 下载解压
cd $LFS/sources
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/gawk/gawk-5.0.1.tar.xz
tar -xvf gawk-5.0.1.tar.xz
# 创建构建目录
mkdir gawk
cd gawk
# 编译
../gawk-5.0.1/configure --prefix=$TOOLS
time make -j4
# 安装
make install

3.21 gettext

国际化、本地化工具

# 下载解压
cd $LFS/sources
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/gettext/gettext-0.20.1.tar.xz
tar -xvf gettext-0.20.1.tar.xz
# 创建构建目录
mkdir gettext
cd gettext
# 编译
../gettext-0.20.1/configure --disable-shared
time make -j4
# 安装
cp -v gettext-tools/src/{msgfmt,msgmerge,xgettext} $TOOLS/bin

3.22 grep

搜索文本

# 下载解压
cd $LFS/sources
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/grep/grep-3.3.tar.xz
tar -xvf grep-3.3.tar.xz
# 创建构建目录
mkdir grep
cd grep
# 编译
../grep-3.3/configure --prefix=$TOOLS
time make -j4
# 安装
make install

3.23 gzip

压缩解压缩

# 下载解压
cd $LFS/sources
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/gzip/gzip-1.10.tar.xz
tar -xvf gzip-1.10.tar.xz
# 创建构建目录
mkdir gzip
cd gzip
# 编译
../gzip-1.10/configure --prefix=$TOOLS
time make -j4
# 安装
make install

3.24 make

构建工具

# 下载解压
cd $LFS/sources
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/make/make-4.2.1.tar.gz
tar -xvf make-4.2.1.tar.gz
# 修改配置
cd make-4.2.1/
sed -i '211,217 d; 219,229 d; 232 d' glob/glob.c
cd ..
# 创建构建目录
mkdir make
cd make
# 编译
../make-4.2.1/configure --prefix=$TOOLS --without-guile
time make -j4
# 安装
make install

3.25 patch

补丁程序

# 下载解压
cd $LFS/sources
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/patch/patch-2.7.6.tar.xz
tar -xvf patch-2.7.6.tar.xz
# 创建构建目录
mkdir patch
cd patch
# 编译
../patch-2.7.6/configure --prefix=$TOOLS
time make -j4
# 安装
make install

3.26 perl

perl语言

# 下载解压
cd $LFS/sources
wget https://www.cpan.org/src/5.0/perl-5.30.0.tar.xz
tar -xvf perl-5.30.0.tar.xz

# 编译
# 重新编译应该删除文件夹从新开始
cd perl-5.30.0/
sh Configure -des -Dprefix=$TOOLS -Dlibs=-lm -Uloclibpth -Ulocincpth
time make -j4
# 安装
cp -v perl cpan/podlators/scripts/pod2man $TOOLS/bin
mkdir -pv $TOOLS/lib/perl5/5.30.0
cp -Rv lib/* $TOOLS/lib/perl5/5.30.0

3.27 python3

python 语言

# 下载解压
cd $LFS/source
wget https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tar.xz
tar -xvf Python-3.7.4.tar.xz 
# 修改配置
cd Python-3.7.4/
sed -i '/def add_multiarch_paths/a \        return' setup.py
# 编译
../Python-3.7.4/configure  --prefix=$TOOLS --without-ensurepip

time make -j4
# 安装
make install

3.28 sed

流编辑器

# 下载解压
cd $LFS/sources
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/sed/sed-4.7.tar.xz
tar -xvf sed-4.7.tar.xz
# 创建构建目录
mkdir sed
cd sed
# 编译
../sed-4.7/configure --prefix=$TOOLS
time make -j4
# 安装
make install

3.29 tar

打包归档

# 下载解压
cd $LFS/sources
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/tar/tar-1.32.tar.xz
tar -xvf tar-1.32.tar.xz
# 创建构建目录
mkdir tar
cd tar
# 编译
../tar-1.32/configure --prefix=$TOOLS
time make -j4
# 安装
make install

3.30 texinfo

读写转换info page

# 下载解压
cd $LFS/sources
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/texinfo/texinfo-6.6.tar.xz
tar -xvf texinfo-6.6.tar.xz
# 创建构建目录
mkdir texinfo
cd texinfo
# 编译
../texinfo-6.6/configure --prefix=$TOOLS
time make -j4
# 安装
make install

3.31 xz

压缩解压缩

# 下载解压
cd $LFS/sources
wget https://tukaani.org/xz/xz-5.2.4.tar.xz
tar -xvf xz-5.2.4.tar.xz
# 创建构建目录
mkdir xz
cd xz
# 编译
../xz-5.2.4/configure --prefix=$TOOLS
time make -j4
# 安装
make install

四、chroot到目标构建系统

# 创建挂载目录
sudo mkdir -pv $LFS/{dev,proc,sys,run}
# 创建初始设备
sudo mknod -m 600 $LFS/dev/console c 5 1
sudo mknod -m 666 $LFS/dev/null c 1 3
# 借用宿主当前设备目录
sudo mount -v --bind /dev $LFS/dev
# 挂载内核虚拟文件系统
sudo mount -vt devpts devpts $LFS/dev/pts -o gid=5,mode=620
sudo mount -vt proc proc $LFS/proc
sudo mount -vt sysfs sysfs $LFS/sys
sudo mount -vt tmpfs tmpfs $LFS/run
# 挂载shm 虚拟文件系统
# /dev/shm 如果是目录,已经借用宿主设备目录的内容,不用多做什么
# /dev/shm 如果是链接,就创建$LFS/目标的目录,chroot之后内核可将信息存放在此目录
# 如 /dev/shm -> /run/shm
# 创建 $LFS//run/shm
[ -h $LFS/dev/shm ] && mkdir -pv $LFS/$(readlink $LFS/dev/shm)

# 为了再次快速进入环境,把代码记录起来
# 机器重启后:. lfsmounts 就能重新挂载
cat << EOF > lfsmounts
# 借用宿主当前设备目录
sudo mount -v --bind /dev \$LFS/dev
# 挂载内核虚拟文件系统
sudo mount -vt devpts devpts \$LFS/dev/pts -o gid=5,mode=620
sudo mount -vt proc proc \$LFS/proc
sudo mount -vt sysfs sysfs \$LFS/sys
sudo mount -vt tmpfs tmpfs \$LFS/run
# 挂载shm 虚拟文件系统
# /dev/shm 如果是目录,已经借用宿主设备目录的内容,不用多做什么
# /dev/shm 如果是链接,就创建$LFS/目标的目录,chroot之后内核可将信息存放在此目录
# 如 /dev/shm -> /run/shm
# 创建 $LFS//run/shm
[ -h \$LFS/dev/shm ] && mkdir -pv \$LFS/\$(readlink \$LFS/dev/shm)
EOF

软件包管理技术

关于动态链接库:

  1. 升级glibc最好重构lfs
  2. 动态库升级,名字更新需要重新编译。如libfoo.so.1更新到libfoo.so.2

独立目录安装:

  1. 须同步更新环境变量:PATH,LD_LIBRARY_PATH,MANPATH, INFOPATH,CPPFLAGS等包含独立目录

伪装安装目录:

./configure --prefix=/usr
make
make DESTDIR=/usr/pkg/libfoo/1.1 install #让支持这种安装方式的包的动态链接库标识为安装到/usr

创建软件包存档(主流): 1.使用伪安装目录技术安装到目录,然后将目录打包:rpm,apt,pkg-utils,portage等。slackware基于tar,不管理依赖。

其他技术:基于时间戳、追踪安装脚本、基于用户

多系统部署LFS,需要更新配置:

  1. /etc/
    1. hosts
    2. fstab
    3. passwd
    4. group
    5. shadow
    6. ld.so.conf
    7. sysconfig/
      1. rc.site
      2. network
      3. ifconfig.eth0
  2. 可能要更新内核

进入chroot环境

# 将再次进入chroot环境需要的步骤记录起来
# 注意后面的\结束表示在一行
cat <<EOF > lfschroot
# chroot 切换根到$LFS
# /tools/bin/env -i 清除环境变量
sudo chroot $LFS \
$TOOLS/bin/env -i \
HOME=/root \
TERM=$TERM \
LFS=/ \
TOOLS=$TOOLS \
LFS_TGT=$LFS_TGT \
PS1='(chroot)(lfs)\u:\w\\$ ' \
PATH=/bin:/usr/bin:/sbin:/usr/sbin:$TOOLS/bin:$TOOLS/sbin \
$TOOLS/bin/bash --login +h 
EOF

# 切换根
# 下次再切换进来只需要:
# . .bashrc
# . lfschroot
source  lfschroot

# 根据FHS标准创建相关目录
mkdir -pv /{bin,boot,etc/{opt,sysconfig},home,lib/firmware,mnt,opt}
mkdir -p /{media/{floppy,cdrom},sbin,srv,var}
# 创建0750权限的/root 目录
install -dv -m 0750 /root
# 创建1777权限的/tmp 目录
install -dv -m 1777 /tmp /var/tmp
mkdir -pv /usr/{,local/}{bin,include,lib,sbin,src}
mkdir -pv /usr/{,local/}share/{color,dict,doc,info,locale,man}
mkdir -v /usr/{,local/}share/{misc,terminfo,zoneinfo}
mkdir -v /usr/libexec
mkdir -pv /usr/{,local/}share/man/man{1..8}
case $(uname -m) in x86_64) mkdir -v /lib64 ;; esac
mkdir -v /var/{log,mail,spool}
ln -sv /run /var/run
ln -sv /run/lock /var/lock
mkdir -pv /var/{opt,cache,lib/{color,misc,locate},local}

# 创建临时替代的工具链接
ln -sv $TOOLS/bin/{bash,cat,chmod,dd,echo,ln,mkdir,pwd,rm,stty,touch} /bin 
ln -sv $TOOLS/bin/{env,install,perl,printf} /usr/bin
ln -sv $TOOLS/lib/libgcc_s.so{,.1} /usr/lib
ln -sv $TOOLS/lib/libstdc++.{a,so{,.6}} /usr/lib
ln -sv bash /bin/sh

# /etc/mtab
ln -sv /proc/self/mounts /etc/mtab
# /etc/passwd
cat > /etc/passwd << "EOF"
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/dev/null:/bin/false
daemon:x:6:6:Daemon User:/dev/null:/bin/false
messagebus:x:18:18:D-Bus Message Daemon User:/var/run/dbus:/bin/false
nobody:x:99:99:Unprivileged User:/dev/null:/bin/false
EOF
# /etc/group
cat > /etc/group << "EOF"
root:x:0:
bin:x:1:daemon
sys:x:2:
kmem:x:3:
tape:x:4:
tty:x:5:
daemon:x:6:
floppy:x:7:
disk:x:8:
lp:x:9:
dialout:x:10:
audio:x:11:
video:x:12:
utmp:x:13:
usb:x:14:
cdrom:x:15:
adm:x:16:
messagebus:x:18:
input:x:24:
mail:x:34:
kvm:x:61:
wheel:x:97:
nogroup:x:99:
users:x:999:
EOF

# 重新登录,将I hove no name!改成root
exec $TOOLS/bin/bash --login +h
# 创建日志
touch /var/log/{btmp,lastlog,faillog,wtmp}
chgrp -v utmp /var/log/lastlog
chmod -v 664 /var/log/lastlog
chmod -v 600 /var/log/btmp

4.1 linux 头文件

内核头文件

make -f ../linux-5.2.21/Makefile mrproper
make -f ../linux-5.2.21/Makefile INSTALL_HDR_PATH=dest headers_install
find dest/include \( -name .install -o -name ..install.cmd \) -delete
cp -rv dest/include/* /usr/include

4.2 man-pages

帮助文档

cd /sources
wget https://www.kernel.org/pub/linux/docs/man-pages/man-pages-5.02.tar.xz
tar -xvf man-pages-5.02.tar.xz
cd man-pages-5.02

make install

4.3 glibc

c语言基本库

内容包括:

  1. catchsegv 段错误终止时创建调用历史
  2. gencat 消息条目
  3. getconf 显示文件系统相关的系统配置变量的值
  4. getenv 获取系统数据库的内容
  5. iconv 字符集转换
  6. iconvconfig 创建加速加载模块配置
  7. ldconfig 配置动态链接器的运行时环境
  8. ldd 报告程序或动态库所依赖的动态库
  9. lddlibc4 协助ldd处理目标文件
  10. locale 本地化语言环境的信息
  11. localedef 编译本地化语言环境
  12. makedb 创建简单文本数据库
  13. mtrace 读取解析内存跟踪文件,并显示
  14. nscd 名字服务缓存后台服务
  15. pcprofiledump 分析生成的dump信息
  16. pldd 列出进程的动态共享目标
  17. sln 静态链接ln程序
  18. sotruss 跟踪指定命令的动态库函数调用
  19. sprof 读取并显示共享目标分析数据
  20. tzselect 询问地理信息获取时区
  21. xtrace 跟踪程序执行过程并打印
  22. zdump 时区数据输出
  23. zic 时区数据编译

库:

  1. ld-2.30.so 用于动态库执行的辅助程序
  2. libBrokenLocale 修复损坏
  3. libSegFault 段错误处理
  4. libanl 异步名字查找
  5. libc c库
  6. libcrypt 密码库
  7. libdl 动态链接接口函数库
  8. libg 不包含函数的空库
  9. libm 数学库
  10. libmcheck 检查内存分配
  11. libnsl 网络服务
  12. libnss 名称服务切换
  13. libpcprofile 预加载配置的可执行文件
  14. libpthread POSIX线程库
  15. libresolv 域名风暴
  16. librt POSIX.1b扩展函数
  17. libthread_db 多线程调试
  18. libutil 标准工具函数

# 增加兼容lib
case $(uname -m) in
i?86)
ln -sfv ld-linux.so.2 /lib/ld-lsb.so.3
;;
x86_64) ln -sfv ../lib/ld-linux-x86-64.so.2 /lib64
ln -sfv ../lib/ld-linux-x86-64.so.2 /lib64/ld-lsb-x86-64.so.3
;;
esac

# 编译
cd glibc
# -ffile-prefix-map 添加/tools到/usr的路径映射
# libc_cv_slibdir 设置库路径
../glibc-2.30/configure --prefix=/usr \
CC="gcc -ffile-prefix-map=$TOOLS=/usr" \
--disable-werror \
--enable-kernel=4.19 \
--enable-stack-protector=strong \
--with-headers=/usr/include \
libc_cv_slibdir=/lib

time make -j4
# 检查测试
# 占位
case $(uname -m) in
i?86)
ln -sfnv $PWD/elf/ld-linux.so.2
/lib ;;
x86_64) ln -sfnv $PWD/elf/ld-linux-x86-64.so.2 /lib ;;
esac

time make check
# 安装
touch /etc/ld.so.conf
## 注意这里要修改源代码目录的Makefile
sed '/test-installation/s@$(PERL)@echo not running@' -i ../glibc-2.30/Makefile
make install
# nscd配置
cp ../glibc-2.30/nscd/nscd.conf /etc/nscd.conf
mkdir -pv /var/cache/nscd
# 本地语言包
mkdir -pv /usr/lib/locale
localedef -i POSIX -f UTF-8 C.UTF-8 2>/dev/null || true
localedef -i cs_cz -f UTF-8 cs_CZ.UTF-8
localedef -i de_DE -f ISO-8859-1 de_DE
localedef -i de_DE@euro -f ISO-8859-15 de_DE@euro
localedef -i de_DE -f UTF-8 de_DE.UTF-8
localedef -i el_GR -f ISO-8859-7 el_GR
localedef -i en_US -f ISO-8859-1 en_US
localedef -i en_US -f UTF-8 en_US.UTF-8
localedef -i zh_CN -f GB18030 zh_CN.GB18030
localedef -i zh_CN -f UTF-8 zh_CN.UTF-8
localedef -i zh_HK -f BIG5-HKSCS zh_HK.BIG-5-HKSCS
localedef -i zh_TW -f BIG5 zh_TW.BIG-5
localedef -i ja_JP -f EUC-JP ja_JP
localedef -i ja_JP -f SHIFT_JIS ja_JP.SIJS
localedef -i ja_JP -f UTF-8 ja_JP.UTF-8
localedef -i zh_TW -f UTF-8 zh_TW.UTF-8
# 配置/etc/nsswitch.conf
cat > /etc/nsswitch.conf << "EOF"
# Begin /etc/nsswitch.conf
passwd: files
group: files
shadow: files
hosts: files dns
networks: files
protocols: files
services: files
ethers: files
rpc: files
# End /etc/nsswitch.conf
EOF
# 配置时区
# 在chroot外部下载并解压
wget https://www.iana.org/time-zones/repository/releases/tzdata2019b.tar.gz
tar -xvf tzdata2019b.tar.gz -C tzdata2019b
# chroot内
cd tzdata2019b
ZONEINFO=/usr/share/zoneinfo
mkdir -pv $ZONEINFO/{posix,right}

for tz in etcetera southamerica northamerica europe africa antarctica asia australasia backward pacificnew systemv; do zic -L /dev/null -d $ZONEINFO ${tz}; zic -L /dev/null -d $ZONEINFO/posix ${tz}; zic -L leapseconds -d $ZONEINFO/right ${tz}; done

cp -v zone.tab zone1970.tab iso3166.tab $ZONEINFO
# 使用上海时区
# 可以用tzselect获取正确的本地时区
zic -d $ZONEINFO -p Asia/Shanghai 
unset ZONEINFO

ln -sfv /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

# 配置动态库加载器
cat > /etc/ld.so.conf << "EOF"
# Begin /etc/ld.so.conf
/usr/local/lib
/opt/lib
# 添加目录下的额外配置文件
include /etc/ld.so.conf.d/*.conf
EOF

# 调整工具链
#ld 指向新的/usr/lib:/lib 搜索地址
mv -v $TOOLS/bin/{ld,ld-old}
mv -v $TOOLS/$(uname -m)-pc-linux-gnu/bin/{ld,ld-old}
mv -v $TOOLS/bin/{ld-new,ld}
ln -sv $TOOLS/bin/ld $TOOLS/$(uname -m)-pc-linux-gnu/bin/ld
# 修改gcc指向新动态链接器和库
gcc -dumpspecs | sed -e "s@$TOOLS@@g" \
-e '/\*startfile_prefix_spec:/{n;s@.*@/usr/lib/ @}' \
-e '/\*cpp:/{n;s@$@ -isystem /usr/include@}' > \
`dirname $(gcc --print-libgcc-file-name)`/specs

# 测试工具链
echo 'int main(){printf("hello lfs.\n");return 0;}' > dummy.c
cc dummy.c -v -Wl,--verbose &>dummy.log
readelf -l a.out
# 输出:
# hello lfs.
./a.out
# 输出:
#/usr/lib/../lib/crt1.o succeeded
#/usr/lib/../lib/crti.o succeeded
#/usr/lib/../lib/crtn.o succeeded
grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log
# 输出:
# #include <...> search starts here:
# /usr/include
grep -B1 '^ /usr/include' dummy.log
# 输出:
# SEARCH_DIR("/usr/lib")
# SEARCH_DIR("/lib")
grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
# 输出:
# attempt to open /lib/libc.so.6 succeeded
grep "/lib.*/libc.so.6 " dummy.log
# 输出:
# found ld-linux-x86-64.so.2 at /lib/ld-linux-x86-64.so.2
grep found dummy.log

4.4 zlib

压缩解压缩

# 下载(chroot外部,因为wget没有安装)
wget https://zlib.net/zlib-1.2.11.tar.xz
tar -xvf zlib-1.2.11.tar.xz
mkdir zlib

# 编译
cd /sources/zlib
../zlib-1.2.11/configure --prefix=/usr

time make -j4
# 测试
time make check

# 安装
make install
mv -v /usr/lib/libz.so.* /lib
ln -sfv ../../lib/libz.so.1.2.11 /usr/lib/libz.so

4.5 file

判断文件类型

# 下载(chroot外部,因为wget没有安装)
# 之前已经下载了

# 编译
cd /sources/file
rm -fr *

../file-5.37/configure --prefix=/usr
time make -j4
# 安装
make install

4.6 readline

命令行历史记录

# 下载(chroot外部,因为wget没有安装)
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/readline/readline-8.0.tar.gz
tar -xvf readline-8.0.tar.gz 
mkdir readline
# 修改配置
cd readline-8.0
sed -i '/MV.*old/d' Makefile.in 
sed -i '/{OLDSUFF}/c:' support/shlib-install 
cd ..
# 编译
cd /sources/readline
../readline-8.0/configure \
--prefix=/usr \
--disable-static \
--docdir=/usr/share/doc/readline-8.0

make SHLIB_LIBS="-L$TOOLS/lib -lncursesw"
# 安装
make SHLIB_LIBS="-L$TOOLS/lib -lncursesw" install

mv -v /usr/lib/lib{readline,history}.so.* /lib
chmod -v u+w /lib/lib{readline,history}.so.*
ln -sfv ../../lib/libreadline.so.8 /usr/lib/libreadline.so
ln -sfv ../../lib/libhistory.so.8 /usr/lib/libhistory.so

install -v -m664 doc/*.{ps,pdf,html,dvi} /usr/share/doc/readline-8.0

4.7 m4

宏处理器

# 下载(chroot外部,因为wget没有安装)

# 编译
cd /sources/m4
rm -rf *
../m4-1.4.18/configure --prefix=/usr
time make -j4
# 安装
make install

4.8 bc

浮点计算器

# 下载(chroot外部,因为wget没有安装)
wget https://github.com/gavinhoward/bc/archive/2.1.3/bc-2.1.3.tar.gz
tar -xvf bc-2.1.3.tar.gz 
# 编译
cd /sources/bc-2.1.3
PREFIX=/usr CC=gcc Cflags="-std=c99" ./configure.sh -G -O3
time make -j4
# 安装
make install

4.9 binutils

链接器,汇编器,其他目标文件工具

内容:

  1. addr2line 转换程序地址为文件名称和行号
  2. ar 归档
  3. as 汇编器
  4. c++filt 链接器用来过滤c++和java符号,防止函数重载冲突
  5. dwp DWARF打包
  6. elfedit 更新elf文件头
  7. gprof 显示调用关系图
  8. ld 链接器
  9. ld.gold 纯elf链接器
  10. ld.bfd ld的硬链接
  11. nm 列出目标文件符号
  12. objcopy 转换目标文件类型
  13. objdump 显示目标文件信息
  14. ranlib 生成归档索引
  15. readelf 显示elf文件信息
  16. size 显示目标文件各部分大小
  17. strings 打印二进制文件内的字符串
  18. strip 从目标文件除去符号

库:

  1. libbfd 二进制文件描述库
  2. libopcodes 用于处理操作码
# 下载(chroot外部,因为wget没有安装)
# 之前已经下载
# 配置
cd /sources/binutils-2.32
sed -i '/@\tincremental_copy/d' gold/testsuite/Makefile.in
cd ..
# 编译
# 应显示:spawn ls
cd binutils
expect -c "spawn ls"
rm -rf *
../binutils-2.32/configure \
--prefix=/usr \
--enable-gold \
--enable-ld=default \
--enable-plugins \
--enable-shared \
--disable-werror \
--enable-64-bit-bfd \
--with-system-zlib

time make tooldir=/usr
# 安装
make tooldir=/usr install

4.10 gmp

数学库

库:

  1. libgmp 精度数学函数
  2. libgmpxx c++版
# 下载(chroot外部,因为wget没有安装)
# 之前已准备好
# 编译
cd /sources
mkdir gmp
cd gmp
../gmp-6.1.2/configure \
--prefix=/usr \
--enable-cxx \
--disable-static \
--docdir=/usr/share/doc/gmp-6.1.2

time make -j4
make html
# 测试
make check 2>&1 | tee gmp-check-log
# 确认190个测试通过
awk '/# PASS:/{total+=$3} ; END{print total}' gmp-check-log
# 安装
make install
make install-html

4.11 mpfr

多精度数学库

库:

  1. libpmpfr
# 下载(chroot外部,因为wget没有安装)
# 之前已经准备好
# 编译
cd /sources
mkdir mpfr
cd mpfr
../mpfr-4.0.2/configure \
--prefix=/usr \
--disable-static \
--enable-thread-safe \
--docdir=/usr/share/doc/mpfr-4.0.2

time make -j4
make html
# 测试
make check
# 安装
make install
make install-html

4.12 mpoc

高精度复数四舍五入数学库

库:

  1. libmpoc
# 下载(chroot外部,因为wget没有安装)
# 之前准备好
# 编译
cd /sources

mkdir mpc
cd mpc
../mpc-1.1.0/configure \
--prefix=/usr \
--disable-static \
--docdir=/usr/share/doc/mpc-1.1.0

make -j4
make html
# 测试
make check
# 安装
make install
make install-html

4.13 shadow

密码文件

内容:

  1. chage 密码更新最大天数
  2. chfn 更改用户全名及其他信息
  3. chgpasswd 批处理更新组密码
  4. chpasswd 批处理更新用户密码
  5. chsh 更改默认shell
  6. expiry 密码过期策略
  7. faillog 登录失败日志
  8. gpasswd 管理组
  9. groupadd 添加组
  10. groupdel 删除组
  11. groupomems 用户管理自己组的成员
  12. groupmod 修改组名称和gid
  13. grpck 验证组文件完整性/etc/group和/etc/gshadow
  14. grpconv 从普通组升级为shadow组
  15. grpunconv 同上,升级并删除
  16. lastlog 最近登录
  17. login 登录
  18. logoutd 退出登录
  19. newgidmap 用户命名空间的gid映射
  20. newgrp 更改当前gid
  21. newuidmap 用户命名空间的uid映射
  22. newusers 批量创建和更新用户帐号
  23. nologin 显示账户不可用信息
  24. passwd 更改密码
  25. pwck 验证密码文件完整性:/etc/passwd和/etc/shadow
  26. pwconv 从普通密码文件升级为shadow密码文件
  27. pwunconv 同上,且删除
  28. sg 更改当前gid
  29. su 更改当前用户
  30. useradd 添加新用户
  31. userdel 删除用户
  32. usermod 修改用户配置
  33. vigr 编辑组密码文件
  34. vipw 编辑用户密码文件
# 下载(chroot外部,因为wget没有安装)
wget https://github.com/shadow-maint/shadow/releases/download/4.7/shadow-4.7.tar.xz
tar -xvf shadow-4.7.tar.xz 
mkdir shadow

# 修改配置
cd /sources/shadow-4.7
sed -i 's/groups$(EXEEXT) //' src/Makefile.in
find man -name Makefile.in -exec sed -i 's/groups\.1 / /'
find man -name Makefile.in -exec sed -i 's/groups\.1 / /' {} \;
find man -name Makefile.in -exec sed -i 's/getspnam\.3 / /' {} \;
find man -name Makefile.in -exec sed -i 's/passwd\.5 / /' {} \;
sed -i -e 's@#ENCRYPT_METHOD DES@ENCRYPT_METHOD SHA512@' -e 's@/var/spool/mail@/var/mail@' etc/login.defs
sed -i 's/1000/999/' etc/useradd

# 编译
../shadow-4.7/configure --sysconfdir=/etc --with-group-name-max-length=32

time make -j4
# 安装
make install
mv -v /usr/bin/passwd /bin
# 设置
pwconv
grpconv

passwd root

4.14 gcc

c/c++编译器

内容:

  1. c++ :c++编译器
  2. cc :c编译器
  3. cpp : c预处理器
  4. g++ : c++编译器
  5. gcc : c编译器
  6. gcc-ar: ar的封装
  7. gcc-nm: nm的封装
  8. gcc-ranlib: ranlib的封装
  9. gcov : 覆盖测试
  10. gcov-dump : gcda和gcno配置工具
  11. gcov-tool : gcda配置工具

库:

  1. libasan 地址消毒剂运行时
  2. libatomic gcc原子内置运行时
  3. libccl c预处理库
  4. libgcc 包含用于gcc的运行时支持
  5. libgcov 指示gcc启用分析时该库被链接
  6. libgomp 用于多语言共享内存平行编程openmp
  7. liblsan 泄漏消毒剂运行时库
  8. liblto——plugin gcc的链接时间优化LTO插件
  9. libquadmath gcc四精度数学库
  10. libssp 堆栈溢出保护
  11. libstdc++ 标准c++库
  12. libstdc++fs 文件系统库
  13. libsupc++ c++语言支持例程
  14. libtsan 数据速率检测工具
  15. libubsan 未定义行为消毒剂
# 下载(chroot外部,因为wget没有安装)
# 之前已经下载
# 编译
cd /sources/gcc
rm -rf *
SED=sed ../gcc-9.2.0/configure \
--prefix=/usr \
--enable-languages=c,c++ \
--disable-multilib \
--disable-bootstrap \
--with-system-zlib

time make -j4
# 检查
ulimit -s 
chown -Rv nobody .
su nobody -s /bin/bash -c "PATH=$PATH make -k check"
# 查看结果
../gcc-9.2.0/contrib/test_summary
# 安装
make install
# 清除不需要的目录
rm -rf /usr/lib/gcc/$(gcc -dumpmachine)/9.2.0/include-fixed/bits/
# 恢复之前被修改的所有者权限
chown -v -R root:root \
/usr/lib/gcc/*linux-gnu/9.2.0/include{,-fixed}
# 兼容FHS标准
ln -sv ../usr/bin/cpp /lib
ln -sv gcc /usr/bin/cc
# 链接时间优化
install -v -dm755 /usr/lib/bfd-plugins
ln -sfv ../../libexec/gcc/$(gcc -dumpmachine)/9.2.0/liblto_plugin.so /usr/lib/bfd-plugins/

# 不知道是那里出错了,gcc默认生成的动态链接地址不正确,补救的方法如下:
# ------------------补丁----------------------
# 修改gcc指向新动态链接器和库
gcc -dumpspecs | sed -e "s@$TOOLS@@g" \
-e '/\*startfile_prefix_spec:/{n;s@.*@/usr/lib/ @}' \
`dirname $(gcc --print-libgcc-file-name)`/specs
#-e '/\\*cpp:/{n;s@$@ -isystem /usr/include@}' > \
# ------------------------------------------- 

# 移动到正确的位置
mkdir -pv /usr/share/gdb/auto-load/usr/lib
mv -v /usr/lib/*gdb.py /usr/share/gdb/auto-load/usr/lib

# 编译测试(这些数据很重要!!!)
cd ..
cc dummy.c  -v -Wl,--verbose &> dummy.log
# 输出:[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
readelf -l a.out | grep interpreter
# 输出:
#/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../lib/crt1.o succeeded
#/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../lib/crti.o succeeded
#/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/../../../../lib/crtn.o succeeded
grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log 
# 输出:
##include <...> search starts here:
#/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/include
#/usr/local/include
#/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/include-fixed
#/usr/include
grep -B4 '^ /usr/include' dummy.log 
# 输出:
#SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib64")
#SEARCH_DIR("/usr/local/lib64")
#SEARCH_DIR("/lib64")
#SEARCH_DIR("/usr/lib64")
#SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib")
#SEARCH_DIR("/usr/local/lib")
#SEARCH_DIR("/lib")
#SEARCH_DIR("/usr/lib");
grep 'SEARCH.*/usr/lib' dummy.log | sed 's|; |\n|g'
# 输出:attempt to open /lib/libc.so.6 succeeded
grep "/lib.*/libc.so.6" dummy.log 
# 输出:found ld-linux-x86-64.so.2 at /lib/ld-linux-x86-64.so.2
grep found dummy.log 
# 执行编译后的程序
./a.out

4.15 bzip

压缩解压缩

# 下载(chroot外部,因为wget没有安装)
wget http://www.linuxfromscratch.org/patches/lfs/9.0/bzip2-1.0.8-install_docs-1.patch

# 配置
cd /sources/bzip2-1.0.8
patch -Np1 -i ../bzip2-1.0.8-install_docs-1.patch

sed -i 's@\(ln -s -f \)$(PREFIX)/bin/@\1@' Makefile
sed -i "s@(PREFIX)/man@(PREFIX)/share/man@g" Makefile

# 编译
make clean
make -f Makefile-libbz2_so 
make clean
make 
# 安装
make PREFIX=/usr install
cp -v bzip2-shared /bin/bzip2
cp -av libbz2.so* /lib
ln -sv ../../lib/libbz2.so.1.0 /usr/lib/libbz2.so
rm -v /usr/bin/{bunzip2,bzcat,bzip2}
ln -sv bzip2 /bin/bunzip2
ln -sv bzip2 /bin/bzcat

4.16 pkg-config

配置make,指定包的云信息

# 下载(chroot外部,因为wget没有安装)
wget https://pkg-config.freedesktop.org/releases/pkg-config-0.29.2.tar.gz
tar -xvf pkg-config-0.29.2.tar.gz 
mkdir pkg-config
# 编译
cd /sources/pkg-config

../pkg-config-0.29.2/configure \
--prefix=/usr \
--with-internal-glib \
--disable-host-tool \
--docdir=/usr/share/doc/pkg-config-0.29.2

time make -j4
# 测试
time make check
# 安装
make install

4.17 ncurses

字符屏幕处理

# 下载(chroot外部,因为wget没有安装)
# 之前下了

# 配置
cd /sources/ncurses-6.1
sed -i '/LIBTOOL_INSTALL/d' c++/Makefile.in
# 编译
cd /sources/ncurses
rm -rf *

../ncurses-6.1/configure --prefix=/usr --mandir=/usr/share/man --with-shared --without-debug --without-normal --enable-pc-files --enable-widec

time make -j4
# 安装
make install
# 移动到正确的位置
mv -v /usr/lib/libncursesw.so.6* /lib 
ln -sfv ../../lib/libncursesw.so.6 /usr/lib/libncursesw.so 
# 让普通版链接到宽字符版
for lib in ncurses form panel menu ; do \
rm -vf /usr/lib/lib${lib}.so; \\
echo "INPUT(-l${lib}w)" > /usr/lib/lib${lib}.so; \\
ln -sfv ${lib}w.pc /usr/lib/pkgconfig/${lib}.pc; \
done
# 支持-lcurses
rm -vf /usr/lib/libcursesw.so
echo "INPUT(-lncursesw)" > /usr/lib/libcursesw.so
ln -sfv libncurses.so /usr/lib/libcurses.so
# 文档
mkdir -v /usr/share/doc/ncurses-6.1
cp -v -R doc/* /usr/share/doc/ncurses-6.1

4.18 attr

# 下载(chroot外部,因为wget没有安装)
wget http://download.savannah.gnu.org/releases/attr/attr-2.4.48.tar.gz
tar -xvf attr-2.4.48.tar.gz 
mkdir attr


# 编译
cd /sources/attr
../attr-2.4.48/configure --prefix=/usr --bindir=/bin --disable-static --sysconfdir=/etc --docdir=/usr/share/doc/attr-2.4.48
time make -j4
# 安装
make install 
mv -v /usr/lib/libattr.so.* /lib
ln -sfv ../../lib/libattr.so.1.1.2448 /usr/lib/libattr.so

4.19 acl

文件访问控制表

# 下载(chroot外部,因为wget没有安装)
wget http://download.savannah.gnu.org/releases/acl/acl-2.2.53.tar.gz
tar -xvf acl-2.2.53.tar.gz 
mkdir acl
# 编译
cd /sources/acl
../acl-2.2.53/configure --prefix=/usr --bindir=/bin --disable-static --libexecdir=/usr/lib --docdir=/usr/share/doc/acl-2.2.53

time make -j4
# 安装
make install
mv -v /usr/lib/libacl.so.* /lib
ln -sfv ../../lib/libacl.so.1.1.2253 /usr/lib/libacl.so

4.20 libcap

权限

# 下载(chroot外部,因为wget没有安装)
wget https://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/libcap-2.27.tar.xz
tar -xvf libcap-2.27.tar.xz 

# 配置
cd libcap-2.27/
sed -i '/install.*STALIBNAME/d' libcap/Makefile


# 编译
cd /sources/libcap-2.27/
time make -j4
# 安装
make RAISE_SETFCAP=no lib=lib prefix=/usr install
chmod -v 755 /usr/lib/libcap.so.2.27
mv -v /usr/lib/libcap.so.* /lib
ln -sfv ../../lib/libcap.so.2 /usr/lib/libcap.so

4.21 sed

流编辑器

# 下载(chroot外部,因为wget没有安装)

# 配置
sed -i 's/usr/tools/' build-aux/help2man
sed -i 's/testsuite.panic-tests.sh//' Makefile.in

# 编译
cd /sources/sed
../sed-4.7/configure --prefix=/usr --bindir=/bin

time make -j4
make html
# 检查
time make check
# 安装
make install

install -d -m755 /usr/share/doc/sed-4.7
install -m644 doc/sed.html /usr/share/doc/sed-4.7/

4.22 psmisc

进程信息

# 下载(chroot外部,因为wget没有安装)
wget https://sourceforge.net/projects/psmisc/files/psmisc/psmisc-23.2.tar.xz
tar -xvf psmisc-23.2.tar.xz 
mkdir psmisc

# 编译
cd /sources/psmisc
../psmisc-23.2/configure --prefix=/usr
time make -j4
# 安装
make install
mv -v /usr/bin/fuser /bin
mv -v /usr/bin/killall /bin

4.23 iana-etc

网络协议

# 下载(chroot外部,因为wget没有安装)
wget http://anduin.linuxfromscratch.org/LFS/iana-etc-2.30.tar.bz2

# 编译
make 
# 安装
make install

4.24 bison

语法生成器

# 下载(chroot外部,因为wget没有安装)

# 配置
cd /sources/bison-3.4.1
sed -i '6855 s/mv/cp/' Makefile.in

# 编译
cd ../bison
../bison-3.4.1/configure --prefix=/usr --docdir=/usr/share/doc/bison-3.4.1

time make -j4
# 安装
make install

4.25 flex

识别文本模式

# 下载(chroot外部,因为wget没有安装)
wget https://github.com/westes/flex/releases/download/v2.6.4/flex-2.6.4.tar.gz
tar -xvf flex-2.6.4.tar.gz 
mkdir flex
# 配置
cd flex-2.6.4/
sed -i "/math.h/a #include <malloc.h>" src/flexdef.h
cd ..

# 编译
cd /sources/flex
HELP2MAN=/tools/bin/true ../flex-2.6.4/configure --prefix=/usr --docdir=/usr/share/doc/flex-2.6.4

time make -j4
# 安装
make install
ln -sv flex /usr/bin/lex

4.26 grep

文本搜索

# 下载(chroot外部,因为wget没有安装)


# 编译
cd /sources/grep
../grep-3.3/configure --prefix=/usr --bindir=/bin

time make -j4
# 测试
time make -k check
# 安装
make install

4.27 bash

bash shell

# 下载(chroot外部,因为wget没有安装)


# 编译
cd /sources/bash
../bash-5.0/configure --prefix=/usr --docdir=/usr/share/doc/bash-5.0 --without-bash-malloc --with-installed-readline
time make -j4
# 检查
chown -Rv nobody .
su nobody -s /bin/bash -c "PATH=$PATH HOME=/home make tests"
# 安装
make install
mv -vf /usr/bin/bash /bin
exec /bin/bash --login +h

4.28 libtool

通用库编译支持

# 下载(chroot外部,因为wget没有安装)
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/libtool/libtool-2.4.6.tar.xz
tar -xvf libtool-2.4.6.tar.xz 
mkdir libtool

# 编译
cd /sources/libtool
../libtool-2.4.6/configure --prefix=/usr

time make -j4
# 安装
make install

4.29 gdbm

gnu 数据库管理器

# 下载(chroot外部,因为wget没有安装)
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/gdbm/gdbm-1.18.1.tar.gz
tar -xvf gdbm-1.18.1.tar.gz 
mkdir gdbm
# 编译
cd /sources/gdbm
../gdbm-1.18.1/configure --prefix=/usr --disable-static --enable-libgdbm-compat
time make -j4
# 安装
make install

4.30 gperf

哈希函数

# 下载(chroot外部,因为wget没有安装)
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/gperf/gperf-3.1.tar.gz
tar -xvf gperf-3.1.tar.gz 

mkdir gperf

# 编译
cd /sources/gperf
../gperf-3.1/configure --prefix=/usr --docdir=/usr/share/doc/gperf-3.1
time make -j4
# 安装
make install

4.31 expat

解析xml

# 下载(chroot外部,因为wget没有安装)
wget https://prdownloads.sourceforge.net/expat/expat-2.2.7.tar.xz
tar -xvf expat-2.2.7.tar.xz 
mkdir expat

# 配置
cd /sources/expat-2.2.7
sed -i 's|usr/bin/env |bin/|' run.sh.in
cd ../expat
# 编译
../expat-2.2.7/configure --prefix=/usr --disable-static --docdir=/usr/share/doc/expat-2.2.7

time make -j4
# 安装
make install

4.32 inetutils

网络工具

# 下载(chroot外部,因为wget没有安装)
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/inetutils/inetutils-1.9.4.tar.xz
tar -xvf inetutils-1.9.4.tar.tar 
mkdir inetutils

# 编译
cd /sources/inetutils
../inetutils-1.9.4/configure --prefix=/usr --localstatedir=/var --disable-logger --disable-whois --disable-rcp --disable-rexec --disable-rlogin --disable-rsh --disable-servers 

time make -j4
# 检查
time make check
# 安装
make install
mv -v /usr/bin/{hostname,ping,ping6,traceroute} /bin
mv -v /usr/bin/ifconfig /sbin

4.33 perl

perl 语言

# 下载(chroot外部,因为wget没有安装)


# 编译(删掉旧的文件夹,重新解压)
cd perl-5.30.0
echo "127.0.0.1 localhost $(hostname)" > /etc/hosts
export BUILD_ZLIB=False
export BUILD_BZIP2=0

sh Configure -des -Dprefix=/usr -Dvendorprefix=/usr -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Duseshrplib -Dusethreads
time make -j4
# 测试
time make -k test
# 安装
make install
unset BUILD_ZLIB BUILD_BZIP2

4.34 XML-Parser

xml解释器的perl expat接口

# 下载(chroot外部,因为wget没有安装)
wget https://cpan.metacpan.org/authors/id/T/TO/TODDR/XML-Parser-2.44.tar.gz
tar -xvf XML-Parser-2.44.tar.gz 
# 编译(make clean先删除之前的编译)
perl Makefile.PL 
make 
# 安装
make install

4.35 intltool

从源文件中提取字符串国际化

# 下载(chroot外部,因为wget没有安装)
wget https://launchpad.net/intltool/trunk/0.51.0/+download/intltool-0.51.0.tar.gz
tar -xvf intltool-0.51.0.tar.gz 
mkdir intltool

# 配置
cd /sources/intltool-0.51.0
sed -i 's:\\\${:\\\$\\{:' intltool-update.in

cd ../intltool

# 编译
../intltool-0.51.0/configure --prefix=/usr
time make -j4
# 安装
make install
install -v -Dm644 doc/I18N-HOWTO /usr/share/doc/intltool-0.51.0/I18N-HOWTO

4.36 autoconf

自动配置,生成Makefile

# 下载(chroot外部,因为wget没有安装)
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/autoconf/autoconf-2.69.tar.xz
tar -xvf autoconf-2.69.tar.xz 
mkdir autoconf

# 配置
cd /sources/autoconf-2.69
sed '361 s/{/\\{/' -i bin/autoscan.in

# 编译
cd ../autoconf
../autoconf-2.69/configure --prefix=/usr

time make -j4
# 安装
make install

4.37 automake

生成Makefile

# 下载(chroot外部,因为wget没有安装)
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/automake/automake-1.16.1.tar.xz
tar -xvf automake-1.16.1.tar.xz 
mkdir automake

# 编译
cd /sources/automake
../automake-1.16.1/configure --prefix=/usr --docdir=/usr/share/doc/automake-1.16.1
time make -j4
# 安装
make install

4.38 xz

压缩解压缩

# 下载(chroot外部,因为wget没有安装)

# 编译
cd /sources/xz
../xz-5.2.4/configure --prefix=/usr --disable-static --docdir=/usr/share/doc/xz-5.2.4
time make -j4
# 安装
make install
mv -v /usr/bin/{lzma,unlzma,lzcat,xz,unxz,xzcat} /bin

mv -v /usr/lib/liblzma.so.* /lib
ln -svf ../../lib/liblzma.so.5.2.4 /usr/lib/liblzma.so

4.39 kmod

加载内核模块

# 下载(chroot外部,因为wget没有安装)
wget https://www.kernel.org/pub/linux/utils/kernel/kmod/kmod-26.tar.xz
tar -xvf kmod-26.tar.xz 
mkdir kmod

# 编译
cd /sources/kmod
../kmod-26/configure --prefix=/usr --bindir=/bin --sysconfdir=/etc --with-rootlibdir=/lib --with-xz --with-zlib 

time make -j4
# 安装
make install

for target in depmod insmod lsmod modinfo modprobe rmmod; do
ln -sfv ../bin/kmod /sbin/$target; 
done

ln -sfv kmod /bin/lsmod

4.40 gettext

本地化

# 下载(chroot外部,因为wget没有安装)
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/gettext/gettext-0.20.1.tar.xz
tar -xvf gettext-0.20.1.tar.xz
mkdir gettext
# 编译
../gettext-0.20.1/configure --prefix=/usr \
--disable-static \
--docdir=/usr/share/doc/gettext-0.20.1
time make -j4
# 安装
make install
chmod -v 0755 /usr/lib/preloadable_libintl.so

4.41 elfutils

elf工具

# 下载(chroot外部,因为wget没有安装)
wget https://sourceware.org/ftp/elfutils/0.177/elfutils-0.177.tar.bz2
tar -xvf elfutils-0.177.tar.bz2
mkdir elfutils
# 编译
cd /sources/elfutils
../elfutils-0.177/configure --prefix=/usr
time make -j4
# 测试
time make check
# 安装
make -C libelf install
install -vm644 config/libelf.pc /usr/lib/pkgconfig

4.42 libffi

可移植编程接口

# 下载(chroot外部,因为wget没有安装)
wget ftp://sourceware.org/pub/libffi/libffi-3.2.1.tar.gz
tar -xvf libffi-3.2.1.tar.gz
mkdir libffi
# 配置
sed -e '/^includesdir/ s/$(libdir).*$/$(includedir)/' \\
-i include/Makefile.in
sed -e '/^includedir/ s/=.*$/=@includedir@/' \
-e 's/^Cflags: -I${includedir}/Cflags:/' \
-i libffi.pc.in
# 编译
cd /sources/libffi
../libffi-3.2.1/configure --prefix=/usr --disable-static --with-gcc-arch=native

time make -j4
# 安装
make install

4.43 openssl

加密

# 下载(chroot外部,因为wget没有安装)
wget  https://www.openssl.org/source/openssl-1.1.1c.tar.gz
tar -xvf openssl-1.1.1c.tar.gz 
mkdir openssl
# 配置
sed -i '/\} data/s/ =.*$/;\n    memset(\&data, 0, sizeof(data));/' \
crypto/rand/rand_lib.c
# 编译
cd /sources/openssl

../openssl-1.1.1c/config --prefix=/usr \
--openssldir=/etc/ssl \
--libdir=lib \
shared \
zlib-dynamic

time make -j4
# 测试
time make test
# 安装
sed -i '/INSTALL_LIBS/s/libcrypto.a libssl.a//' Makefile
make MANSUFFIX=ssl install
# 文档
mv -v /usr/share/doc/openssl /usr/share/doc/openssl-1.1.1c
cp -vfr doc/* /usr/share/doc/openssl-1.1.1c

4.44 python3

程序语言

# 下载(chroot外部,因为wget没有安装)

# 编译(--enable-optimizations 优化可以不添加,编译速度快很多)
../Python-3.7.4/configure \
--prefix=/usr \
--enable-shared \
--with-system-expat \
--with-system-ffi \
--with-ensurepip=yes \
--enable-optimizations

time make -j4
# 安装
make install
# 文档

4.45 ninja

构建工具

# 下载(chroot外部,因为wget没有安装)
wget https://github.com/ninja-build/ninja/archive/v1.9.0/ninja-1.9.0.tar.gz
tar -xvf ninja-1.9.0.tar.gz
# 编译
cd ninja-1.9.0
python3 configure.py --bootstrap
# 测试
./ninja ninja_test
./ninja_test --gtest_filter=-SubprocessTest.SetWithLots
# 安装
install -vm755 ninja /usr/bin/

install -vDm644 misc/bash-completion \
/usr/share/bash-completion/completions/ninja

install -vDm644 misc/zsh-completion \
/usr/share/zsh/site-functions/_ninja

4.46 meson

构建工具

# 下载(chroot外部,因为wget没有安装)
wget https://github.com/mesonbuild/meson/releases/download/0.51.1/meson-0.51.1.tar.gz
tar -xvf meson-0.51.1.tar.gz
# 编译
cd meson-0.51.1
python3 setup.py build

# 安装
python3 setup.py install --root=dest
cp -rv dest/* /

4.47 coreutils

系统基本工具包

# 下载(chroot外部,因为wget没有安装)
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/coreutils/coreutils-8.31.tar.xz
tar -xvf coreutils-8.31.tar.xz

# 补丁
wget http://www.linuxfromscratch.org/patches/lfs/9.0/coreutils-8.31-i18n-1.patch
cd coreutils-8.31 
patch -Np1 -i ../coreutils-8.31-i18n-1.patch
sed -i '/test.lock/s/^/#/' gnulib-tests/gnulib.mk
# 编译
cd /sources/coreutils-8.31
autoreconf -fiv
FORCE_UNSAFE_CONFIGURE=1 ./configure \
--prefix=/usr \
--enable-no-install-program=kill,uptime
time make -j4
# 测试
make NON_ROOT_USERNAME=nobody check-root
echo "dummy:x:1000:nobody" >> /etc/group
chown -Rv nobody .
su nobody -s /bin/bash \
-c "PATH=$PATH make RUN_EXPENSIVE_TESTS=yes check"
sed -i '/dummy/d' /etc/group
# 安装
make install
mv -v /usr/bin/{cat,chgrp,chmod,chown,cp,date,dd,df,echo} /bin
mv -v /usr/bin/{false,ln,ls,mkdir,mknod,mv,pwd,rm} /bin
mv -v /usr/bin/{rmdir,stty,sync,true,uname} /bin
mv -v /usr/bin/chroot /usr/sbin
mv -v /usr/share/man/man1/chroot.1 /usr/share/man/man8/chroot.8
sed -i s/\"1\"/\"8\"/1 /usr/share/man/man8/chroot.8
mv -v /usr/bin/{head,nice,sleep,touch} /bin

4.48 check

c语言单元测试

# 下载(chroot外部,因为wget没有安装)
wget https://github.com/libcheck/check/releases/download/0.12.0/check-0.12.0.tar.gz
tar -xvf check-0.12.0.tar.gz
# 编译
../check-0.12.0/configure --prefix=/usr

time make -j4
# 安装(暂时还不能用,因为/usr/bin/gawk没安装)
make docdir=/usr/share/doc/check-0.12.0 install
sed -i "1 s$TOOLS/usr/" /usr/bin/checkmk

4.49 diffutils

文件和目录的差异工具

# 下载(chroot外部,因为wget没有安装)

# 编译
../diffutils-3.7/configure --prefix=/usr
time make -j4
# 安装
make install

4.50 gawk

操作文本

# 下载(chroot外部,因为wget没有安装)

# 配置
cd gawk-5.0.1
sed -i 's/extras//' Makefile.in
# 编译
../gawk-5.0.1/configure --prefix=/usr

time make -j4
# 测试
time make check
# 安装
make install
# 文档
mkdir -v /usr/share/doc/gawk-5.0.1

cp -v doc/{awkforai.txt,*.{eps,pdf,jpg}} /usr/share/doc/gawk-5.0.1

4.51 findutils

查找文件

# 下载(chroot外部,因为wget没有安装)

# 配置
cd findutils-4.6.0
sed -i 's/test-lock..EXEEXT.//' tests/Makefile.in

# 兼容glibc2.28以上
sed -i 's/IO_ftrylockfile/IO_EOF_SEEN/' gl/lib/*.c
sed -i '/unistd/a #include <sys/sysmacros.h>' gl/lib/mountlist.c
echo "#define _IO_IN_BACKUP 0x100" >> gl/lib/stdio-impl.h
# 编译
../findutils-4.6.0/configure --prefix=/usr --localstatedir=/var/lib/locate

time make -j4
# 检查
time make check
# 安装
make install
sed -i 's|find:=${BINDIR}|find:=/bin|' /usr/bin/updatedb

4.52 groff

格式化文本

# 下载(chroot外部,因为wget没有安装)
wget https://mirrors.tuna.tsinghua.edu.cn/gnu/groff/groff-1.22.4.tar.gz
tar -xvf groff-1.22.4.tar.gz

# 编译
PAGE=A4 ../groff-1.22.4/configure --prefix=/usr
time make -j1 # 必须单线程编译
# 安装
make install

4.53 grub

多重引导管理器

# 下载(chroot外部,因为wget没有安装)


# 编译
../grub-2.04/configure --prefix=/usr --sbindir=/sbin --sysconfdir=/etc --disable-werror --target=x86_64 --with-platform=efi

time make -j4
# 安装
make install
mv -v /etc/bash_completion.d/grub /usr/share/bash-completion/completions

4.54 less

文本分页查看

# 下载(chroot外部,因为wget没有安装)
wget  http://www.greenwoodsoftware.com/less/less-551.tar.gz
tar -xvf less-551.tar.gz

# 编译
../less-551/configure --prefix=/usr --sysconfdir=/etc
time make -j4
# 安装
make install

4.55 gzip

压缩解压缩

# 下载(chroot外部,因为wget没有安装)


# 编译
../gzip-1.10/configure --prefix=/usr
time make -j4
# 安装
make install
mv -v /usr/bin/gzip /bin

4.56 iproute2

网络工具

# 下载(chroot外部,因为wget没有安装)
wget https://www.kernel.org/pub/linux/utils/net/iproute2/iproute2-5.2.0.tar.xz
tar -xvf iproute2-5.2.0.tar.xz

# 配置
cd iproute2-5.2.0
sed -i /ARPD/d Makefile
rm -fv man/man8/arpd.8
sed -i 's/.m_ipt.o//' tc/Makefile
# 编译
cd /sources/iproute2-5.2.0
time make -j1
# 安装
make DOCDIR=/usr/share/doc/iproute2-5.2.0 install

4.57 kbd

键盘键位表

# 下载(chroot外部,因为wget没有安装)
wget https://www.kernel.org/pub/linux/utils/kbd/kbd-2.2.0.tar.xz
tar -xvf kbd-2.2.0.tar.xz
# 补丁
wget http://www.linuxfromscratch.org/patches/lfs/9.0/kbd-2.2.0-backspace-1.patch
cd kbd-2.2.0/
patch -Np1 -i ../kbd-2.2.0-backspace-1.patch 
# 配置
sed -i 's/\(RESIZECONS_PROGS=\)yes/\1no/g' configure
sed -i 's/resizecons.8 //' docs/man/man8/Makefile.in

# 编译
PKG_CONFIG_PATH=$TOOLS/lib/pkgconfig ../kbd-2.2.0/configure --prefix=/usr --disable-vlock
time make -j4
# 检查
time make check
# 安装
make install
# 文档
mkdir -v /usr/share/doc/kbd-2.2.0
cp -R -v ../kbd-2.2.0/docs/doc/* /usr/share/doc/kbd-2.2.0/

4.58 libpipeline

管道

# 下载(chroot外部,因为wget没有安装)


# 编译
../libpipeline-1.5.1/configure --prefix=/usr

time make -j4
# 安装
make install

4.59 make

构建工具

# 下载(chroot外部,因为wget没有安装)

# 配置(删除旧文件夹重新开始)
cd make-4.2.1/
sed -i '211,217 d; 219,229 d; 232 d' glob/glob.c
# 编译
../make-4.2.1/configure --prefix=/usr
time make -j4
# 测试
make PERL5LIB=$PWD/tests/ check
# 安装
make install

4.60 patch

补丁

# 下载(chroot外部,因为wget没有安装)


# 编译
../patch-2.7.6/configure --prefix=/usr
time make -j4
# 安装
make install

4.61 man-db

查看帮助

# 下载(chroot外部,因为wget没有安装)


# 编译
../man-db-2.8.6.1/configure \
--prefix=/usr \
--docdir=/usr/share/doc/man-db-2.8.6.1 \
--sysconfdir=/etc \
--disable-setuid \
--enable-cache-owner=bin \
--with-browser=/usr/bin/lynx \
--with-vgrind=/usr/bin/vgrind \
--with-grap=/usr/bin/grap \
--with-systemdtmpfilesdir= \
--with-systemdsystemunitdir=

time make -j4
# 安装
make install

4.62 tar

打包归档

# 下载(chroot外部,因为wget没有安装)


# 编译
FORCE_UNSAFE_CONFIGURE=1 ../tar-1.32/configure  \
--prefix=/usr \
--bindir=/bin

time make -j4
# 安装
make install
make -C doc install-html docdir=/usr/share/doc/tar-1.32

4.63 texinfo

信息页

# 下载(chroot外部,因为wget没有安装)


# 编译
../texinfo-6.6/configure --prefix=/usr --disable-static
time make -j4
# 安装
make install
make TEXMF=/usr/share/texmf install-tex
# 更新信息(可选)
pushd /usr/share/info
rm -v dir
for f in *
do install-info $f dir 2>/dev/null
done
popd

4.64 vim

编辑器

# 下载(chroot外部,因为wget没有安装)
wget http://github.com/vim/vim/archive/v8.1.1846/vim-8.1.1846.tar.gz
tar -xvf vim-8.1.1846.tar.gz
# 配置
cd vim-8.1.1846
echo '#define SYS_VIMRC_FILE "/etc/vimrc"' >> src/feature.h
# 编译(只能在源文件夹编译)
cd /sources/vim-8.1.1846
./configure --prefix=/usr
time make -j4
# 安装
make install
# 兼容vi
ln -sv vim /usr/bin/vi
for L in /usr/share/man/{,*/}man1/vim.1; do 
ln -sv vim.1 $(dirname $L)/vi.1; 
done

ln -sv ../vim/vim81/doc /usr/share/doc/vim-8.1.1846
# vim配置
cat > /etc/vimrc << "EOF"
" Begin /etc/vimrc
" Ensure defaults are set before customizing settings, not after
source $VIMRUNTIME/defaults.vim
let skip_defaults_vim=1
set nocompatible
set backspace=2
set mouse=
syntax on
if (&term == "xterm") || (&term == "putty")
set background=dark
endif
" End /etc/vimrc
EOF

4.65 procps-ng

进程监视

# 下载(chroot外部,因为wget没有安装)
wget https://sourceforge.net/projects/procps-ng/files/Production/procps-ng-3.3.15.tar.xz
tar -xvf procps-ng-3.3.15.tar.xz

# 编译(源文件夹编译)
cd procps-ng-3.3.15

./configure --prefix=/usr \
--exec-prefix= \
--libdir=/usr/lib \
--docdir=/usr/share/doc/procps-ng-3.3.15 \
--disable-static \
--disable-kill

time make -j4
# 测试
sed -i -r 's|(pmap_initname)\\\$|\1|' \
testsuite/pmap.test/pmap.exp

sed -i '/set tty/d' testsuite/pkill.test/pkill.exp
rm testsuite/pgrep.test/pgrep.exp
make check
# 安装
make install
mv -v /usr/lib/libprocps.so.* /lib
ln -sfv ../../lib/libprocps.so.7.1.0 /usr/lib/libprocps.so

4.66 util-linux

linux 实用程序包

# 下载(chroot外部,因为wget没有安装)
wget https://www.kernel.org/pub/linux/utils/util-linux/v2.34/util-linux-2.34.tar.xz
tar -xvf util-linux-2.34.tar.xz

# 编译
cd /sources/util-linux
# 创建存放目录
mkdir -pv /var/lib/hwclock

../util-linux-2.34/configure ADJTIME_PATH=/var/lib/hwclock/adjtime\
--docdir=/usr/share/doc/util-linux-2.34 \
--disable-chfn-chsh \
--disable-login\
--disable-nologin\
--disable-su\
--disable-setpriv\
--disable-runuser\
--disable-pylibmount \
--disable-static\
--without-python\
--without-systemd\
--without-systemdsystemunitdir
time make -j4
# 安装
make install

4.67 e2fsprogs

ext文件系统工具

# 下载(chroot外部,因为wget没有安装)
wget https://downloads.sourceforge.net/project/e2fsprogs/e2fsprogs/v1.45.3/e2fsprogs-1.45.3.tar.gz
tar -xvf e2fsprogs-1.45.3
# 编译
../e2fsprogs-1.45.3/configure \
--prefix=/usr \
--bindir=/bin \
--with-root-prefix="" \
--enable-elf-shlibs \
--disable-libblkid \
--disable-libuuid \
--disable-uuidd \
--disable-fsck

time make -j4
# 安装
make install
make install-libs
chmod -v u+w /usr/lib/{libcom_err,libe2p,libext2fs,libss}.a
gunzip -v /usr/share/info/libext2fs.info.gz

install -v -m644 doc/com_err.info /usr/share/info

install-info --dir-file=/usr/share/info/dir \
/usr/share/info/libext2fs.info

makeinfo -o doc/com_err.info \
../e2fsprogs-1.45.3/lib/et/com_err.texinfo

install -v -m644 doc/com_err.info /usr/share/info

install-info --dir-file=/usr/share/info/dir \
/usr/share/info/com_err.info

4.68 sysklogd

系统日志

# 下载(chroot外部,因为wget没有安装)
wget http://www.infodrom.org/projects/sysklogd/download/sysklogd-1.5.1.tar.gz
tar -xvf sysklogd-1.5.1

# 配置
cd sysklogd-1.5.1
sed -i '/Error loading kernel symbols/{n;n;d}' ksym_mod.c
sed -i 's/union wait/int/' syslogd.c
# 编译
cd /sources/sysklogd-1.5.1
time make -j4
# 安装
make BINDIR=/sbin install
# sysklogd 配置
cat > /etc/syslog.conf << "EOF"
# Begin /etc/syslog.conf
auth,authpriv.* -/var/log/auth.log
*.*;auth,authpriv.none -/var/log/sys.log
daemon.* -/var/log/daemon.log
kern.* -/var/log/kern.log
mail.* -/var/log/mail.log
user.* -/var/log/user.log
*.emerg *
# End /etc/syslog.conf
EOF

4.69 sysvinit

系统启动、关闭

# 下载(chroot外部,因为wget没有安装)
wget  http://download.savannah.gnu.org/releases/sysvinit/sysvinit-2.95.tar.xz
tar -xvf sysvinit-2.95.tar.xz
# 补丁
wget http://www.linuxfromscratch.org/patches/lfs/9.0/sysvinit-2.95-consolidated-1.patch
cd sysvinit-2.95
patch -Np1 -i ../sysvinit-2.95-consolidated-1.patch
# 编译
cd /sources/sysvinit-2.95
time make -j4
# 安装
make install

4.70 eudev

创建设备节点

# 下载(chroot外部,因为wget没有安装)
wget https://dev.gentoo.org/~blueness/eudev/eudev-3.2.8.tar.gz
tar -xvf eudev-3.2.8.tar.gz

# 编译
../eudev-3.2.8/configure --prefix=/usr \
--bindir=/sbin \
--sbindir=/sbin \
--libdir=/usr/lib \
--sysconfdir=/etc \
--libexecdir=/lib \
--with-rootprefix= \
--with-rootlibdir=/lib \
--enable-manpages \
--disable-static

time make -j4
# 安装
mkdir -pv /lib/udev/rules.d
mkdir -pv /etc/udev/rules.d
make install
# 添加udev规格
wget http://anduin.linuxfromscratch.org/LFS/udev-lfs-20171102.tar.xz
tar -xvf ../udev-lfs-20171102.tar.xz
make -f udev-lfs-20171102/Makefile.lfs install
udevadm hwdb --update

本人增加了几个比较喜欢的工具:

  1. nano
  2. tree
  3. neofetch
  4. which

删除调试符号(可选)

save_lib="ld-2.30.so libc-2.30.so libpthread-2.30.so libthread_db-1.0.so"
cd /lib
for LIB in $save_lib; do
objcopy --only-keep-debug $LIB $LIB.dbg
strip --strip-unneeded $LIB
objcopy --add-gnu-debuglink=$LIB.dbg $LIB
done
save_usrlib="libquadmath.so.0.0.0 libstdc++.so.6.0.27
libitm.so.1.0.0 libatomic.so.1.2.0"
cd /usr/lib
for LIB in $save_usrlib; do
objcopy --only-keep-debug $LIB $LIB.dbg
strip --strip-unneeded $LIB
objcopy --add-gnu-debuglink=$LIB.dbg $LIB
done
unset LIB save_lib save_usrlib

exec $TOOLS/bin/bash

$TOOLS/bin/find /usr/lib -type f -name \*.a \
-exec /tools/bin/strip --strip-debug {} ';'

$TOOLS/bin/find /lib /usr/lib -type f \\( -name \\*.so* -a ! -name \\*dbg \\) \\
-exec $TOOLS/bin/strip --strip-unneeded {} ';'

$TOOLS/bin/find /{bin,sbin} /usr/{bin,sbin,libexec} -type f \\
-exec $TOOLS/bin/strip --strip-all {} ';'

rm -rf /tmp/*
logout

新的登陆文件

cat <<EOF > lfsch2
# chroot 切换根到$LFS
# /usr/bin/env -i 清除环境变量
sudo chroot $LFS \
/usr/bin/env -i \
HOME=/root \
TERM=$TERM \\
LFS=/ \\
TOOLS=$TOOLS \
LFS_TGT=$LFS_TGT \\
PS1='(chroot)(lfs)\u:\w\\\\$ ' \
PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin \
/bin/bash --login 
EOF

# 以后登陆系统只需
. lfsch2 

五、基本系统配置

5.1 system v

# 安装lfs-bootscripts 启动脚本
wget http://www.linuxfromscratch.org/lfs/downloads/9.0/lfs-bootscripts-20190524.tar.xz
tar -xvf lfs-bootscripts-20190524.tar.xz
make install

5.2 udev

内核检测硬件接入,udev将其存储到devtmpfs的内存虚拟文件系统中。

加载驱动步骤:

sysfs:

  1. 内核检测,内核内部的驱动,生成sysfs对象(devtmpfs内建)
  2. 内核模块,在载入时注册
  3. 一旦被挂载/sys,sysfs的硬件数据就可以被用户空间进程使用
  4. 即可被udevd处理(修改)

设备节点:

  1. 设备文件(设备节点)通过devtmpfs文件系统创建
  2. 内核提供uevent给udevd处理
  3. udevd基于/etc/udev/rules.d、/lib/udev/rules.d、/run/udev/rules.d定义的规则,建立额外的符号链接

加载模块:

  1. 内核模块包含别名(modinfo查看)
  2. 总线驱动导出信息:/sys/bus/pci/devices/*/modalias
  3. udevd 根据uevent环境变量(等于modalias)调用/sbin/modprobe加载模块
  4. /etc/modprobe.d/*.conf 配置依赖关系
    1. softdep xxx post: yyy
  5. /etc/sysconfig/modules 系统预加载模块
  6. /etc/modprobe.d/blacklist.conf 屏蔽模块
    1. blacklist xxx
  7. /lib/udev/devices 创建静态设备节点

udev 规则:

  1. SUBSYSTEM=="net"
  2. ACTION=="add"
  3. DRIVERS=="?*"
  4. ATTR{address}
  5. ATTR{type}=="1"
  6. NAME

5.3 网络配置

网卡配置文件:

  • /etc/sysconfig/ifconfig.xxx
ONBOOT=yes #自动启动
IFACE=eth0 #接口名称
SERVICE=ipv4-static #获取ip的模式
IP=192.168.1.2 
GATEWAY=192.168.1.1 #网关
PREFIX=24 #ip前缀,即网络段
BORADCAST=192.168.1.255 # 广播

dns配置文件:

  • /etc/resolv.conf
domain me.pc
nameserver 192.168.1.1
nameserver 114.114.114.114

主机配置文件:

  • /etc/hosts
127.0.0.1 localhost me.pc

# ip6 设置
::1 localhost
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

5.4 启动脚本

运行级别:

  • 0 : 关闭
  • 1 : 单用户
  • 2 : 多用户无网络
  • 3 : 多用户
  • 4 : 预留
  • 5 : 图形界面
  • 6 : 重启

init初始化程序的配置:

  1. /etc/inittab :主配置
  2. /etc/rc.d/rcs.d/ :S开头的脚本
  3. /etc/rc.d/rc?.d/ :initdefault 默认数字,运行级别
  4. /etc/rc.d/init.d/rc :主程序
  5. /lib/lsb/init-functions :函数库
  6. /etc/sysconfig/rc.site :参数
  7. /run/var/bootlog :启动日志(运行时动态)
  8. /var/log/boot.log :启动日志
# Begin /etc/inittab
id:3:initdefault:
si::sysinit:/etc/rc.d/init.d/rc S

l0:0:wait:/etc/rc.d/init.d/rc 0
l1:S1:wait:/etc/rc.d/init.d/rc 1
l2:2:wait:/etc/rc.d/init.d/rc 2
l3:3:wait:/etc/rc.d/init.d/rc 3
l4:4:wait:/etc/rc.d/init.d/rc 4
l5:5:wait:/etc/rc.d/init.d/rc 5
l6:6:wait:/etc/rc.d/init.d/rc 6

ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
su:S016:once:/sbin/sulogin

1:2345:respawn:/sbin/agetty --noclear tty1 9600
2:2345:respawn:/sbin/agetty tty2 9600
3:2345:respawn:/sbin/agetty tty3 9600
4:2345:respawn:/sbin/agetty tty4 9600
5:2345:respawn:/sbin/agetty tty5 9600
6:2345:respawn:/sbin/agetty tty6 9600 

# End /etc/inittab

S*表示启动运行,K*表示停止运行。

脚本参数:

  1. start : 启动
  2. stop : 停止
  3. restart : 重启
  4. reload : 更新配置
  5. status : 状态

udev 启动脚本:

  1. /etc/rc.d/init.d/udev
  2. /etc/rc.d/init.d/udev_retry :子系统事件

系统时钟:

  1. /etc/localtime : 时区
  2. /etc/sysconfig/clock : 时钟配置
UTC=1
CLOCKPARAMS=

console 控制台:

  1. /etc/sysconfig/console
  2. /usr/share/keymaps
  3. /usr/share/consolefonts
LOGLEVEL=7
KEYMAP=

5.5 bash启动配置

  1. /etc/passwd (/bin/login)
  2. /etc/profile
  3. ~/.bash_profile
  4. /etc/locale.conf :本地语言
  5. ~/.bashrc
  6. /etc/inputrc : 键盘布局
  7. ~/.inputrc
  8. /etc/shells : 可以shell列表
# 查询字符映射表标准名称,显示UTF-8
LC_ALL=zh_CN.utf8 locale charmap
# 返回Chinese
LC_ALL=zh_CN.utf8 locale language

cat > /etc/profile << "EOF"
# Begin /etc/profile
export LANG=zh_CN.UTF-8
# End /etc/profile
EOF

cat > /etc/shells << "EOF"
# Begin /etc/shells
/bin/sh
/bin/bash
# End /etc/shells
EOF

六、安装内核和引导

6.1 挂载配置

  1. /etc/fstab

fsck磁盘检查次序,三种:0不检查,1优先,2次级

dump 备份。

挂载选项:windows文件系统需要指定iocharset 字符集,vfat、smbfs需要指定codepage字符页码。

<xxx><fff><yyy>替换为实际环境值:

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

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

/dev/<xxx>   /          <fff>       defaults                1   1
/dev/<yyy>   swap       swap        pri=1                   0   0
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

6.2 编译内核

mkdir /sources/linux4
cd /sources/linux4

# 生成默认编译设置
make -f ../linux-5.2.21/Makefile defconfig 
# 自定义编译设置
make menuconfig 

保证设置如下菜单:

Device Drivers --->
Generic Driver Options --->
[ ] Support for uevent helper [CONFIG_UEVENT_HELPER]
[*] Maintain a devtmpfs filesystem to mount at /dev [CONFIG_DEVTMPFS]

Kernel hacking --->
Choose kernel unwinder (Frame pointer unwinder)
---> [CONFIG_UNWINDER_FRAME_POINTER]
# 编译
time make -j4
# 安装模块
make modules_install
# 复制内核到/boot
cp -iv arch/x86_64/boot/bzImage  \
/boot/vmlinuz-5.2.21-ddu-9.0

cp -iv System.map  /boot/System.map-5.2.21
cp -iv .config /boot/config-5.2.21
# 安装文档
install -d /usr/share/doc/linux-5.2.21

cp -r ../linux-5.2.21/Documentation/* \
/usr/share/doc/linux-5.2.21/

配置linux usb模块加载顺序:

install -v -m755 -d /etc/modprobe.d

cat > /etc/modprobe.d/usb.conf << "EOF"
# Begin /etc/modprobe.d/usb.conf
install ohci_hcd /sbin/modprobe ehci_hcd ; /sbin/modprobe -i ohci_hcd ; true
install uhci_hcd /sbin/modprobe ehci_hcd ; /sbin/modprobe -i uhci_hcd ; true
# End /etc/modprobe.d/usb.conf
EOF

6.3 grub设置

这里用映像文件加虚拟机演示:

# 创建一个3g的映像文件
dd if=/dev/zero of=ddu.img bs=1G count=3 status=progress
# 用parted分区
# 创建gpt分区表
parted ddu.img mktable gpt
# 分引导分区100m,前端留1m
parted ddu.img unit mib mkpart BOOT fat32 1 101
# 查看剩余空间,显示3072
parted ddu.img unit mib print free
# 分剩余空间给根分区,后端留1m
parted ddu.img unit mib mkpart ROOT  102 3071
# 设置分区标志
parted ddu.img set 1 esp on

# 加载loop设备分区
sudo losetup -Pf ddu.img
# 查看loop设备分区
lsblk # 查看设备路径,显示loop1p1 和loop1p2
# 首次使用格式化
sudo mkfs.vfat -F 32 -n ESP /dev/loop1p1
sudo mkfs.ext4 -L DDU-1.0 /dev/loop1p2
# 挂载文件夹
mkdir -pv ddu-1.0/{esp,root}
sudo mount /dev/loop1p1 ddu-1.0/esp
sudo mount /dev/loop1p2 ddu-1.0/root

# 复制内容,排除已经没有作用的构建文件夹
sudo cp -a $LFS/{bin,home,lib64,opt,root,sbin,usr,boot,etc,lib,srv,var,mnt,tmp} ddu-1.0/root
sudo mkdir -pv ddu-1.0/root/{media,mnt,tmp} #临时文件夹
sudo mkdir -pv ddu-1.0/root/{dev,proc,sys,run} # 创建特殊文件夹

# 修改fstab
lsblk -f # 查看设备的uuid,并更改fstab对应值
# 挂载esp分区到lfs系统
sudo mkdir -v /boot/efi
sudo mount /dev/loop1p1 $LFS/boot/efi

# 配置版本信息
echo 9.0> /etc/lfs-release

cat > /etc/lsb-release << EOF
DISTRIB_ID="deepin day day use"
DISTRIB_RELEASE="9.0"
DISTRIB_CODENAME="ddu"
DISTRIB_DESCRIPTION="lfs ddu"
EOF

# 安装grub环境
grub-install --target=x86_64-efi --removable --no-nvram
grub-install --target=x86_64-efi --bootloader-id=ddu --no-nvram
# 配置启动菜单
grub-mkconfig -o /boot/grub/grub.cfg

# 因为是chroot环境,grub并不能识别正确的磁盘信息,所以必须手工修正
cp /boot/grub/x86_64-efi/load.cfg /boot/grub/
# 手工把正确根分区uuid替换掉
nano /boot/grub/load.cfg
# 重新生成正确的引导程序
grub-mkimage --directory '/usr/lib/grub/x86_64-efi' --prefix '/boot/grub' --output 'grub.efi' --format 'x86_64-efi' --compression 'auto'  --config '/boot/grub/load.cfg' 'fat' 'part_gpt' 'ext2' 'part_gpt' 'search_fs_uuid' 
cp -vf /boot/grub/grub.efi /boot/efi/efi/boot/BOOTX64.EFI 
cp -vf /boot/grub/grub.efi /boot/efi/efi/ddu/grubx64.efi
# 同样的方法,将菜单也进行修正
nano /boot/grub/grub.cfg 

完毕。 启动系统

参考

  1. 包的下载地址:http://www.linuxfromscratch.org/lfs/view/9.0/chapter03/packages.html
  2. 不要用exa代替ls,否则会:checking whether build environment is sane... configure: error: newly created file is older than distributed files!
  3. 清华有gnu系列的软件包镜像:https://mirrors.tuna.tsinghua.edu.cn/gnu/
  4. 解决unable to initialize decompress status for section .debug_aranges and crti.o: file not recognized: File format not recognized:https://vulpine.club/@uvok/102350923194781276
  5. devfs 的用户空间实现: http://www.kroah.com/linux/talks/ols_2003_udev_paper/Reprint-Kroah-Hartman-OLS2003.pdf
  6. sysfs 文件系统: http://www.kernel.org/pub/linux/kernel/people/mochel/doc/papers/ols-2005/mochel.pdf
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/coder_lw/wiki.git
git@gitee.com:coder_lw/wiki.git
coder_lw
wiki
wiki
master

搜索帮助