从零开始构建Linux
Posted Reid21
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从零开始构建Linux相关的知识,希望对你有一定的参考价值。
目的:深入了解以Linux内核为基础的系统是如何组成,运行,以构建一个最基础的,纯净的系统。
LFS构建步骤
宿主机准备
- linux操作系统安装
- 使用独立硬盘,创建分区
- 配置用户和组
- 下载所有需要的软件包源代码
准备开发环境
构建一个基本开发环境
构造完整的目标系统
配置系统启动脚本
启动系统
一、宿主系统准备
1.1.安装所需要依赖包
[root@node ~]# yum install -y bash binutils bison bzip2 coreutils diffutils findutils gawk gcc glibc grep gzip kernel m4 make patch perl sed tar texinfo xz gcc-c++ flex
检查
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` sed --version | head -n1 tar --version | head -n1 makeinfo --version | head -n1 xz --version | head -n1 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 [root@node ~]# bash version-check.sh bash, version 4.2.46(2)-release /bin/sh -> /usr/bin/bash Binutils: version 2.27-34.base.el7 bison (GNU Bison) 3.0.4 yacc not found ##使用bison来替代 ,语法分析器 [root@node ~]# ln -sv /usr/bin/bison /usr/bin/yacc ‘/usr/bin/yacc’ -> ‘/usr/bin/bison’ Also check for some library consistency: cat > library-check.sh << "EOF" #!/bin/bash for lib in lib{gmp,mpfr,mpc}.la; do echo $lib: $(if find /usr/lib* -name $lib| grep -q $lib;then :;else echo not;fi) found done unset lib EOF [root@node ~]# bash library-check.sh libgmp.la: not found libmpfr.la: not found libmpc.la: not found
1.2.术语说明
- 宿主系统 host system(用于制作系统的系统)
- 目标系统 target system(最终制作出来的系统)
- 临时系统 temporary system(在制作系统过程中,需要一个小型过渡的系统,这个系统在帮助完成目标系统制作后就不使用)
- 编译工具 compiler(gcc等)
- 工具链 tools chain(开发中有很多依赖,为了不重复开发,可以做成公共的来调用 )
- 原工具链: 宿主系统的工具链
- 预工具链:用于生成临时工具链的工具链
- 临时工具链:用于生成临时系统的工具链
- 目标工具链:用于生成目标系统的工具链
- 辅助工具 associated tools(除编译外,类似make这种辅助的)
- 运行环境 running environment(运行系统上可有多个环境,这些环境有各自root目录和环境的设置)
头文件:C开发,在编译时以.h结尾,存放函数,接口的描述,结构体信息
纯净度:当前系统与依赖于其他系统的相关性
1.3.源代码编译过程:源代码编译成可执行文件流程
描述:三个阶段
- 配置configure
生成配置文件,文件名通常是makefile
- 编译make
最复杂阶段,根据配置生成的makefile,执行一系列动作,如创建一些必要的文件,调用工具链环境中的命令来编译源代码和链接目标文件,
最终生成所需要的可执行文件,函数库和各种辅助文件
- 安装make install
copy到相应的目录中
1.4.工具链(vim例子)
描述:linux下二进制文件都采用共享库的运行方式,可以减少程序文件的代码量,使用应用程序占用的空间更小,
运行过程中要访问共享库,必须存在系统中,而且要在搜索路径中可以找到,如果共享库丢失或者应用程
序找不到就会报错
vim:
vim的所编译过程: 依赖于各种库,要编译vim,vim依赖于ncurses,ncurses依赖于glibc,这种依赖关系就是工具链,由编译器,汇编器,和相应的库函数组成的,在linux上常使用的是gcc,bintuils,和glibc组合的工具链,工具链的原则是从某一个工具链编译出来的二进制文件或者库函数文件,必须链接到该工具的函数库,无论是静态还是动态,从图上可以看出ncurses和vim都是链接在glibc上,也就是工具链的函数库部分就是glibc,glibc是"自给自足的"的,不依赖于函数库就可以完成编译的链接,最终要制作的系统包含完整的工具链,因为希望目标系统是一个纯净的系统,可以独立运行,不依赖于外部,所以其中的工具链到最终是要依赖于工具链内部的glibc,可以通过工具链的两种依赖方式,可以很方便从源生最原始的工具链到制作出来的工个链
- gcc、binutiils运行时依赖于glibc
- 外部依赖:依赖于工具链之外的glibc
- 内部依赖:依赖于工具链中的glibc
图中的软件包存在依赖关系,有依赖必须先安装,要编译vim要先编译ncurses,要编译ncurses,要先安装glibc,决定了要按次顺来操作,一般生成共享库或程序文件时,链接器来链接所依赖的函数库,因次在编译某个软件包前,编译它所依赖的软件不仅是要安装头文件,还是因为在用到它所提供的函数库,否则就无法完成编译链接的过程.
linux内核部分:虽然运行任何程序都要使用到内核,但是在制作目标系统的过程中,目标系统的内核并不需要先编译和安装,因为使用Linux内核并不像使用glibc需要使用动态链接库来调用,内核的调用是通过glibc的各种函数库,或其他函数库通过系统调用来进行的,所以并不需要一开始编译安装内核,只需要内核所需要的头文件就可以.
[root@node ~]# ldd /usr/bin/vim linux-vdso.so.1 => (0x00007ffd621f3000) libm.so.6 => /lib64/libm.so.6 (0x00007fd292cf8000) libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fd292ad0000) libtinfo.so.5 => /lib64/libtinfo.so.5 (0x00007fd2928a6000) libacl.so.1 => /lib64/libacl.so.1 (0x00007fd29269d000) libgpm.so.2 => /lib64/libgpm.so.2 (0x00007fd292495000) libdl.so.2 => /lib64/libdl.so.2 (0x00007fd292291000) libperl.so => /usr/lib64/perl5/CORE/libperl.so (0x00007fd291f03000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fd291ce6000) libc.so.6 => /lib64/libc.so.6 (0x00007fd291919000) /lib64/ld-linux-x86-64.so.2 (0x00007fd293000000) libpcre.so.1 => /lib64/libpcre.so.1 (0x00007fd2916b8000) libattr.so.1 => /lib64/libattr.so.1 (0x00007fd2914b2000) libncurses.so.5 => /lib64/libncurses.so.5 (0x00007fd29128b000) libresolv.so.2 => /lib64/libresolv.so.2 (0x00007fd291072000) libnsl.so.1 => /lib64/libnsl.so.1 (0x00007fd290e57000) libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007fd290c20000) libutil.so.1 => /lib64/libutil.so.1 (0x00007fd290a1d000) libfreebl3.so => /lib64/libfreebl3.so (0x00007fd290819000)
1.5.工具链制作关系
描述:工具链是由编译器,汇编器,函数库等组成的,工具链有两种依赖方式,图中从原工具链A等通过工具链B生成目标系统的工具链C,C与A没有关系,所以是纯净的,但是还是需要临时工具链B的帮助
工具链分步实现过程
- 最开始原系统只有一个工具链A
- 使用工具链A生成gcc_B和binutils_B,由于工具链之间的依赖关系,gcc_B和binutils_B都链接到glibA上,这时还不构成完整的工具链,因为要依赖于工具链A的glibA,不是纯净的工具链依赖于外部
- 编译成一个新的程序A,依赖于gcc_B和binutils_B,glib_A
- 编译出一个新的glib_B
- 把gcc_B和binutils_B的链接对象调整为glib_B,这时可以形成完整的工具链B
- 工具链B可以编译成一个新的应用程序B,它依赖于glibc_B,这种属于外部依赖
- 使用现有的临时工具链,编译出gcc_C和binutils_C,形成工具链C,它使用工具链B的glibc_B作为函数库,形成与原始没关系纯净的目标系统的工具链C
summary: 整个过程的关键点是编译工具可以修改指定的函数库,也就是可以修改依赖方式,通过设置内部和外部依赖的相互转换,工具链B从内部依赖变成外部依赖,这个过程称为调整工具链,以最终实现纯净的一个工具链C
1.6.制作步骤概述
描述:三个阶段按顺序依次执行,每个阶段都为下个阶段做准备,而且三个阶段都是相互交叉,上一个阶段为下一阶段做准备
- 预工具链阶段
- 临时系统阶段
- 目标系统阶段
过程:
- 宿主系统:要求并不高,与目标系统架构兼容,不兼容使用交叉编译制作,宿主系统包含工具链和辅助命令,在制作过程中称为源工具链
- 创建预工具链,为了建立临时工具链,预工具链是由源工具链生成,创建初是内部依赖方式的工具链,用它编译出来的工具链需要链接到
宿主系统的glibc上,
- 生成临时工具链,为了完成临时系统,它需要脱离宿主系统的运行环境,临时工具链本身也是临时系统的重要组成部分,预工具链负责生成临时系统的glibc,当glibc完成后,能预工具链的依赖关系进行调整,把预工具链变成外部依赖的工具链,调整完成后就生成临时编译工具,临时编译工具依赖于临时系统的glibc,临时编译工具与glibc组成临时工具链,这样预工具链的使命就完成了,由临时工具链替代预工具链进行临时系统的制作,这个临时工具链是内部依赖,它不依赖于宿系统的函数库
- 编译一个软件系统编译工具,通常还需要其他程序参与,只是靠临时工具链是无法完成对目标系统的制作的,所以需要一个相对完整的环境,所以是一个临时系统,临时系统的完成需要宿主系统的辅助命令参与,临时工具链将不依赖于宿主系统的辅助命令来编译软件,这样就可以为临时系统脱离宿主系统作好准备,临时工具链将继续完成临时系统的制作,制作临时系统的目的就是为制作目标系统提供一个不依赖于宿主系统的环境,临时工具链生成临时系统,可以保证各种工具软件所依赖的函数库是临时系统自身的函数库,而不是宿主系统的函数库,在完成临时系统的制作后,就可以让临时系统脱离原有的系统,用临时系统制作,就是为了让目标系统成为独立可扩展的系统,所以必须为目标系统生成一个目标工具链
- 用临时系统生成目标系统的glibc,然后调整临时工具链,使用其编译出来的程序文件和库文件链接到目标系统的glibc上,及从内部依赖变成外部系统的方式,在编译目标系统上的gcc,binutils,完成了目标工具链的建立,临时工具链完成它的使命,但是临时工具链中的辅助命令还要继续使用,直到目标工具链中有相应辅助,形成一个完整的目标工具链环境
- 为了让目标系统能自足进行更新扩展,目标系统也需要有最基本的编译环境,虽然已经生成目标工具链,但是辅助命令还是使用临时系统的,这时需要编译出来一些辅助命令,安装到目标系统中,从而形成目标工具链环境
- 在具体操作过程中,可以按照生成临时系统的内容编译各种辅助命令,也可以根据需要安装更多的辅助命令,或者是其他的程序,在目标工具链环境生成之后,就像生成一个车间,可以把目标环境系统进行进一步的完善,还要运行启动系统需要grub之类
1.7.磁盘分区准备
- 40GB: 8g是swap, 32g其他使用ext4 [root@node ~]# fdisk /dev/sdb Device Boot Start End Blocks Id System /dev/sdb1 2048 16779263 8388608 83 Linux /dev/sdb2 16779264 83886079 33553408 83 Linux [root@node ~]# mkswap /dev/sdb1 [root@node ~]# mkfs.ext4 /dev/sdb2 设置环境变量挂载 [root@node ~]# export LFS=/mnt/lfs [root@node ~]# mkdir -pv $LFS [root@node ~]# mount | grep $LFS /dev/sdb2 on /mnt/lfs type ext4 (rw,relatime,seclabel,data=ordered) [root@node ~]# source .bash_profile [root@node ~]# tail -1 .bash_profile export LFS=/mnt/lfs 或: [root@node ~]# tail -1 /etc/fstab /dev/sdb2 /mnt/lfs ext4 defaults 0 0 [root@node ~]# mount -a
二、软件包及补丁
下载地址:http://ftp.lfs-matrix.net/pub/lfs/lfs-packages/
[root@node ~]# mkdir -v $LFS/downloads 进行md5校验: http://ftp.lfs-matrix.net/pub/lfs/lfs-packages/MD5SUMS [root@node downloads]# md5sum lfs-packages-8.0.tar 2d1672ebe969628fc53d483a898fb500 lfs-packages-8.0.tar [root@node downloads]# tar xf lfs-packages-8.0.tar [root@node downloads]# mv 8.0/* . 创建源码目录: [root@node ~]# mkdir $LFS/sources [root@node ~]# chmod a+wt $LFS/sources
三、目录和专用用户准备
3.1.目录结构准备
- /mnt/lfs目录作为"创作基地"
- $LFS/tools是"临时系统"
[root@node ~]# mkdir $LFS/tools - 在宿主系统中创建符号链接/tools的,将其指向$LFS/tools,目的是宿主系统运行环境和目标系统运行环境都可以使用/tools,指向临时目录使用的命令 [root@node ~]# ln -sv $LFS/tools / ‘/tools’ -> ‘/mnt/lfs/tools’
3.2.添加LFS用户
[root@node ~]# groupadd lfs [root@node ~]# useradd -s /bin/bash -g lfs -m -k /dev/null lfs #-k指定一个空设备,是防止从/etc/skel中复制模板,不使用发行版的模板,完全自定义 [root@node ~]# echo lfs | passwd --stdin lfs [root@node ~]# chown lfs $LFS/tools [root@node ~]# chown lfs $LFS/sources [root@node ~]# ls -l $LFS total 28 drwxr-xr-x. 3 root root 4096 Jan 6 17:00 downloads drwx------. 2 root root 16384 Jan 6 15:57 lost+found drwxrwxrwt. 2 lfs root 4096 Jan 6 16:32 sources drwxr-xr-x. 2 lfs root 4096 Jan 6 17:07 tools
3.3.创建简单的环境变量
[root@node ~]# su - lfs cat > ~/.bash_profile << "EOF" exec env -i HOME=$HOME TERM=$TERM PS1=\'\\u:\\w\\$ \' /bin/bash EOF cat > ~/.bashrc << "EOF" set +h #关闭bash的hash功能,随后有些工具要马上生效,如果更新缓存需要时间 umask 022 LFS=/mnt/lfs LC_ALL=POSIX LFS_TGT=$(uname -m)-lfs-linux-gnu #编译的架构要一致,如果不一样要调 PATH=/tools/bin:/bin:/usr/bin #搜索路径,而且hash,可以让它马上生效 export LFS LC_ALL LFS_TGT PATH EOF 检查: [root@node ~]# su - lfs Last login: Sun Jan 6 17:17:29 CST 2019 on pts/0 lfs:~$ export declare -x HOME="/home/lfs" declare -x LC_ALL="POSIX" declare -x LFS="/mnt/lfs" declare -x LFS_TGT="x86_64-lfs-linux-gnu" declare -x OLDPWD declare -x PATH="/tools/bin:/bin:/usr/bin" declare -x PS1="\\\\u:\\\\w\\\\\\$ " declare -x PWD="/home/lfs" declare -x SHLVL="1" declare -x TERM="xterm"
3.4.软件包的编译时间
- SBU是标准编译单位,使用binutils作为一个值,其他与它来作比较
- 通过time来确定
3.5.测试
描:include一个标准的io输入,在函数主体打印一个hello world,返回0,没有语法错误是正常
cat > test.c << "EOF" #include <stdio.h> main() { printf("hello World\\n"); return 0; } EOF lfs:~$ gcc test.c lfs:~$ ls a.out test.c lfs:~$ ./a.out hello World
四、构建临时系统
描述:要制作临时工具链,要先生成一个预工具链,LFS文档中并不没有提及,是为了更好理解
- 利用宿主系统安装的组件生成预工具链,再使用预工具链生成临时工具链,再根据临时工具链生成辅助命令,形成临时系统
- 预工具链主要有两个工具:汇编链接器bintuils和gcc
- 构建临时系统
- 构建与宿主系统无关的临时工具链,包括库,编译器,汇编器等
- 使用临时工具链生成辅助命令
- 最终要实现临时系统是要安装在lfs目录下tools目录,与宿主系统目录分开,与目标系统目录也分开
4.1.编译的次序
- 预工具链
Bintuils-2.27 gcc和glibc的configure命令都会需要一些汇编器和链接器的检查测试,所以首先要编译安装bintuils [root@node ~]# type ld GUN链接器,把目标文件链接到可执行程序 ld is /usr/bin/ld [root@node ~]# whatis ld ld (1) - The GNU linker [root@node ~]# whereis ld ld: /usr/bin/ld /usr/bin/ld.bfd /usr/bin/ld.gold /usr/share/man/man1/ld.1.gz [root@node ~]# ld --verbose | grep SEARCH 链接器重要配置是库文件从那里搜索,以下是宿主系统中默认的 SEARCH_DIR("=/usr/x86_64-redhat-linux/lib64"); SEARCH_DIR("=/usr/lib64"); SEARCH_DIR("=/usr/local/lib64"); SEARCH_DIR("=/lib64"); SEARCH_DIR("=/usr/x86_64-redhat-linux/lib"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); 当使用gcc编译程序时,如果使用gcc参数--verbose,它调用链接器时也会传参数,可以把ld里链接那些文件都显示出来 [root@node tmp]# gcc test.c -Wl,--verbose 2>&1 |grep succ 把预处理,编译,汇编的过程都显示,还包括gcc的include搜索次序 attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o succeeded attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o succeeded attempt to open /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o succeeded attempt to open /tmp/ccG2XNzN.o succeeded GCC-6.3.0 Linux-4.9.9 API Headers 把头文件copy到tools目录下,可以使用是glibc与内核进行个性化交互
- 临时工具链
Glibc-2.25 考虑编译器和头文件的来源 Libstdc++-6.3.0 标准c++库 Binutils-2.27 第二次,要通过一个开关项指定ld的搜索路径--with-lib-path=/tools/lib,使用得临时工具链的生成与宿主系统作一个隔离 GCC-6.3.0 第二次gcc,也要调整,要直接修改gcc的源代码文件,告诉gcc以后使用的动态链接器要使用自己的,不修改会嵌入宿主系统的/lib一般动态库,造成可能不纯净
- 辅助命令
4.2.GUN screen命令
编译流程:编译时间过长
- 进入到LFS的源文件目录,即用sources目录
- 以lfs用户身份,解压要编译的软件包
- 进入到解压后创建目录中
- 根据指南说明编译、检查、安装软件包
- 回退到源文件目录
- 除非特别说明,删除解压出来的目录和所有编译过程中生成的目录
GUN screen使用的场景
- 需要长时间连接
- 防止意外网络中断
功能:
- 会话恢复:只要screen进程没有被终止,在其内部运行的会话就可以恢复,登录主机screen -r恢复,如果暂时性离开,可以使用分离命令detach保证其中的程序正常的运行,把session进行挂起,切换到后台,在screen中每个会话都是独立运行的,每个会话各自编号自己的输入输出缓存,
- 多窗口
- 会话共享:有些人可能会使用QQ提供远程协助的技术支持,screen也可以让一个或多个用户从不同终端多次登录到一个会话中,并且共享会话中所有特性,看到是相同完全一样的输出,提供窗口访问控制权的限制,对窗口进行密码保护
[root@node ~]# yum install screen -y screen [-AmRvx -ls -wipe][-d <作业名称>][-h <行数>][-r <作业名称>][-s ][-S <作业名称>] 参数说明 -A 将所有的视窗都调整为目前终端机的大小。 -d <作业名称> 将指定的screen作业离线。 -h <行数> 指定视窗的缓冲区行数。 -m 即使目前已在作业中的screen作业,仍强制建立新的screen作业。 -r <作业名称> 恢复离线的screen作业。 -R 先试图恢复离线的作业。若找不到离线的作业,即建立新的screen作业。 -s 指定建立新视窗时,所要执行的shell。 -S <作业名称> 指定screen作业的名称。 -v 显示版本信息。 -x 恢复之前离线的screen作业。 -ls或--list 显示目前所有的screen作业。 -wipe 检查目前所有的screen作业,并删除已经无法使用的screen作业。 常用参数: 列出当前所有的session,当着有当前活动有人使用,另一个是已经分离 screen ls 新建一个叫reid的session screen -S reid 回到reid这个session screen -r reid 远程detach某个session screen -d reid 结束当前session 并回到reid这个session screen -d -r reid 在每个screen session 下,所有命令都以 ctrl+a(C-a) 开始。 注:技巧,是按完ctrl+a后松开,再按如shift ?,要松开ctril+a再按其他键 C-a ? -> 显示所有键绑定信息 C-a c -> 创建一个新的运行shell的窗口并切换到该窗口 C-a n -> Next,切换到下一个 window C-a p -> Previous,切换到前一个 window C-a 0..9 -> 切换到第 0..9 个 window Ctrl+a [Space] -> 由视窗0循序切换到视窗9 C-a C-a -> 在两个最近使用的 window 间切换 C-a x -> 锁住当前的 window,需用用户密码解锁 **C-a d -> detach,暂时离开当前session,将目前的 screen session (可能含有多个 windows) 丢到后台执行,并会回到还没进 screen 时的状态,此时在 screen session 里,每个 window 内运行的 process (无论是前台/后台)都在继续执行,即使 logout 也不影响。 C-a z -> 把当前session放到后台执行,用 shell 的 fg 命令则可回去。 C-a w -> 显示所有窗口列表 C-a t -> Time,显示当前时间,和系统的 load C-a k -> kill window,强行关闭当前的 window C-a [ -> 进入 copy mode,在 copy mode 下可以回滚、搜索、复制就像用使用 vi 一样 C-b Backward,PageUp C-f Forward,PageDown H(大写) High,将光标移至左上角 L Low,将光标移至左下角 0 移到行首 $ 行末 w forward one word,以字为单位往前移 b backward one word,以字为单位往后移 Space 第一次按为标记区起点,第二次按为终点 Esc 结束 copy mode C-a ] -> Paste,把刚刚在 copy mode 选定的内容贴上 操作: [root@node ~]# screen -S backup 退出ctrl+a 再按d [detached from 12849.backup] 暂时离开,到后台执行 [root@node ~]# screen -ls There is a screen on: 12849.backup (Detached) job的名称 1 Socket in /var/run/screen/S-root. [root@node ~]# screen -r backup 恢复 [root@node ~]# screen -S vim-opt vim tom.txt [detached from 12866.vim-opt] [root@node ~]# screen -ls There are screens on: 12866.vim-opt (Detached) 12849.backup (Detached) 2 Sockets in /var/run/screen/S-root. 使用id恢复: [root@node ~]# screen -r 12866 看多个ctrl+a 再按w ctrl+a 再按c,创建一个新的screen 清除dead会话 screen -wipe 关闭或杀死窗口 ctrl+a K screen高级应用 - 会话共享 screen -x [root@node ~]# screen -S kk [root@node ~]# screen -x kk 进入到同一个会话 - 会话锁定与解锁 ctrl+a s ctrl+a q 屏幕不输出,但是还是会被接收,想不给其他人看见时先按ctrl+a s - 发送命令到screen screen -S reid -X screen ping ip - 屏幕分割 ctrl+a S ctrl+a | - 复制、粘贴模式 ctrl+a <Esc> 或copy:ctrl+a [ paste: ctrl+a ]
4.3.Binutils的第一遍
[root@node ~]# screen [root@node ~]# su - lfs Last login: Sun Jan 6 17:22:48 CST 2019 on pts/0 lfs:~$ cd $LFS/sources lfs:/mnt/lfs/sources$ tar xf $LFS/downloads/binutils-2.27.tar.bz2 lfs:/mnt/lfs/sources$ cd binutils-2.27/ #包括链接器,汇编器,和其他处理工具,之所以第一个处理binutils是因为他们的gcc,glibc的configure阶段会对链接器等做检查 lfs:/mnt/lfs/sources/binutils-2.27$ mkdir build lfs:/mnt/lfs/sources/binutils-2.27$ cd build lfs:/mnt/lfs/sources/binutils-2.27/build$ #一般linux源代码都需要配置值,过程可以检查环境的状态,与及配值自身的选项,还可以通过参数设置出来的软件是启用或禁用 lfs:/mnt/lfs/sources/binutils-2.27/build$ time ../configure --prefix=/tools \\ --with-sysroot=$LFS \\ --with-lib-path=/tools/lib \\ --target=$LFS_TGT \\ --disable-nls \\ --disable-werror 解释: -prefix=/tools 软件包安装目录,同时也为其他目录设置一个基础的目录,相当于windows安装时的一个自定义目录 --with-sysroot=$LFS 交叉编译用于告诉编译系统在那查找所需要的文件, --with-lib-path=/tools/lib 编译好后链接器一些库的路径存放的位置 --disable-nls 国际语言支持,根据不同的语言环境变量来显示语言环境的技术,由于是做一个预工具链的binutils,不需要长期使用, 所以在编译时,可以禁用这个功能,从而加快编译的速度 --disable-werror 禁止宿主机上的一些警告事件,以防编译的终止 configure命令:主要是检查平台安装的一些特性,检测到是cc,还是gcc,configure是一个shell脚本,make是用来编译的,configure检查 后,最终会生成一个makefile,make就通过这个makefile来读取指令,make install是用来进行安装,也是通过makefile来 读取指令,安装到相应的位置上, 时间: real 0m13.983s -- user 0m6.628s sys 0m7.193s lfs:/mnt/lfs/sources/binutils-2.27/build$ time make real 10m20.188s user 7m10.288s sys 3m19.655s - 如果在x86_64上编译,需要创建一个符号文件来确保工具链的完整性 lfs:/mnt/lfs/sources/binutils-2.27/build$ ls /tools/ -l total 0 lfs:/mnt/lfs/sources/binutils-2.27/build$ case $(uname -m) in x86_64) mkdir -v /tools/lib && ln -sv lib /tools/lib64 ;; esac mkdir: created directory \'/tools/lib\' \'/tools/lib64\' -> \'lib\' 注:如果是x86_64实际会建一个lib文件夹,再做一个软件连接 lfs:/mnt/lfs/sources/binutils-2.27/build$ ls /tools/ -l total 4 drwxr-xr-x. 2 lfs lfs 4096 Jan 6 20:15 lib lrwxrwxrwx. 1 lfs lfs 3 Jan 6 20:15 lib64 -> lib 安装软件包:install相当于个copy的过程 lfs:/mnt/lfs/sources/binutils-2.27/build$ time make install real 0m13.277s user 0m5.955s sys 0m7.826s lfs:/mnt/lfs/sources/binutils-2.27/build$ ls /tools/ -l total 16 drwxr-xr-x. 2 lfs lfs 4096 Jan 6 20:16 bin drwxr-xr-x. 2 lfs lfs 4096 Jan 6 20:15 lib lrwxrwxrwx. 1 lfs lfs 3 Jan 6 20:15 lib64 -> lib drwxr-xr-x. 4 lfs lfs 4096 Jan 6 20:16 share drwxr-xr-x. 4 lfs lfs 4096 Jan 6 20:16 x86_64-lfs-linux-gnu 删除编译目录和源代码目录:为了避免一些不必要的问题 lfs:/mnt/lfs/sources/binutils-2.27/build$ cd $LFS/sources lfs:/mnt/lfs/sources$ rm -rf binutils-2.27/
4.4.gcc第一遍
- 自己先做一个gcc lfs:/mnt/lfs/sources$ tar xf ../downloads/gcc-6.3.0.tar.bz2 注:增加一些软件包,都与数据运算有关,gpm是任何精度的算法库,mpfr是一个高精度浮点算法库 lfs:/mnt/lfs/sources$ cd gcc-6.3.0/ lfs:/mnt/lfs/sources/gcc-6.3.0$ tar xf $LFS/downloads/mpfr-3.1.5.tar.xz lfs:/mnt/lfs/sources/gcc-6.3.0$ mv mpfr-3.1.5 mpfr lfs:/mnt/lfs/sources/gcc-6.3.0$ tar xf $LFS/downloads/gmp-6.1.2.tar.xz lfs:/mnt/lfs/sources/gcc-6.3.0$ mv gmp-6.1.2 gmp lfs:/mnt/lfs/sources/gcc-6.3.0$ tar xf $LFS/downloads/mpc-1.0.3.tar.gz lfs:/mnt/lfs/sources/gcc-6.3.0$ mv mpc-1.0.3 mpc - 修改gcc默认动态链接库,把/lib或/lib64修改到/tools下 lfs:/mnt/lfs/sources/gcc-6.3.0$ 注:在gcc原文件目录下,找到这几个文件linux,i386/linux{,64}}.h,对它们做备份,再做一个替换,把目录加个tools 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 - 对平台做调整 lfs:/mnt/lfs/sources/gcc-6.3.0$ case $(uname -m) in x86_64) sed -e \'/m64=/s/lib64/lib/\' \\ -i.orig gcc/config/i386/t-linux64 ;; esac - 创建新的目录 lfs:/mnt/lfs/sources/gcc-6.3.0$ mkdir build lfs:/mnt/lfs/sources/gcc-6.3.0$ cd build/ - configure 建议:参数 ../configure \\ --target=$LFS_TGT \\ --prefix=/tools \\ --with-glibc-version=2.11 \\ --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-libmpx \\ --disable-libquadmath \\ --disable-libssp \\ --disable-libvtv \\ --disable-libstdcxx \\ --enable-languages=c,c++ - make lfs:/mnt/lfs/sources/gcc-6.3.0/build$ time make real 45m18.791s user 36m47.849s sys 8m33.278s - 安装 lfs:/mnt/lfs/sources/gcc-6.3.0/build$ make install - 删除相应的包 lfs:/mnt/lfs/sources/gcc-6.3.0/build$ cd $LFS/sources lfs:/mnt/lfs/sources$ rm -rf gcc-6.3.0 注:到此预工具链完成
4.5.Linux-4.9.9 API 头文件
搭述:编译glibc时,需要使用内核,要安装相关内核头文件,这部分文件是存放在内核源代码中的,所以在内核源代码中提取各种头文件,通过这部分头文件可以让编译器了解如何让内核提供的各种各样的功能,通过接口的调用需要运行的程序,
lfs:~$ cd $LFS/sources lfs:/mnt/lfs/sources$ tar xf ../downloads/linux-4.9.9.tar.xz lfs:/mnt/lfs/sources$ cd linux-4.9.9/ lfs:/mnt/lfs/sources/linux-4.9.9$ make mrproper #清除多余的源代码,主要得到一个干净的内核,内核源代码中可能保住编译残留的信息,这些信息会对后面产生不必要的内容, #所以在安装头部前进行一些清理的工作,清理除了mrproper,还有make clean,clean是清除当前目录下编译生产的文件,但是它 #会保持一些配置文件,mrproper会删除所有的文件,包括编译,配置,备份等文件,所以进行一次干净内核编译之前都会用到它 lfs:/mnt/lfs/sources/linux-4.9.9$ time make INSTALL_HDR_PATH=dest headers_install #提取可用的内核头文件,INSTALL_HDR_PATH=dest这是头部安装的文件,实际上是有一个副作用, #安装过程中不加INSTALL_HDR_PATH=dest到目录中,会把安装目录目标文件夹都给删除后,再安装头部文件, #如果目标文件夹是空的,可以,有东西就可能比较大些,默认安装路径是/usr/include,现在要安装/tools/include, #所以通dest这个变量来指定 real 0m28.704s user 0m12.109s sys 0m18.641s lfs:/mnt/lfs/sources/linux-4.9.9$ ls dest/include/ asm asm-generic drm linux misc mtd rdma scsi sound uapi video xen lfs:/mnt/lfs/sources/linux-4.9.9$ cp -rv dest/include/* /tools/include #纯手工的安装 - 删除无用的文件 lfs:/mnt/lfs/sources$ rm -rf linux-4.9.9
4.6.Glibc-2.25
描述:glibc的安装,又叫GNU的基本C库,它是linux内核的核心组件,它保证了应用程序和内核之间的调用,通过它对内核的包装,可以实现应用程序源代码级别的可移植性,glibc可以认为内核和应用程序之间的桥梁,通过它所实现的函数可以将Unix的程序在不修改或者在极小修改的情况下,可以迁移到linux上,需要所的就是重新编译这个程序。
lfs:/mnt/lfs/sources$ tar xf ../downloads/glibc-2.25.tar.xz lfs:/mnt/lfs/sources/glibc-2.25$ mkdir build lfs:/mnt/lfs/sources/glibc-2.25$ cd build/ lfs:/mnt/lfs/sources/glibc-2.25/build$ ../configure \\ --prefix=/tools \\ --host=$LFS_TGT \\ --build=$(../scripts/config.guess) \\ --enable-kernel=2.6.32 \\ --with-headers=/tools/include \\ libc_cv_forced_unwind=yes \\ libc_cv_c_cleanup=yes real 0m5.999s user 0m1.292s sys 0m1.907s lfs:/mnt/lfs/sources/glibc-2.25/build$ time make real 11m34.307s user 8m38.528s sys 2m57.258s lfs:/mnt/lfs/sources/glibc-2.25/build$ time make install real 1m45.307s user 1m18.925s sys 0m26.433s lfs:/mnt/lfs/sources/glibc-2.25/build$ /tools/lib/libc.so.6 GNU C Library (GNU libc) stable release version 2.25, by Roland McGrath et al. #2.25是编译安装glibc的target的版本号 Copyright (C) 2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiled by GNU CC version 6.3.0. #由这个版本编译出2.25,这是预工具链的gcc Available extensions: crypt add-on version 2.1 by Michael Glad and others GNU Libidn by Simon Josefsson Native POSIX Threads Library by Ulrich Drepper et al BIND-8.2.3-T5B libc ABIs: UNIQUE IFUNC For bug reporting instructions, please see: <http://www.gnu.org/software/libc/bugs.html>. lfs:/mnt/lfs/sources/glibc-2.25/build$ rpm -qa|grep gcc libgcc-4.8.5-36.el7.x86_64 gcc-c++-4.8.5-36.el7.x86_64 gcc-4.8.5-36.el7.x86_64 宿主系统的gcc lfs:/mnt/lfs/sources/glibc-2.25/build$ echo $PATH /tools/bin:/bin:/usr/bin #lfs用户的PATH中,把/tools/bin作为搜索路径的第一位,也就是这个里面的gcc是现在所编译的glibc2.25的编译器 - 检查(glibc特别重要) #做一个空的c文件 lfs:/mnt/lfs/sources/glibc-2.25/build$ echo \'int main(){}\' > dummy.c #通过cc来做编译 lfs:/mnt/lfs/sources/glibc-2.25/build$ $LFS_TGT-gcc dummy.c #根据编译的结果,读a.out里面的信息,再使用grep做一个过滤 lfs:/mnt/lfs/sources/glibc-2.25/build$ readelf -l a.out | grep \': /tools\' [Requesting program interpreter: /tools/lib64/ld-linux-x86-64.so.2] #说明glibc是编译成功 lfs:/mnt/lfs/sources/glibc-2.25/build$ rm -v dummy.c a.out #删除历史文件 lfs:/mnt/lfs/sources/glibc-2.25/build$ cd .. lfs:/mnt/lfs/sources/glibc-2.25$ cd .. lfs:/mnt/lfs/sources$ rm -rf glibc-2.25
4.7.libstdc
描述:标准的C++库,是gcc源文件中的一部分
lfs:/mnt/lfs/sources$ tar xf ../downloads/gcc-6.3.0.tar.bz2 lfs:/mnt/lfs/sources$ cd gcc-6.3.0/ lfs:/mnt/lfs/sources/gcc-6.3.0$ mkdir build lfs:/mnt/lfs/sources/gcc-6.3.0$ cd build/ lfs:/mnt/lfs/sources/gcc-6.3.0/build$ time ../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++/6.3.0 real 1m37.799s user 0m46.485s sys 0m54.102s lfs:/mnt/lfs/sources/gcc-6.3.0/build$ time make real 3m3.254s user 2m31.882s sys 0m31.807s lfs:/mnt/lfs/sources/gcc-6.3.0/build$ time make install real 0m21.459s user 0m7.771s sys 0m14.503s lfs:/mnt/lfs/sources/gcc-6.3.0/build$ cd .. lfs:/mnt/lfs/sources/gcc-6.3.0$ cd .. lfs:/mnt/lfs/sources$ rm -rf gcc-6.3.0 - 编译binutils(汇编工具) 描述:是第二次,之前使用的预工具链,还是依赖于host系统中的glibc,无法脱离宿主系统运行,所以 现在有了预工具链后,还要编译binutils,作为临时工具链,来代替binutils中的工具 lfs:/mnt/lfs/sources$ tar xf ../downloads/binutils-2.27.tar.bz2 lfs:/mnt/lfs/sources$ cd binutils-2.27/ lfs:/mnt/lfs/sources/binutils-2.27$ mkdir build lfs:/mnt/lfs/sources/binutils-2.27$ cd build/ 环境变量的定义 描述:只是针对configure来做的,主要告诉configure,编译器从那里来找,指定使用的编译器而不是宿主系统自有的, lfs:/mnt/lfs/sources/binutils-2.27/build$ CC=$LFS_TGT-gcc \\ AR=$LFS_TGT-ar \\ RANLIB=$LFS_TGT-ranlib \\ ../configure \\ --prefix=/tools \\ --disable-nls \\ --disable-werror \\ --with-lib-path=/tools/lib \\ --with-sysroot lfs:/mnt/lfs/sources/binutils-2.27/build$ time make real 10m9.743s user 7m24.319s sys 2m55.368s lfs:/mnt/lfs/sources/binutils-2.27/build$ time make install real 0m11.551s user 0m5.900s sys 0m6.266s 进行链接器的调整 描述:-C是指定目录,对当前ld子目录来做clean动作, lfs:/mnt/lfs/sources/binutils-2.27/build$ ls -l drwxr-xr-x. 7 lfs lfs 4096 Jan 6 23:38 ld lfs:/mnt/lfs/sources/binutils-2.27/build$ make -C ld clean lfs:/mnt/lfs/sources/binutils-2.27/build$ make -C ld LIB_PATH=/usr/lib:/lib #对ld目录下文件做make,指定链接器库的搜索路径,下面有一个很重要的命令ld-new lfs:/mnt/lfs/sources/binutils-2.27/build$ cp -v ld/ld-new /tools/bin 删除多余目录 lfs:/mnt/lfs/sources/binutils-2.27/build$ cd ../../ lfs:/mnt/lfs/sources$ rm -rf binutils-2.27
4.8.gcc
描述: 第二次编译gcc,因为之前的gcc是预工具链的,现在要创建一个临时工具链的gcc,来替代预工具链的,第一次编译时是会安装一些系统内部文件,里面的头文件不是一个完整的,第二次临时工具链必须要有一个完整的头文件
lfs:/mnt/lfs/sources$ tar xf ../downloads/gcc-6.3.0.tar.bz2 lfs:/mnt/lfs/sources$ cd gcc-6.3.0/ lfs:/mnt/lfs/sources/gcc-6.3.0$ cat gcc/limitx.h gcc/glimits.h gcc/limity.h > \\ `dirname $($LFS_TGT-gcc -print-libgcc-file-name)`/include-fixed/limits.h lfs:/mnt/lfs/sources/gcc-6.3.0$ 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 是x86_64的要做修改操作 lfs:/mnt/lfs/sources/gcc-6.3.0$ case $(uname -m) in x86_64) sed -e \'/m64=/s/lib64/lib/\' \\ -i.orig gcc/config/i386/t-linux64 ;; esac 使用算法的包: lfs:/mnt/lfs/sources/gcc-6.3.0$ tar xf ../../downloads/mpfr-3.1.5.tar.xz lfs:/mnt/lfs/sources/gcc-6.3.0$ mv mpfr-3.1.5 mpfr lfs:/mnt/lfs/sources/gcc-6.3.0$ tar xf ../../downloads/gmp-6.1.2.tar.xz lfs:/mnt/lfs/sources/gcc-6.3.0$ mv gmp-6.1.2 gmp lfs:/mnt/lfs/sources/gcc-6.3.0$ tar xf ../../downloads/mpc-1.0.3.tar.gz lfs:/mnt/lfs/sources/gcc-6.3.0$ mv mpc-1.0.3 mpc configure: lfs:/mnt/lfs/sources/gcc-6.3.0$ mkdir build lfs:/mnt/lfs/sources/gcc-6.3.0$ cd build lfs:/mnt/lfs/sources/gcc-6.3.0/build$ CC=$LFS_TGT-gcc \\ CXX=$LFS_TGT-g++ \\ AR=$LFS_TGT-ar \\ RANLIB=$LFS_TGT-ranlib \\ ../configure \\ --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 lfs:/mnt/lfs/sources/gcc-6.3.0/build$ time make #如果失败,要使用clean来清除下,再操作 lfs:/mnt/lfs/sources/gcc-6.3.0/build$ time make install lfs:/mnt/lfs/sources/gcc-6.3.0/build$ ln -sv gcc /tools/bin/cc # 有些软件是调用写死的CC来操作,而不是现在所编译出来的gcc,为了让这此程序能顺利运行, # 所以要创建一个软件连接,在这个阶段gcc出来后,相当于临时工具链已经完整了,对于临时 # 工具链是否能编译出来一个正常的程序,会有一个测试,写一个空的只能主函数的C文件,再 # 使用cc来编译,对于a.out文件使用readelf来读下信息,有特定的输出内容. lfs:/mnt/lfs/sources/gcc-6.3.0/build$ echo \'int main(){}\' > dummy.c cc dummy.c readelf -l a.out | grep \': /tools\' [Requesting program interpreter: /tools/lib/ld-linux.so.2] #输出结果 删除 lfs:/mnt/lfs/sources/gcc-6.3.0/build$ cd ../../ lfs:/mnt/lfs/sources$ rm -rf gcc-6.3.0
4.9.tcl,expect,dejagun,check
描述: 给后续的软件包提供make check之类测试支持
lfs:/mnt/lfs/sources$ tar xf ../downloads/tcl-core8.6.6-src.tar.gz lfs:/mnt/lfs/sources$ cd tcl8.6.6/unix/ lfs:/mnt/lfs/sources/tcl8.6.6/unix$ ./configure --prefix=/tools lfs:/mnt/lfs/sources/tcl8.6.6/unix$ make 检测:对于一些重要的安装包,与编译是否正常,与系统文件是否一致,可能根据平台的不一样会有一些警告,这时要做些忽略, 传递一个变量时区设置为UTC lfs:/mnt/lfs/sources/tcl8.6.6/unix$ time TZ=UTC make test Tests ended at Sun Jan 06 18:57:04 UTC 2019 all.tcl: Total 31259 Passed 29921 Skipped 1285 Failed 53 Sourced 148 Test Files. Files with failing tests: http.test httpold.test Number of tests skipped for each constraint: 9 !ieeeFloatingPoint 3 asyncPipeChan 76 bigEndian 5 bug-3057639 49 dde 4 dontCopyLinks 63 emptyTest 2 hasIsoLocale 1 knownBadTest 39 knownBug 100 localeRegexp 48 longIs32bit 14 macosxFileAttr 76 memory 46 nonPortable 5 notNetworkFilesystem 9 nt 1 pcOnly 4 readonlyAttr 3 singleTestInterp 1 testexprparser && !ieeeFloatingPoint 1 testwinclock 21 testwordend 189 thread 2 unthreaded 2 wideBiggerThanInt 497 win 4 winVista real 15m48.677s user 1m18.065s sys 0m13.138s lfs:/mnt/lfs/sources/tcl8.6.6/unix$ make install lfs:/mnt/lfs/sources/tcl8.6.6/unix$ chmod -v u+w /tools/lib/libtcl8.6.so lfs:/mnt/lfs/sources/tcl8.6.6/unix$ make install-private-headers lfs:/mnt/lfs/sources/tcl8.6.6/unix$ ln -sv tclsh8.6 /tools/bin/tclsh lfs:/mnt/lfs/sources/tcl8.6.6/unix$ ls -l /tools/bin/tcl* lrwxrwxrwx. 1 lfs lfs 8 Jan 7 03:02 /tools/bin/tclsh -> tclsh8.6 -rwxr-xr-x. 1 lfs lfs 13152 Jan 7 03:01 /tools/bin/tclsh8.6 删除遗留文件: lfs:/mnt/lfs/sources/tcl8.6.6/unix$ cd ../../ lfs:/mnt/lfs/sources$ rm -rf tcl8.6.6 expect 描述:与当前用户进行交互时,人无须干预实现自行交互 lfs:/mnt/lfs/sources$ tar xf ../downloads/expect5.45.tar.gz lfs:/mnt/lfs/sources$ cd expect5.45/ lfs:/mnt/lfs/sources/expect5.45$ ##备份与修改配置 cp -v configure{,.orig} sed \'s:/usr/local/bin:/bin:\' configure.orig > configure configure 指定tcl的库和include lfs:/mnt/lfs/sources/expect5.45$ ./configure --prefix=/tools \\ --with-tcl=/tools/lib \\ --with-tclinclude=/tools/include lfs:/mnt/lfs/sources/expect5.45$ time make lfs:/mnt/lfs/sources/expect5.45$ time make test 安装:SCRIPTS可以避免安装一些额外脚本 lfs:/mnt/lfs/sources/expect5.45$ make SCRIPTS="" install lfs:/mnt/lfs/sources/expect5.45$ find /tools/ -name "libexpect*" /tools/lib/expect5.45/libexpect5.45.so /tools/man/man3/libexpect.3 删除遗留文件: lfs:/mnt/lfs/sources/expect5.45$ cd ../ lfs:/mnt/lfs/sources$ rm -rf expect5.45 dejaGNU 描述: 主要做一些单元测试,把程序run起来向它发送一些字符串,等待程序返回结果,软件测试时用得比较多, deja是使用expect来做测试,expect使用了tcl,有依赖关系 lfs:/mnt/lfs/sources$ tar xf ../downloads/dejagnu-1.6.tar.gz lfs:/mnt/lfs/sources$ cd dejagnu-1.6/ lfs:/mnt/lfs/sources/dejagnu-1.6$ ./configure --prefix=/tools lfs:/mnt/lfs/sources/dejagnu-1.6$ make install lfs:/mnt/lfs/sources/dejagnu-1.6$ make check lfs:/mnt/lfs/sources/dejagnu-1.6$ type runtest runtest is /tools/bin/runtest lfs:/mnt/lfs/sources/dejagnu-1.6$ cd .. lfs:/mnt/lfs/sources$ rm -rf dejagnu-1.6 check 描述:C语言测试的一个框架,它会测试提供,如fork一个子进程,小的,单元测试的接口 lfs:/mnt/lfs/sources$ tar xf ../downloads/check-0.11.0.tar.gz lfs:/mnt/lfs/sources$ cd check-0.11.0/ lfs:/mnt/lfs/sources/check-0.11.0$ PKG_CONFIG= ./configure --prefix=/tools lfs:/mnt/lfs/sources/check-0.11.0$ make lfs:/mnt/lfs/sources/check-0.11.0$ time make check #要做些单元测试,会有报告 real 5m53.066s user 0m1.275s sys 0m2.017s lfs:/mnt/lfs/sources/check-0.11.0$ make install lfs:/mnt/lfs/sources/check-0.11.0$ type checkmk checkmk is /tools/bin/checkmk lfs:/mnt/lfs/sources/check-0.11.0$ cd .. lfs:/mnt/lfs/sources$ rm -rf check-0.11.0
4.10.ncurse bash bison bzip2
描述: 为了让临时工具链彻底脱离宿主系统,还需要建立临时系统,第一类是使用交互环境bash,第二类是程序编译的命令,第三类是程序使用的函数库
ncurse: n是new,ncurse是GNU计划的一部分,来替代curses这个非开源软件,如开源的vim替代非开源的vi,ncurse是一套编程类库,它提供的函数是使用来生成文本的界面,vi,screen都是使用ncurses
lfs:/mnt/lfs/sources$ tar xf ../downloads/ncurses-6.0.tar.gz lfs:/mnt/lfs/sources$ cd ncurses-6.0/ lfs:/mnt/lfs/sources/ncurses-6.0$ sed -i s/mawk// configure lfs:/mnt/lfs/sources/ncurses-6.0$ ./configure --prefix=/tools \\ --with-shared \\ --without-debug \\ --without-ada \\ --enable-widec \\ --enable-overwrite lfs:/mnt/lfs/sources/ncurses-6.0$ make lfs:/mnt/lfs/sources/ncurses-6.0$ make install lfs:/mnt/lfs/sources/ncurses-6.0$ find /tools/ -name "*ncurse*" /tools/share/man/man1/ncursesw6-config.1.gz /tools/share/man/man3/ncurses.3x.gz /tools/include/ncurses.h /tools/include/ncurses_dll.h /tools/lib/libncursesw.so /tools/lib/libncursesw.so.6 /tools/lib/libncursesw.a /tools/lib/libncursesw.so.6.0 /tools/lib/libncurses++w.a /tools/bin/ncursesw6-config lfs:/mnt/lfs/sources/ncurses-6.0$ cd .. lfs:/mnt/lfs/sources$ rm -rf ncurses-6.0 bash 描述:选项--without-bash-malloc是不使用bash自身的内存分配功能,而使用glibc的memory location的函数 lfs:/mnt/lfs/sources$ tar xf ../downloads/bash-4.4.tar.gz lfs:/mnt/lfs/sources$ cd bash-4.4/ lfs:/mnt/lfs/sources/bash-4.4$ ./configure --prefix=/tools --without-bash-malloc lfs:/mnt/lfs/sources/bash-4.4$ make lfs:/mnt/lfs/sources/bash-4.4$ make test lfs:/mnt/lfs/sources/bash-4.4$ make install lfs:/mnt/lfs/sources/bash-4.4$ ln -sv bash /tools/bin/sh \'/tools/bin/sh\' -> \'bash\' lfs:/mnt/lfs/sources/bash-4.4$ ls /tools/lib/bash/ Makefile.inc finfo ln mypid printenv rmdir strftime truefalse unlink basename head logname pathchk push setpgid sync tty whoami dirname id mkdir print realpath sleep tee uname lfs:/mnt/lfs/sources/bash-4.4$ cd .. lfs:/mnt/lfs/sources$ rm -rf bash-4.4 bison 描述:语法分析器,对代码的语法,方法进行分析,bison与yacc兼容 lfs:/mnt/lfs/sources$ tar xf ../downloads/bison-3.0.4.tar.xz lfs:/mnt/lfs/sources$ cd bison-3.0.4/ lfs:/mnt/lfs/sources/bison-3.0.4$ ./configure --prefix=/tools lfs:/mnt/lfs/sources/bison-3.0.4$ make lfs:/mnt/lfs/sources/bison-3.0.4$ time make check real 5m14.892s user 4m12.633s sys 1m10.166s lfs:/mnt/lfs/sources/bison-3.0.4$ make install lfs:/mnt/lfs/sources/bison-3.0.4$ cd .. lfs:/mnt/lfs/sources$ rm -rf bison-3.0.4 bzip 描述:包含压缩和觖压缩的工具,它是独立的开源项目,它不是GUN计划的一部分,官网上说明刚修改一个漏洞, CVE,有些公共安全的服务机构,它就是一个公共漏洞的,各个厂商可能会发现一些漏洞,各有各的叫法, 为了标准化,就成立一个组织把它统一起来,使得发现的漏洞信息,可能各个厂商做法就一样,就根据CVE 这个标准来做,bzip2是一个著名的压缩解压缩软件,很大发行版本都有它,CVE-2010-0405,它某一个函数 有一个溢出的漏洞,可以恶意软件使用ddos把系统搞崩溃,如果闭源,这个问题就不容易发现,只有厂商 知道,如果开源被看到可能就很快修改。 lfs:/mnt/lfs/sources$ tar xf ../downloads/bzip2-1.0.6.tar.gz lfs:/mnt/lfs/sources$ cd bzip2-1.0.6/ lfs:/mnt/lfs/sources/bzip2-1.0.6$ make lfs:/mnt/lfs/sources/bzip2-1.0.6$ make PREFIX=/tools install lfs:/mnt/lfs/sources/bzip2-1.0.6$ cd .. lfs:/mnt/lfs/sources$ rm -rf bzip2-1.0.6
4.11.coreutils Diffutils file find
coreutils: 这个软件包包含设置基本属性的工具,常用的chown,是GNU项目中一个很重要的组件,解决操作系统最基本问题, 严格说最基本是解决柴米油盐,酱醋茶也不一定是必须的。 lfs:/mnt/lfs/sources$ tar xf ../downloads/coreutils-8.26.tar.xz lfs:/mnt/lfs/sources$ cd coreutils-8.26/ lfs:/mnt/lfs/sources/coreutils-8.26$ ./configure --prefix=/tools --enable-install-program=hostname #coreutils默认不安装hostname就返回当前,后续有些测试套件要使用hostname命令,所以安装coretuils时把它也编译了 lfs:/mnt/lfs/sources/coreutils-8.26$ time make real 4m8.547s user 3m15.379s sys 0m56.197s lfs:/mnt/lfs/sources/coreutils-8.26$ time make RUN_EXPENSIVE_TESTS=yes check real 11m12.658s user 3m30.002s sys 7m55.864s lfs:/mnt/lfs/sources/coreutils-8.26$ time make install real 0m3.360s user 0m2.312s sys 0m1.262s lfs:/mnt/lfs/sources/coreutils-8.26$ type hostname hostname is /tools/bin/hostname lfs:/mnt/lfs/sources/coreutils-8.26$ cd .. lfs:/mnt/lfs/sources$ rm -rf coreutils-8.26 diffutils lfs:/mnt/lfs/sources$ tar xf ../downloads/diffutils-3.5.tar.xz lfs:/mnt/lfs/sources$ cd diffutils-3.5/ lfs:/mnt/lfs/sources/diffutils-3.5$ ./configure --prefix=/tools lfs:/mnt/lfs/sources/diffutils-3.5$ make lfs:/mnt/lfs/sources/diffutils-3.5$ make check lfs:/mnt/lfs/sources/diffutils-3.5$ make install lfs:/mnt/lfs/sources/diffutils-3.5$ cd .. lfs:/mnt/lfs/sources$ rm -rf diffutils-3.5 file lfs:/mnt/lfs/sources$ tar xf ../downloads/file-5.30.tar.gz lfs:/mnt/lfs/sources$ cd file-5.30/ lfs:/mnt/lfs/sources/file-5.30$ ./configure --prefix=/tools lfs:/mnt/lfs/sources/file-5.30$ make lfs:/mnt/lfs/sources/file-5.30$ make install lfs:/mnt/lfs/sources/file-5.30$ type file file is /tools/bin/file lfs:/mnt/lfs/sources/file-5.30$ cd .. lfs:/mnt/lfs/sources$ rm -rf file-5.30 find lfs:/mnt/lfs/sources$ tar xf ../downloads/findutils-4.6.0.tar.gz lfs:/mnt/lfs/sources$ cd findutils-4.6.0/ lfs:/mnt/lfs/sources/findutils-4.6.0$ ./configure --prefix=/tools lfs:/mnt/lfs/sources/findutils-4.6.0$ make lfs:/mnt/lfs/sources/findutils-4.6.0$ type find find is /bin/find lfs:/mnt/lfs/sources/findutils-4.6.0$ echo $PATH 因为环境变量首先找/tools,找不到再找宿主系统的 /tools/bin:/bin:/usr/bin lfs:/mnt/lfs/sources/findutils-4.6.0$ time make check real 1m10.801s user 0m31.105s sys 0m32.145s lfs:/mnt/lfs/sources/findutils-4.6.0$ time make install real 0m1.538s user 0m1.022s sys 0m0.631s lfs:/mnt/lfs/sources/findutils-4.6.0$ cd .. lfs:/mnt/lfs/sources$ rm -rf findutils-4.6.0
4.12.gawk gettext grep
gawk: g是GNU,awk是文本处理工具,生成报告 lfs:/mnt/lfs/sources$ tar xf ../downloads/gawk-4.1.4.tar.xz lfs:/mnt/lfs/sources$ cd gawk-4.1.4/ lfs:/mnt/lfs/sources/gawk-4.1.4$ ./configure --prefix=/tools lfs:/mnt/lfs/sources/gawk-4.1.4$ make lfs:/mnt/lfs/sources/gawk-4.1.4$ make check make[2]: Leaving directory `/mnt/lfs/sources/gawk-4.1.4/test\' 有些警告可以忽略 make[1]: *** [check] Error 1 make[1]: Leaving directory `/mnt/lfs/sources/gawk-4.1.4/test\' make: *** [check-recursive] Error lfs:/mnt/lfs/sources/gawk-4.1.4$ make install lfs:/mnt/lfs/sources/gawk-4.1.4$ cd .. lfs:/mnt/lfs/sources$ rm -rf gawk-4.1.4 gettext 描述:多语言支持的函数库,如手机的操作系统,把语言设置成中文,微信语言会是中文显示,如果把操作系统修改成英文, 微信也会变,它默认是根据操作系统来设置的,这就是多语言,gettext是可以根据用户当前语言的环境变量来显示一些 什么样的信息,如它一搜索的现在语言的环境变量是英文,现在就直接显示英文,如果是简体中文就看看搜索的程序中的 库里面是有没有这个单词所针对或者变量所针对的中文,如果没有中文就返回这个原始的英文的内容 gettext比较之前安装的组件要多,但是现在是临时工具链可以不安装这么多 lfs:/mnt/lfs/sources$ tar xf ../downloads/gettext-0.19.8.1.tar.xz lfs:/mnt/lfs/sources$ cd gettext-0.19.8.1/gettext-tools/ lfs:/mnt/lfs/sources/gettext-0.19.8.1/gettext-tools$ EMACS="no" ./configure --prefix=/tools --disable-shared #解压后进入一个子目录进行configure,EMACS="no"把这个字符编译器一些个性去掉,而且禁用它的一些动态库,而且编译时只需要编译所需要的 lfs:/mnt/lfs/sources/gettext-0.19.8.1/gettext-tools$ make -C gnulib-lib lfs:/mnt/lfs/sources/gettext-0.19.8.1/gettext-tools$ make -C intl pluralx.c lfs:/mnt/lfs/sources/gettext-0.19.8.1/gettext-tools$ make -C src msgfmt lfs:/mnt/lfs/sources/gettext-0.19.8.1/gettext-tools$ make -C src msgmerge lfs:/mnt/lfs/sources/gettext-0.19.8.1/gettext-tools$ make -C src xgettext lfs:/mnt/lfs/sources/gettext-0.19.8.1/gettext-tools$ cp -v src/{msgfmt,msgmerge,xgettext} /tools/bin lfs:/mnt/lfs/sources/gettext-0.19.8.1/gettext-tools$ cd ../.. lfs:/mnt/lfs/sources$ rm -rf gettext-0.19.8.1 grep lfs:/mnt/lfs/sources$ tar xf ../downloads/grep-3.0.tar.xz lfs:/mnt/lfs/sources$ cd grep-3.0/ lfs:/mnt/lfs/sources/grep-3.0$ ./configure --prefix=/tools lfs:/mnt/lfs/sources/grep-3.0$ make lfs:/mnt/lfs/sources/grep-3.0$ time make check real 0m33.926s user 0m19.127s sys 0m18.063s lfs:/mnt/lfs/sources/grep-3.0$ make install lfs:/mnt/lfs/sources/grep-3.0$ cd .. lfs:/mnt/lfs/sources$ rm -rf grep-3.0
4.13.gzip m4 make
gzip 描述:GNU的zip lfs:/mnt/lfs/sources$ tar xf ../downloads/gzip-1.8.tar.xz lfs:/mnt/lfs/sources$ cd gzip-1.8/ lfs:/mnt/lfs/sources/gzip-1.8$ ./configure --prefix=/tools lfs:/mnt/lfs/sources/gzip-1.8$ make lfs:/mnt/lfs/sources/gzip-1.8$ make check lfs:/mnt/lfs/sources/gzip-1.8$ make install lfs:/mnt/lfs/sources/gzip-1.8$ cd .. lfs:/mnt/lfs/sources$ rm -rf gzip-1.8 M4 描述:宏的预处理器,宏如去超市买一颗口香糖,上面有标签草莓味,苹果味的,标签理解为这盒口香糖, 打开口香糖盒,把它从盒子倒出来,就是宏的展开,可以把宏理解为一个标签,类似于对某种事物 贴了一上标签,在编程中提高效率,早期对于汇编时,基本是离不开宏的 M4实际就是用户输入一些文本将其进行输出 lfs:/mnt/lfs/sources$ tar xf ../downloads/m4-1.4.18.tar.xz lfs:/mnt/lfs/sources$ cd m4-1.4.18/ lfs:/mnt/lfs/sources/m4-1.4.18$ ./configure --prefix=/tools lfs:/mnt/lfs/sources/m4-1.4.18$ make lfs:/mnt/lfs/sources/m4-1.4.18$ make check lfs:/mnt/lfs/sources/m4-1.4.18$ make install lfs:/mnt/lfs/sources/m4-1.4.18$ cd .. lfs:/mnt/lfs/sources$ rm -rf m4-1.4.18 make 描述:管理员可以通过它来编译安装很多工具,有两种做法,一种是make直接回车,还有是后面跟一些类似于参数的, 如check,install等等,可以理解为像接收命令行参数一样,接收目标,这些目标会在makefile里面,有相应的 描述,makefile是通过configure来生成的,也有可能本身就带有,make在执行时会扫描makefile,找到目标后 可能有依赖关系,如果找到目标后有依赖关系,依赖本身还是目标,它会再扫描makefile,来确定这种依赖关系, 一层层地依赖,最后找到最底层的依赖关系表后,然后进行编译,最后编译主目标,可以在大型的开发项目里, 把它分割成一个个可管理的模块,可以使用make和makefile来管理各个文件之间非常复杂的关系。如果没有Make 和makefile,每次都要使用gcc来编译,对于程序员来说简直就是一场灾难。 #--without-guile这个选项最主要是打断临时工具链和宿主系统之间的关系,如果不加这个,可能链接到宿主系统上一个叫guile的 #库,这样可能会出现问题,可以理解为是一种隔离机制,保证了临时系统和宿主系统之间是独立的无关的。 lfs:/mnt/lfs/sources$ tar xf ../downloads/make-4.2.1.tar.bz2 lfs:/mnt/lfs/sources$ cd make-4.2.1/ lfs:/mnt/lfs/sources/make-4.2.1$ ./configure --prefix=/tools --without-guile lfs:/mnt/lfs/sources/make-4.2.1$ make lfs:/mnt/lfs/sources/make-4.2.1$ make check lfs:/mnt/lfs/sources/make-4.2.1$ make install lfs:/mnt/lfs/sources/make-4.2.1$ type make make is /tools/bin/make lfs:/mnt/lfs/sources/make-4.2.1$ cd .. lfs:/mnt/lfs/sources$ rm -rf make-4.2.1
4.14.patch perl sed tar
patch: 能过补丁命令来修改或者创建文件的一个程序,补丁文件通常是由diff来生成的,windows通常是 解决一些安全,功能的一些Bug问题,这里的源代码的补丁是一种高效率修改源代码的方法,如在 有一个文件夹a,是源代码的文件,可能下面还有些子目录,如何进行高效率的修改,假如把一个 新版本的源代码放置在b中,步骤: 使用diff命令将a,b两个文件夹进行比较,把比较的差异写入另一个文件中,它就是所说的补丁文件 再使用patch命令来进行打补丁 lfs:/mnt/lfs/sources$ tar xf ../downloads/patch-2.7.5.tar.xz lfs:/mnt/lfs/sources$ cd patch-2.7.5/ lfs:/mnt/lfs/sources/patch-2.7.5$ ./configure --prefix=/tools lfs:/mnt/lfs/sources/patch-2.7.5$ make lfs:/mnt/lfs/sources/patch-2.7.5$ make check lfs:/mnt/lfs/sources/patch-2.7.5$ make install lfs:/mnt/lfs/sources/patch-2.7.5$ cd .. lfs:/mnt/lfs/sources$ rm -rf patch-2.7.5 perl 描述:借鉴了C的一些功能特性,最方便是它的正则表达式功能,还有大量第三方的代码库, lfs:/mnt/lfs/sources$ tar xf ../downloads/perl-5.24.1.tar.bz2 lfs:/mnt/lfs/sources$ cd perl-5.24.1/ lfs:/mnt/lfs/sources/perl-5.24.1$ sh Configure -des -Dprefix=/tools -Dlibs=-lm lfs:/mnt/lfs/sources/perl-5.24.1$ make #安装是通常cp对相关的命令进行复制 lfs:/mnt/lfs/sources/perl-5.24.1$ cp -v perl cpan/podlators/scripts/pod2man /tools/bin lfs:/mnt/lfs/sources/perl-5.24.1$ mkdir -pv /tools/lib/perl5/5.24.1 lfs:/mnt/lfs/sources/perl-5.24.1$ cp -Rv lib/* /tools/lib/perl5/5.24.1 lfs:/mnt/lfs/sources/perl-5.24.1$ cd .. lfs:/mnt/lfs/sources$ rm -rf perl-5.24.1 sed lfs:/mnt/lfs/sources$ tar xf ../downloads/sed-4.4.tar.xz lfs:/mnt/lfs/sources$ cd sed-4.4/ lfs:/mnt/lfs/sources/sed-4.4$ ./configure --prefix=/tools lfs:/mnt/lfs/sources/sed-4.4$ make lfs:/mnt/lfs/sources/sed-4.4$ make check lfs:/mnt/lfs/sources/sed-4.4$ make install lfs:/mnt/lfs/sources/sed-4.4$ cd .. lfs:/mnt/lfs/sources$ rm -rf sed-4.4 tar lfs:/mnt/lfs/sources$ tar xf ../downloads/tar-1.29.tar.xz lfs:/mnt/lfs/sources$ cd tar-1.29/ lfs:/mnt/lfs/sources/tar-1.29$ ./configure --prefix=/tools lfs:/mnt/lfs/sources/tar-1.29$ make lfs:/mnt/lfs/sources/tar-1.29$ make check #时间比较长 lfs:/mnt/lfs/sources/tar-1.29$ make install lfs:/mnt/lfs/sources/tar-1.29$ cd .. lfs:/mnt/lfs/sources$ rm -rf tar-1.29
4.15.texinfo util-linux xz
texinfo 描述:是一个文档系统,可以根据单一的源文件同时生成多种在线文档的版本,根据texinfo可以创建html,pdf等 lfs:/mnt/lfs/sources$ tar xf ../downloads/texinfo-6.3.tar.xz lfs:/mnt/lfs/sources$ cd texinfo-6.3/ lfs:/mnt/lfs/sources/texinfo-6.3$ ./configure --prefix=/tools #会有报错,但是可以忽略 lfs:/mnt/lfs/sources/texinfo-6.3$ make lfs:/mnt/lfs/sources/texinfo-6.3$ make check lfs:/mnt/lfs/sources/texinfo-6.3$ make install lfs:/mnt/lfs/sources/texinfo-6.3$ cd .. lfs:/mnt/lfs/sources$ rm -rf texinfo-6.3 util-linux 描述:包含各种各样的工具,作为一个临时系统需要有一个硬盘驱动器的加载,mount或格式化分区之类, 工具里包含一堆这种命令。 lfs:/mnt/lfs/sources$ tar xf ../downloads/util-linux-2.29.1.tar.xz lfs:/mnt/lfs/sources$ cd util-linux-2.29.1/ lfs:/mnt/lfs/sources/util-linux-2.29.1$ ./configure --prefix=/tools \\ --without-python \\ --disable-makeinstall-chown \\ --without-systemdsystemunitdir \\ PKG_CONFIG="" lfs:/mnt/lfs/sources/util-linux-2.29.1$ make lfs:/mnt/lfs/sources/util-linux-2.29.1$ make install lfs:/mnt/lfs/sources/util-linux-2.29.1$ cd .. lfs:/mnt/lfs/sources$ rm -rf util-linux-2.29.1 xz 描述:压缩和解压缩工具 lfs:/mnt/lfs/sources$ tar xf ../downloads/xz-5.2.3.tar.xz lfs:/mnt/lfs/sources$ cd xz-5.2.3/ lfs:/mnt/lfs/sources/xz-5.2.3以上是关于从零开始构建Linux的主要内容,如果未能解决你的问题,请参考以下文章
LFS 系列从零开始 DIY Linux 系统:构建临时系统 - Linux-3.19
LFS 系列从零开始 DIY Linux 系统:构建 LFS 系统 - Autoconf-2.69